@fiddle-digital/string-tune 1.1.45 → 1.1.47
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.
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +75 -4
- package/dist/index.d.ts +75 -4
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.js.map
CHANGED
|
@@ -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/StringMirrorObject.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/SystemState.ts","../src/states/TimeState.ts","../src/states/ViewportState.ts","../src/core/StringData.ts","../src/models/IModuleLifecyclePermissions.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/EasingFunctionTool.ts","../src/tools/MagneticPullTool.ts","../src/tools/LerpColorTool.ts","../src/tools/LerpVector2Tool.ts","../src/tools/TransformScaleParserTool.ts","../src/tools/SplitOptionsParserTool.ts","../src/tools/RuleParserTool.ts","../src/tools/ValidationTool.ts","../src/core/StringToolsContainer.ts","../src/utils/isCoarsePointer.ts","../src/utils/style-txn.ts","../src/modules/cursor/StringCursor.ts","../src/modules/cursor/StringImpulse.ts","../src/modules/cursor/StringMagnetic.ts","../src/utils/frame-dom.ts","../src/modules/cursor/CursorReactiveModule.ts","../src/modules/cursor/StringSpotlight.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/CanvasKerningApplier.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","../src/modules/input/StringForm.ts","../src/core/managers/CenterCache.ts","../src/core/managers/HoverTracker.ts","../src/modules/scroll/StringScroller.ts","../src/utils/ParsePartOf.ts","../src/modules/scroll/StringProgressPart.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 { StringImpulse } from \"./modules/cursor/StringImpulse\";\r\nimport { StringMagnetic } from \"./modules/cursor/StringMagnetic\";\r\nimport { StringSpotlight } from \"./modules/cursor/StringSpotlight\";\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\nimport { StringForm } from \"./modules/input/StringForm\";\r\nimport { ISettingsChangeData } from \"./models/event/ISettingsChangeData\";\r\nimport { CenterCache } from \"./core/managers/CenterCache\";\r\nimport { HoverTracker } from \"./core/managers/HoverTracker\";\r\nimport { CursorReactiveModule } from \"./modules/cursor/CursorReactiveModule\";\r\nimport { StringScroller } from \"./modules/scroll/StringScroller\";\r\nimport { parsePartOf } from \"./utils/ParsePartOf\";\r\nimport { StringProgressPart } from \"./modules/scroll/StringProgressPart\";\r\nimport { frameDOM } from \"./utils/frame-dom\";\r\nimport { styleTxn } from \"./utils/style-txn\";\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 private onContainerTransitionEndBind: any;\r\n private onResizeObserverBind: 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 /** Caches the center positions of string objects. */\r\n private centers: CenterCache;\r\n\r\n /** Tracks hover states of string objects. */\r\n private hoverManager: HoverTracker;\r\n\r\n private observerContainerResize: ResizeObserver | null = null;\r\n\r\n public canRebuild: boolean = true;\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 this.objectManager.checkInview();\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 this.observerContainerResize?.unobserve(this.context.data.scroll.container);\r\n\r\n this.data.scroll.elementContainer.removeEventListener(\r\n \"transitionend\",\r\n this.onContainerTransitionEndBind\r\n );\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.data.scroll.elementContainer.addEventListener(\r\n \"transitionend\",\r\n this.onContainerTransitionEndBind\r\n );\r\n this.observerContainerResize?.observe(this.context.data.scroll.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 scrollPosition() {\r\n return this.data.scroll.current;\r\n }\r\n\r\n public get scrollHeight() {\r\n return this.data.viewport.contentHeight;\r\n }\r\n\r\n public get containerHeight() {\r\n return this.data.viewport.windowHeight;\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 public set FPSTrackerVisible(visible: boolean) {\r\n this.data.system.fpsTracker = visible;\r\n this.eventManager.emit(\"tracker:fps:visible\", visible);\r\n }\r\n\r\n public set PositionTrackerVisible(visible: boolean) {\r\n this.data.system.positionTracker = visible;\r\n this.eventManager.emit(\"tracker:position:visible\", visible);\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 this.tools\r\n );\r\n\r\n this.centers = new CenterCache();\r\n this.hoverManager = new HoverTracker();\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 centers: this.centers,\r\n hover: this.hoverManager,\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 \"global-class\": false,\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 \"cursor-lerp\": \"0.75\",\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 \"position-strength\": 3,\r\n \"position-tension\": 0.05,\r\n \"position-friction\": 0.15,\r\n \"position-max-velocity\": 10,\r\n \"position-update-threshold\": 0.1,\r\n \"rotation-strength\": 0.75,\r\n \"rotation-tension\": 0.06,\r\n \"rotation-friction\": 0.18,\r\n \"rotation-max-angular-velocity\": 6,\r\n \"rotation-max-angle\": 18,\r\n \"rotation-update-threshold\": 0.15,\r\n \"max-offset\": 220,\r\n \"sleep-epsilon\": 0.01,\r\n \"continuous-push\": true,\r\n });\r\n\r\n this.onContainerTransitionEndBind = this.onContainerTransitionEnd.bind(this);\r\n\r\n this.onResizeObserverBind = this.onResizeObserverEvent.bind(this);\r\n this.observerContainerResize = new ResizeObserver(this.onResizeObserverBind);\r\n this.observerContainerResize.observe(this.context.data.scroll.container);\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.eventManager.on(`wheel`, this.onWheelBind);\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 centers: this.centers,\r\n hover: this.hoverManager,\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(\"scroll\", this.onScrollBind);\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 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\" || 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(this.context.data.scroll.container, config);\r\n\r\n this.use(StringInview);\r\n\r\n const htmlFontSize = window.getComputedStyle(document.documentElement).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.querySelectorAll(\"[string-copy-from],[data-string-copy-from]\").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\r\n if (connectTargetId && connectTargetId.length > 0) {\r\n this.objectManager.linkMirror(connectTargetId, element as HTMLElement);\r\n }\r\n });\r\n // document.querySelectorAll(\"[string-part-of],[data-string-part-of]\").forEach((element) => {\r\n // let partOfTargetId = this.tools.domAttribute.process({\r\n // element: element as HTMLElement,\r\n // key: \"part-of\",\r\n // fallback: \"\",\r\n // });\r\n // let partOfData = parsePartOf(partOfTargetId as string);\r\n // if (partOfData) {\r\n // if (partOfData.id && partOfData.id.length > 0) {\r\n // if (this.objectManager.all.has(partOfData.id)) {\r\n // let partOfObject = new StringObject(\"\", element as HTMLElement);\r\n // partOfObject.setProperty(\"part-of-id\", partOfData.id);\r\n // partOfObject.setProperty(\"start\", partOfData.start);\r\n // partOfObject.setProperty(\"end\", partOfData.end);\r\n\r\n // this.objectManager.all.get(partOfData.id)!.partOf.push(partOfObject);\r\n // } else {\r\n // this.objectManager.enqueuePartOf(partOfData.id, element as HTMLElement);\r\n // }\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 isDesktop: this.data.viewport.windowWidth > 1024,\r\n widthChanged: true,\r\n heightChanged: true,\r\n scrollHeightChanged: true,\r\n isForceRebuild: false,\r\n });\r\n }\r\n\r\n private onResizeObserverEvent() {\r\n this.debouncedResize();\r\n }\r\n\r\n private onContainerTransitionEnd(event: TransitionEvent) {\r\n if (event.target === this.context.data.scroll.container) {\r\n this.onResize();\r\n this.moduleManager.onResize();\r\n this.moduleManager.onScroll();\r\n this.moduleManager.onFrame();\r\n }\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 frameDOM.measure(() => {\r\n this.moduleManager.onMouseMoveMeasure();\r\n });\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(\"[string-isolation],[data-string-isolation]\");\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 this.eventManager.emit(`scroll:start`, null);\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 this.eventManager.emit(`scroll:stop`, null);\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(data: ISettingsChangeData) {\r\n this.cursorController.onSettingsChange(data);\r\n this.objectManager.onSettingsChange(data);\r\n this.moduleManager.onSettingsChange(data);\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\r\n this.context.centers.invalidateAll();\r\n\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\r\n frameDOM.measure(() => {\r\n this.moduleManager.onScrollMeasure();\r\n });\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\r\n frameDOM.mutate(() => {\r\n styleTxn.begin();\r\n this.moduleManager.onMutate();\r\n styleTxn.commit();\r\n });\r\n\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(force: boolean = false): void {\r\n if (this.canRebuild == false) {\r\n return;\r\n }\r\n\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 =\r\n window.getComputedStyle(container).scale == \"none\"\r\n ? transformScale\r\n : Number(window.getComputedStyle(container).scale);\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current * this.context.data.viewport.transformScale;\r\n const isDesktop = width > 1024;\r\n\r\n const widthChanged = this.prevWidth !== width;\r\n const heightChanged = this.prevHeight !== height;\r\n const scrollHeightChanged = this.context.data.viewport.contentHeight !== newScrollHeight;\r\n\r\n const shouldRebuild = widthChanged || (isDesktop && heightChanged) || scrollHeightChanged;\r\n\r\n this.context.data.scroll.topPosition = Math.floor(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(document.documentElement).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 (widthChanged || (typeof force === \"boolean\" && force)) {\r\n this.moduleManager.onResizeWidth();\r\n }\r\n if (shouldRebuild || (typeof force === \"boolean\" && force)) {\r\n if (this.context.data.scroll.container.scrollTop > 0) {\r\n this.context.data.scroll.current = this.context.data.scroll.container.scrollTop;\r\n this.context.data.scroll.target = this.context.data.scroll.container.scrollTop;\r\n }\r\n\r\n this.scrollManager.updateResponsiveMode();\r\n this.moduleManager.onResize();\r\n this.onSettingsChange({\r\n isDesktop,\r\n widthChanged,\r\n heightChanged,\r\n scrollHeightChanged,\r\n isForceRebuild: force === true,\r\n });\r\n this.moduleManager.onScroll();\r\n this.moduleManager.onScrollMeasure();\r\n this.moduleManager.onFrame();\r\n }\r\n }\r\n\r\n /**\r\n * Scrolls the container to the specified element identified by a CSS selector, applying an optional offset.\r\n *\r\n * Calculates the vertical position of the target element relative to the scroll container and updates the scroll delta accordingly.\r\n * If the element is not found, a warning is logged to the console.\r\n *\r\n * @param selector - The CSS selector string used to identify the target element.\r\n * @param offset - Optional. The number of pixels to offset from the target element's top position. Defaults to 0.\r\n */\r\n public scrollToElement(selector: string, offset: number = 0) {\r\n const element = document.querySelector(selector);\r\n if (element) {\r\n const rect = element.getBoundingClientRect();\r\n const scrollTop =\r\n rect.top + window.pageYOffset - this.data.scroll.container.clientTop - offset;\r\n this.context.data.scroll.delta = scrollTop - this.data.scroll.current;\r\n } else {\r\n console.warn(`Element not found: ${selector}`);\r\n }\r\n }\r\n\r\n public scrollTo(position: number) {\r\n this.scrollManager.get().scrollTo(position);\r\n }\r\n\r\n public invalidateCenter(id: string): void {\r\n this.centers.invalidate(id);\r\n }\r\n\r\n /**\r\n * Forces center cache recalculation for all tracked objects.\r\n * Useful when DOM geometry changes outside of StringTune's control.\r\n */\r\n public invalidateCenters(): void {\r\n this.centers.invalidateAll();\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(\"scroll\", this.onScrollBind);\r\n this.data.scroll.container?.removeEventListener(\"wheel\", this.onWheelBind);\r\n this.data.scroll.elementContainer.removeEventListener(\r\n \"transitionend\",\r\n this.onContainerTransitionEndBind\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 this.eventManager.off(`wheel`, this.onWheelBind);\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 StringForm,\r\n StringImpulse,\r\n StringMagnetic,\r\n StringParallax,\r\n StringPositionTracker,\r\n StringProgress,\r\n StringResponsive,\r\n StringSpotlight,\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 StringScroller,\r\n StringProgressPart,\r\n CursorReactiveModule,\r\n frameDOM,\r\n styleTxn,\r\n type ScrollMarkRule as ScrollTriggerRule,\r\n type StringContext,\r\n};\r\n","import { ISettingsChangeData } from \"../../models/event/ISettingsChangeData\";\r\nimport { 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 private lastMouseX: number = 0;\r\n private lastMouseY: number = 0;\r\n private lastMouseTime: number = 0;\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\r\n this.onSettingsChange({\r\n isDesktop: context.data.viewport.windowWidth > 1024,\r\n isForceRebuild: false,\r\n widthChanged: true,\r\n heightChanged: true,\r\n scrollHeightChanged: true,\r\n });\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 const now = performance.now();\r\n const dt = now - this.lastMouseTime;\r\n\r\n if (dt > 0) {\r\n this.context.data.cursor.velocityX = (e.clientX - this.lastMouseX) / dt;\r\n this.context.data.cursor.velocityY = (e.clientY - this.lastMouseY) / dt;\r\n }\r\n\r\n this.lastMouseX = e.clientX;\r\n this.lastMouseY = e.clientY;\r\n this.lastMouseTime = now;\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({\r\n from: smoothedX,\r\n to: targetX,\r\n progress: this.smoothingFactor,\r\n });\r\n const stepY = this.context.tools.lerp.process({\r\n from: smoothedY,\r\n to: targetY,\r\n progress: this.smoothingFactor,\r\n });\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(data: ISettingsChangeData): void {\r\n let lerp = Number(this.context.settings[\"cursor-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 private stateEvents: Set<string> = new Set();\r\n private lastPayloads: Record<string, any> = {};\r\n\r\n constructor() {\r\n this.stateEvents.add(\"screen:mobile\");\r\n this.stateEvents.add(\"screen:tablet\");\r\n this.stateEvents.add(\"screen:laptop\");\r\n this.stateEvents.add(\"screen:desktop\");\r\n this.stateEvents.add(\"start\");\r\n }\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 | null\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 if (\r\n this.stateEvents.has(fullEvent) &&\r\n this.lastPayloads[fullEvent] !== undefined\r\n ) {\r\n callback(this.lastPayloads[fullEvent]);\r\n }\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 if (this.stateEvents.has(eventName)) {\r\n this.lastPayloads[eventName] = payload;\r\n }\r\n const set = this.listeners[eventName];\r\n if (!set) return;\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 { ISettingsChangeData } from \"../../models/event/ISettingsChangeData\";\r\nimport { IStringModule } from \"../IStringModule\";\r\nimport { StringModule } from \"../StringModule\";\r\n\r\ntype LifecycleName =\r\n | \"destroy\"\r\n | \"onInit\"\r\n | \"onFrame\"\r\n | \"onMutate\"\r\n | \"onScrollMeasure\"\r\n | \"onMouseMoveMeasure\"\r\n | \"onScroll\"\r\n | \"onResizeWidth\"\r\n | \"onResize\"\r\n | \"onMouseMove\"\r\n | \"onWheel\"\r\n | \"onDirectionChange\"\r\n | \"onScrollStart\"\r\n | \"onScrollStop\"\r\n | \"onAxisChange\"\r\n | \"onDeviceChange\"\r\n | \"onScrollConfigChange\"\r\n | \"onSettingsChange\"\r\n | \"onDOMMutate\";\r\n\r\nfunction toLifecycleArgs(\r\n lifecycle: LifecycleName,\r\n data: StringData,\r\n arg?: unknown,\r\n arg2?: unknown\r\n): unknown[] {\r\n switch (lifecycle) {\r\n case \"onFrame\":\r\n case \"onMutate\":\r\n case \"onScrollMeasure\":\r\n case \"onMouseMoveMeasure\":\r\n case \"onScroll\":\r\n return [data];\r\n case \"onMouseMove\":\r\n case \"onWheel\":\r\n return arg ? [arg] : [];\r\n case \"onDOMMutate\":\r\n return arg && arg2 ? [arg, arg2] : [];\r\n case \"onSettingsChange\":\r\n return [];\r\n default:\r\n return [];\r\n }\r\n}\r\n\r\nexport class ModuleManager {\r\n private modules: StringModule[] = [];\r\n private uiModules: StringModule[] = [];\r\n private allModules: StringModule[] = [];\r\n\r\n constructor(private data: StringData) {}\r\n\r\n register(module: StringModule): void {\r\n if (module.type === 1) {\r\n this.modules.push(module);\r\n } else if (module.type === 2) {\r\n this.uiModules.push(module);\r\n }\r\n\r\n this.rebuildAllModules();\r\n }\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 onInit(): void {\r\n this.callAll(\"onInit\");\r\n }\r\n\r\n onFrame(): void {\r\n this.callAll(\"onFrame\");\r\n }\r\n\r\n onMutate(): void {\r\n this.callAll(\"onMutate\");\r\n }\r\n\r\n onScrollMeasure(): void {\r\n this.callAll(\"onScrollMeasure\");\r\n }\r\n\r\n onMouseMoveMeasure(): void {\r\n this.callAll(\"onMouseMoveMeasure\");\r\n }\r\n\r\n onScroll(): void {\r\n this.callAll(\"onScroll\");\r\n }\r\n\r\n onResizeWidth(): void {\r\n this.callAll(\"onResizeWidth\");\r\n }\r\n\r\n onResize(): void {\r\n this.callAll(\"onResize\");\r\n }\r\n\r\n onMouseMove(e: MouseEvent): void {\r\n this.callAll(\"onMouseMove\", e);\r\n }\r\n\r\n onWheel(e: WheelEvent): void {\r\n this.callAll(\"onWheel\", e);\r\n }\r\n\r\n onDirectionChange(): void {\r\n this.callAll(\"onDirectionChange\");\r\n }\r\n\r\n onScrollStart(): void {\r\n this.callAll(\"onScrollStart\");\r\n }\r\n\r\n onScrollStop(): void {\r\n this.callAll(\"onScrollStop\");\r\n }\r\n\r\n onAxisChange(): void {\r\n this.callAll(\"onAxisChange\");\r\n }\r\n\r\n onDeviceChange(): void {\r\n this.callAll(\"onDeviceChange\");\r\n }\r\n\r\n onScrollConfigChange(): void {\r\n this.callAll(\"onScrollConfigChange\");\r\n }\r\n\r\n onSettingsChange(_data: ISettingsChangeData): void {\r\n this.callAll(\"onSettingsChange\");\r\n }\r\n\r\n onDOMMutate(added: NodeList, removed: NodeList): void {\r\n this.callAll(\"onDOMMutate\", added, removed);\r\n }\r\n\r\n destroy(): void {\r\n this.callAll(\"destroy\");\r\n this.modules = [];\r\n this.uiModules = [];\r\n this.allModules = [];\r\n }\r\n\r\n get all(): IStringModule[] {\r\n return this.allModules;\r\n }\r\n\r\n get core(): IStringModule[] {\r\n return this.modules;\r\n }\r\n\r\n get ui(): IStringModule[] {\r\n return this.uiModules;\r\n }\r\n\r\n private callAll(lifecycle: LifecycleName, arg?: unknown, arg2?: unknown): void {\r\n this.callLifecycle(this.modules, lifecycle, arg, arg2);\r\n this.callLifecycle(this.uiModules, lifecycle, arg, arg2);\r\n }\r\n\r\n private callLifecycle(\r\n modules: StringModule[],\r\n lifecycle: LifecycleName,\r\n arg?: unknown,\r\n arg2?: unknown\r\n ): void {\r\n if (modules.length === 0) {\r\n return;\r\n }\r\n\r\n const args = toLifecycleArgs(lifecycle, this.data, arg, arg2);\r\n\r\n for (let i = 0; i < modules.length; i++) {\r\n const module = modules[i];\r\n if (!module) continue;\r\n\r\n (module as any)[lifecycle](...args);\r\n }\r\n }\r\n\r\n private rebuildAllModules(): void {\r\n this.allModules = [...this.modules, ...this.uiModules];\r\n }\r\n}\r\n","import type { StringObject } from \"./StringObject\";\n\nexport type MirrorEasingFn = (value: number) => number;\n\n/**\n * Lightweight wrapper that mirrors a primary StringObject while keeping\n * its own easing and state. Intended for elements linked via\n * `[string-copy-from]`.\n */\nexport class StringMirrorObject {\n public readonly id: string;\n public readonly htmlElement: HTMLElement;\n\n private properties = new Map<string, any>();\n private easingFn?: MirrorEasingFn;\n\n constructor(id: string, element: HTMLElement, private parent: StringObject) {\n this.id = id;\n this.htmlElement = element;\n }\n\n public get parentObject(): StringObject {\n return this.parent;\n }\n\n public setProperty<T>(key: string, value: T): void {\n this.properties.set(key, value);\n }\n\n public getProperty<T>(key: string): T {\n return this.properties.get(key) ?? null;\n }\n\n public setEasing(easing: MirrorEasingFn | null | undefined): void {\n this.easingFn = easing ?? undefined;\n }\n\n public getEasing(): MirrorEasingFn | undefined {\n return this.easingFn;\n }\n\n /**\n * Returns eased progress using mirror easing (if set) or fallback.\n */\n public applyProgress(rawProgress: number, fallback?: MirrorEasingFn): number {\n const easing = this.easingFn ?? fallback;\n return easing ? easing(rawProgress) : rawProgress;\n }\n}\n","import { IStringModule } from \"../core/IStringModule\";\nimport { EventManager } from \"../core/managers/EventManager\";\nimport { StringMirrorObject } from \"./StringMirrorObject\";\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 /**\n * Mirror objects linked via `string-copy-from`.\n */\n private mirrors = new Map<string, StringMirrorObject>();\n\r\n /**\n * Internal key-value store of dynamic object properties (like offsets, progress, etc.).\n */\n private properties: Map<string, any> = new Map();\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();\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 /**\n * Retrieves a previously stored property value.\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) => {\n module.removeObject(this.id);\n });\n }\n\n /**\n * Shows the object, applies visual class and notifies connected modules.\n */\n public show(): void {\n this.htmlElement.classList.add(\"-inview\");\n }\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 {\n if (!this.modules.includes(module)) {\n this.modules.push(module);\n }\n }\n\n public addMirror(mirror: StringMirrorObject): void {\n this.mirrors.set(mirror.id, mirror);\n }\n\n public removeMirror(id: string): void {\n this.mirrors.delete(id);\n }\n\n public get mirrorObjects(): StringMirrorObject[] {\n return Array.from(this.mirrors.values());\n }\n\n public get connects(): HTMLElement[] {\n return this.mirrorObjects.map((mirror) => mirror.htmlElement);\n }\n}\n","import { ModuleManager } from \"./ModuleManager\";\r\nimport { StringData } from \"../StringData\";\r\nimport { StringMirrorObject } from \"../../objects/StringMirrorObject\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EventManager } from \"./EventManager\";\r\nimport { ISettingsChangeData } from \"../../models/event/ISettingsChangeData\";\r\nimport { StringToolsContainer } from \"../StringToolsContainer\";\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 mirrors = new Map<string, StringMirrorObject>();\r\n private mirrorId = 1;\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 private tools: StringToolsContainer\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) ? this.objects.get(idAttr)! : new StringObject(idAttr, el);\r\n\r\n el.setAttribute(key, object.id);\r\n\r\n const keysAttr = el.getAttribute(\"string\") ?? el.getAttribute(\"data-string\");\r\n\r\n if (keysAttr) {\r\n object.keys = (keysAttr ?? \"\")\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter(Boolean);\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 (\"setupCoreProperties\" in m && typeof m[\"setupCoreProperties\"] === \"function\") {\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) => this.attachMirrorToObject(object, 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 this.checkInviewForObject(object);\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 obj.mirrorObjects.forEach((mirror) => {\r\n mirror.htmlElement.removeAttribute(\"string-mirror-id\");\r\n this.mirrors.delete(mirror.id);\r\n\r\n const copyFromId =\r\n mirror.htmlElement.getAttribute(\"string-copy-from\") ??\r\n mirror.htmlElement.getAttribute(\"data-string-copy-from\");\r\n if (copyFromId) {\r\n this.enqueueConnection(copyFromId, mirror.htmlElement);\r\n }\r\n });\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 if (this.connectQueue.some((item) => item.id === id && item.element === element)) {\r\n return;\r\n }\r\n this.connectQueue.push({ id, element });\r\n }\r\n\r\n public linkMirror(id: string, element: HTMLElement): void {\r\n const parent = this.objects.get(id);\r\n if (parent) {\r\n this.attachMirrorToObject(parent, element);\r\n } else {\r\n this.enqueueConnection(id, element);\r\n }\r\n }\r\n\r\n private attachMirrorToObject(object: StringObject, element: HTMLElement): StringMirrorObject {\r\n const existingId =\r\n element.getAttribute(\"string-mirror-id\") ?? element.getAttribute(\"data-string-mirror-id\");\r\n\r\n if (existingId) {\r\n const existing = this.mirrors.get(existingId);\r\n if (existing) {\r\n if (existing.parentObject === object) {\r\n return existing;\r\n }\r\n existing.parentObject.removeMirror(existingId);\r\n this.mirrors.delete(existingId);\r\n }\r\n }\r\n\r\n const mirrorId = existingId ?? `string-mirror-${this.mirrorId++}`;\r\n const mirror = new StringMirrorObject(mirrorId, element, object);\r\n element.setAttribute(\"string-mirror-id\", mirrorId);\r\n object.addMirror(mirror);\r\n this.mirrors.set(mirrorId, mirror);\r\n\r\n const easingAttr =\r\n element.getAttribute(\"string-easing\") ?? element.getAttribute(\"data-string-easing\");\r\n if (easingAttr && easingAttr.trim().length > 0) {\r\n mirror.setEasing(this.tools.easingFunction.process({ easing: easingAttr }));\r\n mirror.setProperty(\"easing\", easingAttr);\r\n }\r\n return mirror;\r\n }\r\n\r\n private detachMirrorByElement(element: HTMLElement): void {\r\n const mirrorId =\r\n element.getAttribute(\"string-mirror-id\") ?? element.getAttribute(\"data-string-mirror-id\");\r\n if (!mirrorId) return;\r\n this.detachMirrorById(mirrorId);\r\n element.removeAttribute(\"string-mirror-id\");\r\n }\r\n\r\n private detachMirrorById(mirrorId: string): void {\r\n const mirror = this.mirrors.get(mirrorId);\r\n if (!mirror) return;\r\n mirror.parentObject.removeMirror(mirrorId);\r\n this.mirrors.delete(mirrorId);\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 outsideProp = obj.getProperty<boolean>(\"outside-container\");\r\n const outsideAttrValue =\r\n el.getAttribute(\"string-outside-container\") ??\r\n el.getAttribute(\"data-string-outside-container\");\r\n const outsideAttrNormalized =\r\n outsideAttrValue != null ? outsideAttrValue.trim().toLowerCase() : null;\r\n const outsideAttrFlag =\r\n outsideAttrNormalized === \"\" ||\r\n outsideAttrNormalized === \"true\" ||\r\n outsideAttrNormalized === \"1\";\r\n const isOutsideContainer = outsideProp != null ? outsideProp === true : outsideAttrFlag;\r\n const observerRoot =\r\n this.data.scroll.container === document.body || isOutsideContainer\r\n ? null\r\n : this.data.scroll.container;\r\n\r\n const progressObserver = new IntersectionObserver(progressCallback, {\r\n root: observerRoot,\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 this.detachMirrorByElement(element);\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.querySelectorAll(\"[string],[data-string]\").forEach((child) => {\r\n if (this.isFixed(child as HTMLElement)) return;\r\n this.handleRemoved(child as HTMLElement);\r\n });\r\n\r\n element\r\n .querySelectorAll(\"[string-copy-from],[data-string-copy-from]\")\r\n .forEach((child) => this.detachMirrorByElement(child as HTMLElement));\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 (element.hasAttribute(\"string\") && !element.hasAttribute(\"string-inited\")) {\r\n this.add(element);\r\n }\r\n\r\n element\r\n .querySelectorAll(\"[string]:not([string-inited]),[data-string]:not([string-inited])\")\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\r\n if (copyFrom) {\r\n this.linkMirror(copyFrom, element);\r\n }\r\n\r\n element\r\n .querySelectorAll(\"[string-copy-from],[data-string-copy-from]\")\r\n .forEach((child) => {\r\n const childCopyFrom =\r\n child.getAttribute(\"string-copy-from\") ??\r\n child.getAttribute(\"data-string-copy-from\");\r\n if (childCopyFrom) {\r\n this.linkMirror(childCopyFrom, child as HTMLElement);\r\n }\r\n });\r\n });\r\n\r\n if (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0) {\r\n this.modules.onDOMMutate(mutation.addedNodes, mutation.removedNodes);\r\n }\r\n\r\n // Let modules know about DOM rebuild\r\n this.modules.all.forEach((m) => m.onDOMRebuild());\r\n }\r\n });\r\n });\r\n\r\n observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Removes an object and its observers.\r\n */\r\n private handleRemoved(el: HTMLElement): void {\r\n const id = el.getAttribute(\"string-id\") ?? el.getAttribute(\"data-string-id\");\r\n if (!id) return;\r\n\r\n const copyFrom =\r\n el.getAttribute(\"string-copy-from\") ?? 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(data: ISettingsChangeData) {\r\n this.objects.forEach((object) => {\r\n this.modules.core.forEach((m) => {\r\n let isCanRebuild = false;\r\n if (data.isDesktop) {\r\n if (m.permissions.desktop.rebuild.scrollHeight && data.scrollHeightChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.desktop.rebuild.width && data.widthChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.desktop.rebuild.height && data.heightChanged) {\r\n isCanRebuild = true;\r\n }\r\n } else {\r\n if (m.permissions.mobile.rebuild.scrollHeight && data.scrollHeightChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.mobile.rebuild.width && data.widthChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.mobile.rebuild.height && data.heightChanged) {\r\n isCanRebuild = true;\r\n }\r\n }\r\n\r\n if (isCanRebuild || data.isForceRebuild) {\r\n if (m.canConnect(object)) {\r\n const attributes = this.getAllAttributes(object.htmlElement);\r\n m.initializeObject(this.globalId, object, object.htmlElement, attributes);\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 /**\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 this.checkInviewForObject(object);\r\n });\r\n }\r\n\r\n private checkInviewForObject(object: StringObject) {\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\r\n const start = Math.min(inviewStart, inviewEnd);\r\n const end = Math.max(inviewStart, inviewEnd);\r\n const isNowInView = scrollPos >= start && scrollPos <= end;\r\n\r\n let direction: \"enter-top\" | \"enter-bottom\" | \"exit-top\" | \"exit-bottom\" | null = null;\r\n if (!wasInView && isNowInView) {\r\n const distToStart = Math.abs(scrollPos - start);\r\n const distToEnd = Math.abs(end - scrollPos);\r\n direction = distToStart <= distToEnd ? \"enter-top\" : \"enter-bottom\";\r\n } else if (wasInView && !isNowInView) {\r\n direction = scrollPos < start ? \"exit-top\" : \"exit-bottom\";\r\n }\r\n if (isNowInView !== wasInView) {\r\n object.setProperty(\"is-inview\", isNowInView);\r\n this.events.emit(`object:inview:${object.id}`, {\r\n inView: isNowInView,\r\n direction,\r\n });\r\n isNowInView ? object.show() : object.hide();\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(0, this.context.data.scroll.current);\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(this.context.data.scroll.current, 0);\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Creates a new ScrollController instance.\r\n * @param context Shared context containing data and settings.\r\n */\r\n constructor(context: StringContext) {\r\n this.document = document;\r\n this.context = context;\r\n }\r\n\r\n /**\r\n * Called when scroll direction changes (up ↔ down).\r\n * Override this callback in subclasses or instances.\r\n */\r\n public onChangeDirection = () => {};\r\n\r\n /**\r\n * Called when scroll starts (user input).\r\n * Override this callback in subclasses or instances.\r\n */\r\n public onScrollStart = () => {};\r\n\r\n /**\r\n * Called when scroll ends.\r\n * Override this callback in subclasses or instances.\r\n */\r\n public onScrollStop = () => {};\r\n\r\n /**\r\n * Scroll-to function called on each frame.\r\n * This will be reassigned depending on scroll direction.\r\n */\r\n public onCalcUpdate: () => void = () => {\r\n this.context.data.scroll.scrollContainer?.scrollTo(0, this.context.data.scroll.current);\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((rule) => rule.id !== id);\r\n }\r\n\r\n public scrollTo(position: number) {}\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 public scrollTo(position: number) {\r\n this.context.data.scroll.target = position;\r\n this.context.data.scroll.delta = 1;\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","/**\r\n * CSS class names applied to `<html>` element based on scroll direction.\r\n */\r\nexport const SCROLL_CLASS_NAMES = {\r\n SCROLL_FORWARD: \"-scroll-forward\",\r\n SCROLL_BACKWARD: \"-scroll-backward\",\r\n SCROLLING_FORWARD: \"-scrolling-forward\",\r\n SCROLLING_BACKWARD: \"-scrolling-backward\",\r\n} as const;\r\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 this.context.events.emit(`scroll:direction:change`, this.context.data.scroll.isScrollingDown);\r\n\r\n if (this.context.settings[\"global-class\"]) {\r\n document.documentElement.classList.toggle(SCROLL_CLASS_NAMES.SCROLLING_FORWARD, newDirection);\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLLING_BACKWARD,\r\n !newDirection\r\n );\r\n document.documentElement.classList.toggle(SCROLL_CLASS_NAMES.SCROLL_FORWARD, newDirection);\r\n document.documentElement.classList.toggle(SCROLL_CLASS_NAMES.SCROLL_BACKWARD, !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 = this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.target = this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current * 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 = this.context.data.scroll.delta * this.context.data.scroll.speedAccelerate;\r\n\r\n this.context.data.scroll.target = Math.min(\r\n Math.max(0, this.context.data.scroll.target + this.scrollForce),\r\n this.context.data.scroll.bottomPosition\r\n );\r\n this.context.data.scroll.delta -= this.scrollForce;\r\n\r\n this.context.data.scroll.lerped =\r\n (this.context.data.scroll.target - this.context.data.scroll.current) *\r\n this.context.data.scroll.speed;\r\n\r\n const absVelocity = Math.abs(this.context.data.scroll.lerped);\r\n if (this.context.data.scroll.lerped > 0) {\r\n this.context.data.scroll.current = Math.ceil(\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 * 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 === this.context.data.scroll.bottomPosition &&\r\n scrollDirection > 0;\r\n\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 public scrollTo(position: number) {\r\n this.context.data.scroll.target = position;\r\n this.context.data.scroll.delta = 1;\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 < 1024;\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 * Velocity in X direction, calculated from smoothed position.\r\n */\r\n velocityX: number = 0;\r\n\r\n /**\r\n * Velocity in Y direction, calculated from smoothed position.\r\n */\r\n velocityY: 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","export class SystemState {\n fpsTracker: boolean = false;\n positionTracker: boolean = false;\n}\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 { SystemState } from \"../states/SystemState\";\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 system = new SystemState();\r\n}\r\n","export interface ModuleLifecyclePermissionsItem {\n rebuild: {\n width: boolean;\n height: boolean;\n scrollHeight: boolean;\n };\n}\nexport class ModuleLifecyclePermissions {\n desktop: ModuleLifecyclePermissionsItem = {\n rebuild: {\n width: true,\n height: true,\n scrollHeight: true,\n },\n };\n mobile: ModuleLifecyclePermissionsItem = {\n rebuild: {\n width: true,\n height: true,\n scrollHeight: true,\n },\n };\n}\n","import { IStringModule } from \"./IStringModule\";\r\nimport { StringObject } from \"../objects/StringObject\";\r\nimport { StringMirrorObject } from \"../objects/StringMirrorObject\";\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\nimport { ModuleLifecyclePermissions } from \"../models/IModuleLifecyclePermissions\";\r\nimport { CenterCache } from \"./managers/CenterCache\";\r\nimport { HoverTracker } from \"./managers/HoverTracker\";\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 /**\r\n * Cache for storing and managing object centers.\r\n */\r\n protected centers: CenterCache;\r\n\r\n /**\r\n * Tracker for managing hover states of objects.\r\n */\r\n protected hover: HoverTracker;\r\n\r\n public permissions: ModuleLifecyclePermissions = new ModuleLifecyclePermissions();\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 this.centers = context.centers;\r\n this.hover = context.hover;\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: \"outside-container\", type: \"boolean\", fallback: this.settings[\"outside-container\"] },\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: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n const top = boundingRect.top;\r\n return (\r\n Math.floor(top) +\r\n this.data.scroll.container.scrollTop * this.data.viewport.transformScale\r\n );\r\n },\r\n },\r\n {\r\n key: \"end\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n const top = boundingRect.top;\r\n const height = boundingRect.height;\r\n return top + height - this.data.scroll.transformedCurrent;\r\n },\r\n },\r\n {\r\n key: \"size\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n return boundingRect.height;\r\n },\r\n },\r\n {\r\n key: \"half-width\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n return boundingRect.width / 2;\r\n },\r\n },\r\n {\r\n key: \"half-height\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\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\" ? fallback(element, object, boundingRect) : fallback;\r\n const raw = this.tools.domAttribute.process({\r\n element,\r\n key,\r\n fallback: attributes[key] ?? this.settings[key] ?? resolvedFallback,\r\n });\r\n\r\n let parsed = this.parseAttribute(raw, type, {\r\n element,\r\n boundingRect,\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>(\"start-position\", startPosition - this.data.scroll.topPosition);\r\n object.setProperty<number>(\"end-position\", endPosition - this.data.scroll.topPosition);\r\n object.setProperty<number>(\"difference-position\", endPosition - startPosition);\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 object.getProperty<number>(\"start-position\") + inviewTop\r\n );\r\n object.setProperty<number>(\r\n \"inview-end-position\",\r\n object.getProperty<number>(\"end-position\") + 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 boundingRect?: DOMRect;\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 context.boundingRect != 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 boundingRect: context.boundingRect,\r\n baseRem: context.baseRem,\r\n });\r\n } else {\r\n return 0;\r\n }\r\n\r\n case \"breakpoint-dimension\":\r\n if (\r\n context.element != null &&\r\n context.viewportHeight != null &&\r\n context.baseRem != null &&\r\n context.boundingRect != null\r\n ) {\r\n let parsedBreakpoint = value.trim().split(\"|\");\r\n let breakpoints: Array<{ breakpoint: number; value: number }> = [];\r\n for (const item of parsedBreakpoint) {\r\n if (item.includes(\":\")) {\r\n const [key, val] = item.split(\":\");\r\n breakpoints.push({\r\n breakpoint: parseInt(key),\r\n value: this.tools.unitParser.process({\r\n value: `${val}|`,\r\n element: context.element,\r\n viewportHeight: context.viewportHeight,\r\n boundingRect: context.boundingRect,\r\n baseRem: context.baseRem,\r\n }),\r\n });\r\n } else {\r\n breakpoints.push({\r\n breakpoint: 0,\r\n value: this.tools.unitParser.process({\r\n value: item,\r\n element: context.element,\r\n viewportHeight: context.viewportHeight,\r\n boundingRect: context.boundingRect,\r\n baseRem: context.baseRem,\r\n }),\r\n });\r\n }\r\n }\r\n return breakpoints;\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 this.onObjectDisconnected(object);\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 * Called when an object is disconnected. Can be overridden to clean up styles or logic.\r\n * @param object The disconnected object.\r\n */\r\n onObjectDisconnected(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 copyFn: (el: HTMLElement, mirror?: StringMirrorObject) => void = applyFn\r\n ) {\r\n if (object.getProperty(\"self-disable\") !== true) {\r\n applyFn(object.htmlElement);\r\n }\r\n object.mirrorObjects.forEach((mirror) => copyFn(mirror.htmlElement, mirror));\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 onMutate(data: StringData): void {}\r\n onScrollMeasure(data: StringData): void {}\r\n onMouseMoveMeasure(data: StringData): void {}\r\n /** Called when the window or layout is resized. */\r\n onResize(): void {}\r\n\r\n /** Called when the layout is resized width. */\r\n onResizeWidth(): 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 boundingRect: DOMRect;\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, boundingRect }: UnitParserInput): number {\r\n const parts = value\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter(Boolean);\r\n\r\n let sum = 0;\r\n for (const part of parts) {\r\n let v = part;\r\n let isNegative = false;\r\n if (v.startsWith(\"-\")) {\r\n isNegative = true;\r\n v = v.slice(1);\r\n }\r\n let result = 0;\r\n if (v === \"selfHeight\") {\r\n result = element.offsetHeight;\r\n } else if (v.endsWith(\"px\")) {\r\n result = parseFloat(v);\r\n } else if (v.endsWith(\"%\")) {\r\n result = (parseFloat(v) / 100) * viewportHeight;\r\n } else if (v.endsWith(\"rem\")) {\r\n result = parseFloat(v) * baseRem;\r\n } else if (v.endsWith(\"sh\")) {\r\n result = (parseFloat(v) * boundingRect.height) / 100;\r\n } else {\r\n result = parseFloat(v);\r\n }\r\n\r\n sum += isNegative ? -result : result;\r\n }\r\n\r\n return sum;\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 * Input for parsing origin to normalized coordinates.\r\n * Supports formats like `'left top'`, `'center center'`, `'50% 50%'`, `'35% 76%'`.\r\n */\r\ninterface OriginToNormalizedInput {\r\n /** Raw origin string, e.g. `'left top'`, `'center'`, `'50% 25%'`. */\r\n value: string;\r\n}\r\n\r\n/**\r\n * Output: normalized origin coordinates (0-1 range).\r\n */\r\ninterface NormalizedOrigin {\r\n /** Normalized X coordinate (0 = left, 0.5 = center, 1 = right). */\r\n x: number;\r\n /** Normalized Y coordinate (0 = top, 0.5 = center, 1 = bottom). */\r\n y: number;\r\n}\r\n\r\n/** Keyword mappings for horizontal axis. */\r\nconst HORIZONTAL_KEYWORDS: Record<string, number> = {\r\n left: 0,\r\n center: 0.5,\r\n right: 1,\r\n};\r\n\r\n/** Keyword mappings for vertical axis. */\r\nconst VERTICAL_KEYWORDS: Record<string, number> = {\r\n top: 0,\r\n center: 0.5,\r\n bottom: 1,\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 * Also provides `toNormalized()` method to convert origin strings to `{ x, y }` coordinates.\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 if (!value) return \"center\";\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 /**\r\n * Parses an origin string to normalized `{ x, y }` coordinates (0-1 range).\r\n *\r\n * Supported formats:\r\n * - Single keyword: `'center'`, `'top'`, `'left'`, etc.\r\n * - Two keywords: `'left top'`, `'right bottom'`, `'center center'`\r\n * - Percentages: `'50% 50%'`, `'0% 100%'`, `'35% 76%'`\r\n * - Mixed: `'left 25%'`, `'50% top'`\r\n *\r\n * @param input - The origin string to parse.\r\n * @returns Normalized `{ x, y }` coordinates.\r\n */\r\n toNormalized({ value }: OriginToNormalizedInput): NormalizedOrigin {\r\n const raw = this.process({ value });\r\n const parts = raw.toLowerCase().split(/\\s+/).filter(Boolean);\r\n\r\n if (parts.length === 0) {\r\n return { x: 0.5, y: 0.5 };\r\n }\r\n\r\n if (parts.length === 1) {\r\n const single = parts[0];\r\n const parsed = this.parseValue(single);\r\n\r\n // If it's a horizontal keyword, use center for Y\r\n if (single in HORIZONTAL_KEYWORDS && !(single in VERTICAL_KEYWORDS)) {\r\n return { x: parsed, y: 0.5 };\r\n }\r\n // If it's a vertical keyword, use center for X\r\n if (single in VERTICAL_KEYWORDS && !(single in HORIZONTAL_KEYWORDS)) {\r\n return { x: 0.5, y: parsed };\r\n }\r\n // 'center' or percentage applies to both\r\n return { x: parsed, y: parsed };\r\n }\r\n\r\n // Two parts: determine which is X and which is Y\r\n const [first, second] = parts;\r\n\r\n // Check if keywords need to be swapped (e.g., \"top left\" → x=left, y=top)\r\n const firstIsVerticalOnly = first in VERTICAL_KEYWORDS && !(first in HORIZONTAL_KEYWORDS);\r\n const secondIsHorizontalOnly = second in HORIZONTAL_KEYWORDS && !(second in VERTICAL_KEYWORDS);\r\n\r\n if (firstIsVerticalOnly || secondIsHorizontalOnly) {\r\n // Swap: first is Y, second is X\r\n return {\r\n x: this.parseValue(second, \"horizontal\"),\r\n y: this.parseValue(first, \"vertical\"),\r\n };\r\n }\r\n\r\n // Default order: first is X, second is Y\r\n return {\r\n x: this.parseValue(first, \"horizontal\"),\r\n y: this.parseValue(second, \"vertical\"),\r\n };\r\n }\r\n\r\n /**\r\n * Parses a single value (keyword or percentage) to a normalized number.\r\n */\r\n private parseValue(val: string, axis?: \"horizontal\" | \"vertical\"): number {\r\n // Check keywords\r\n if (axis === \"horizontal\" && val in HORIZONTAL_KEYWORDS) {\r\n return HORIZONTAL_KEYWORDS[val];\r\n }\r\n if (axis === \"vertical\" && val in VERTICAL_KEYWORDS) {\r\n return VERTICAL_KEYWORDS[val];\r\n }\r\n if (val in HORIZONTAL_KEYWORDS) {\r\n return HORIZONTAL_KEYWORDS[val];\r\n }\r\n if (val in VERTICAL_KEYWORDS) {\r\n return VERTICAL_KEYWORDS[val];\r\n }\r\n\r\n // Parse percentage\r\n if (val.endsWith(\"%\")) {\r\n const num = parseFloat(val);\r\n if (!isNaN(num)) {\r\n return num / 100;\r\n }\r\n }\r\n\r\n // Parse plain number (treat as percentage)\r\n const num = parseFloat(val);\r\n if (!isNaN(num)) {\r\n // If it's a small number (0-1), treat as normalized\r\n // If it's larger, treat as percentage\r\n return num > 1 ? num / 100 : num;\r\n }\r\n\r\n // Default to center\r\n return 0.5;\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\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 { IStringTool } from \"../core/IStringTool\";\n\nexport interface RuleParserInput {\n value: string;\n}\n\nexport interface RuleParserResult {\n key: string;\n params?: string[];\n}\n\nexport default class RuleParserTool implements IStringTool<RuleParserInput, RuleParserResult[]> {\n process({ value }: RuleParserInput): RuleParserResult[] {\n const result: string[] = [];\n let current = \"\";\n let depth = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value[i];\n if (c === \"(\") depth++;\n if (c === \")\") depth--;\n if (c === \"|\" && depth === 0) {\n if (current.trim()) result.push(current.trim());\n current = \"\";\n } else {\n current += c;\n }\n }\n if (current.trim()) result.push(current.trim());\n\n return result.map((ruleStr) => {\n const match = ruleStr.match(/^(\\w+)(?:\\((.*)\\))?$/);\n if (match) {\n const [, key, params] = match;\n if (params) {\n return { key, params: params.split(\",\").map((s) => s.trim()) };\n }\n return { key };\n }\n\n const colonIndex = ruleStr.indexOf(\":\");\n if (colonIndex !== -1) {\n const key = ruleStr.slice(0, colonIndex).trim();\n const paramsString = ruleStr.slice(colonIndex + 1).trim();\n const params = paramsString ? paramsString.split(\",\").map((s) => s.trim()) : undefined;\n return { key, params };\n }\n\n return { key: ruleStr };\n });\n }\n}\n","import { IStringTool } from \"../core/IStringTool\";\r\nimport { RuleParserResult } from \"./RuleParserTool\";\r\n\r\nexport interface ValidationContext {\r\n fieldKey?: string;\r\n values?: Record<string, any>;\r\n getValue?: (key: string) => any;\r\n}\r\n\r\nexport interface ValidateInput {\r\n rules: RuleParserResult[];\r\n value: any;\r\n type?: \"input\" | \"beforeinput\";\r\n context?: ValidationContext;\r\n}\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: string[];\r\n}\r\n\r\ntype ValidatorFn = (value: any, params?: string[], context?: ValidationContext) => boolean;\r\n\r\nexport class ValidationTool implements IStringTool<ValidateInput, ValidationResult> {\r\n process({ rules, value, type = \"input\", context }: ValidateInput): ValidationResult {\r\n const errors: string[] = [];\r\n for (const rule of rules) {\r\n var beforeInputValidatorFn: ValidatorFn | null = null;\r\n var inputValidatorFn: ValidatorFn | null = null;\r\n var inputValid = true;\r\n var beforeInputValid = true;\r\n\r\n if (type == \"input\") {\r\n inputValidatorFn = this.inputValidators[rule.key];\r\n if (!inputValidatorFn) continue;\r\n }\r\n if (type == \"beforeinput\") {\r\n beforeInputValidatorFn = this.beforeInputValidators[rule.key];\r\n if (!beforeInputValidatorFn) continue;\r\n }\r\n\r\n if (inputValidatorFn) {\r\n inputValid = inputValidatorFn(value, rule.params, context);\r\n }\r\n if (beforeInputValidatorFn) {\r\n beforeInputValid = beforeInputValidatorFn(value, rule.params, context);\r\n }\r\n\r\n if (!beforeInputValid) {\r\n errors.push(this.getErrorMessage(rule.key, rule.params));\r\n }\r\n if (!inputValid) {\r\n errors.push(this.getErrorMessage(rule.key, rule.params));\r\n }\r\n }\r\n return { valid: errors.length === 0, errors };\r\n }\r\n\r\n inputValidators: Record<string, ValidatorFn> = {\r\n required: (v) => v != null && String(v).trim() !== \"\",\r\n min: (v, params) => typeof v === \"string\" && v.length >= Number(params?.[0] ?? 0),\r\n max: (v, params) =>\r\n typeof v === \"string\" && v.length <= Number(params?.[0] ?? Number.MAX_SAFE_INTEGER),\r\n checked: (v) => {\r\n if (Array.isArray(v)) {\r\n return v.length > 0;\r\n }\r\n if (v === true || v === \"true\" || v === 1 || v === \"1\") {\r\n return true;\r\n }\r\n if (typeof v === \"string\") {\r\n const normalized = v.trim().toLowerCase();\r\n if (normalized === \"false\" || normalized === \"0\") {\r\n return false;\r\n }\r\n return normalized.length > 0;\r\n }\r\n return !!v;\r\n },\r\n email: (v) => typeof v === \"string\" && /^[\\w-.]+@([\\w-]+\\.)+[\\w-]{2,4}$/.test(v),\r\n phone: (v) => {\r\n if (typeof v !== \"string\") return false;\r\n const normalized = v.trim();\r\n if (normalized === \"\") return false;\r\n if (!/^[0-9()\\s+-.]+$/.test(normalized)) return false;\r\n const digitCount = normalized.replace(/\\D/g, \"\").length;\r\n return digitCount >= 7 && digitCount <= 15;\r\n },\r\n number: (v) => typeof v === \"string\" && /^-?\\d+(\\.\\d+)?$/.test(v),\r\n integer: (v) => typeof v === \"string\" && /^-?\\d+$/.test(v),\r\n url: (v) =>\r\n typeof v === \"string\" &&\r\n /^(https?:\\/\\/)?([\\w\\-]+\\.)+[\\w\\-]+(\\/[\\w\\-._~:\\/?#[\\]@!$&'()*+,;=]*)?$/.test(v),\r\n regex: (v, params) => this.testByRegex(v, params?.[0]),\r\n alpha: (v) => this.testByRegex(v, \"^[A-Za-z]+$\", true),\r\n alpha_num: (v) => this.testByRegex(v, \"^[A-Za-z0-9]+$\", true),\r\n alpha_dash: (v) => this.testByRegex(v, \"^[A-Za-z0-9_-]+$\", true),\r\n same: (v, params, context) => {\r\n const targetKey = params?.[0];\r\n const otherValue = this.getContextValue(context, targetKey);\r\n if (targetKey && otherValue === undefined) return false;\r\n return this.areValuesEqual(v, otherValue);\r\n },\r\n different: (v, params, context) => {\r\n const targetKey = params?.[0];\r\n const otherValue = this.getContextValue(context, targetKey);\r\n if (targetKey && otherValue === undefined) return false;\r\n return !this.areValuesEqual(v, otherValue);\r\n },\r\n range: (v, params) => {\r\n if (v == null || v === \"\") return true;\r\n const value = Number(v);\r\n const min = Number(params?.[0]);\r\n const max = Number(params?.[1]);\r\n if (Number.isNaN(value) || Number.isNaN(min) || Number.isNaN(max)) {\r\n return false;\r\n }\r\n return value >= min && value <= max;\r\n },\r\n digits: (v, params) => {\r\n if (typeof v !== \"string\") return false;\r\n const length = Number(params?.[0] ?? 0);\r\n if (length <= 0) return false;\r\n return new RegExp(`^\\\\d{${length}}$`).test(v);\r\n },\r\n ip: (v) => typeof v === \"string\" && (this.isIPv4(v) || this.isIPv6(v)),\r\n mimes: (v, params) => this.validateMimes(v, params),\r\n max_size: (v, params) => {\r\n const limit = Number(params?.[0]);\r\n if (!limit || limit <= 0) return true;\r\n return this.validateMaxSize(v, limit);\r\n },\r\n after: (v, params, context) => this.compareDates(v, params, context, \"after\"),\r\n before: (v, params, context) => this.compareDates(v, params, context, \"before\"),\r\n };\r\n\r\n beforeInputValidators: Record<string, ValidatorFn> = {\r\n number: (v) => /^-?\\d*\\.?\\d*$/.test(v),\r\n integer: (v) => /^-?\\d*$/.test(v),\r\n email: (v) => /^[\\w@.\\-+]*$/.test(v),\r\n phone: (v) => /^[0-9()\\s+-.]*$/.test(v),\r\n letters: (v) => /^[a-zA-Z]*$/.test(v),\r\n lettersSpaces: (v) => /^[a-zA-Z\\s]*$/.test(v),\r\n lettersNumbers: (v) => /^[a-zA-Z0-9]*$/.test(v),\r\n alpha: (v) => /^[A-Za-z]*$/.test(v),\r\n alpha_num: (v) => /^[A-Za-z0-9]*$/.test(v),\r\n alpha_dash: (v) => /^[A-Za-z0-9_-]*$/.test(v),\r\n digits: (v, params) => {\r\n const length = Number(params?.[0] ?? 0);\r\n if (length <= 0) return /^\\d*$/.test(v);\r\n return new RegExp(`^\\\\d{0,${length}}$`).test(v);\r\n },\r\n url: (v) => /^[a-zA-Z0-9\\-._~:\\/?#\\[\\]@!$&'()*+,;=%]*$/.test(v),\r\n pattern: (v, params) => {\r\n try {\r\n return new RegExp(params?.[0] || \"\").test(v);\r\n } catch {\r\n return true;\r\n }\r\n },\r\n };\r\n\r\n getErrorMessage(key: string, params?: string[]): string {\r\n switch (key) {\r\n case \"required\":\r\n return \"This field is required\";\r\n case \"email\":\r\n return \"Invalid email address\";\r\n case \"min\":\r\n return `Minimum ${params?.[0]} characters`;\r\n case \"max\":\r\n return `Maximum ${params?.[0]} characters`;\r\n case \"phone\":\r\n return \"Invalid phone number\";\r\n case \"number\":\r\n return \"Only numbers are allowed\";\r\n case \"integer\":\r\n return \"Only whole numbers are allowed\";\r\n case \"url\":\r\n return \"Invalid URL address\";\r\n case \"checked\":\r\n return \"You must accept\";\r\n case \"regex\":\r\n return \"Value does not match the required pattern\";\r\n case \"alpha\":\r\n return \"Only letters are allowed\";\r\n case \"alpha_num\":\r\n return \"Only letters and numbers are allowed\";\r\n case \"alpha_dash\":\r\n return \"Only letters, numbers, dashes, and underscores are allowed\";\r\n case \"same\":\r\n return \"Values do not match\";\r\n case \"different\":\r\n return \"Values must be different\";\r\n case \"range\":\r\n return `Value must be between ${params?.[0]} and ${params?.[1]}`;\r\n case \"digits\":\r\n return `Value must contain exactly ${params?.[0]} digits`;\r\n case \"ip\":\r\n return \"Invalid IP address\";\r\n case \"mimes\":\r\n return `Allowed file types: ${params?.join(\", \")}`;\r\n case \"max_size\":\r\n return `File must be smaller than ${params?.[0]} KB`;\r\n case \"after\":\r\n return `Date must be after ${params?.[0]}`;\r\n case \"before\":\r\n return `Date must be before ${params?.[0]}`;\r\n default:\r\n return \"Invalid value\";\r\n }\r\n }\r\n\r\n private validateMimes(value: any, params?: string[]): boolean {\r\n if (!params || params.length === 0) return true;\r\n const files = this.extractFiles(value);\r\n if (files.length === 0) return true;\r\n const allowed = params.map((p) => p.trim().toLowerCase());\r\n return files.every((file) => this.isMimeAllowed(file, allowed));\r\n }\r\n\r\n private validateMaxSize(value: any, limitKb: number): boolean {\r\n const files = this.extractFiles(value);\r\n if (files.length === 0) return true;\r\n const maxBytes = limitKb * 1024;\r\n return files.every((file) => {\r\n if (typeof file.size !== \"number\") return true;\r\n return file.size <= maxBytes;\r\n });\r\n }\r\n\r\n private extractFiles(value: any): Array<{ name?: string; size?: number; type?: string }> {\r\n if (!value) return [];\r\n const files: Array<{ name?: string; size?: number; type?: string }> = [];\r\n\r\n if (typeof File !== \"undefined\" && value instanceof File) {\r\n files.push(value);\r\n return files;\r\n }\r\n\r\n if (typeof FileList !== \"undefined\" && value instanceof FileList) {\r\n return Array.from(value);\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n value.forEach((item) => {\r\n files.push(...this.extractFiles(item));\r\n });\r\n return files;\r\n }\r\n\r\n if (typeof value === \"object\" && (\"name\" in value || \"size\" in value || \"type\" in value)) {\r\n files.push(value as any);\r\n return files;\r\n }\r\n\r\n if (typeof value === \"string\" && value !== \"\") {\r\n files.push({ name: value });\r\n }\r\n\r\n return files;\r\n }\r\n\r\n private isMimeAllowed(file: { name?: string; type?: string }, allowed: string[]): boolean {\r\n const mime = (file.type || \"\").toLowerCase();\r\n const ext = this.getFileExtension(file.name);\r\n return allowed.some((rule) => {\r\n const normalized = rule.replace(/^\\./, \"\").toLowerCase();\r\n if (!normalized) return false;\r\n if (normalized.includes(\"/\")) {\r\n return mime === normalized;\r\n }\r\n return ext === normalized;\r\n });\r\n }\r\n\r\n private getFileExtension(name?: string): string {\r\n if (!name) return \"\";\r\n const parts = name.split(\".\");\r\n if (parts.length <= 1) return \"\";\r\n return (parts.pop() || \"\").toLowerCase();\r\n }\r\n\r\n private compareDates(\r\n value: any,\r\n params: string[] | undefined,\r\n context: ValidationContext | undefined,\r\n mode: \"before\" | \"after\"\r\n ): boolean {\r\n if (value == null || value === \"\") return true;\r\n const target = params?.[0];\r\n if (!target) return true;\r\n const currentDate = this.toDate(value);\r\n const referenceDate = this.resolveDateReference(target, context);\r\n if (!currentDate || !referenceDate) return false;\r\n return mode === \"after\"\r\n ? currentDate.getTime() > referenceDate.getTime()\r\n : currentDate.getTime() < referenceDate.getTime();\r\n }\r\n\r\n private resolveDateReference(token: string, context?: ValidationContext): Date | null {\r\n const contextualValue = this.getContextValue(context, token);\r\n if (contextualValue !== undefined) {\r\n return this.toDate(contextualValue);\r\n }\r\n if (token.toLowerCase() === \"now\") {\r\n return new Date();\r\n }\r\n if (token.toLowerCase() === \"today\") {\r\n const today = new Date();\r\n today.setHours(0, 0, 0, 0);\r\n return today;\r\n }\r\n return this.toDate(token);\r\n }\r\n\r\n private toDate(value: any): Date | null {\r\n if (value == null || value === \"\") return null;\r\n if (value instanceof Date) {\r\n return Number.isNaN(value.getTime()) ? null : value;\r\n }\r\n if (typeof value === \"number\") {\r\n const date = new Date(value);\r\n return Number.isNaN(date.getTime()) ? null : date;\r\n }\r\n if (typeof value === \"string\") {\r\n const timestamp = Date.parse(value);\r\n if (!Number.isNaN(timestamp)) {\r\n return new Date(timestamp);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private testByRegex(value: any, pattern?: string, allowEmpty = false): boolean {\r\n if (pattern == null || pattern === \"\") return true;\r\n const stringValue = typeof value === \"string\" ? value : value == null ? \"\" : String(value);\r\n if (allowEmpty && stringValue === \"\") return true;\r\n try {\r\n const { source, flags } = this.normalizeRegex(pattern);\r\n return new RegExp(source, flags).test(stringValue);\r\n } catch {\r\n return true;\r\n }\r\n }\r\n\r\n private normalizeRegex(pattern: string): { source: string; flags: string } {\r\n const trimmed = pattern.trim();\r\n if (trimmed.startsWith(\"/\") && trimmed.lastIndexOf(\"/\") > 0) {\r\n const lastSlashIndex = trimmed.lastIndexOf(\"/\");\r\n const source = trimmed.slice(1, lastSlashIndex);\r\n const flags = trimmed.slice(lastSlashIndex + 1);\r\n return { source, flags };\r\n }\r\n return { source: trimmed, flags: \"\" };\r\n }\r\n\r\n private getContextValue(context: ValidationContext | undefined, key?: string): any {\r\n if (!context || !key) return undefined;\r\n if (context.values && Object.prototype.hasOwnProperty.call(context.values, key)) {\r\n return context.values[key];\r\n }\r\n if (context.getValue) {\r\n return context.getValue(key);\r\n }\r\n return undefined;\r\n }\r\n\r\n private areValuesEqual(a: any, b: any): boolean {\r\n if (Array.isArray(a) || Array.isArray(b)) {\r\n return JSON.stringify(a) === JSON.stringify(b);\r\n }\r\n return a === b;\r\n }\r\n\r\n private isIPv4(value: string): boolean {\r\n const segments = value.split(\".\");\r\n if (segments.length !== 4) return false;\r\n return segments.every((segment) => {\r\n if (!/^\\d+$/.test(segment)) return false;\r\n const num = Number(segment);\r\n return num >= 0 && num <= 255;\r\n });\r\n }\r\n\r\n private isIPv6(value: string): boolean {\r\n if (!value) return false;\r\n if (value === \"::\") return true;\r\n const parts = value.split(\"::\");\r\n if (parts.length > 2) return false;\r\n\r\n const hextetPattern = /^[0-9a-fA-F]{1,4}$/;\r\n const segments = value.split(\":\");\r\n if (parts.length === 2) {\r\n return (\r\n segments.every((segment) => segment === \"\" || hextetPattern.test(segment)) &&\r\n segments.length <= 8\r\n );\r\n }\r\n return segments.length === 8 && segments.every((segment) => hextetPattern.test(segment));\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 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\nimport RuleParserTool from \"../tools/RuleParserTool\";\r\nimport { ValidationTool } from \"../tools/ValidationTool\";\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 ruleParser: RuleParserTool;\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 public ruleParser = new RuleParserTool();\r\n}\r\n","export function isCoarsePointer(): boolean {\n const mm =\n typeof window !== \"undefined\" && typeof window.matchMedia === \"function\"\n ? window.matchMedia(\"(pointer: coarse)\").matches\n : false;\n const touch = typeof navigator !== \"undefined\" ? (navigator.maxTouchPoints || 0) > 0 : false;\n const narrow = typeof window !== \"undefined\" ? window.innerWidth <= 768 : false;\n return mm || touch || narrow;\n}\n","type StyleValue = string | number;\ntype StyleVars = Record<string, StyleValue>;\ntype StyleProps = Record<string, StyleValue>;\n\nclass StyleTxn {\n private pendingVars = new Map<Element, StyleVars>();\n private pendingProps = new Map<Element, StyleProps>();\n private isOpen = false;\n\n public begin(): void {\n if (this.isOpen) return;\n this.isOpen = true;\n }\n\n public setVars(el: Element, vars: StyleVars): void {\n if (!this.isOpen) {\n console.warn(\"StyleTxn: call begin() first to set custom properties.\");\n return;\n }\n const currentVars = this.pendingVars.get(el) ?? {};\n for (const [k, v] of Object.entries(vars)) {\n if (currentVars[k] === v) continue;\n currentVars[k] = v;\n }\n this.pendingVars.set(el, currentVars);\n }\n\n public setProps(el: Element, props: StyleProps): void {\n if (!this.isOpen) {\n console.warn(\"StyleTxn: call begin() first to set standard properties.\");\n return;\n }\n const currentProps = this.pendingProps.get(el) ?? {};\n for (const [k, v] of Object.entries(props)) {\n if (currentProps[k] === v) continue;\n currentProps[k] = v;\n }\n\n this.pendingProps.set(el, currentProps);\n }\n\n public run(fn: () => void): void {\n const alreadyOpen = this.isOpen;\n if (!alreadyOpen) {\n this.begin();\n }\n try {\n fn();\n if (!alreadyOpen) {\n this.commit();\n }\n } catch (error) {\n if (!alreadyOpen) {\n this.cancel();\n }\n throw error;\n }\n }\n\n public commit(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n\n for (const [el, vars] of this.pendingVars) {\n const style = (el as HTMLElement).style;\n for (const [k, v] of Object.entries(vars)) {\n style.setProperty(k, String(v));\n }\n }\n this.pendingVars.clear();\n\n for (const [el, props] of this.pendingProps) {\n const style = (el as HTMLElement).style;\n for (const [k, v] of Object.entries(props)) {\n (style as any)[k] = String(v);\n }\n }\n this.pendingProps.clear();\n }\n\n public cancel(): void {\n this.pendingVars.clear();\n this.pendingProps.clear();\n this.isOpen = false;\n }\n}\n\nexport const styleTxn = new StyleTxn();\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\nimport { isCoarsePointer } from \"../../utils/isCoarsePointer\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\ntype CursorTargetState = {\r\n prevX: number;\r\n prevY: number;\r\n};\r\n\r\ntype CursorObjectDimensions = {\r\n width: number;\r\n height: number;\r\n halfWidth: number;\r\n halfHeight: number;\r\n};\r\n\r\ntype CursorPrevSnapshot = {\r\n x: number;\r\n y: number;\r\n stepX: number;\r\n stepY: number;\r\n};\r\n\r\ntype CursorPortal = {\r\n id: string;\r\n element: HTMLElement;\r\n content: HTMLElement | null;\r\n prev: CursorPrevSnapshot;\r\n hoverCount: number;\r\n showTimer: ReturnType<typeof setTimeout> | null;\r\n lerp: number | null;\r\n};\r\n\r\nconst targetStates = new WeakMap<StringObject, CursorTargetState>();\r\nconst CURSOR_EPSILON = 0.0005;\r\nconst DEFAULT_CURSOR_ID = \"default\";\r\nconst CURSOR_PORTAL_SELECTOR = \"[string-cursor],[data-string-cursor]\";\r\nconst CURSOR_PORTAL_CONTENT_SELECTOR = \"[string-cursor-content],[data-string-cursor-content]\";\r\nconst MIN_FRAME_DELTA = 1 / 240;\r\n\r\nfunction getTargetState(object: StringObject): CursorTargetState {\r\n let state = targetStates.get(object);\r\n if (!state) {\r\n state = { prevX: Number.NaN, prevY: Number.NaN };\r\n targetStates.set(object, state);\r\n }\r\n return state;\r\n}\r\n\r\n/**\r\n * StringCursor Module\r\n *\r\n * Handles cursor tracking and hover states for StringTune objects.\r\n *\r\n * Safari Navigation Fix:\r\n * Safari has an issue where mouseleave events are not fired when navigation occurs\r\n * (especially with NuxtLink/router navigation). This module includes several\r\n * workarounds to ensure proper cleanup:\r\n *\r\n * 1. MutationObserver - detects when elements are removed from DOM\r\n * 2. beforeunload/pagehide - captures traditional navigation\r\n * 3. visibilitychange - captures modern SPA navigation\r\n * 4. DOM existence checks - prevents operations on removed elements\r\n */\r\nexport class StringCursor extends StringModule {\r\n private cursorPrev: CursorPrevSnapshot = {\r\n x: Number.NaN,\r\n y: Number.NaN,\r\n stepX: Number.NaN,\r\n stepY: Number.NaN,\r\n };\r\n private cursorPortals: Map<string, CursorPortal[]> = new Map();\r\n private hoveredObjects: Set<StringObject> = new Set();\r\n private globalListenersBound = false;\r\n private boundBeforeUnload = () => this.cleanupHoverTargets();\r\n private boundPageHide = () => this.cleanupHoverTargets();\r\n private boundVisibilityChange = () => {\r\n if (document.hidden) {\r\n this.cleanupHoverTargets();\r\n }\r\n };\r\n protected enabled = true;\r\n\r\n private lastFrameTime: number = 0;\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"cursor\";\r\n\r\n this.permissions.mobile.rebuild.height = false;\r\n this.permissions.mobile.rebuild.width = false;\r\n this.permissions.mobile.rebuild.scrollHeight = false;\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: \"cursor-target\",\r\n type: \"string\",\r\n fallback: this.settings[\"cursor-target\"] ?? DEFAULT_CURSOR_ID,\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 if (isCoarsePointer()) {\r\n this.enabled = false;\r\n }\r\n\r\n this.collectCursorPortals();\r\n if (this.enabled) {\r\n this.bindGlobalLifecycleListeners();\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 onMutate(data: StringData): void {\r\n if (!this.enabled) return;\r\n\r\n const now = performance.now();\r\n\r\n let dt = this.lastFrameTime ? (now - this.lastFrameTime) / 1000 : 0.016;\r\n this.lastFrameTime = now;\r\n if (dt > 0.1) dt = 0.1;\r\n if (dt < MIN_FRAME_DELTA) dt = MIN_FRAME_DELTA;\r\n\r\n const cursorX = this.data.cursor.targetX;\r\n const cursorY = this.data.cursor.targetY;\r\n\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 baseLerp = object.getProperty<number>(\"lerp\") ?? 0.15;\r\n const frameLerp = this.getFrameAdjustedLerp(baseLerp, dt);\r\n\r\n const dimensions = this.getObjectDimensions(object);\r\n const { halfWidth, halfHeight, width, height } = dimensions;\r\n\r\n if (isOver && !isDisabled) {\r\n const { cx, cy } = this.centers.getCenter(object);\r\n const elementX = cursorX - (cx - halfWidth);\r\n const elementY = cursorY - (cy - halfHeight);\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 = 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: frameLerp,\r\n });\r\n const lerpedY = this.tools.lerp.process({\r\n from: py,\r\n to: elementY,\r\n progress: frameLerp,\r\n });\r\n\r\n const updatedX = px + lerpedX;\r\n const updatedY = py + lerpedY;\r\n const pixelChanged =\r\n Math.abs(updatedX - px) > CURSOR_EPSILON || Math.abs(updatedY - py) > CURSOR_EPSILON;\r\n\r\n object.setProperty(\"mouse-pixel-x\", updatedX);\r\n object.setProperty(\"mouse-pixel-y\", updatedY);\r\n\r\n const alignment = object.getProperty<string>(\"alignment\") ?? \"center\";\r\n const offsetX = this.calculateOffset(alignment, updatedX, width);\r\n const offsetY = this.calculateOffset(alignment, updatedY, height);\r\n\r\n object.setProperty(\"mouse-x\", offsetX);\r\n object.setProperty(\"mouse-y\", offsetY);\r\n\r\n const coordsChanged = this.setMouseCoordinates(object, offsetX, offsetY);\r\n\r\n if (coordsChanged) {\r\n this.events.emit(`cursor:move:${object.id}`, {\r\n x: offsetX,\r\n y: offsetY,\r\n });\r\n }\r\n if (pixelChanged) {\r\n this.events.emit(`cursor:pixel:${object.id}`, {\r\n x: updatedX,\r\n y: updatedY,\r\n });\r\n }\r\n } else {\r\n object.setProperty(\"mouse-pixel-x\", elementX);\r\n object.setProperty(\"mouse-pixel-y\", elementY);\r\n if (object.getProperty<boolean>(\"is-mouse-move\")) {\r\n object.setProperty(\"is-mouse-move\", false);\r\n this.events.emit(`cursor:end:${object.id}`, null);\r\n }\r\n this.setMouseCoordinates(object, 0, 0);\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 targetX = this.calculateOffset(\"center\", halfWidth, width);\r\n const targetY = this.calculateOffset(\"center\", halfHeight, height);\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: frameLerp,\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: frameLerp,\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 this.setMouseCoordinates(object, 0, 0);\r\n } else {\r\n this.setMouseCoordinates(object, newMouseX, newMouseY);\r\n }\r\n }\r\n }\r\n });\r\n\r\n if (this.cursorPortals.size > 0) {\r\n const { stepX, stepY, smoothedX, smoothedY } = this.data.cursor;\r\n const prev = this.cursorPrev;\r\n const cursorChanged =\r\n !Number.isFinite(prev.x) ||\r\n Math.abs(smoothedX - prev.x) > CURSOR_EPSILON ||\r\n Math.abs(smoothedY - prev.y) > CURSOR_EPSILON ||\r\n Math.abs(stepX - prev.stepX) > CURSOR_EPSILON ||\r\n Math.abs(stepY - prev.stepY) > CURSOR_EPSILON;\r\n\r\n if (cursorChanged) {\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.cursorPrev = { x: smoothedX, y: smoothedY, stepX, stepY };\r\n }\r\n\r\n const targetX = this.data.cursor.targetX;\r\n const targetY = this.data.cursor.targetY;\r\n this.cursorPortals.forEach((bucket) => {\r\n bucket.forEach((portal) => {\r\n this.updatePortalPosition(portal, targetX, targetY, dt);\r\n });\r\n });\r\n }\r\n }\r\n\r\n onObjectConnected(object: StringObject) {\r\n const element = object.htmlElement;\r\n this.centers.attach(object);\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(\"enter\", object.getProperty<(object: StringObject) => void>(\"onEnterEvent\"));\r\n object.setProperty(\"onLeaveEvent\", this.onLeaveObject.bind(this));\r\n object.events.on(\"leave\", object.getProperty<(object: StringObject) => void>(\"onLeaveEvent\"));\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 if (!document.contains(object.htmlElement)) {\r\n return;\r\n }\r\n\r\n object.setProperty(\"is-mouse-over\", true);\r\n this.hoveredObjects.add(object);\r\n\r\n const cursorClass = this.getCursorClass(object);\r\n\r\n this.withPortalsForObject(object, (portal) => {\r\n if (cursorClass) {\r\n portal.element.classList.add(cursorClass);\r\n }\r\n this.incrementPortalHover(portal);\r\n });\r\n\r\n object.htmlElement.addEventListener(\"mouseleave\", object.getProperty(\"mouseleave\"));\r\n }\r\n\r\n onMouseLeave(object: StringObject) {\r\n object.setProperty(\"is-mouse-over\", false);\r\n this.hoveredObjects.delete(object);\r\n\r\n const cursorClass = this.getCursorClass(object);\r\n\r\n this.withPortalsForObject(object, (portal) => {\r\n if (cursorClass) {\r\n portal.element.classList.remove(cursorClass);\r\n }\r\n this.decrementPortalHover(portal);\r\n });\r\n\r\n if (document.contains(object.htmlElement)) {\r\n object.htmlElement.removeEventListener(\"mouseleave\", object.getProperty(\"mouseleave\"));\r\n }\r\n }\r\n\r\n private onEnterObject(object: StringObject) {\r\n object.htmlElement.addEventListener(\"mouseenter\", object.getProperty(\"mouseenter\"));\r\n }\r\n\r\n private onLeaveObject(object: StringObject) {\r\n object.htmlElement.removeEventListener(\"mouseenter\", object.getProperty(\"mouseenter\"));\r\n object.htmlElement.removeEventListener(\"mouseleave\", object.getProperty(\"mouseleave\"));\r\n }\r\n\r\n private safariNavigationCleanup(object: StringObject): void {\r\n if (object.getProperty<boolean>(\"is-mouse-over\")) {\r\n this.onMouseLeave(object);\r\n }\r\n }\r\n\r\n private onElementRemovedFromDOM(object: StringObject): void {\r\n if (object.getProperty<boolean>(\"is-mouse-over\")) {\r\n this.onMouseLeave(object);\r\n }\r\n }\r\n\r\n onObjectDisconnected(object: StringObject): void {\r\n if (object.getProperty<boolean>(\"is-mouse-over\")) {\r\n this.onMouseLeave(object);\r\n }\r\n }\r\n\r\n onDOMRebuild(): void {\r\n if (!this.enabled) return;\r\n this.collectCursorPortals();\r\n }\r\n\r\n onDOMMutate(added: NodeList, removed: NodeList): void {\r\n if (!this.enabled) return;\r\n if (this.shouldRefreshPortals(added) || this.shouldRefreshPortals(removed)) {\r\n this.collectCursorPortals();\r\n }\r\n if (removed.length > 0) {\r\n this.handleRemovedNodes(removed);\r\n }\r\n }\r\n\r\n private collectCursorPortals(): void {\r\n this.cursorPortals.clear();\r\n const nodes = document.querySelectorAll(CURSOR_PORTAL_SELECTOR);\r\n nodes.forEach((node) => {\r\n if (!(node instanceof HTMLElement)) return;\r\n const id = this.resolvePortalId(node);\r\n const customLerp = this.resolvePortalLerp(node);\r\n const content = node.matches(CURSOR_PORTAL_CONTENT_SELECTOR)\r\n ? node\r\n : (node.querySelector(CURSOR_PORTAL_CONTENT_SELECTOR) as HTMLElement | null);\r\n\r\n const targetX = this.data.cursor.targetX;\r\n const targetY = this.data.cursor.targetY;\r\n const portal: CursorPortal = {\r\n id,\r\n element: node,\r\n content,\r\n prev: { x: targetX, y: targetY, stepX: 0, stepY: 0 },\r\n hoverCount: 0,\r\n showTimer: null,\r\n lerp: customLerp,\r\n };\r\n\r\n const existing = this.cursorPortals.get(id);\r\n if (existing) {\r\n existing.push(portal);\r\n } else {\r\n this.cursorPortals.set(id, [portal]);\r\n }\r\n });\r\n }\r\n\r\n private resolvePortalId(element: HTMLElement): string {\r\n const attrSources = [\r\n element.getAttribute(\"data-string-cursor\"),\r\n element.getAttribute(\"string-cursor\"),\r\n element.getAttribute(\"data-string-cursor-id\"),\r\n element.getAttribute(\"string-cursor-id\"),\r\n ];\r\n\r\n for (const source of attrSources) {\r\n if (source && source.trim().length > 0) {\r\n return source.trim();\r\n }\r\n }\r\n\r\n return DEFAULT_CURSOR_ID;\r\n }\r\n\r\n private resolvePortalLerp(element: HTMLElement): number | null {\r\n const raw =\r\n element.getAttribute(\"data-string-cursor-lerp\") ??\r\n element.getAttribute(\"string-cursor-lerp\") ??\r\n this.settings[\"cursor-lerp\"];\r\n if (!raw) {\r\n return null;\r\n }\r\n\r\n const value = parseFloat(raw);\r\n if (!Number.isFinite(value)) {\r\n return null;\r\n }\r\n\r\n const clamped = Math.min(1, Math.max(0.01, value));\r\n return this.tools.adaptiveLerp.process({\r\n value: clamped,\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 private shouldRefreshPortals(nodes: NodeList): boolean {\r\n for (const node of nodes) {\r\n if (!(node instanceof Element)) continue;\r\n if (node.matches(CURSOR_PORTAL_SELECTOR)) {\r\n return true;\r\n }\r\n if (node.querySelector(CURSOR_PORTAL_SELECTOR)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n private withPortalsForObject(\r\n object: StringObject | null,\r\n cb: (portal: CursorPortal) => void\r\n ): void {\r\n const portals = this.getPortalsForObject(object);\r\n portals.forEach((portal) => cb(portal));\r\n }\r\n\r\n private getPortalsForObject(object: StringObject | null): CursorPortal[] {\r\n if (this.cursorPortals.size === 0) {\r\n return [];\r\n }\r\n\r\n const ids = this.extractPortalIds(object);\r\n const selected: CursorPortal[] = [];\r\n\r\n ids.forEach((id) => {\r\n if (id === \"*\") {\r\n this.cursorPortals.forEach((bucket) => {\r\n bucket.forEach((portal) => selected.push(portal));\r\n });\r\n return;\r\n }\r\n\r\n const normalized = id.length > 0 ? id : DEFAULT_CURSOR_ID;\r\n const portals = this.cursorPortals.get(normalized);\r\n if (portals) {\r\n portals.forEach((portal) => selected.push(portal));\r\n }\r\n });\r\n\r\n if (selected.length === 0) {\r\n const fallbackBucket =\r\n this.cursorPortals.get(DEFAULT_CURSOR_ID) ?? this.cursorPortals.values().next().value;\r\n if (fallbackBucket && fallbackBucket.length > 0) {\r\n fallbackBucket.forEach((portal: any) => selected.push(portal));\r\n }\r\n }\r\n\r\n return selected;\r\n }\r\n\r\n private extractPortalIds(object: StringObject | null): string[] {\r\n if (!object) return [DEFAULT_CURSOR_ID];\r\n const raw = object.getProperty<string>(\"cursor-target\");\r\n if (typeof raw !== \"string\" || raw.trim().length === 0) {\r\n return [DEFAULT_CURSOR_ID];\r\n }\r\n\r\n return raw\r\n .split(/[,|]/)\r\n .map((value) => value.trim())\r\n .filter(Boolean);\r\n }\r\n\r\n private incrementPortalHover(portal: CursorPortal): void {\r\n portal.hoverCount++;\r\n portal.element.classList.remove(\"-show\");\r\n this.restartPortalShowTimer(portal);\r\n }\r\n\r\n private decrementPortalHover(portal: CursorPortal): void {\r\n portal.hoverCount = Math.max(0, portal.hoverCount - 1);\r\n if (portal.hoverCount === 0) {\r\n this.clearPortalShowTimer(portal);\r\n portal.element.classList.remove(\"-show\");\r\n }\r\n }\r\n\r\n private restartPortalShowTimer(portal: CursorPortal): void {\r\n this.clearPortalShowTimer(portal);\r\n if (!portal.element.isConnected) {\r\n portal.showTimer = null;\r\n return;\r\n }\r\n portal.element.classList.add(\"-show\");\r\n portal.showTimer = null;\r\n }\r\n\r\n private clearPortalShowTimer(portal: CursorPortal): void {\r\n if (portal.showTimer) {\r\n clearTimeout(portal.showTimer);\r\n portal.showTimer = null;\r\n }\r\n }\r\n\r\n private updatePortalPosition(\r\n portal: CursorPortal,\r\n targetX: number,\r\n targetY: number,\r\n dt: number\r\n ): void {\r\n if (!portal.element.isConnected) return;\r\n\r\n const prev = portal.prev;\r\n\r\n const currentX = Number.isFinite(prev.x) ? prev.x : targetX;\r\n const currentY = Number.isFinite(prev.y) ? prev.y : targetY;\r\n\r\n const factor = portal.lerp ?? 0.1;\r\n const fpsAdjustedLerp = this.getFrameAdjustedLerp(factor, dt);\r\n\r\n const stepX = (targetX - currentX) * fpsAdjustedLerp;\r\n const stepY = (targetY - currentY) * fpsAdjustedLerp;\r\n\r\n const safeDt = dt > 1e-4 ? dt : 1 / 60;\r\n const normalizedVelocityX = stepX / (safeDt * 60);\r\n const normalizedVelocityY = stepY / (safeDt * 60);\r\n\r\n if (Math.abs(stepX) < CURSOR_EPSILON && Math.abs(stepY) < CURSOR_EPSILON) {\r\n return;\r\n }\r\n\r\n const nextX = currentX + stepX;\r\n const nextY = currentY + stepY;\r\n\r\n portal.element.style.setProperty(\"--x\", nextX.toFixed(2));\r\n portal.element.style.setProperty(\"--y\", nextY.toFixed(2));\r\n\r\n portal.element.style.setProperty(\"--x-lerp\", normalizedVelocityX.toFixed(3));\r\n portal.element.style.setProperty(\"--y-lerp\", normalizedVelocityY.toFixed(3));\r\n\r\n prev.x = nextX;\r\n prev.y = nextY;\r\n prev.stepX = stepX;\r\n prev.stepY = stepY;\r\n }\r\n\r\n private handleRemovedNodes(nodes: NodeList): void {\r\n if (this.hoveredObjects.size === 0) {\r\n return;\r\n }\r\n Array.from(this.hoveredObjects).forEach((object) => {\r\n if (!object.htmlElement.isConnected) {\r\n this.onElementRemovedFromDOM(object);\r\n }\r\n });\r\n }\r\n\r\n private cleanupHoverTargets(): void {\r\n if (this.hoveredObjects.size === 0) {\r\n return;\r\n }\r\n Array.from(this.hoveredObjects).forEach((object) => this.safariNavigationCleanup(object));\r\n }\r\n\r\n private bindGlobalLifecycleListeners(): void {\r\n if (this.globalListenersBound) {\r\n return;\r\n }\r\n window.addEventListener(\"beforeunload\", this.boundBeforeUnload);\r\n window.addEventListener(\"pagehide\", this.boundPageHide);\r\n document.addEventListener(\"visibilitychange\", this.boundVisibilityChange);\r\n this.globalListenersBound = true;\r\n }\r\n\r\n private unbindGlobalLifecycleListeners(): void {\r\n if (!this.globalListenersBound) {\r\n return;\r\n }\r\n window.removeEventListener(\"beforeunload\", this.boundBeforeUnload);\r\n window.removeEventListener(\"pagehide\", this.boundPageHide);\r\n document.removeEventListener(\"visibilitychange\", this.boundVisibilityChange);\r\n this.globalListenersBound = false;\r\n }\r\n\r\n private setMouseCoordinates(object: StringObject, x: number, y: number): boolean {\r\n if (object.getProperty(\"cursor-target-style-disable\")) {\r\n return false;\r\n }\r\n\r\n const state = getTargetState(object);\r\n const roundedX =\r\n Math.abs(x) < CURSOR_EPSILON && Number.isFinite(state.prevX)\r\n ? state.prevX\r\n : Math.round(x * 100) / 100;\r\n const roundedY =\r\n Math.abs(y) < CURSOR_EPSILON && Number.isFinite(state.prevY)\r\n ? state.prevY\r\n : Math.round(y * 100) / 100;\r\n\r\n if (\r\n Number.isFinite(state.prevX) &&\r\n Math.abs(roundedX - state.prevX) <= CURSOR_EPSILON &&\r\n Number.isFinite(state.prevY) &&\r\n Math.abs(roundedY - state.prevY) <= CURSOR_EPSILON\r\n ) {\r\n return false;\r\n }\r\n\r\n state.prevX = roundedX;\r\n state.prevY = roundedY;\r\n\r\n const valueX = roundedX.toFixed(2);\r\n const valueY = roundedY.toFixed(2);\r\n\r\n this.applyToElementAndConnects(object, (el) => {\r\n styleTxn.setVars(el, { \"--x\": valueX, \"--y\": valueY });\r\n });\r\n\r\n return true;\r\n }\r\n\r\n private getFrameAdjustedLerp(base: number, dt: number): number {\r\n const clampedBase = Math.min(0.99, Math.max(0.001, base));\r\n if (!Number.isFinite(dt) || dt <= 0) {\r\n return clampedBase;\r\n }\r\n\r\n const normalizedDt = Math.max(dt, MIN_FRAME_DELTA);\r\n const frames = normalizedDt * 60;\r\n const adjusted = 1 - Math.pow(1 - clampedBase, frames);\r\n return Math.min(0.999, Math.max(0.0001, adjusted));\r\n }\r\n\r\n private getObjectDimensions(object: StringObject): CursorObjectDimensions {\r\n const element = object.htmlElement;\r\n const fallbackWidth = element.offsetWidth || element.clientWidth || element.scrollWidth || 1;\r\n const fallbackHeight =\r\n element.offsetHeight || element.clientHeight || element.scrollHeight || 1;\r\n\r\n const rawHalfWidth = object.getProperty<number>(\"half-width\");\r\n const rawHalfHeight = object.getProperty<number>(\"half-height\");\r\n\r\n const halfWidth =\r\n typeof rawHalfWidth === \"number\" && Number.isFinite(rawHalfWidth)\r\n ? rawHalfWidth\r\n : fallbackWidth / 2;\r\n const halfHeight =\r\n typeof rawHalfHeight === \"number\" && Number.isFinite(rawHalfHeight)\r\n ? rawHalfHeight\r\n : fallbackHeight / 2;\r\n\r\n const width = halfWidth > 0 ? halfWidth * 2 : fallbackWidth;\r\n const height = halfHeight > 0 ? halfHeight * 2 : fallbackHeight;\r\n\r\n return { width, height, halfWidth, halfHeight };\r\n }\r\n\r\n private calculateOffset(alignment: string, mousePos: number, size: number): 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 override removeObject(id: string): void {\r\n if (!this.enabled) return super.removeObject(id);\r\n const obj = this.objectMapOnPage.get(id);\r\n if (obj) {\r\n this.centers.detach(obj);\r\n }\r\n super.removeObject(id);\r\n }\r\n\r\n override destroy(): void {\r\n this.unbindGlobalLifecycleListeners();\r\n this.hoveredObjects.clear();\r\n super.destroy();\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 StringImpulse extends StringModule {\r\n private originObservers = new WeakMap<StringObject, MutationObserver>();\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"impulse\";\r\n\r\n this.attributesToMap.push(\r\n { key: \"position-strength\", type: \"number\", fallback: this.settings[\"position-strength\"] },\r\n { key: \"position-tension\", type: \"number\", fallback: this.settings[\"position-tension\"] },\r\n { key: \"position-friction\", type: \"number\", fallback: this.settings[\"position-friction\"] },\r\n {\r\n key: \"position-max-velocity\",\r\n type: \"number\",\r\n fallback: this.settings[\"position-max-velocity\"],\r\n },\r\n {\r\n key: \"position-update-threshold\",\r\n type: \"number\",\r\n fallback: this.settings[\"position-update-threshold\"],\r\n },\r\n\r\n // rotate\r\n { key: \"rotation-strength\", type: \"number\", fallback: this.settings[\"rotation-strength\"] },\r\n { key: \"rotation-tension\", type: \"number\", fallback: this.settings[\"rotation-tension\"] },\r\n { key: \"rotation-friction\", type: \"number\", fallback: this.settings[\"rotation-friction\"] },\r\n {\r\n key: \"rotation-max-angular-velocity\",\r\n type: \"number\",\r\n fallback: this.settings[\"rotation-max-angular-velocity\"],\r\n },\r\n { key: \"rotation-max-angle\", type: \"number\", fallback: this.settings[\"rotation-max-angle\"] },\r\n {\r\n key: \"rotation-update-threshold\",\r\n type: \"number\",\r\n fallback: this.settings[\"rotation-update-threshold\"],\r\n },\r\n\r\n { key: \"max-offset\", type: \"number\", fallback: this.settings[\"max-offset\"] },\r\n { key: \"sleep-epsilon\", type: \"number\", fallback: this.settings[\"sleep-epsilon\"] },\r\n { key: \"continuous-push\", type: \"boolean\", fallback: this.settings[\"continuous-push\"] },\r\n {\r\n key: \"rotation-origin\",\r\n type: \"string\",\r\n fallback: this.settings[\"rotation-origin\"] ?? \"center center\",\r\n }\r\n );\r\n }\r\n\r\n override onObjectConnected(object: StringObject): void {\r\n super.onObjectConnected(object);\r\n\r\n object.setProperty(\"offset-x\", 0);\r\n object.setProperty(\"offset-y\", 0);\r\n object.setProperty(\"velocity-x\", 0);\r\n object.setProperty(\"velocity-y\", 0);\r\n\r\n object.setProperty(\"angle-deg\", 0);\r\n object.setProperty(\"ang-vel-deg\", 0);\r\n\r\n object.setProperty(\"__prev-css-x\", 0);\r\n object.setProperty(\"__prev-css-y\", 0);\r\n object.setProperty(\"__prev-css-rot\", 0);\r\n\r\n object.setProperty(\"__push-latch\", false);\r\n object.setProperty(\"__rotate-latch\", false);\r\n\r\n // Cache parsed rotation origin\r\n this.cacheRotationOrigin(object);\r\n\r\n // Watch for rotation-origin attribute changes\r\n this.observeRotationOrigin(object);\r\n\r\n this.hover.track(object);\r\n this.centers.attach(object);\r\n }\r\n\r\n override onObjectDisconnected(object: StringObject): void {\r\n this.hover.untrack(object);\r\n this.centers.detach(object);\r\n\r\n // Cleanup rotation-origin observer\r\n const observer = this.originObservers.get(object);\r\n if (observer) {\r\n observer.disconnect();\r\n this.originObservers.delete(object);\r\n }\r\n }\r\n\r\n override onMouseMove(_e?: MouseEvent): void {\r\n if (!_e) return;\r\n\r\n const cursorVelocityX = this.data.cursor.velocityX;\r\n const cursorVelocityY = this.data.cursor.velocityY;\r\n if (cursorVelocityX === 0 && cursorVelocityY === 0) return;\r\n\r\n const mouseX = this.data.cursor.targetX;\r\n const mouseY = this.data.cursor.targetY;\r\n\r\n for (const object of this.objects) {\r\n const rect = object.htmlElement.getBoundingClientRect();\r\n const isUnderCursor =\r\n mouseX >= rect.left && mouseX <= rect.right && mouseY >= rect.top && mouseY <= rect.bottom;\r\n\r\n if (isUnderCursor) {\r\n {\r\n const w = rect.width || 1;\r\n const side01 = Math.max(0, Math.min(1, (this.data.cursor.targetX - rect.left) / w));\r\n this.events.emit(`object:impulse:${object.id}:side`, { value: side01 });\r\n }\r\n\r\n const positionStrength = object.getProperty<number>(\"position-strength\") || 0;\r\n if (positionStrength !== 0) {\r\n const isContinuousPush = object.getProperty<boolean>(\"continuous-push\") ?? true;\r\n const isLatched = object.getProperty<boolean>(\"__push-latch\") === true;\r\n if (isContinuousPush || !isLatched) {\r\n let objectVelocityX = object.getProperty<number>(\"velocity-x\") || 0;\r\n let objectVelocityY = object.getProperty<number>(\"velocity-y\") || 0;\r\n objectVelocityX += cursorVelocityX * positionStrength;\r\n objectVelocityY += cursorVelocityY * positionStrength;\r\n object.setProperty(\"velocity-x\", objectVelocityX);\r\n object.setProperty(\"velocity-y\", objectVelocityY);\r\n if (!isContinuousPush) object.setProperty(\"__push-latch\", true);\r\n }\r\n }\r\n\r\n const rotationStrength = object.getProperty<number>(\"rotation-strength\") ?? 0.75;\r\n if (rotationStrength !== 0) {\r\n const isContinuousPush = object.getProperty<boolean>(\"continuous-push\") ?? true;\r\n const isLatched = object.getProperty<boolean>(\"__rotate-latch\") === true;\r\n\r\n if (isContinuousPush || !isLatched) {\r\n const { centerX, centerY } = this.getRotationOriginFromRect(object, rect);\r\n const relativeX = mouseX - centerX;\r\n const relativeY = mouseY - centerY;\r\n const torque = relativeX * cursorVelocityY - relativeY * cursorVelocityX;\r\n\r\n let angularVelocityDeg = object.getProperty<number>(\"ang-vel-deg\") || 0;\r\n angularVelocityDeg += torque * rotationStrength * 0.02;\r\n object.setProperty(\"ang-vel-deg\", angularVelocityDeg);\r\n if (!isContinuousPush) object.setProperty(\"__rotate-latch\", true);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Parses and caches the rotation origin for an object.\r\n * Called once on object connection and when attribute changes.\r\n */\r\n private cacheRotationOrigin(object: StringObject): void {\r\n const originValue = object.getProperty<string>(\"rotation-origin\") ?? \"center center\";\r\n const { x, y } = this.tools.originParser.toNormalized({ value: originValue });\r\n object.setProperty(\"__rotation-origin-x\", x);\r\n object.setProperty(\"__rotation-origin-y\", y);\r\n }\r\n\r\n /**\r\n * Observes changes to the rotation-origin attribute and re-caches when changed.\r\n */\r\n private observeRotationOrigin(object: StringObject): void {\r\n const attrName = \"string-rotation-origin\";\r\n const dataAttrName = \"data-string-rotation-origin\";\r\n\r\n const observer = new MutationObserver((mutations) => {\r\n for (const mutation of mutations) {\r\n if (\r\n mutation.type === \"attributes\" &&\r\n (mutation.attributeName === attrName || mutation.attributeName === dataAttrName)\r\n ) {\r\n // Re-read attribute and update cache\r\n const newValue =\r\n object.htmlElement.getAttribute(attrName) ??\r\n object.htmlElement.getAttribute(dataAttrName);\r\n if (newValue !== null) {\r\n object.setProperty(\"rotation-origin\", newValue);\r\n }\r\n this.cacheRotationOrigin(object);\r\n break;\r\n }\r\n }\r\n });\r\n\r\n observer.observe(object.htmlElement, {\r\n attributes: true,\r\n attributeFilter: [attrName, dataAttrName],\r\n });\r\n\r\n this.originObservers.set(object, observer);\r\n }\r\n\r\n /**\r\n * Calculates the rotation origin point using cached normalized values and provided rect.\r\n * Avoids re-parsing origin string and extra getBoundingClientRect calls.\r\n */\r\n private getRotationOriginFromRect(\r\n object: StringObject,\r\n rect: DOMRect\r\n ): { centerX: number; centerY: number } {\r\n const normalizedX = object.getProperty<number>(\"__rotation-origin-x\") ?? 0.5;\r\n const normalizedY = object.getProperty<number>(\"__rotation-origin-y\") ?? 0.5;\r\n\r\n return {\r\n centerX: rect.left + rect.width * normalizedX,\r\n centerY: rect.top + rect.height * normalizedY,\r\n };\r\n }\r\n\r\n onFrame(_: StringData): void {\r\n const mouseX = this.data.cursor.targetX;\r\n const mouseY = this.data.cursor.targetY;\r\n\r\n for (const objectItem of this.objects) {\r\n const rect = objectItem.htmlElement.getBoundingClientRect();\r\n const isUnderCursor =\r\n mouseX >= rect.left && mouseX <= rect.right && mouseY >= rect.top && mouseY <= rect.bottom;\r\n\r\n if (!isUnderCursor && objectItem.getProperty<boolean>(\"__push-latch\") === true) {\r\n objectItem.setProperty(\"__push-latch\", false);\r\n }\r\n if (!isUnderCursor && objectItem.getProperty<boolean>(\"__rotate-latch\") === true) {\r\n objectItem.setProperty(\"__rotate-latch\", false);\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.objects.length; i++) {\r\n const object = this.objects[i];\r\n\r\n let offsetX = object.getProperty<number>(\"offset-x\") || 0;\r\n let offsetY = object.getProperty<number>(\"offset-y\") || 0;\r\n let velocityX = object.getProperty<number>(\"velocity-x\") || 0;\r\n let velocityY = object.getProperty<number>(\"velocity-y\") || 0;\r\n\r\n const positionTension = object.getProperty<number>(\"position-tension\") ?? 0.05;\r\n const positionFriction = object.getProperty<number>(\"position-friction\") ?? 0.15;\r\n const maxVelocity = object.getProperty<number>(\"position-max-velocity\") ?? 120;\r\n const maxOffset = object.getProperty<number>(\"max-offset\") ?? 220;\r\n\r\n velocityX -= positionTension * offsetX;\r\n velocityY -= positionTension * offsetY;\r\n\r\n const velocityDecay = 1 - positionFriction;\r\n velocityX *= velocityDecay;\r\n velocityY *= velocityDecay;\r\n\r\n if (velocityX > maxVelocity) velocityX = maxVelocity;\r\n else if (velocityX < -maxVelocity) velocityX = -maxVelocity;\r\n if (velocityY > maxVelocity) velocityY = maxVelocity;\r\n else if (velocityY < -maxVelocity) velocityY = -maxVelocity;\r\n\r\n offsetX += velocityX;\r\n offsetY += velocityY;\r\n\r\n if (offsetX > maxOffset) offsetX = maxOffset;\r\n else if (offsetX < -maxOffset) offsetX = -maxOffset;\r\n if (offsetY > maxOffset) offsetY = maxOffset;\r\n else if (offsetY < -maxOffset) offsetY = -maxOffset;\r\n\r\n let angleDeg = object.getProperty<number>(\"angle-deg\") || 0;\r\n let angularVelocityDeg = object.getProperty<number>(\"ang-vel-deg\") || 0;\r\n\r\n const rotationTension = object.getProperty<number>(\"rotation-tension\") ?? 0.06;\r\n const rotationFriction = object.getProperty<number>(\"rotation-friction\") ?? 0.18;\r\n const maxAngularVelocityDeg =\r\n object.getProperty<number>(\"rotation-max-angular-velocity\") ?? 6;\r\n const maxRotationAngleDeg = object.getProperty<number>(\"rotation-max-angle\") ?? 18;\r\n\r\n angularVelocityDeg -= rotationTension * angleDeg;\r\n angularVelocityDeg *= 1 - rotationFriction;\r\n\r\n if (angularVelocityDeg > maxAngularVelocityDeg) angularVelocityDeg = maxAngularVelocityDeg;\r\n else if (angularVelocityDeg < -maxAngularVelocityDeg)\r\n angularVelocityDeg = -maxAngularVelocityDeg;\r\n\r\n angleDeg += angularVelocityDeg;\r\n\r\n if (angleDeg > maxRotationAngleDeg) {\r\n angleDeg = maxRotationAngleDeg;\r\n angularVelocityDeg *= 0.35;\r\n } else if (angleDeg < -maxRotationAngleDeg) {\r\n angleDeg = -maxRotationAngleDeg;\r\n angularVelocityDeg *= 0.35;\r\n }\r\n\r\n const sleepEpsilon = object.getProperty<number>(\"sleep-epsilon\") ?? 0.01;\r\n const isPositionAsleep =\r\n velocityX * velocityX + velocityY * velocityY < sleepEpsilon * sleepEpsilon &&\r\n offsetX * offsetX + offsetY * offsetY < sleepEpsilon * sleepEpsilon;\r\n\r\n const isRotationAsleep =\r\n Math.abs(angularVelocityDeg) < sleepEpsilon && Math.abs(angleDeg) < sleepEpsilon;\r\n\r\n if (isPositionAsleep) {\r\n if (velocityX || velocityY || offsetX || offsetY) {\r\n object.setProperty(\"offset-x\", 0);\r\n object.setProperty(\"offset-y\", 0);\r\n object.setProperty(\"velocity-x\", 0);\r\n object.setProperty(\"velocity-y\", 0);\r\n offsetX = offsetY = velocityX = velocityY = 0;\r\n }\r\n } else {\r\n object.setProperty(\"offset-x\", offsetX);\r\n object.setProperty(\"offset-y\", offsetY);\r\n object.setProperty(\"velocity-x\", velocityX);\r\n object.setProperty(\"velocity-y\", velocityY);\r\n }\r\n\r\n if (isRotationAsleep) {\r\n if (angleDeg || angularVelocityDeg) {\r\n object.setProperty(\"angle-deg\", 0);\r\n object.setProperty(\"ang-vel-deg\", 0);\r\n angleDeg = angularVelocityDeg = 0;\r\n }\r\n } else {\r\n object.setProperty(\"angle-deg\", angleDeg);\r\n object.setProperty(\"ang-vel-deg\", angularVelocityDeg);\r\n }\r\n\r\n const positionUpdateThreshold =\r\n object.getProperty<number>(\"position-update-threshold\") ?? 0.1;\r\n const rotationUpdateThreshold =\r\n object.getProperty<number>(\"rotation-update-threshold\") ?? 0.15;\r\n\r\n const prevCssX = object.getProperty<number>(\"__prev-css-x\") || 0;\r\n const prevCssY = object.getProperty<number>(\"__prev-css-y\") || 0;\r\n const prevCssRot = object.getProperty<number>(\"__prev-css-rot\") || 0;\r\n\r\n const cssTranslateX = Math.round(offsetX * 10) / 10;\r\n const cssTranslateY = Math.round(offsetY * 10) / 10;\r\n const cssRotateDeg = Math.round(angleDeg * 10) / 10;\r\n\r\n const needsPositionUpdate =\r\n Math.abs(cssTranslateX - prevCssX) > positionUpdateThreshold ||\r\n Math.abs(cssTranslateY - prevCssY) > positionUpdateThreshold;\r\n\r\n const needsRotationUpdate = Math.abs(cssRotateDeg - prevCssRot) > rotationUpdateThreshold;\r\n\r\n if (needsPositionUpdate || needsRotationUpdate) {\r\n this.applyToElementAndConnects(object, (el) => {\r\n if (needsPositionUpdate) {\r\n el.style.setProperty(\"--push-x\", String(cssTranslateX));\r\n el.style.setProperty(\"--push-y\", String(cssTranslateY));\r\n this.events.emit(`object:impulse:${object.id}:move`, {\r\n x: cssTranslateX,\r\n y: cssTranslateY,\r\n });\r\n }\r\n if (needsRotationUpdate) {\r\n el.style.setProperty(\"--push-rotation\", String(cssRotateDeg));\r\n this.events.emit(`object:impulse:${object.id}:rotate`, { rotation: cssRotateDeg });\r\n }\r\n });\r\n\r\n if (needsPositionUpdate) {\r\n object.setProperty(\"__prev-css-x\", cssTranslateX);\r\n object.setProperty(\"__prev-css-y\", cssTranslateY);\r\n }\r\n if (needsRotationUpdate) {\r\n object.setProperty(\"__prev-css-rot\", cssRotateDeg);\r\n }\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\nexport class StringMagnetic extends StringModule {\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"magnetic\";\r\n\r\n this.permissions.mobile.rebuild.height = false;\r\n this.permissions.mobile.rebuild.width = false;\r\n this.permissions.mobile.rebuild.scrollHeight = false;\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 = rect.left + rect.width / 2;\r\n const centerY = rect.top + rect.height / 2;\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 = object.getProperty<number>(\"magnetic-target-x\") ?? 0;\r\n let targetMagneticY = 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(\"magnetic-x\", object.getProperty(\"magnetic-target-x\"));\r\n }\r\n if (lerpY > -0.01 && lerpY < 0.01) {\r\n lerpY = 0;\r\n object.setProperty(\"magnetic-y\", object.getProperty(\"magnetic-target-y\"));\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","type Job = () => void;\n\nclass FrameDOM {\n private measureQueue: Job[] = [];\n private mutateQueue: Job[] = [];\n private scheduled = false;\n\n public measure(fn: Job): void {\n this.measureQueue.push(fn);\n this.schedule();\n }\n\n public mutate(fn: Job): void {\n this.mutateQueue.push(fn);\n this.schedule();\n }\n\n private schedule(): void {\n if (this.scheduled) {\n return;\n }\n\n this.scheduled = true;\n requestAnimationFrame(() => {\n const mQueue = this.measureQueue;\n this.measureQueue = [];\n for (let i = 0; i < mQueue.length; i++) {\n try {\n mQueue[i]();\n } catch (e) {\n console.error(\"Error in frameDOM measure task:\", e);\n }\n }\n\n const wQueue = this.mutateQueue;\n this.mutateQueue = [];\n for (let i = 0; i < wQueue.length; i++) {\n try {\n wQueue[i]();\n } catch (e) {\n console.error(\"Error in frameDOM mutate task:\", e);\n }\n }\n\n this.scheduled = false;\n });\n }\n}\n\nexport const frameDOM = new FrameDOM();\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\nimport { frameDOM } from \"../../utils/frame-dom\";\r\nimport { isCoarsePointer } from \"../../utils/isCoarsePointer\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\nexport abstract class CursorReactiveModule extends StringModule {\r\n protected nearOnly = true;\r\n protected useAllObjects = false;\r\n protected maxDistanceMultiplier = 1;\r\n protected updateThreshold = 0.1;\r\n\r\n protected enabled = true;\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n if (isCoarsePointer()) {\r\n this.enabled = false;\r\n }\r\n }\r\n\r\n override onObjectConnected(object: StringObject): void {\r\n if (!this.enabled) return;\r\n super.onObjectConnected(object);\r\n this.centers.attach(object);\r\n this.hover.track(object);\r\n }\r\n\r\n override removeObject(id: string): void {\r\n if (!this.enabled) return super.removeObject(id);\r\n const obj = this.objectMapOnPage.get(id);\r\n if (obj) {\r\n this.centers.detach(obj);\r\n this.hover.untrack(obj);\r\n }\r\n super.removeObject(id);\r\n }\r\n\r\n override onScroll(): void {\r\n if (!this.enabled) return;\r\n this.centers.invalidateAll();\r\n this.scheduleCursorUpdate();\r\n }\r\n\r\n override onMouseMoveMeasure(data: StringData) {\r\n if (!this.enabled) return;\r\n super.onMouseMoveMeasure(data);\r\n this.refreshPointerState();\r\n }\r\n\r\n override onScrollMeasure(data: StringData) {\r\n if (!this.enabled) return;\r\n super.onScrollMeasure(data);\r\n this.refreshPointerState();\r\n }\r\n\r\n protected getCursorTargets(allowFallback = false): StringObject[] {\r\n if (!this.enabled) return [];\r\n const near = this.hover.activeObjects();\r\n if (this.nearOnly && near.length) return near;\r\n if (this.useAllObjects) return this.objectsOnPage;\r\n if (this.objects.length > 0) return this.objects;\r\n return allowFallback ? this.objectsOnPage : this.objects;\r\n }\r\n\r\n protected refreshPointerState(target?: StringObject, allowFallback = false): void {\r\n if (!this.enabled) return;\r\n\r\n const mx = this.data.cursor.targetX;\r\n const my = this.data.cursor.targetY;\r\n const targets = target ? [target] : this.getCursorTargets(allowFallback);\r\n\r\n const maxDistanceSq =\r\n !this.nearOnly && this.maxDistanceMultiplier > 0\r\n ? Math.pow(this.data.viewport.windowWidth * this.maxDistanceMultiplier, 2)\r\n : null;\r\n\r\n for (const obj of targets) {\r\n const { cx, cy } = this.centers.getCenter(obj);\r\n const dx = mx - cx;\r\n const dy = my - cy;\r\n const d2 = dx * dx + dy * dy;\r\n\r\n if (this.nearOnly) {\r\n const far = d2 > this.data.viewport.windowWidth * this.data.viewport.windowWidth;\r\n if (far && !this.hover.isActive(obj)) continue;\r\n } else if (maxDistanceSq !== null && d2 > maxDistanceSq) {\r\n continue;\r\n }\r\n\r\n obj.setProperty(\"dx\", dx);\r\n obj.setProperty(\"dy\", dy);\r\n obj.setProperty(\"dist\", Math.sqrt(d2));\r\n }\r\n }\r\n\r\n private scrollUpdateScheduled = false;\r\n\r\n protected scheduleCursorUpdate(): void {\r\n if (!this.enabled || this.scrollUpdateScheduled) return;\r\n this.scrollUpdateScheduled = true;\r\n\r\n frameDOM.measure(() => {\r\n this.refreshPointerState();\r\n frameDOM.mutate(() => {\r\n this.scrollUpdateScheduled = false;\r\n styleTxn.run(() => {\r\n this.onCursorScrollUpdate();\r\n });\r\n });\r\n });\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-empty-function\r\n protected onCursorScrollUpdate(): void {}\r\n}\r\n","import { StringData } from \"../../core/StringData\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { frameDOM } from \"../../utils/frame-dom\";\r\nimport { isCoarsePointer } from \"../../utils/isCoarsePointer\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\nimport { CursorReactiveModule } from \"./CursorReactiveModule\";\r\n\r\nconst TAU = Math.PI * 2;\r\nconst RAD2DEG = 180 / Math.PI;\r\nconst clamp01 = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);\r\n\r\nconst shortestArc = (from: number, to: number) => {\r\n let d = (to - from) % TAU;\r\n if (d > Math.PI) d -= TAU;\r\n if (d < -Math.PI) d += TAU;\r\n return from + d;\r\n};\r\n\r\ntype SpotlightState = {\r\n angle: number;\r\n dist: number;\r\n tAngle: number;\r\n tDist: number;\r\n prevDeg: number;\r\n prevDist: number;\r\n};\r\n\r\nconst spotState = new WeakMap<StringObject, SpotlightState>();\r\nconst getSpot = (o: StringObject): SpotlightState => {\r\n let s = spotState.get(o);\r\n if (!s) {\r\n s = { angle: 0, dist: 0, tAngle: 0, tDist: 0, prevDeg: NaN, prevDist: NaN };\r\n spotState.set(o, s);\r\n }\r\n return s;\r\n};\r\n\r\nexport class StringSpotlight extends CursorReactiveModule {\r\n constructor(context: any) {\r\n super(context);\r\n this.htmlKey = \"spotlight\";\r\n\r\n this.nearOnly = false;\r\n this.useAllObjects = false;\r\n this.maxDistanceMultiplier = 1;\r\n\r\n this.attributesToMap.push(\r\n {\r\n key: \"lerp\",\r\n type: \"number\",\r\n fallback: this.settings[\"lerp\"],\r\n transform: (v: number) =>\r\n clamp01(\r\n this.tools.adaptiveLerp.process({\r\n value: v,\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 { key: \"angle-threshold\", type: \"number\", fallback: 0.2 },\r\n { key: \"distance-threshold\", type: \"number\", fallback: 0.5 },\r\n { key: \"deadzone\", type: \"number\", fallback: 4 },\r\n { key: \"dist-max\", type: \"number\", fallback: 0 }\r\n );\r\n }\r\n\r\n initializeObject(\r\n id: number,\r\n obj: StringObject,\r\n el: HTMLElement,\r\n attrs: Record<string, any>\r\n ): void {\r\n super.initializeObject(id, obj, el, attrs);\r\n\r\n obj.setProperty(\"spotlight-angle-rad\", 0);\r\n obj.setProperty(\"spotlight-distance\", 0);\r\n obj.setProperty(\"spotlight-angle-rad-target\", 0);\r\n obj.setProperty(\"spotlight-distance-target\", 0);\r\n\r\n frameDOM.measure(() => {\r\n this.refreshPointerState(obj, /*allowFallback=*/ true);\r\n frameDOM.mutate(() => {\r\n styleTxn.run(() => {\r\n this.updateSpotlightState(obj, {\r\n forceImmediate: true,\r\n forceEmit: true,\r\n bypassDeadzone: true,\r\n });\r\n });\r\n });\r\n });\r\n }\r\n\r\n override onMutate(data: StringData): void {\r\n if (this.enabled) {\r\n super.onMutate(data);\r\n const targets = this.getCursorTargets(/*allowFallback=*/ false);\r\n const list = targets.length > 0 ? targets : this.getCursorTargets(/*allowFallback=*/ true);\r\n list.forEach((object) => {\r\n this.updateSpotlightState(object);\r\n });\r\n }\r\n }\r\n\r\n protected onCursorScrollUpdate(): void {\r\n const targets = this.getCursorTargets(/*allowFallback=*/ false);\r\n const list = targets.length > 0 ? targets : this.getCursorTargets(/*allowFallback=*/ true);\r\n\r\n list.forEach((object) => {\r\n this.updateSpotlightState(object, { bypassDeadzone: true });\r\n });\r\n }\r\n\r\n private updateSpotlightState(\r\n object: StringObject,\r\n options: { forceImmediate?: boolean; forceEmit?: boolean; bypassDeadzone?: boolean } = {}\r\n ): void {\r\n const dx = object.getProperty<number>(\"dx\");\r\n const dy = object.getProperty<number>(\"dy\");\r\n const dist = object.getProperty<number>(\"dist\");\r\n\r\n if (!Number.isFinite(dx) || !Number.isFinite(dy) || !Number.isFinite(dist)) {\r\n return;\r\n }\r\n\r\n const s = getSpot(object);\r\n\r\n const DEADZONE = object.getProperty<number>(\"deadzone\") ?? 4;\r\n if (options.bypassDeadzone || dist! > DEADZONE) {\r\n s.tAngle = Math.atan2(dy!, dx!);\r\n }\r\n\r\n const distMax = object.getProperty<number>(\"dist-max\") ?? 0;\r\n s.tDist = distMax > 0 ? Math.min(dist!, distMax) : dist!;\r\n\r\n object.setProperty(\"spotlight-distance-target\", s.tDist);\r\n object.setProperty(\"spotlight-angle-rad-target\", s.tAngle);\r\n\r\n if (options.forceImmediate) {\r\n s.angle = s.tAngle;\r\n s.dist = s.tDist;\r\n } else {\r\n const lerp = clamp01(object.getProperty<number>(\"lerp\") ?? 0.15);\r\n const nextA = shortestArc(s.angle, s.tAngle);\r\n s.angle += (nextA - s.angle) * lerp;\r\n s.dist += (s.tDist - s.dist) * lerp;\r\n }\r\n\r\n object.setProperty(\"spotlight-angle-rad\", s.angle);\r\n object.setProperty(\"spotlight-distance\", s.dist);\r\n\r\n const degRaw = s.angle * RAD2DEG - 90;\r\n\r\n const angleEps = object.getProperty<number>(\"angle-threshold\") ?? 0.2;\r\n const distEps = object.getProperty<number>(\"distance-threshold\") ?? 0.5;\r\n\r\n const angleChanged =\r\n options.forceEmit || Number.isNaN(s.prevDeg) || Math.abs(degRaw - s.prevDeg) > angleEps;\r\n const distChanged =\r\n options.forceEmit || Number.isNaN(s.prevDist) || Math.abs(s.dist - s.prevDist) > distEps;\r\n\r\n if (angleChanged || distChanged) {\r\n const cssDeg = Math.round(degRaw * 10) / 10;\r\n const cssDist = Math.round(s.dist * 10) / 10;\r\n\r\n this.applyToElementAndConnects(object, (el) => {\r\n styleTxn.setVars(el, {\r\n \"--spotlight-angle\": String(cssDeg),\r\n \"--spotlight-angle-deg\": `${cssDeg}deg`,\r\n \"--spotlight-distance\": String(cssDist),\r\n });\r\n });\r\n\r\n s.prevDeg = degRaw;\r\n s.prevDist = s.dist;\r\n\r\n this.events.emit(`spotlight:update:${object.id}`, {\r\n distance: cssDist,\r\n angleDeg: cssDeg,\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\nconst ASPECT_CLASS = \"-aspect-ready\";\r\n\r\ntype Dims = { width: number; height: number };\r\n\r\nfunction isSvgSource(src: string): boolean {\r\n if (!src) return false;\r\n const lower = src.toLowerCase();\r\n if (lower.endsWith(\".svg\")) return true;\r\n if (lower.startsWith(\"data:image/svg\")) return true;\r\n return false;\r\n}\r\n\r\ninterface LazyImageState {\r\n src: string;\r\n aspectReady: boolean;\r\n contentReady: boolean;\r\n aspectLoading: boolean;\r\n contentLoading: boolean;\r\n pendingActivation: boolean;\r\n width?: number;\r\n height?: number;\r\n aspectPromise?: Promise<void>;\r\n unsubscribe?: () => void;\r\n rangeAttempted: boolean;\r\n blobUrl?: string;\r\n controller?: AbortController;\r\n\r\n fetching: boolean;\r\n allowSrcFallback?: boolean;\r\n}\r\n\r\nfunction parsePng(b: ArrayBuffer): Dims {\r\n const d = new DataView(b);\r\n if (b.byteLength < 24) return { width: 0, height: 0 };\r\n if (d.getUint32(0) !== 0x89504e47 || d.getUint32(4) !== 0x0d0a1a0a)\r\n return { width: 0, height: 0 };\r\n if (d.getUint32(12) !== 13 || d.getUint32(16) !== 0x49484452) return { width: 0, height: 0 };\r\n return { width: d.getUint32(20, false), height: d.getUint32(24, false) };\r\n}\r\n\r\nfunction parseJpeg(b: ArrayBuffer): Dims {\r\n const d = new DataView(b);\r\n if (d.getUint16(0) !== 0xffd8) return { width: 0, height: 0 };\r\n let o = 2;\r\n while (o + 9 < b.byteLength) {\r\n const m = d.getUint16(o);\r\n o += 2;\r\n if (m === 0xffda || m === 0xffd9) break;\r\n const len = d.getUint16(o);\r\n if (len < 2 || o + len > b.byteLength) break;\r\n if (\r\n (m >= 0xffc0 && m <= 0xffc3) ||\r\n (m >= 0xffc5 && m <= 0xffc7) ||\r\n (m >= 0xffc9 && m <= 0xffcb) ||\r\n (m >= 0xffcd && m <= 0xffcf)\r\n ) {\r\n return { height: d.getUint16(o + 3), width: d.getUint16(o + 5) };\r\n }\r\n o += len;\r\n }\r\n return { width: 0, height: 0 };\r\n}\r\n\r\nfunction parseWebp(b: ArrayBuffer): Dims {\r\n const d = new DataView(b);\r\n if (b.byteLength < 16) return { width: 0, height: 0 };\r\n\r\n if (d.getUint32(0, true) !== 0x46464952 || d.getUint32(8, true) !== 0x50424557)\r\n return { width: 0, height: 0 };\r\n\r\n let i = 12;\r\n while (i + 8 <= b.byteLength) {\r\n const chunkHeader = d.getUint32(i, false);\r\n const chunkSize = d.getUint32(i + 4, true);\r\n const dataOffset = i + 8;\r\n\r\n if (chunkHeader === 0x56503858) {\r\n const w = (d.getUint16(dataOffset + 4, true) | (d.getUint8(dataOffset + 6) << 16)) + 1;\r\n const h = (d.getUint16(dataOffset + 7, true) | (d.getUint8(dataOffset + 9) << 16)) + 1;\r\n return { width: w, height: h };\r\n }\r\n\r\n if (chunkHeader === 0x56503820) {\r\n if (\r\n dataOffset + 10 <= b.byteLength &&\r\n d.getUint8(dataOffset + 3) === 0x9d &&\r\n d.getUint8(dataOffset + 4) === 0x01 &&\r\n d.getUint8(dataOffset + 5) === 0x2a\r\n ) {\r\n const w = d.getUint16(dataOffset + 6, true) & 0x3fff;\r\n const h = d.getUint16(dataOffset + 8, true) & 0x3fff;\r\n return { width: w, height: h };\r\n }\r\n }\r\n\r\n if (chunkHeader === 0x5650384c) {\r\n if (dataOffset + 5 <= b.byteLength && d.getUint8(dataOffset) === 0x2f) {\r\n const b0 = d.getUint8(dataOffset + 1);\r\n const b1 = d.getUint8(dataOffset + 2);\r\n const b2 = d.getUint8(dataOffset + 3);\r\n const b3 = d.getUint8(dataOffset + 4);\r\n\r\n const w = 1 + (((b1 & 0x3f) << 8) | b0);\r\n const h = 1 + (((b3 & 0x0f) << 10) | (b2 << 2) | ((b1 & 0xc0) >> 6));\r\n return { width: w, height: h };\r\n }\r\n }\r\n\r\n i = dataOffset + chunkSize + (chunkSize & 1);\r\n }\r\n return { width: 0, height: 0 };\r\n}\r\n\r\nfunction tryParseDims(buffer: ArrayBuffer, ct?: string | null): Dims {\r\n const c = (ct || \"\").toLowerCase();\r\n if (c.includes(\"png\")) return parsePng(buffer);\r\n if (c.includes(\"jpeg\") || c.includes(\"jpg\")) return parseJpeg(buffer);\r\n if (c.includes(\"webp\")) return parseWebp(buffer);\r\n let d = parsePng(buffer);\r\n if (d.width) return d;\r\n d = parseJpeg(buffer);\r\n if (d.width) return d;\r\n d = parseWebp(buffer);\r\n if (d.width) return d;\r\n return { width: 0, height: 0 };\r\n}\r\n\r\nasync function fetchImageStreamWithDims(\r\n src: string,\r\n opts?: {\r\n credentials?: RequestCredentials;\r\n referrerPolicy?: ReferrerPolicy;\r\n signal?: AbortSignal;\r\n },\r\n onDims?: (d: Dims) => void\r\n): Promise<{\r\n dims: { width: number; height: number } | null;\r\n blobUrl: string;\r\n contentType?: string | null;\r\n}> {\r\n const res = await fetch(src, {\r\n mode: \"cors\",\r\n credentials: opts?.credentials ?? \"omit\",\r\n referrerPolicy: opts?.referrerPolicy,\r\n signal: opts?.signal,\r\n cache: \"default\",\r\n });\r\n if (!res.ok || !res.body) throw new Error(`HTTP ${res.status}`);\r\n\r\n const ct = res.headers.get(\"content-type\");\r\n const reader = res.body.getReader();\r\n\r\n const PROBE_CAP = 1048576;\r\n const TRY_STEP = 4096;\r\n\r\n const probe = new Uint8Array(PROBE_CAP);\r\n let probeLen = 0;\r\n let lastTriedLen = 0;\r\n\r\n const chunks: ArrayBuffer[] = [];\r\n let dims: Dims | null = null;\r\n let announced = false;\r\n\r\n for (;;) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n if (!value) continue;\r\n\r\n const part = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);\r\n chunks.push(part);\r\n\r\n if (!dims && probeLen < PROBE_CAP) {\r\n const toCopy = Math.min(value.byteLength, PROBE_CAP - probeLen);\r\n if (toCopy > 0) {\r\n probe.set(value.subarray(0, toCopy), probeLen);\r\n probeLen += toCopy;\r\n }\r\n if (probeLen - lastTriedLen >= TRY_STEP) {\r\n const view = probeLen === probe.byteLength ? probe : probe.slice(0, probeLen);\r\n const d = tryParseDims(view.buffer, ct);\r\n if (d.width && d.height) {\r\n dims = d;\r\n if (!announced && onDims) {\r\n onDims(dims);\r\n announced = true;\r\n }\r\n }\r\n lastTriedLen = probeLen;\r\n }\r\n }\r\n }\r\n\r\n if (!dims) {\r\n const full = await new Response(new Blob(chunks)).arrayBuffer();\r\n const d = tryParseDims(full, ct);\r\n if (d.width && d.height) {\r\n dims = d;\r\n if (!announced && onDims) {\r\n onDims(dims);\r\n announced = true;\r\n }\r\n }\r\n }\r\n\r\n const blob = new Blob(chunks, { type: ct || \"application/octet-stream\" });\r\n const blobUrl = URL.createObjectURL(blob);\r\n return { dims, blobUrl, contentType: ct };\r\n}\r\n\r\nexport class StringLazy extends StringModule {\r\n private isStartLoaded = false;\r\n private loadingCount = 0;\r\n private imageStates = new WeakMap<HTMLImageElement, LazyImageState>();\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"lazy\";\r\n }\r\n\r\n onInit(): void {\r\n const images = document.querySelectorAll(\"img[string-lazy], img[data-string-lazy]\");\r\n images.forEach((img) => this.ensureState(img as HTMLImageElement));\r\n this.isStartLoaded = true;\r\n }\r\n\r\n onObjectConnected(object: StringObject): void {\r\n const element = object.htmlElement;\r\n if (!(element instanceof HTMLImageElement)) return;\r\n const state = this.ensureState(element);\r\n\r\n if (!state.aspectReady && !state.aspectLoading) {\r\n this.prepareAspectRatio(element);\r\n }\r\n\r\n const listener = (data: { inView: boolean } | undefined) => {\r\n this.handleInView(element, state, !!data?.inView);\r\n };\r\n if (state.unsubscribe) state.unsubscribe();\r\n this.events.on(`object:inview:${object.id}`, listener);\r\n state.unsubscribe = () => this.events.off(`object:inview:${object.id}`, listener);\r\n if (this.isStartLoaded && (object.getProperty<boolean>(\"is-inview\") ?? false)) {\r\n this.handleInView(element, state, true);\r\n }\r\n }\r\n\r\n onObjectDisconnected(object: StringObject): void {\r\n const element = object.htmlElement;\r\n if (!(element instanceof HTMLImageElement)) return;\r\n const state = this.imageStates.get(element);\r\n if (!state) return;\r\n state.pendingActivation = false;\r\n if (state.controller) state.controller.abort();\r\n if (state.blobUrl) URL.revokeObjectURL(state.blobUrl);\r\n if (state.unsubscribe) {\r\n state.unsubscribe();\r\n state.unsubscribe = undefined;\r\n }\r\n }\r\n\r\n private ensureState(img: HTMLImageElement): LazyImageState {\r\n let state = this.imageStates.get(img);\r\n if (!state) {\r\n const src = this.readSource(img);\r\n state = {\r\n src,\r\n aspectReady: false,\r\n contentReady: false,\r\n aspectLoading: false,\r\n contentLoading: false,\r\n pendingActivation: false,\r\n rangeAttempted: false,\r\n fetching: false,\r\n };\r\n this.imageStates.set(img, state);\r\n if (!img.classList.contains(\"lazyLoad\")) img.classList.add(\"lazyLoad\");\r\n if (img.dataset && !img.dataset.stringLazySrc && src) img.dataset.stringLazySrc = src;\r\n return state;\r\n }\r\n if (!state.src) state.src = this.readSource(img);\r\n return state;\r\n }\r\n\r\n private readSource(img: HTMLImageElement): string {\r\n const raw = this.tools.domAttribute.process({ element: img, key: this.htmlKey, fallback: \"\" });\r\n if (typeof raw === \"string\") return raw;\r\n if (raw == null) return \"\";\r\n return String(raw);\r\n }\r\n\r\n private handleInView(img: HTMLImageElement, state: LazyImageState, inView: boolean): void {\r\n state.pendingActivation = inView;\r\n if (!inView) return;\r\n if (state.aspectReady) {\r\n this.maybeActivateImage(img, state);\r\n } else if (!state.aspectLoading) {\r\n this.prepareAspectRatio(img);\r\n }\r\n }\r\n\r\n private async prepareAspectRatio(img: HTMLImageElement): Promise<void> {\r\n const state = this.ensureState(img);\r\n if (!state.src || state.aspectLoading || state.aspectReady) return;\r\n\r\n if (isSvgSource(state.src)) {\r\n state.aspectReady = true;\r\n state.allowSrcFallback = true;\r\n this.maybeActivateImage(img, state);\r\n return;\r\n }\r\n\r\n state.aspectLoading = true;\r\n state.fetching = true;\r\n\r\n const crossOrigin = img.getAttribute(\"crossorigin\");\r\n const referrerPolicy = img.getAttribute(\"referrerpolicy\") as ReferrerPolicy | null;\r\n const ac = new AbortController();\r\n state.controller = ac;\r\n\r\n try {\r\n const { blobUrl } = await fetchImageStreamWithDims(\r\n state.src,\r\n {\r\n credentials: crossOrigin === \"use-credentials\" ? \"include\" : \"omit\",\r\n referrerPolicy: referrerPolicy || undefined,\r\n signal: ac.signal,\r\n },\r\n\r\n (d) => {\r\n if (d.width > 0 && d.height > 0 && !state.aspectReady) {\r\n img.style.aspectRatio = `${d.width} / ${d.height}`;\r\n img.classList.add(ASPECT_CLASS);\r\n state.width = d.width;\r\n state.height = d.height;\r\n state.aspectReady = true;\r\n }\r\n }\r\n );\r\n\r\n state.blobUrl = blobUrl;\r\n\r\n if (!state.aspectReady && state.width && state.height) {\r\n img.style.aspectRatio = `${state.width} / ${state.height}`;\r\n img.classList.add(ASPECT_CLASS);\r\n state.aspectReady = true;\r\n }\r\n } catch {\r\n state.allowSrcFallback = true;\r\n state.aspectReady = true;\r\n } finally {\r\n state.fetching = false;\r\n state.aspectLoading = false;\r\n\r\n this.maybeActivateImage(img, state);\r\n }\r\n }\r\n\r\n private maybeActivateImage(img: HTMLImageElement, state: LazyImageState): void {\r\n if (!state.pendingActivation || state.contentReady || state.contentLoading) return;\r\n if (!state.aspectReady || !state.src) return;\r\n\r\n if (state.fetching && !state.blobUrl) return;\r\n\r\n if (state.blobUrl || state.allowSrcFallback) {\r\n this.activateImage(img, state);\r\n }\r\n }\r\n\r\n private activateImage(img: HTMLImageElement, state: LazyImageState): void {\r\n state.contentLoading = true;\r\n this.loadingCount++;\r\n const finalize = (loaded: boolean) => {\r\n if (!state.contentLoading) return;\r\n state.contentLoading = false;\r\n state.pendingActivation = false;\r\n this.loadingCount = Math.max(0, this.loadingCount - 1);\r\n if (loaded) {\r\n state.contentReady = true;\r\n img.classList.add(\"-loaded\");\r\n }\r\n if (this.loadingCount === 0) this.events.emit(\"image:load:all\", null);\r\n };\r\n const onLoad = () => finalize(true);\r\n const onError = () => finalize(false);\r\n img.addEventListener(\"load\", onLoad, { once: true });\r\n img.addEventListener(\"error\", onError, { once: true });\r\n img.decoding = \"async\";\r\n img.loading = img.loading || \"lazy\";\r\n\r\n if (state.blobUrl) {\r\n img.removeAttribute(\"srcset\");\r\n img.removeAttribute(\"sizes\");\r\n img.src = state.blobUrl;\r\n } else {\r\n img.src = state.src;\r\n }\r\n\r\n if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {\r\n img.removeEventListener(\"load\", onLoad);\r\n img.removeEventListener(\"error\", onError);\r\n finalize(true);\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: 1023,\r\n }),\r\n [DeviceType.Laptop]: new StringResponsiveQueryDevice({\r\n min: 1024,\r\n max: 1365,\r\n }),\r\n [DeviceType.Desktop]: new StringResponsiveQueryDevice({ min: 1366 }),\r\n };\r\n\r\n private isMobileMedia: boolean = false;\r\n private isTabletMedia: boolean = false;\r\n private isLaptopMedia: boolean = false;\r\n private isDesktopMedia: boolean = false;\r\n\r\n private matchMedias: { [key in DeviceType]: MediaQueryList } = {\r\n [DeviceType.Mobile]: window.matchMedia(this.queries[DeviceType.Mobile].mediaQuery),\r\n [DeviceType.Tablet]: window.matchMedia(this.queries[DeviceType.Tablet].mediaQuery),\r\n [DeviceType.Laptop]: window.matchMedia(this.queries[DeviceType.Laptop].mediaQuery),\r\n [DeviceType.Desktop]: window.matchMedia(this.queries[DeviceType.Desktop].mediaQuery),\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.tablet.min == undefined ? null : config.tablet.min,\r\n config.tablet.max ?? null\r\n );\r\n this.matchMedias[DeviceType.Tablet] = window.matchMedia(\r\n this.queries[DeviceType.Tablet].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.laptop.min == undefined ? null : config.laptop.min,\r\n config.laptop.max ?? null\r\n );\r\n this.matchMedias[DeviceType.Laptop] = window.matchMedia(\r\n this.queries[DeviceType.Laptop].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.desktop.min == undefined ? null : config.desktop.min,\r\n config.desktop.max ?? null\r\n );\r\n this.matchMedias[DeviceType.Desktop] = window.matchMedia(\r\n this.queries[DeviceType.Desktop].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 && this.queries[DeviceType.Mobile].enable;\r\n const isTabletMedia =\r\n this.matchMedias[DeviceType.Tablet].matches && this.queries[DeviceType.Tablet].enable;\r\n const isLaptopMedia =\r\n this.matchMedias[DeviceType.Laptop].matches && this.queries[DeviceType.Laptop].enable;\r\n const isDesktopMedia =\r\n this.matchMedias[DeviceType.Desktop].matches && this.queries[DeviceType.Desktop].enable;\r\n\r\n if (this.isMobileMedia != isMobileMedia) {\r\n this.events.emit(\"screen:mobile\", isMobileMedia);\r\n }\r\n if (this.isTabletMedia != isTabletMedia) {\r\n this.events.emit(\"screen:tablet\", isTabletMedia);\r\n }\r\n if (this.isLaptopMedia != isLaptopMedia) {\r\n this.events.emit(\"screen:laptop\", isLaptopMedia);\r\n }\r\n if (this.isDesktopMedia != isDesktopMedia) {\r\n this.events.emit(\"screen:desktop\", isDesktopMedia);\r\n }\r\n\r\n this.isMobileMedia = isMobileMedia;\r\n this.isTabletMedia = isTabletMedia;\r\n this.isLaptopMedia = isLaptopMedia;\r\n this.isDesktopMedia = isDesktopMedia;\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 }\r\n if (element.hasAttribute(\"string-tablet\") && isTabletMedia) {\r\n showElement = true;\r\n }\r\n if (element.hasAttribute(\"string-laptop\") && isLaptopMedia) {\r\n showElement = true;\r\n }\r\n if (element.hasAttribute(\"string-desktop\") && isDesktopMedia) {\r\n showElement = true;\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\"] ?? 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 = -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 > 1024) {\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(\"--glide\", this.data.scroll.displacement.toString());\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(MAX_DISPLACEMENT, this.acceleration + ACCELERATION_STEP);\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(MIN_VELOCITY, this.data.scroll.lerped * this.displacement * this.acceleration)\r\n );\r\n this.objects.forEach((object) => {\r\n this.applyToElementAndConnects(object, (el) => {\r\n el.style.setProperty(\"--glide\", this.data.scroll.displacement.toString());\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 { StringMirrorObject } from \"../../objects/StringMirrorObject\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EasingFunctionOutput } from \"../../tools/EasingFunctionTool\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\nexport class StringProgress extends StringModule {\r\n protected updateScheduled = false;\r\n\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 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 private recomputeProgress(object: StringObject): void {\r\n const startPosition = object.getProperty<number>(\"start-position\") ?? 0;\r\n const differencePosition = object.getProperty<number>(\"difference-position\") ?? 0;\r\n\r\n let rawProgress = 0;\r\n rawProgress = Math.min(\r\n 1,\r\n Math.max(0, (this.data.scroll.transformedCurrent - startPosition) / differencePosition)\r\n );\r\n\r\n object.setProperty<number>(\"progress-raw\", rawProgress);\r\n\r\n const easing = object.getProperty<EasingFunctionOutput>(\"easing\");\r\n const progress = typeof easing === \"function\" ? easing(rawProgress) : rawProgress;\r\n this.applyProgressValue(object, progress);\r\n }\r\n\r\n private applyProgressValue(object: StringObject, progress: number): void {\r\n object.setProperty<number>(\"progress\", progress);\r\n }\r\n\r\n calculatePositions(object: StringObject, windowSize: number) {\r\n super.calculatePositions(object, windowSize);\r\n this.recomputeProgress(object);\r\n }\r\n\r\n onScroll(data: StringData): void {\r\n super.onScroll(data);\r\n }\r\n\r\n onObjectConnected(object: StringObject) {\r\n super.onObjectConnected(object);\r\n }\r\n\r\n onScrollMeasure(data: StringData) {\r\n this.objects.forEach((object) => {\r\n this.recomputeProgress(object);\r\n });\r\n }\r\n\r\n onMutate() {\r\n this.objects.forEach((object) => {\r\n this.updateObjectProgress(object);\r\n });\r\n }\r\n\r\n private updateObjectProgress(object: StringObject): void {\r\n const key = object.getProperty<string>(\"key\");\r\n const progress = object.getProperty<number>(\"progress\");\r\n\r\n const rawProgress = object.getProperty<number>(\"progress-raw\") ?? progress;\r\n const progressStr = progress.toString();\r\n const parentEasing = object.getProperty<EasingFunctionOutput>(\"easing\");\r\n\r\n this.events.emit(`object:progress:${object.id}`, progress);\r\n\r\n this.applyToElementAndConnects(\r\n object,\r\n (el) => {\r\n if (key) {\r\n styleTxn.setVars(el, { [key]: progressStr });\r\n }\r\n },\r\n (el: HTMLElement, mirror?: StringMirrorObject) => {\r\n if (!mirror) return;\r\n const eased = mirror.applyProgress(\r\n rawProgress,\r\n typeof parentEasing === \"function\" ? parentEasing : undefined\r\n );\r\n mirror.setProperty(\"progress\", eased);\r\n if (key) {\r\n styleTxn.setVars(el, { [key]: eased.toString() });\r\n }\r\n }\r\n );\r\n }\r\n\r\n onObjectDisconnected(object: StringObject): void {\r\n super.onObjectDisconnected(object);\r\n const key = object.getProperty<string>(\"key\");\r\n if (!key) return;\r\n\r\n const clearCustomProperty = (el: HTMLElement) => {\r\n el.style.removeProperty(key);\r\n };\r\n\r\n clearCustomProperty(object.htmlElement);\r\n object.mirrorObjects.forEach((mirror) => {\r\n clearCustomProperty(mirror.htmlElement);\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 { frameDOM } from \"../../utils/frame-dom\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\nimport { StringProgress } from \"./StringProgress\";\r\n\r\ntype ParallaxTransformResult = { transform: string };\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 private updateScheduledTransform = false;\r\n private calculateParallaxForObject: (object: StringObject) => ParallaxTransformResult | null;\r\n\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 this.calculateParallaxForObject = this.calculateDesktopParallax;\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(\"parallax-sign\", Math.sign(object.getProperty<number>(\"parallax\")));\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 calculatePositions(object: StringObject, windowSize: number) {\r\n super.calculatePositions(object, windowSize);\r\n object.setProperty(\"transform-value\", this.calculateParallaxForObject(object));\r\n }\r\n\r\n override onScroll(data: StringData): void {\r\n super.onScroll(data);\r\n }\r\n\r\n override onResize(): void {\r\n const isDesktop = window.innerWidth > 1024;\r\n this.calculateParallaxForObject = isDesktop\r\n ? this.calculateDesktopParallax\r\n : this.calculateMobileParallax;\r\n }\r\n\r\n onScrollMeasure(data: StringData) {\r\n super.onScrollMeasure(data);\r\n this.objects.forEach((object) => {\r\n object.setProperty(\"transform-value\", this.calculateParallaxForObject(object));\r\n });\r\n }\r\n\r\n onMutate() {\r\n this.objects.forEach((object) => {\r\n const transformData = object.getProperty<ParallaxTransformResult>(\"transform-value\");\r\n this.applyToElementAndConnects(object, (el) => {\r\n styleTxn.setProps(el, transformData);\r\n });\r\n });\r\n }\r\n\r\n private calculateDesktopParallax = (object: StringObject): ParallaxTransformResult => {\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 / this.data.viewport.transformScale;\r\n const translation = sign * factor * (screenSize * start + progress * screenSize * end);\r\n\r\n this.events.emit(`object:parallax:${object.id}`, translation);\r\n\r\n return { transform: `translate3d(0, ${translation}px, 0)` };\r\n };\r\n\r\n private calculateMobileParallax = (object: StringObject): ParallaxTransformResult => {\r\n this.events.emit(`object:parallax:${object.id}`, 0);\r\n return { transform: `translate3d(0, 0px, 0)` };\r\n };\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 = {\r\n BEFORE_ELEMENT: \"-before-element\",\r\n AFTER_ELEMENT: \"-after-element\",\r\n} as const;\r\n","import { CalculatedValue } from \"../../models/text/CalculatedValue\";\r\nimport { LayoutLine } from \"./SplitMeasuredTokens\";\r\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\r\nimport { SPLIT_ELEMENT_CLASS } from \"../../models/text/SplitElementClass\";\r\nimport { FontMetrics } from \"./CanvasKerningApplier\";\r\n\r\nfunction getWholeWordSplitClass(word: any): string[] {\r\n if (!word || !Array.isArray(word.chars) || word.chars.length === 0) return [];\r\n const first = (word.chars[0] as any).splitClass ?? [];\r\n if (first.length === 0) return [];\r\n for (const ch of word.chars) {\r\n const cls = (ch as any).splitClass ?? [];\r\n if (cls.length !== first.length) return [];\r\n for (let i = 0; i < cls.length; i++) {\r\n if (cls[i] !== first[i]) return [];\r\n }\r\n }\r\n return first;\r\n}\r\n\r\nexport function BuildDOMTree(\r\n layoutLines: LayoutLine[],\r\n options: ISplitOptions,\r\n fontMetrics: FontMetrics\r\n): { fragment: DocumentFragment; extraProps: Map<string, string> } {\r\n const fragment = document.createDocumentFragment();\r\n let localCharIndex = 0;\r\n\r\n const hasLine =\r\n hasOption(options, \"line\") || hasOption(options, \"charLine\") || hasOption(options, \"wordLine\");\r\n\r\n const hasChar =\r\n hasOption(options, \"char\") || hasOption(options, \"charLine\") || hasOption(options, \"charWord\");\r\n\r\n let wordsCount = 0;\r\n layoutLines.forEach((line) => (wordsCount += line.words.length));\r\n wordsCount--;\r\n\r\n let charsCount = 0;\r\n layoutLines.forEach((line) => line.words.forEach((w) => (charsCount += w.chars.length)));\r\n\r\n const linesCount = layoutLines.length;\r\n const wordsGlobalCount = wordsCount + 1;\r\n\r\n const extraProps = new Map<string, string>();\r\n\r\n layoutLines.forEach((line, li) => {\r\n const isLastInLayout = li === layoutLines.length - 1;\r\n\r\n let container: HTMLElement | DocumentFragment = fragment;\r\n const wordsForLine: string[] = [];\r\n\r\n if (hasLine) {\r\n container = document.createElement(\"span\");\r\n container.setAttribute(\"aria-hidden\", \"true\");\r\n container.classList.add(\"-s-line\");\r\n if (line.isBeforeElement)\r\n (container as HTMLElement).classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\r\n if (line.isAfterElement)\r\n (container as HTMLElement).classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\r\n (container as HTMLElement).style.setProperty(\"--line-index\", String(line.lineIndex));\r\n (container as HTMLElement).style.setProperty(\"--word-total\", String(line.words.length));\r\n applyStyles(container as HTMLElement, (line as any).calculatedValues, options);\r\n }\r\n\r\n line.words.forEach((word, wi) => {\r\n if (hasLine) {\r\n wordsCount = line.words.length - 1;\r\n }\r\n const isLast = wi === wordsCount;\r\n const isElementWord = word.chars.length === 1 && word.chars[0].token.type === \"element\";\r\n if (isElementWord) {\r\n const original = word.chars[0].token.node.cloneNode(true) as HTMLElement;\r\n container.appendChild(original);\r\n return;\r\n }\r\n\r\n const wordText = word.chars.map((c) => c.char).join(\"\");\r\n if (wordText) {\r\n wordsForLine.push(wordText);\r\n }\r\n\r\n const hasWord =\r\n hasOption(options, \"word\") ||\r\n hasOption(options, \"charWord\") ||\r\n hasOption(options, \"wordLine\");\r\n\r\n const wordEl = hasWord ? document.createElement(\"span\") : (container as HTMLElement);\r\n\r\n const wholeWordClass = getWholeWordSplitClass(word);\r\n\r\n if (hasWord) {\r\n wordEl.setAttribute(\"aria-hidden\", \"true\");\r\n wordEl.classList.add(\"-s-word\");\r\n if (word.isBeforeElement) wordEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\r\n if (word.isAfterElement) wordEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\r\n wordEl.style.setProperty(\"--word-index\", String(word.wordIndexGlobal));\r\n wordEl.style.setProperty(\"--char-total\", String(word.chars.length));\r\n wordEl.setAttribute(\"data-split-content\", wordText);\r\n applyStyles(wordEl, (word as any).calculatedValues, options);\r\n\r\n if (wholeWordClass.length) {\r\n wordEl.classList.add(...wholeWordClass);\r\n }\r\n }\r\n\r\n if (hasChar) {\r\n word.chars.forEach((char, charIndex) => {\r\n if (char.char === \" \" || char.char === \"\\t\") return;\r\n\r\n const charNode = document.createElement(\"span\");\r\n charNode.setAttribute(\"aria-hidden\", \"true\");\r\n const charEl = charNode as HTMLElement;\r\n\r\n charEl.classList.add(\"-s-char\");\r\n if (char.isBeforeElement) charEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\r\n if (char.isAfterElement) charEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\r\n\r\n charEl.textContent = char.char;\r\n charEl.setAttribute(\"data-split-content\", char.char);\r\n charEl.style.setProperty(\"--char-index\", String(localCharIndex++));\r\n\r\n const nextChar = word.chars[charIndex + 1];\r\n if (nextChar) {\r\n const kerning = fontMetrics.getKerning(char.char, nextChar.char);\r\n if (Math.abs(kerning) > 0.01) {\r\n charEl.style.marginRight = `${kerning.toFixed(2)}px`;\r\n }\r\n }\r\n\r\n applyStyles(charEl, (char as any).calculatedValues, options);\r\n\r\n const splitClassChar: string[] = (char as any).splitClass ?? [];\r\n if (splitClassChar.length && !wholeWordClass.length) {\r\n charEl.classList.add(...splitClassChar);\r\n }\r\n\r\n wordEl.appendChild(charNode);\r\n });\r\n } else {\r\n const textNode = document.createTextNode(wordText);\r\n wordEl.appendChild(textNode);\r\n }\r\n\r\n if (hasWord) {\r\n container.appendChild(wordEl);\r\n }\r\n\r\n if (hasLine) {\r\n if (!isLast) {\r\n wordEl.appendChild(document.createTextNode(\"\\u00a0\"));\r\n } else if (!isLastInLayout) {\r\n container.appendChild(document.createElement(\"br\"));\r\n }\r\n } else {\r\n if (!isLast) {\r\n wordEl.appendChild(document.createTextNode(\"\\u00a0\"));\r\n }\r\n }\r\n });\r\n\r\n if (hasLine) {\r\n const lineText = wordsForLine.join(\" \");\r\n (container as HTMLElement).setAttribute(\"data-split-content\", lineText);\r\n fragment.appendChild(container as HTMLElement);\r\n }\r\n });\r\n\r\n if (hasChar) {\r\n extraProps.set(\"--char-global-total\", String(charsCount));\r\n }\r\n if (\r\n hasOption(options, \"word\") ||\r\n hasOption(options, \"charWord\") ||\r\n hasOption(options, \"wordLine\")\r\n ) {\r\n extraProps.set(\"--word-global-total\", String(wordsGlobalCount));\r\n }\r\n if (hasLine) {\r\n extraProps.set(\"--line-global-total\", String(linesCount));\r\n }\r\n\r\n return { fragment, extraProps };\r\n}\r\n\r\nfunction applyStyles(\r\n el: HTMLElement,\r\n calculatedValues: CalculatedValue[] | undefined,\r\n options: ISplitOptions\r\n) {\r\n if (!calculatedValues) return;\r\n for (const val of calculatedValues) {\r\n if (!isOptionEnabled(val.type, val.align, options)) continue;\r\n const varName = generateVariableName(val.type, val.align);\r\n el.style.setProperty(varName, String(val.value));\r\n }\r\n}\r\n\r\nfunction isOptionEnabled(type: string, align: string, options: ISplitOptions): boolean {\r\n const group = options[type as keyof ISplitOptions] ?? [];\r\n return (\r\n Array.isArray(group) &&\r\n group.some((item) =>\r\n align.startsWith(\"random\") ? item.align.startsWith(\"random\") : item.align === align\r\n )\r\n );\r\n}\r\n\r\nfunction generateVariableName(type: string, align: string): string {\r\n const norm = align.startsWith(\"random\") ? \"random\" : align;\r\n return `--${type}-${norm}`;\r\n}\r\n\r\nfunction hasOption(options: ISplitOptions, key: keyof ISplitOptions): boolean {\r\n return Array.isArray(options[key]) && options[key]!.length > 0;\r\n}\r\n","export type Token =\r\n | {\r\n type: \"text\";\r\n id: string;\r\n node: Text;\r\n content: string;\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"space\";\r\n id: string;\r\n node: Text;\r\n content: string;\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"element\";\r\n id: string;\r\n node: HTMLElement;\r\n tagName: string;\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"br\";\r\n id: string;\r\n node: HTMLElement;\r\n tagName: \"br\";\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"other\";\r\n id: string;\r\n node: Node;\r\n meta?: Record<string, any>;\r\n };\r\n\r\nlet tokenCounter = 0;\r\n\r\nexport function BuildTokens(nodes: NodeListOf<ChildNode>): Token[] {\r\n tokenCounter = 0;\r\n const tokens: Token[] = [];\r\n\r\n const pushWithMeta = (t: Token, extra: Record<string, any> | undefined) => {\r\n if (extra && Object.keys(extra).length) {\r\n t.meta = { ...(t.meta || {}), ...extra };\r\n }\r\n tokens.push(t);\r\n };\r\n\r\n const processNode = (node: ChildNode, carryMeta?: Record<string, any>) => {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === \"split-class\") {\r\n const classes = (el.getAttribute(\"class\") ?? \"\").split(/\\s+/).filter(Boolean);\r\n const extraMeta = {\r\n ...(carryMeta || {}),\r\n splitClass: [...((carryMeta?.splitClass as string[]) ?? []), ...classes],\r\n };\r\n el.childNodes.forEach((child) => processNode(child as ChildNode, extraMeta));\r\n return;\r\n }\r\n\r\n if (tag === \"br\") {\r\n pushWithMeta(\r\n {\r\n type: \"br\",\r\n id: `br_${tokenCounter++}`,\r\n node: el,\r\n tagName: \"br\",\r\n },\r\n carryMeta\r\n );\r\n return;\r\n }\r\n\r\n pushWithMeta(\r\n {\r\n type: \"element\",\r\n id: `el_${tokenCounter++}`,\r\n node: el,\r\n tagName: tag,\r\n },\r\n carryMeta\r\n );\r\n return;\r\n }\r\n\r\n if (node.nodeType === Node.TEXT_NODE) {\r\n const text = node.nodeValue ?? \"\";\r\n const id = `text_${tokenCounter++}`;\r\n if (text.trim()) {\r\n pushWithMeta({ type: \"text\", id, node: node as Text, content: text }, carryMeta);\r\n } else {\r\n pushWithMeta({ type: \"space\", id, node: node as Text, content: text }, carryMeta);\r\n }\r\n return;\r\n }\r\n\r\n pushWithMeta({ type: \"other\", id: `node_${tokenCounter++}`, node }, carryMeta);\r\n };\r\n\r\n nodes.forEach((n) => processNode(n as ChildNode));\r\n return tokens;\r\n}\r\n","type PairKey = `${string}|${string}`;\n\nexport class FontMetrics {\n private ctx: CanvasRenderingContext2D;\n private font: string = \"\";\n private cache = {\n kerning: new Map<PairKey, number>(),\n charWidth: new Map<string, number>(),\n };\n\n constructor(element: HTMLElement) {\n const canvas = document.createElement(\"canvas\");\n this.ctx = canvas.getContext(\"2d\")!;\n this.setFontFromElement(element);\n }\n\n public setFontFromElement(element: HTMLElement): void {\n const cs = window.getComputedStyle(element);\n const font = `${cs.fontStyle} ${cs.fontVariant} ${cs.fontWeight} ${cs.fontSize}/${cs.lineHeight} ${cs.fontFamily}`;\n if (font !== this.font) {\n this.font = font;\n this.ctx.font = this.font;\n this.cache.kerning.clear();\n this.cache.charWidth.clear();\n }\n }\n\n public getCharWidth(char: string): number {\n if (this.cache.charWidth.has(char)) {\n return this.cache.charWidth.get(char)!;\n }\n const width = this.ctx.measureText(char).width;\n this.cache.charWidth.set(char, width);\n return width;\n }\n\n public getKerning(charA: string, charB: string): number {\n const pair = `${charA}${charB}`;\n const key: PairKey = `${this.font}|${pair}`;\n\n if (this.cache.kerning.has(key)) {\n return this.cache.kerning.get(key)!;\n }\n\n const widthWithKerning = this.ctx.measureText(pair).width;\n const widthWithoutKerning = this.getCharWidth(charA) + this.getCharWidth(charB);\n\n const kerning = widthWithKerning - widthWithoutKerning;\n\n this.cache.kerning.set(key, kerning);\n return kerning;\n }\n\n public measureWord(word: string): number {\n let totalWidth = 0;\n for (let i = 0; i < word.length; i++) {\n const char = word[i];\n totalWidth += this.getCharWidth(char);\n\n if (i > 0) {\n const prevChar = word[i - 1];\n totalWidth += this.getKerning(prevChar, char);\n }\n }\n return totalWidth;\n }\n}\n","import { Token } from \"./BuildTokens\";\r\nimport { FontMetrics } from \"./CanvasKerningApplier\";\r\n\r\nexport type MeasuredToken = {\r\n token: Token;\r\n rect: DOMRect;\r\n};\r\n\r\nfunction splitTokensByBr(tokens: Token[]): Token[][] {\r\n const result: Token[][] = [];\r\n let chunk: Token[] = [];\r\n for (const token of tokens) {\r\n if (token.type === \"br\") {\r\n if (chunk.length) result.push(chunk);\r\n result.push([token]);\r\n chunk = [];\r\n } else {\r\n chunk.push(token);\r\n }\r\n }\r\n if (chunk.length) result.push(chunk);\r\n return result;\r\n}\r\n\r\nexport function LayoutMeasurer(\r\n tokens: Token[],\r\n container: HTMLElement,\r\n fontMetrics: FontMetrics\r\n): MeasuredToken[] {\r\n const wrapper = document.createElement(\"div\");\r\n const computed = window.getComputedStyle(container);\r\n\r\n wrapper.style.position = \"absolute\";\r\n wrapper.style.visibility = \"hidden\";\r\n wrapper.style.pointerEvents = \"none\";\r\n wrapper.style.width = container.clientWidth + \"px\";\r\n wrapper.style.padding = computed.padding;\r\n wrapper.style.font = computed.font;\r\n wrapper.style.letterSpacing = computed.letterSpacing;\r\n wrapper.style.lineHeight = computed.lineHeight;\r\n wrapper.style.fontVariant = computed.fontVariant;\r\n wrapper.style.fontStretch = computed.fontStretch;\r\n wrapper.style.wordBreak = computed.wordBreak;\r\n wrapper.style.wordWrap = computed.wordWrap;\r\n wrapper.style.whiteSpace = computed.whiteSpace;\r\n\r\n const spaceMeasurer = document.createElement(\"span\");\r\n spaceMeasurer.textContent = \"\\u00a0\";\r\n wrapper.appendChild(spaceMeasurer);\r\n const spaceWidth = spaceMeasurer.getBoundingClientRect().width;\r\n wrapper.removeChild(spaceMeasurer);\r\n wrapper.style.width = container.clientWidth + spaceWidth + \"px\";\r\n wrapper.style.boxSizing = \"border-box\";\r\n\r\n container.appendChild(wrapper);\r\n\r\n const measured: MeasuredToken[] = [];\r\n const chunks = splitTokensByBr(tokens);\r\n\r\n let isAfterElement = false;\r\n let lastTokenWasSpace = false;\r\n let prevMeasuredWasText = false;\r\n\r\n for (const chunk of chunks) {\r\n if (chunk.length === 1 && chunk[0].type === \"br\") {\r\n measured.push({ token: chunk[0], rect: new DOMRect(0, 0, 0, 0) });\r\n continue;\r\n }\r\n if (chunk.length === 0) continue;\r\n\r\n wrapper.innerHTML = \"\";\r\n\r\n const wordSpans: HTMLSpanElement[] = [];\r\n const tokenInfo: Array<{\r\n token: Token;\r\n wordIndex?: number;\r\n hadLeadingSpace?: boolean;\r\n hadTrailingSpace?: boolean;\r\n }> = [];\r\n\r\n chunk.forEach((token) => {\r\n switch (token.type) {\r\n case \"text\": {\r\n const raw = token.content;\r\n const hadLeadingSpace = /^\\s/.test(raw);\r\n const hadTrailingSpace = /\\s$/.test(raw);\r\n\r\n const words = raw\r\n .trim()\r\n .split(/\\s+/)\r\n .filter((w) => w.length > 0);\r\n\r\n words.forEach((word, wIdx) => {\r\n const span = document.createElement(\"span\");\r\n span.style.display = \"inline-block\";\r\n span.textContent = word;\r\n wrapper.appendChild(span);\r\n\r\n if (wIdx < words.length - 1 || hadTrailingSpace) {\r\n wrapper.appendChild(document.createTextNode(\" \"));\r\n }\r\n\r\n wordSpans.push(span);\r\n tokenInfo.push({\r\n token: {\r\n type: \"text\",\r\n id: \"\",\r\n node: token.node,\r\n content: word,\r\n meta: {\r\n ...(token.meta || {}),\r\n joinPrev:\r\n wIdx === 0\r\n ? !hadLeadingSpace && !lastTokenWasSpace && prevMeasuredWasText\r\n : false,\r\n },\r\n },\r\n wordIndex: wordSpans.length - 1,\r\n hadLeadingSpace,\r\n hadTrailingSpace,\r\n });\r\n });\r\n\r\n lastTokenWasSpace = hadTrailingSpace;\r\n prevMeasuredWasText = true;\r\n break;\r\n }\r\n\r\n case \"element\": {\r\n const node = token.node.cloneNode(true);\r\n const span = document.createElement(\"span\");\r\n span.style.display = \"inline-block\";\r\n span.appendChild(node);\r\n wrapper.appendChild(span);\r\n wordSpans.push(span);\r\n tokenInfo.push({ token, wordIndex: wordSpans.length - 1 });\r\n isAfterElement = true;\r\n prevMeasuredWasText = false;\r\n lastTokenWasSpace = false;\r\n break;\r\n }\r\n\r\n case \"space\":\r\n lastTokenWasSpace = true;\r\n break;\r\n\r\n case \"other\":\r\n prevMeasuredWasText = false;\r\n lastTokenWasSpace = false;\r\n break;\r\n }\r\n });\r\n\r\n wrapper.offsetHeight;\r\n\r\n tokenInfo.forEach((info, idx) => {\r\n if (info.wordIndex !== undefined) {\r\n const span = wordSpans[info.wordIndex];\r\n const domRect = span.getBoundingClientRect();\r\n\r\n let rect: DOMRect;\r\n if (info.token.type === \"text\") {\r\n const accurateWidth = fontMetrics.measureWord(info.token.content);\r\n rect = new DOMRect(domRect.x, domRect.y, accurateWidth, domRect.height);\r\n } else {\r\n rect = domRect;\r\n }\r\n\r\n const measuredToken: MeasuredToken = {\r\n token: info.token,\r\n rect: rect,\r\n };\r\n\r\n if (isAfterElement && info.token.type === \"text\") {\r\n isAfterElement = false;\r\n measuredToken.token.meta = {\r\n ...(measuredToken.token.meta || {}),\r\n isAfterElement: true,\r\n };\r\n }\r\n\r\n measured.push(measuredToken);\r\n\r\n if (info.token.type === \"element\") {\r\n const prev = measured[measured.length - 2];\r\n if (prev?.token.type === \"text\") {\r\n prev.token.meta = { ...(prev.token.meta || {}), isBeforeElement: true };\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n container.removeChild(wrapper);\r\n return measured;\r\n}\r\n","import { MeasuredToken } from \"./LayoutMeasurer\";\r\nimport { Token } from \"./BuildTokens\";\r\nimport { FontMetrics } from \"./CanvasKerningApplier\";\r\n\r\nexport type ProcessedChar = {\r\n char: string;\r\n rect: DOMRect;\r\n token: Token;\r\n charIndexGlobal: number;\r\n charIndexInLine: number;\r\n charIndexInWord: number;\r\n isBeforeElement?: boolean;\r\n isAfterElement?: boolean;\r\n};\r\n\r\nexport type ProcessedWord = {\r\n chars: ProcessedChar[];\r\n rect: DOMRect;\r\n wordIndexGlobal: number;\r\n wordIndexInLine: number;\r\n isBeforeElement?: boolean;\r\n isAfterElement?: boolean;\r\n};\r\n\r\nexport type LayoutLine = {\r\n words: ProcessedWord[];\r\n rect: DOMRect;\r\n lineIndex: number;\r\n isBeforeElement?: boolean;\r\n isAfterElement?: boolean;\r\n};\r\n\r\nconst LINE_TOLERANCE = 5;\r\n\r\nexport function SplitMeasuredTokens(\r\n measured: MeasuredToken[],\r\n container: HTMLElement,\r\n fontMetrics: FontMetrics\r\n): LayoutLine[] {\r\n const lines: LayoutLine[] = [];\r\n let currentLine: LayoutLine | null = null;\r\n let y = 0;\r\n\r\n let charIndexGlobal = 0;\r\n let wordIndexGlobal = 0;\r\n\r\n measured.forEach((mt) => {\r\n const token = mt.token;\r\n const isBefore = token.meta?.isBeforeElement ?? false;\r\n const isAfter = token.meta?.isAfterElement ?? false;\r\n\r\n if (token.type === \"br\") {\r\n currentLine = null;\r\n return;\r\n }\r\n\r\n if (token.type === \"text\") {\r\n const wordText = token.content;\r\n const splitClass: string[] = (token.meta?.splitClass as string[]) ?? [];\r\n const joinPrev = !!token.meta?.joinPrev;\r\n\r\n const chars: ProcessedChar[] = [];\r\n let currentXInWord = 0;\r\n\r\n for (let i = 0; i < wordText.length; i++) {\r\n const ch = wordText[i];\r\n const prev = i > 0 ? wordText[i - 1] : null;\r\n\r\n const charWidth = fontMetrics.getCharWidth(ch);\r\n const kerning = prev ? fontMetrics.getKerning(prev, ch) : 0;\r\n\r\n currentXInWord += kerning;\r\n\r\n const charRect = new DOMRect(\r\n mt.rect.left + currentXInWord,\r\n mt.rect.top,\r\n charWidth,\r\n mt.rect.height\r\n );\r\n\r\n const pc: ProcessedChar = {\r\n char: ch,\r\n rect: charRect,\r\n token,\r\n charIndexInWord: i,\r\n charIndexInLine: 0,\r\n charIndexGlobal: charIndexGlobal++,\r\n };\r\n\r\n if (splitClass.length) (pc as any).splitClass = splitClass;\r\n\r\n chars.push(pc);\r\n currentXInWord += charWidth;\r\n }\r\n\r\n if (chars.length > 0) {\r\n const lastChar = chars[chars.length - 1];\r\n if (isBefore) lastChar.isBeforeElement = true;\r\n if (isAfter) lastChar.isAfterElement = true;\r\n }\r\n\r\n const currentY = Math.round(mt.rect.top);\r\n const baselineY = Math.round(y);\r\n const isNewLine = !currentLine || Math.abs(currentY - baselineY) > LINE_TOLERANCE;\r\n if (isNewLine) {\r\n y = currentY;\r\n currentLine = { words: [], rect: mt.rect, lineIndex: lines.length };\r\n lines.push(currentLine);\r\n }\r\n if (!currentLine) return;\r\n\r\n if (joinPrev && currentLine.words.length > 0) {\r\n const target = currentLine.words[currentLine.words.length - 1];\r\n\r\n const charsBeforeAll = currentLine.words.reduce((acc, w) => acc + w.chars.length, 0);\r\n const baseInWord = target.chars.length;\r\n\r\n chars.forEach((c, i) => {\r\n c.charIndexInLine = charsBeforeAll + i;\r\n c.charIndexInWord = baseInWord + i;\r\n });\r\n\r\n target.chars.push(...chars);\r\n target.rect = mergeRects([target.rect, mt.rect]);\r\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\r\n if (isBefore) target.isBeforeElement = true;\r\n if (isAfter) target.isAfterElement = true;\r\n return;\r\n }\r\n\r\n const wordIndexInLine = currentLine.words.length;\r\n const charsBefore = currentLine.words.reduce((acc, w) => acc + w.chars.length, 0);\r\n chars.forEach((c, i) => (c.charIndexInLine = charsBefore + i));\r\n\r\n const processedWord: ProcessedWord = {\r\n chars,\r\n rect: mt.rect,\r\n wordIndexGlobal: wordIndexGlobal++,\r\n wordIndexInLine,\r\n isBeforeElement: isBefore,\r\n isAfterElement: isAfter,\r\n };\r\n\r\n currentLine.words.push(processedWord);\r\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\r\n if (isBefore) currentLine.isBeforeElement = true;\r\n if (isAfter) currentLine.isAfterElement = true;\r\n return;\r\n }\r\n\r\n if (token.type === \"element\") {\r\n const rect = mt.rect;\r\n const currentY = Math.round(rect.top);\r\n const baselineY = Math.round(y);\r\n const isNewLine = !currentLine || Math.abs(currentY - baselineY) > LINE_TOLERANCE;\r\n\r\n if (isNewLine) {\r\n y = currentY;\r\n currentLine = { words: [], rect, lineIndex: lines.length };\r\n lines.push(currentLine);\r\n }\r\n if (!currentLine) return;\r\n\r\n const wordIndexInLine = currentLine.words.length;\r\n const charsBefore = currentLine.words.reduce((acc, w) => acc + w.chars.length, 0);\r\n\r\n const chars: ProcessedChar[] = [\r\n {\r\n char: \"[E]\",\r\n rect,\r\n token,\r\n charIndexInWord: 0,\r\n charIndexInLine: charsBefore,\r\n charIndexGlobal: charIndexGlobal++,\r\n },\r\n ];\r\n\r\n const processedWord: ProcessedWord = {\r\n chars,\r\n rect,\r\n wordIndexGlobal: wordIndexGlobal++,\r\n wordIndexInLine,\r\n isBeforeElement: false,\r\n isAfterElement: false,\r\n };\r\n\r\n currentLine.words.push(processedWord);\r\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\r\n }\r\n });\r\n\r\n return lines;\r\n}\r\n\r\nfunction mergeRects(rects: DOMRect[]): DOMRect {\r\n if (rects.length === 0) return new DOMRect(0, 0, 0, 0);\r\n const left = Math.min(...rects.map((r) => r.left));\r\n const top = Math.min(...rects.map((r) => r.top));\r\n const right = Math.max(...rects.map((r) => r.right));\r\n const bottom = Math.max(...rects.map((r) => r.bottom));\r\n return new DOMRect(left, top, right - left, bottom - top);\r\n}\r\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 { FontMetrics } from \"../../utils/text/CanvasKerningApplier\";\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 this.permissions.mobile.rebuild.height = false;\r\n this.permissions.mobile.rebuild.width = false;\r\n //this.permissions.mobile.rebuild.scrollHeight = false;\r\n }\r\n\r\n onResizeWidth(): 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\") ?? element.getAttribute(\"data-string-split\") ?? \"\";\r\n const options: ISplitOptions = this.tools.optionsParser.process({\r\n attributeValue: attr,\r\n });\r\n const { fragment, result, extraProps } = this.split(element, options);\r\n object.setProperty(\"nodes\", fragment.childNodes);\r\n element.setAttribute(\"aria-label\", originalHtml);\r\n element.innerHTML = \"\";\r\n element.appendChild(result);\r\n\r\n extraProps.forEach((value: string, key: string) => {\r\n element.style.setProperty(key, value);\r\n });\r\n\r\n const restoreAfter = element.getAttribute(\"string-split-restore-after\");\r\n if (restoreAfter && !isNaN(Number(restoreAfter))) {\r\n setTimeout(() => {\r\n element.innerHTML = originalHtml!;\r\n element.classList.add(\"-restored\");\r\n }, Number(restoreAfter));\r\n }\r\n }\r\n\r\n public split(element: HTMLElement, options: ISplitOptions) {\r\n const fontMetrics = new FontMetrics(element);\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, fontMetrics);\r\n const layoutLines: LayoutLine[] = SplitMeasuredTokens(measured, element, fontMetrics);\r\n this.applyCalculatedValues(layoutLines, options);\r\n const dom = BuildDOMTree(layoutLines, options, fontMetrics);\r\n return {\r\n fragment: frag,\r\n result: dom.fragment,\r\n extraProps: dom.extraProps,\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(opt: ISplitOptionItem, index: number, total: number): 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(lines: LayoutLine[], options: ISplitOptions): 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(opt, word.wordIndexInLine, line.words.length),\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(opt, char.charIndexGlobal, totalCharsGlobal),\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(opt, char.charIndexInWord, word.chars.length),\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(opt, char.charIndexInLine, totalCharsInLine),\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/** Attribute selector for FPS tracker elements */\r\nconst ATTR_FPS = \"data-fps\";\r\n\r\n/**\r\n * FPS Tracker Module.\r\n * Broadcasts frame rate to elements with `data-fps` attribute.\r\n * Also creates an optional debug display element.\r\n */\r\nexport class StringFPSTracker extends StringModule {\r\n private displayElement: HTMLDivElement | null = null;\r\n private intervalId: number = 0;\r\n private frameCount = 0;\r\n\r\n /** Cached elements with data-fps attribute */\r\n private fpsElements: Set<HTMLElement> = new Set();\r\n\r\n /** MutationObserver for DOM changes */\r\n private observer: MutationObserver | null = null;\r\n\r\n /** Last known FPS to avoid redundant updates */\r\n private lastFps = -1;\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, scans for elements, and starts interval.\r\n */\r\n onInit(): void {\r\n if (this.data.system.fpsTracker) {\r\n this.createDisplayElement();\r\n }\r\n\r\n // Listen for visibility toggle\r\n this.events.on(\"tracker:fps:visible\", this.onVisibilityChange.bind(this));\r\n\r\n this.scanElements();\r\n this.observeDOM();\r\n\r\n this.intervalId = window.setInterval(() => {\r\n this.updateFPS(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, observer, and interval.\r\n */\r\n destroy(): void {\r\n clearInterval(this.intervalId);\r\n this.observer?.disconnect();\r\n this.removeDisplayElement();\r\n this.fpsElements.clear();\r\n }\r\n\r\n /**\r\n * Handles visibility toggle from external API.\r\n */\r\n private onVisibilityChange(visible: boolean): void {\r\n if (visible) {\r\n this.createDisplayElement();\r\n } else {\r\n this.removeDisplayElement();\r\n }\r\n }\r\n\r\n /**\r\n * Removes the display element and its styles.\r\n */\r\n private removeDisplayElement(): void {\r\n this.displayElement?.remove();\r\n this.displayElement = null;\r\n }\r\n\r\n /**\r\n * Updates all tracked elements with current FPS.\r\n */\r\n private updateFPS(fps: number): void {\r\n if (fps === this.lastFps) return;\r\n this.lastFps = fps;\r\n\r\n const fpsStr = String(fps);\r\n\r\n // Update cached elements\r\n for (const el of this.fpsElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_FPS, fpsStr);\r\n }\r\n }\r\n\r\n // Update debug display\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_FPS, fpsStr);\r\n }\r\n\r\n this.events.emit(\"fps\", fps);\r\n }\r\n\r\n /**\r\n * Scans document for elements with data-fps attribute.\r\n */\r\n private scanElements(): void {\r\n this.fpsElements.clear();\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_FPS}]`).forEach((el) => {\r\n if (el !== this.displayElement) {\r\n this.fpsElements.add(el);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Observes DOM for added/removed elements with data-fps attribute.\r\n */\r\n private observeDOM(): void {\r\n this.observer = new MutationObserver((mutations) => {\r\n let needsRescan = false;\r\n\r\n for (const mutation of mutations) {\r\n // Check added nodes\r\n for (const node of mutation.addedNodes) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n if (el.hasAttribute(ATTR_FPS)) needsRescan = true;\r\n if (el.querySelector(`[${ATTR_FPS}]`)) needsRescan = true;\r\n }\r\n }\r\n\r\n // Check removed nodes - clean from cache\r\n for (const node of mutation.removedNodes) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n this.fpsElements.delete(node as HTMLElement);\r\n }\r\n }\r\n }\r\n\r\n if (needsRescan) {\r\n this.scanElements();\r\n }\r\n });\r\n\r\n this.observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Creates and styles the floating FPS display.\r\n */\r\n private createDisplayElement(): void {\r\n if (this.displayElement) return;\r\n\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.setAttribute(ATTR_FPS, \"0\");\r\n document.body.appendChild(el);\r\n\r\n // Inject dynamic CSS\r\n const styleId = \"string-fps-tracker-style\";\r\n if (!document.getElementById(styleId)) {\r\n const style = document.createElement(\"style\");\r\n style.id = styleId;\r\n style.innerHTML = `\r\n [${ATTR_FPS}]::before {\r\n content: 'FPS: ' attr(${ATTR_FPS});\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n }\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/** Attribute selectors for position tracker elements */\r\nconst ATTR_VAL = \"data-val\";\r\nconst ATTR_VAL_PCT = \"data-val-pct\";\r\nconst ATTR_DIR = \"data-dir\";\r\n\r\n/**\r\n * Tracker module that broadcasts scroll position to elements with data attributes.\r\n * Elements with `data-val`, `data-val-pct`, or `data-dir` will receive updates.\r\n * Also creates an optional debug display element.\r\n */\r\nexport class StringPositionTracker extends StringModule {\r\n private displayElement: HTMLDivElement | null = null;\r\n\r\n /** Cached elements by attribute type */\r\n private valElements: Set<HTMLElement> = new Set();\r\n private valPctElements: Set<HTMLElement> = new Set();\r\n private dirElements: Set<HTMLElement> = new Set();\r\n\r\n /** MutationObserver for DOM changes */\r\n private observer: MutationObserver | null = null;\r\n\r\n /** Last known values to avoid redundant updates */\r\n private lastVal = -1;\r\n private lastValPct = -1;\r\n private lastDir = \"\";\r\n\r\n /** Previous scroll position for direction detection */\r\n private previousCurrent = 0;\r\n\r\n /** Timeout for resetting direction to idle state */\r\n private idleTimeout: ReturnType<typeof setTimeout> | null = null;\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 debug element and scans for tracked elements.\r\n */\r\n onInit(): void {\r\n if (this.data.system.positionTracker) {\r\n this.createDisplayElement();\r\n }\r\n\r\n // Listen for visibility toggle\r\n this.events.on(\"tracker:position:visible\", this.onVisibilityChange.bind(this));\r\n\r\n this.scanElements();\r\n this.observeDOM();\r\n }\r\n\r\n /**\r\n * Called on scroll — updates all tracked elements with position data.\r\n */\r\n onScroll(data: StringData): void {\r\n const current = data.scroll.current;\r\n const target = data.scroll.target;\r\n const contentHeight = data.viewport.contentHeight;\r\n const windowHeight = data.viewport.windowHeight;\r\n\r\n const val = Math.round(current);\r\n const maxScroll = Math.max(1, contentHeight - windowHeight);\r\n const valPct = Math.round((current / maxScroll) * 100);\r\n\r\n // Determine scroll direction\r\n let direction: string;\r\n if (current !== target) {\r\n // Smooth scroll: compare current vs target (lerping)\r\n direction = current < target ? \"↓\" : \"↑\";\r\n } else if (current !== this.previousCurrent) {\r\n // Default scroll: compare with previous position\r\n direction = current > this.previousCurrent ? \"↓\" : \"↑\";\r\n } else {\r\n // No movement\r\n direction = this.lastDir || \"•\";\r\n }\r\n\r\n this.previousCurrent = current;\r\n\r\n // Reset idle timeout - will set direction to neutral after scroll stops\r\n if (this.idleTimeout) {\r\n clearTimeout(this.idleTimeout);\r\n }\r\n if (direction !== \"•\") {\r\n this.idleTimeout = setTimeout(() => {\r\n this.setDirection(\"•\");\r\n }, 150);\r\n }\r\n\r\n // Update data-val elements\r\n if (val !== this.lastVal) {\r\n this.lastVal = val;\r\n const valStr = String(val);\r\n for (const el of this.valElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_VAL, valStr);\r\n }\r\n }\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_VAL, valStr);\r\n }\r\n }\r\n\r\n // Update data-val-pct elements\r\n if (valPct !== this.lastValPct) {\r\n this.lastValPct = valPct;\r\n const pctStr = String(valPct);\r\n for (const el of this.valPctElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_VAL_PCT, pctStr);\r\n }\r\n }\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_VAL_PCT, pctStr);\r\n }\r\n }\r\n\r\n // Update data-dir elements\r\n this.setDirection(direction);\r\n\r\n this.events.emit(\"scroll-position\", { val, valPct, direction });\r\n }\r\n\r\n /**\r\n * Updates direction on all tracked elements.\r\n */\r\n private setDirection(direction: string): void {\r\n if (direction === this.lastDir) return;\r\n this.lastDir = direction;\r\n\r\n for (const el of this.dirElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_DIR, direction);\r\n }\r\n }\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_DIR, direction);\r\n }\r\n }\r\n\r\n /**\r\n * Cleans up DOM observer and display element.\r\n */\r\n destroy(): void {\r\n if (this.idleTimeout) {\r\n clearTimeout(this.idleTimeout);\r\n }\r\n this.observer?.disconnect();\r\n this.removeDisplayElement();\r\n this.valElements.clear();\r\n this.valPctElements.clear();\r\n this.dirElements.clear();\r\n }\r\n\r\n /**\r\n * Handles visibility toggle from external API.\r\n */\r\n private onVisibilityChange(visible: boolean): void {\r\n if (visible) {\r\n this.createDisplayElement();\r\n } else {\r\n this.removeDisplayElement();\r\n }\r\n }\r\n\r\n /**\r\n * Removes the display element.\r\n */\r\n private removeDisplayElement(): void {\r\n this.displayElement?.remove();\r\n this.displayElement = null;\r\n }\r\n\r\n /**\r\n * Scans document for elements with tracking attributes.\r\n */\r\n private scanElements(): void {\r\n this.valElements.clear();\r\n this.valPctElements.clear();\r\n this.dirElements.clear();\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_VAL}]`).forEach((el) => {\r\n if (el !== this.displayElement) this.valElements.add(el);\r\n });\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_VAL_PCT}]`).forEach((el) => {\r\n if (el !== this.displayElement) this.valPctElements.add(el);\r\n });\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_DIR}]`).forEach((el) => {\r\n if (el !== this.displayElement) this.dirElements.add(el);\r\n });\r\n }\r\n\r\n /**\r\n * Observes DOM for added/removed elements with tracking attributes.\r\n */\r\n private observeDOM(): void {\r\n this.observer = new MutationObserver((mutations) => {\r\n let needsRescan = false;\r\n\r\n for (const mutation of mutations) {\r\n // Check added nodes\r\n for (const node of mutation.addedNodes) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n if (this.hasTrackingAttr(el)) needsRescan = true;\r\n // Check descendants\r\n if (el.querySelector(`[${ATTR_VAL}],[${ATTR_VAL_PCT}],[${ATTR_DIR}]`)) {\r\n needsRescan = true;\r\n }\r\n }\r\n }\r\n\r\n // Check removed nodes - clean from cache\r\n for (const node of mutation.removedNodes) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n this.valElements.delete(el);\r\n this.valPctElements.delete(el);\r\n this.dirElements.delete(el);\r\n }\r\n }\r\n }\r\n\r\n if (needsRescan) {\r\n this.scanElements();\r\n }\r\n });\r\n\r\n this.observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Checks if element has any tracking attribute.\r\n */\r\n private hasTrackingAttr(el: HTMLElement): boolean {\r\n return el.hasAttribute(ATTR_VAL) || el.hasAttribute(ATTR_VAL_PCT) || el.hasAttribute(ATTR_DIR);\r\n }\r\n\r\n /**\r\n * Creates and styles the floating position indicator.\r\n */\r\n private createDisplayElement(): void {\r\n if (this.displayElement) return;\r\n\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(ATTR_DIR, \"•\");\r\n el.setAttribute(ATTR_VAL, \"0\");\r\n el.setAttribute(ATTR_VAL_PCT, \"0\");\r\n document.body.appendChild(el);\r\n\r\n // Inject dynamic CSS\r\n const styleId = \"string-position-tracker-style\";\r\n if (!document.getElementById(styleId)) {\r\n const style = document.createElement(\"style\");\r\n style.id = styleId;\r\n style.innerHTML = `\r\n [${ATTR_DIR}][${ATTR_VAL}][${ATTR_VAL_PCT}]::before {\r\n content: attr(${ATTR_DIR}) ' | ' attr(${ATTR_VAL}) 'px (' attr(${ATTR_VAL_PCT}) '%)';\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n }\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","/**\r\n * Discrete state classes applied to sequence elements.\r\n */\r\nexport enum SequenceState {\r\n ACTIVE = \"-active\",\r\n ENTERING = \"-entering\",\r\n LEAVING = \"-leaving\",\r\n DISABLED = \"-disabled\",\r\n}\r\n\r\n/**\r\n * Event data for sequence transitions.\r\n */\r\nexport interface SequenceEventData {\r\n /** Slider identifier */\r\n slider: string;\r\n /** Current step index */\r\n step: number;\r\n /** Transition progress from 0 to 1 (optional, for manual scrubbing) */\r\n transitionProgress?: number;\r\n /** Direction of transition: 1 = forward, -1 = backward */\r\n direction?: 1 | -1;\r\n /** Custom duration for this transition in ms (overrides element's sequence-duration) */\r\n duration?: number;\r\n /** Skip animation and switch instantly */\r\n instant?: boolean;\r\n}\r\n\r\n/**\r\n * CSS custom property names for sequence.\r\n */\r\nexport const SequenceProgressVars = {\r\n /** Unified progress variable (0 to 1) */\r\n PROGRESS: \"--sequence-progress\",\r\n /** Direction of current transition (1 or -1) */\r\n DIRECTION: \"--sequence-direction\",\r\n} as const;\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport {\r\n SequenceState,\r\n SequenceEventData,\r\n SequenceProgressVars,\r\n} from \"../../models/slider/SequenceState\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EasingFunctionOutput } from \"../../tools/EasingFunctionTool\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\ninterface TransitionState {\r\n fromStep: number;\r\n toStep: number;\r\n direction: 1 | -1;\r\n startTime: number;\r\n enteringDuration: number;\r\n leavingDuration: number;\r\n}\r\n\r\ninterface StepElements {\r\n objects: StringObject[];\r\n enteringDuration: number;\r\n leavingDuration: number;\r\n}\r\n\r\ninterface TriggerData {\r\n slider: string;\r\n step: number | \"next\" | \"prev\";\r\n loop: boolean;\r\n}\r\n\r\ninterface GlobalSliderSettings {\r\n enteringDuration?: number;\r\n leavingDuration?: number;\r\n enteringEasing?: string;\r\n leavingEasing?: string;\r\n activeStep?: number;\r\n}\r\n\r\ntype DurationKey = \"enteringDuration\" | \"leavingDuration\";\r\ntype EasingKey = \"enteringEasing\" | \"leavingEasing\";\r\n\r\nexport class StringSequence extends StringModule {\r\n private activeStep = new Map<string, number>();\r\n private leavingStep = new Map<string, number>();\r\n private transitions = new Map<string, TransitionState>();\r\n private elementIndex = new Map<string, StepElements>();\r\n private triggerElements = new Map<HTMLElement, TriggerData>();\r\n private globalSettings = new Map<string, GlobalSliderSettings>();\r\n private defaultDuration: number;\r\n private initialized = false;\r\n private static readonly ALL_STATES = Object.values(SequenceState);\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"sequence\";\r\n this.defaultDuration = this.settings[\"sequence-duration\"] ?? 600;\r\n\r\n this.attributesToMap = [\r\n ...this.attributesToMap,\r\n { key: \"sequence\", type: \"string\", fallback: \"\" },\r\n { key: \"sequence-trigger\", type: \"string\", fallback: \"\" },\r\n { key: \"entering-easing\", type: \"string\", fallback: \"\" },\r\n { key: \"leaving-easing\", type: \"string\", fallback: \"\" },\r\n { key: \"entering-duration\", type: \"string\", fallback: \"\" },\r\n { key: \"leaving-duration\", type: \"string\", fallback: \"\" },\r\n { key: \"sequence-duration\", type: \"string\", fallback: \"\" },\r\n { key: \"active-step\", type: \"string\", fallback: \"\" },\r\n ];\r\n }\r\n\r\n onInit(): void {\r\n super.onInit();\r\n this.events.on<SequenceEventData>(\"sequence\", this.onSequenceEvent.bind(this));\r\n this.scanStandaloneTriggers();\r\n }\r\n\r\n private scanStandaloneTriggers(): void {\r\n const els = document.querySelectorAll<HTMLElement>(\r\n \"[string-sequence-trigger]:not([string-inited])\"\r\n );\r\n for (const el of els) {\r\n const trigger = el.getAttribute(\"string-sequence-trigger\");\r\n const parsed = trigger ? this.parseTriggerKey(trigger) : null;\r\n if (parsed) {\r\n this.triggerElements.set(el, parsed);\r\n el.addEventListener(\"click\", this.onTriggerClick);\r\n }\r\n }\r\n }\r\n\r\n private parseGlobalSettingsFromObject(object: StringObject): void {\r\n const get = (k: string) => object.getProperty<string>(k);\r\n const seq = get(\"sequence-duration\");\r\n\r\n this.tryParseGlobalSetting(seq, \"enteringDuration\");\r\n this.tryParseGlobalSetting(seq, \"leavingDuration\");\r\n this.tryParseGlobalSetting(get(\"entering-duration\"), \"enteringDuration\");\r\n this.tryParseGlobalSetting(get(\"leaving-duration\"), \"leavingDuration\");\r\n this.tryParseGlobalSetting(get(\"entering-easing\"), \"enteringEasing\");\r\n this.tryParseGlobalSetting(get(\"leaving-easing\"), \"leavingEasing\");\r\n this.tryParseGlobalSetting(get(\"active-step\"), \"activeStep\");\r\n }\r\n\r\n private tryParseGlobalSetting(attr: string | null, key: keyof GlobalSliderSettings): void {\r\n if (!attr) return;\r\n const match = attr.match(/^(.+)\\[(.+)\\]$/);\r\n if (!match) return;\r\n\r\n const [, slider, value] = match;\r\n const settings = this.globalSettings.get(slider) ?? {};\r\n this.globalSettings.set(slider, settings);\r\n\r\n (settings as Record<string, string | number>)[key] =\r\n key === \"enteringEasing\" || key === \"leavingEasing\" ? value : parseFloat(value);\r\n\r\n this.applyGlobalSettingsToExistingObjects(slider);\r\n }\r\n\r\n private applyGlobalSettingsToExistingObjects(slider: string): void {\r\n const global = this.globalSettings.get(slider);\r\n if (!global) return;\r\n\r\n for (const [key, group] of this.elementIndex) {\r\n const parsed = this.parseSequenceKey(key);\r\n if (parsed?.slider !== slider) continue;\r\n\r\n if (global.enteringDuration !== undefined) group.enteringDuration = global.enteringDuration;\r\n if (global.leavingDuration !== undefined) group.leavingDuration = global.leavingDuration;\r\n\r\n for (const obj of group.objects) this.resolveEasings(obj, key);\r\n }\r\n }\r\n\r\n private initializeSliders(): void {\r\n const sliders = new Set<string>();\r\n for (const key of this.elementIndex.keys()) {\r\n const p = this.parseSequenceKey(key);\r\n if (p) sliders.add(p.slider);\r\n }\r\n\r\n for (const slider of sliders) {\r\n if (this.activeStep.has(slider)) continue;\r\n const global = this.globalSettings.get(slider);\r\n let step = global?.activeStep ?? 0;\r\n if (!this.elementIndex.has(`${slider}[${step}]`)) step = 0;\r\n this.switchInstant(slider, step, 1);\r\n }\r\n }\r\n\r\n private tryApplyPendingActiveStep(slider: string): void {\r\n if (this.activeStep.has(slider)) return;\r\n const step = this.globalSettings.get(slider)?.activeStep;\r\n if (step !== undefined && this.elementIndex.has(`${slider}[${step}]`)) {\r\n this.switchInstant(slider, step, 1);\r\n }\r\n }\r\n\r\n override canConnect(object: StringObject): boolean {\r\n return object.keys.includes(\"sequence\") || object.keys.includes(\"sequence-trigger\");\r\n }\r\n\r\n override onObjectConnected(object: StringObject): void {\r\n super.onObjectConnected(object);\r\n this.parseGlobalSettingsFromObject(object);\r\n\r\n let sequence = object.getProperty<string>(\"sequence\");\r\n const trigger = object.getProperty<string>(\"sequence-trigger\");\r\n\r\n if (!sequence && trigger) {\r\n const p = this.parseTriggerKey(trigger);\r\n if (p && typeof p.step === \"number\") {\r\n sequence = `${p.slider}[${p.step}]`;\r\n object.setProperty(\"sequence\", sequence);\r\n }\r\n }\r\n\r\n if (sequence) {\r\n const parsed = this.parseSequenceKey(sequence);\r\n if (parsed) {\r\n let group = this.elementIndex.get(sequence);\r\n if (!group) {\r\n const { enteringDuration, leavingDuration } = this.resolveDurations(object, sequence);\r\n group = { objects: [], enteringDuration, leavingDuration };\r\n this.elementIndex.set(sequence, group);\r\n }\r\n group.objects.push(object);\r\n this.resolveEasings(object, sequence);\r\n\r\n const active = this.activeStep.get(parsed.slider);\r\n this.setState(\r\n object,\r\n active === parsed.step ? SequenceState.ACTIVE : SequenceState.DISABLED,\r\n active === parsed.step ? 1 : 0,\r\n 1\r\n );\r\n this.tryApplyPendingActiveStep(parsed.slider);\r\n }\r\n }\r\n\r\n if (trigger) {\r\n const p = this.parseTriggerKey(trigger);\r\n if (p) {\r\n this.triggerElements.set(object.htmlElement, p);\r\n object.htmlElement.addEventListener(\"click\", this.onTriggerClick);\r\n }\r\n }\r\n }\r\n\r\n private parseTriggerKey(key: string): TriggerData | null {\r\n const m = key.match(/^(.+)\\[(next|prev|\\d+)(\\|loop)?\\]$/);\r\n if (!m) return null;\r\n const step = m[2] === \"next\" || m[2] === \"prev\" ? m[2] : parseInt(m[2], 10);\r\n return { slider: m[1], step, loop: m[3] === \"|loop\" };\r\n }\r\n\r\n private getMaxStep(slider: string): number {\r\n let max = -1;\r\n for (const key of this.elementIndex.keys()) {\r\n const p = this.parseSequenceKey(key);\r\n if (p?.slider === slider && p.step > max) max = p.step;\r\n }\r\n return max;\r\n }\r\n\r\n private resolveDuration(\r\n object: StringObject,\r\n slider: string,\r\n key: DurationKey,\r\n attrKey: string\r\n ): number {\r\n const attr = object.getProperty<string>(attrKey);\r\n const seqAttr = object.getProperty<string>(\"sequence-duration\");\r\n const global = this.globalSettings.get(slider)?.[key];\r\n\r\n if (attr && !attr.includes(\"[\")) {\r\n const v = parseFloat(attr);\r\n if (!isNaN(v)) return v;\r\n }\r\n if (seqAttr && !seqAttr.includes(\"[\")) {\r\n const v = parseFloat(seqAttr);\r\n if (!isNaN(v)) return v;\r\n }\r\n return global ?? this.defaultDuration;\r\n }\r\n\r\n private resolveDurations(object: StringObject, sequence: string) {\r\n const slider = this.parseSequenceKey(sequence)?.slider ?? \"\";\r\n return {\r\n enteringDuration: this.resolveDuration(\r\n object,\r\n slider,\r\n \"enteringDuration\",\r\n \"entering-duration\"\r\n ),\r\n leavingDuration: this.resolveDuration(object, slider, \"leavingDuration\", \"leaving-duration\"),\r\n };\r\n }\r\n\r\n private resolveEasing(\r\n object: StringObject,\r\n slider: string,\r\n key: EasingKey,\r\n attrKey: string\r\n ): void {\r\n let easing = object.getProperty<string | EasingFunctionOutput>(attrKey);\r\n if (!easing || (typeof easing === \"string\" && easing.includes(\"[\"))) {\r\n easing = this.globalSettings.get(slider)?.[key] ?? this.settings[\"easing\"] ?? \"ease-out\";\r\n }\r\n if (typeof easing === \"string\") {\r\n object.setProperty(attrKey, this.tools.easingFunction.process({ easing }));\r\n }\r\n }\r\n\r\n private resolveEasings(object: StringObject, sequence: string): void {\r\n const slider = this.parseSequenceKey(sequence)?.slider;\r\n if (!slider) return;\r\n this.resolveEasing(object, slider, \"enteringEasing\", \"entering-easing\");\r\n this.resolveEasing(object, slider, \"leavingEasing\", \"leaving-easing\");\r\n }\r\n\r\n override onObjectDisconnected(object: StringObject): void {\r\n super.onObjectDisconnected(object);\r\n\r\n const sequence = object.getProperty<string>(\"sequence\");\r\n if (sequence) {\r\n const group = this.elementIndex.get(sequence);\r\n if (group) {\r\n const idx = group.objects.indexOf(object);\r\n if (idx !== -1) group.objects.splice(idx, 1);\r\n if (!group.objects.length) this.elementIndex.delete(sequence);\r\n }\r\n }\r\n\r\n if (this.triggerElements.has(object.htmlElement)) {\r\n object.htmlElement.removeEventListener(\"click\", this.onTriggerClick);\r\n this.triggerElements.delete(object.htmlElement);\r\n }\r\n }\r\n\r\n private parseSequenceKey(key: string): { slider: string; step: number } | null {\r\n const m = key.match(/^(.+)\\[(\\d+)\\]$/);\r\n return m ? { slider: m[1], step: parseInt(m[2], 10) } : null;\r\n }\r\n\r\n private onTriggerClick = (e: Event): void => {\r\n const data = this.triggerElements.get(e.currentTarget as HTMLElement);\r\n if (!data) return;\r\n\r\n const current = this.activeStep.get(data.slider) ?? 0;\r\n const max = this.getMaxStep(data.slider);\r\n let target: number, dir: 1 | -1;\r\n\r\n if (data.step === \"next\") {\r\n target = current + 1;\r\n dir = 1;\r\n if (!this.elementIndex.has(`${data.slider}[${target}]`)) {\r\n if (data.loop && max >= 0) target = 0;\r\n else return;\r\n }\r\n } else if (data.step === \"prev\") {\r\n target = current - 1;\r\n dir = -1;\r\n if (target < 0) {\r\n if (data.loop && max >= 0) target = max;\r\n else return;\r\n }\r\n if (!this.elementIndex.has(`${data.slider}[${target}]`)) return;\r\n } else {\r\n target = data.step;\r\n if (current === target) return;\r\n dir = target > current ? 1 : -1;\r\n }\r\n\r\n this.startTransition(data.slider, target, dir);\r\n };\r\n\r\n private onSequenceEvent(data: SequenceEventData): void {\r\n const { slider, step, transitionProgress, direction = 1, duration, instant } = data;\r\n const current = this.activeStep.get(slider);\r\n\r\n if (current === step && transitionProgress === undefined) return;\r\n\r\n if (transitionProgress !== undefined) {\r\n this.handleScrub(slider, step, transitionProgress, direction);\r\n } else if (instant) {\r\n this.switchInstant(slider, step, direction);\r\n } else {\r\n this.startTransition(slider, step, direction, duration);\r\n }\r\n }\r\n\r\n private startTransition(\r\n slider: string,\r\n toStep: number,\r\n direction: 1 | -1,\r\n customDuration?: number\r\n ): void {\r\n const fromStep = this.activeStep.get(slider);\r\n const prevLeaving = this.leavingStep.get(slider);\r\n\r\n if (prevLeaving !== undefined && prevLeaving !== fromStep) {\r\n this.setStepState(slider, prevLeaving, SequenceState.DISABLED, 0, direction);\r\n }\r\n\r\n const enteringGroup = this.elementIndex.get(`${slider}[${toStep}]`);\r\n const leavingGroup =\r\n fromStep !== undefined ? this.elementIndex.get(`${slider}[${fromStep}]`) : null;\r\n\r\n if (fromStep !== undefined) this.leavingStep.set(slider, fromStep);\r\n this.activeStep.set(slider, toStep);\r\n\r\n this.transitions.set(slider, {\r\n fromStep: fromStep ?? toStep,\r\n toStep,\r\n direction,\r\n startTime: this.data.time.now,\r\n enteringDuration: customDuration ?? enteringGroup?.enteringDuration ?? this.defaultDuration,\r\n leavingDuration: customDuration ?? leavingGroup?.leavingDuration ?? this.defaultDuration,\r\n });\r\n }\r\n\r\n private handleScrub(slider: string, step: number, progress: number, direction: 1 | -1): void {\r\n this.transitions.delete(slider);\r\n const current = this.activeStep.get(slider);\r\n\r\n if (current !== step) {\r\n const prev = this.leavingStep.get(slider);\r\n if (prev !== undefined) this.setStepState(slider, prev, SequenceState.DISABLED, 0, direction);\r\n if (current !== undefined) this.leavingStep.set(slider, current);\r\n this.activeStep.set(slider, step);\r\n }\r\n\r\n this.applyProgress(slider, progress, progress, direction);\r\n }\r\n\r\n private switchInstant(slider: string, step: number, direction: 1 | -1): void {\r\n this.transitions.delete(slider);\r\n const current = this.activeStep.get(slider);\r\n const leaving = this.leavingStep.get(slider);\r\n\r\n if (leaving !== undefined)\r\n this.setStepState(slider, leaving, SequenceState.DISABLED, 0, direction);\r\n if (current !== undefined && current !== step)\r\n this.setStepState(slider, current, SequenceState.DISABLED, 0, direction);\r\n\r\n this.activeStep.set(slider, step);\r\n this.leavingStep.delete(slider);\r\n this.setStepState(slider, step, SequenceState.ACTIVE, 1, direction);\r\n }\r\n\r\n private applyProgress(\r\n slider: string,\r\n enteringProg: number,\r\n leavingProg: number,\r\n direction: 1 | -1\r\n ): void {\r\n const active = this.activeStep.get(slider)!;\r\n const leaving = this.leavingStep.get(slider);\r\n\r\n this.setStepState(\r\n slider,\r\n active,\r\n enteringProg >= 1 ? SequenceState.ACTIVE : SequenceState.ENTERING,\r\n enteringProg,\r\n direction\r\n );\r\n\r\n if (leaving !== undefined && leaving !== active) {\r\n if (leavingProg >= 1) {\r\n this.setStepState(slider, leaving, SequenceState.DISABLED, 0, direction);\r\n this.leavingStep.delete(slider);\r\n } else {\r\n this.setStepState(slider, leaving, SequenceState.LEAVING, leavingProg, direction);\r\n }\r\n }\r\n }\r\n\r\n private setStepState(\r\n slider: string,\r\n step: number,\r\n state: SequenceState,\r\n progress: number,\r\n direction: 1 | -1\r\n ): void {\r\n const group = this.elementIndex.get(`${slider}[${step}]`);\r\n if (group) for (const obj of group.objects) this.setState(obj, state, progress, direction);\r\n }\r\n\r\n private setState(\r\n object: StringObject,\r\n state: SequenceState,\r\n rawProgress: number,\r\n direction: 1 | -1\r\n ): void {\r\n const el = object.htmlElement;\r\n const currentState = object.getProperty<SequenceState>(\"_state\");\r\n const currentDir = object.getProperty<number>(\"_direction\");\r\n\r\n const easing = object.getProperty<EasingFunctionOutput>(\r\n state === SequenceState.LEAVING ? \"leaving-easing\" : \"entering-easing\"\r\n );\r\n const progress = typeof easing === \"function\" ? easing(rawProgress) : rawProgress;\r\n\r\n if (currentState !== state) {\r\n el.classList.remove(...StringSequence.ALL_STATES);\r\n el.classList.add(state);\r\n object.setProperty(\"_state\", state);\r\n }\r\n\r\n if (currentDir !== direction) {\r\n object.setProperty(\"_direction\", direction);\r\n styleTxn.run(() =>\r\n styleTxn.setVars(el, { [SequenceProgressVars.DIRECTION]: direction.toString() })\r\n );\r\n }\r\n }\r\n\r\n onFrame(data: StringData): void {\r\n super.onFrame(data);\r\n\r\n if (!this.initialized) {\r\n this.initialized = true;\r\n this.initializeSliders();\r\n }\r\n\r\n for (const [slider, t] of this.transitions) {\r\n const elapsed = data.time.now - t.startTime;\r\n const enteringProg = Math.min(1, elapsed / t.enteringDuration);\r\n const leavingProg = Math.min(1, elapsed / t.leavingDuration);\r\n\r\n this.applyProgress(slider, enteringProg, leavingProg, t.direction);\r\n\r\n if (enteringProg >= 1 && leavingProg >= 1) this.transitions.delete(slider);\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\nimport { RuleParserResult } from \"../../tools/RuleParserTool\";\r\nimport type { ValidationContext } from \"../../tools/ValidationTool\";\r\n\r\ntype FormField = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\r\n\r\ninterface RegisteredEvent {\r\n eventElement: EventTarget;\r\n eventType: string;\r\n eventCallback: EventListenerOrEventListenerObject;\r\n}\r\n\r\ninterface FieldEntry {\r\n field: FormField;\r\n key: string;\r\n rules: RuleParserResult[];\r\n supportsRealtime: boolean;\r\n needsContext: boolean;\r\n inputEventType: \"input\" | \"change\";\r\n inputHandler: EventListener;\r\n beforeInputHandler?: EventListener;\r\n}\r\n\r\ntype FormState = {\r\n object: StringObject;\r\n form: HTMLFormElement;\r\n entries: FieldEntry[];\r\n values: Record<string, any>;\r\n events: RegisteredEvent[];\r\n};\r\n\r\nexport class StringForm extends StringModule {\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"form\";\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\r\n const existingEvents = object.getProperty<Array<RegisteredEvent>>(\"form-events\") ?? [];\r\n existingEvents.forEach((evt) => {\r\n evt.eventElement.removeEventListener(evt.eventType, evt.eventCallback);\r\n });\r\n existingEvents.length = 0;\r\n object.setProperty(\"form-events\", existingEvents);\r\n\r\n super.onObjectConnected(object);\r\n const form = object.htmlElement as HTMLFormElement;\r\n\r\n const fieldEntries: FieldEntry[] = [];\r\n const fieldValues: Record<string, any> = {};\r\n\r\n this.getInteractiveFields(form).forEach((field, idx) =>\r\n this.registerField(field, form, fieldEntries, fieldValues, existingEvents, idx)\r\n );\r\n\r\n const submitCallback = (event: Event) => {\r\n event.preventDefault();\r\n let allValid = true;\r\n const data: Record<string, any> = {};\r\n const processedRadioKeys = new Set<string>();\r\n for (const entry of fieldEntries) {\r\n const field = entry.field;\r\n if (!field.isConnected || !this.shouldValidateField(field)) continue;\r\n if (this.isRadioField(field)) {\r\n if (processedRadioKeys.has(entry.key)) {\r\n continue;\r\n }\r\n processedRadioKeys.add(entry.key);\r\n }\r\n const { key, rules, needsContext } = entry;\r\n const value = this.getFieldValue(field);\r\n data[key] = value;\r\n fieldValues[key] = value;\r\n\r\n const { valid, errors } = this.tools.validation.process({\r\n rules,\r\n value,\r\n context: this.buildContext(needsContext, key, fieldValues),\r\n });\r\n\r\n this.applyValidationState(form, field, key, valid, errors, \"submit\");\r\n\r\n if (!valid) {\r\n allValid = false;\r\n }\r\n }\r\n\r\n if (allValid) {\r\n this.events.emit(`form:submit:${object.id}`, data);\r\n } else {\r\n const processedRadioKeys = new Set<string>();\r\n const firstInvalidEntry = fieldEntries.find((entry) => {\r\n const field = entry.field;\r\n if (!field.isConnected || !this.shouldValidateField(field)) return false;\r\n if (this.isRadioField(field)) {\r\n if (processedRadioKeys.has(entry.key)) {\r\n return false;\r\n }\r\n processedRadioKeys.add(entry.key);\r\n }\r\n const { key, rules, needsContext } = entry;\r\n const value = this.getFieldValue(field);\r\n fieldValues[key] = value;\r\n const { valid } = this.tools.validation.process({\r\n rules,\r\n value,\r\n context: this.buildContext(needsContext, key, fieldValues),\r\n });\r\n return !valid;\r\n });\r\n if (firstInvalidEntry?.field && typeof firstInvalidEntry.field.focus === \"function\") {\r\n firstInvalidEntry.field.focus();\r\n }\r\n this.events.emit(`form:invalid:${object.id}`);\r\n }\r\n };\r\n\r\n form.addEventListener(\"submit\", submitCallback);\r\n existingEvents.push({ eventElement: form, eventType: \"submit\", eventCallback: submitCallback });\r\n\r\n object.setProperty(\"form-field-entries\", fieldEntries);\r\n object.setProperty(\"form-field-values\", fieldValues);\r\n }\r\n\r\n onObjectConnected(object: StringObject) {}\r\n\r\n onDOMMutate(added: NodeList, removed: NodeList): void {\r\n if (this.objects.length === 0) {\r\n return;\r\n }\r\n\r\n if (added.length > 0) {\r\n this.handleMutationAdditions(added);\r\n }\r\n\r\n if (removed.length > 0) {\r\n this.handleMutationRemovals(removed);\r\n }\r\n }\r\n\r\n private applyValidationState(\r\n form: HTMLFormElement,\r\n field: FormField,\r\n key: string,\r\n valid: boolean,\r\n errors: string[],\r\n phase: \"live\" | \"submit\"\r\n ): void {\r\n const errorBlock = form.querySelector(`[string-input=\"error[${key}]\"]`);\r\n const groupBlock = form.querySelector(`[string-input=\"group[${key}]\"]`);\r\n if (errorBlock) {\r\n errorBlock.innerHTML = \"\";\r\n errors.forEach((message) => {\r\n const span = document.createElement(\"span\");\r\n span.textContent = message;\r\n errorBlock.appendChild(span);\r\n });\r\n }\r\n if (phase === \"live\") {\r\n field.classList.toggle(\"-invalid\", !valid);\r\n field.classList.remove(\"-error\");\r\n } else {\r\n field.classList.remove(\"-invalid\");\r\n field.classList.toggle(\"-error\", !valid);\r\n }\r\n field.classList.toggle(\"-valid\", valid);\r\n if (groupBlock) {\r\n if (phase === \"live\") {\r\n groupBlock.classList.toggle(\"-invalid\", !valid);\r\n groupBlock.classList.remove(\"-error\");\r\n } else {\r\n groupBlock.classList.remove(\"-invalid\");\r\n groupBlock.classList.toggle(\"-error\", !valid);\r\n }\r\n groupBlock.classList.toggle(\"-valid\", valid);\r\n }\r\n\r\n const eventSuffix = valid ? \"valid\" : phase === \"live\" ? \"invalid\" : \"error\";\r\n this.events.emit(`form:field:${eventSuffix}:${key}`, {\r\n key,\r\n field,\r\n errors,\r\n phase,\r\n valid,\r\n });\r\n }\r\n\r\n private getInteractiveFields(form: HTMLFormElement): FormField[] {\r\n return Array.from(form.querySelectorAll(\"[string-input]\"))\r\n .filter((el) => !this.isServiceFieldAttribute(el.getAttribute(\"string-input\") || \"\"))\r\n .filter((el): el is FormField => this.isFormFieldElement(el))\r\n .map((el) => el as FormField);\r\n }\r\n\r\n private getFieldRules(field: FormField): RuleParserResult[] {\r\n const ruleString =\r\n this.tools.domAttribute.process({\r\n element: field,\r\n key: \"input\",\r\n }) ?? \"\";\r\n return this.tools.ruleParser.process({ value: ruleString });\r\n }\r\n\r\n private registerField(\r\n field: FormField,\r\n form: HTMLFormElement,\r\n fieldEntries: FieldEntry[],\r\n fieldValues: Record<string, any>,\r\n events: RegisteredEvent[],\r\n preferredIndex?: number\r\n ): void {\r\n if (!this.isFormFieldElement(field)) return;\r\n if (field.closest(\"form\") !== form) return;\r\n if (fieldEntries.some((entry) => entry.field === field)) return;\r\n\r\n const registeredIndex = this.registerFieldIndex(field, preferredIndex ?? fieldEntries.length);\r\n const key = this.getInputKey(field, registeredIndex);\r\n const rules = this.getFieldRules(field);\r\n const supportsRealtime = this.supportsBeforeInputValidation(rules);\r\n const needsContext = this.requiresContext(rules);\r\n const inputEventType = this.getInputEventType(field);\r\n\r\n const entry: FieldEntry = {\r\n field,\r\n key,\r\n rules,\r\n supportsRealtime,\r\n needsContext,\r\n inputEventType,\r\n inputHandler: () => undefined,\r\n };\r\n\r\n const inputHandler = (event: Event) => {\r\n const target = (event.currentTarget || event.target) as FormField | null;\r\n if (!target || !target.isConnected || !this.shouldValidateField(target)) {\r\n return;\r\n }\r\n const value = this.getFieldValue(target);\r\n fieldValues[entry.key] = value;\r\n const context = this.buildContext(entry.needsContext, entry.key, fieldValues);\r\n\r\n const { valid, errors } = this.tools.validation.process({\r\n rules: entry.rules,\r\n value,\r\n context,\r\n });\r\n\r\n this.applyValidationState(form, target, entry.key, valid, errors, \"live\");\r\n };\r\n\r\n entry.inputHandler = inputHandler;\r\n field.addEventListener(inputEventType, inputHandler);\r\n events.push({ eventElement: field, eventType: inputEventType, eventCallback: inputHandler });\r\n\r\n if (\r\n supportsRealtime &&\r\n (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement)\r\n ) {\r\n const beforeInputHandler = (event: Event) => {\r\n const inputEvent = event as InputEvent;\r\n if (inputEvent.isComposing || inputEvent.inputType?.startsWith(\"insertComposition\")) {\r\n return;\r\n }\r\n const target = (event.currentTarget || event.target) as FormField | null;\r\n if (\r\n !target ||\r\n !(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) ||\r\n !target.isConnected\r\n ) {\r\n return;\r\n }\r\n\r\n const start = target.selectionStart ?? 0;\r\n const end = target.selectionEnd ?? 0;\r\n let nextVal = target.value;\r\n\r\n switch (inputEvent.inputType) {\r\n case \"deleteContentBackward\":\r\n nextVal =\r\n start === end && start > 0\r\n ? target.value.slice(0, start - 1) + target.value.slice(end)\r\n : target.value.slice(0, start) + target.value.slice(end);\r\n break;\r\n case \"deleteContentForward\":\r\n nextVal =\r\n start === end && start < target.value.length\r\n ? target.value.slice(0, start) + target.value.slice(start + 1)\r\n : target.value.slice(0, start) + target.value.slice(end);\r\n break;\r\n case \"insertFromPaste\":\r\n case \"insertFromDrop\":\r\n case \"insertReplacementText\":\r\n nextVal =\r\n target.value.slice(0, start) + (inputEvent.data || \"\") + target.value.slice(end);\r\n break;\r\n default:\r\n if (typeof inputEvent.data === \"string\") {\r\n nextVal = target.value.slice(0, start) + inputEvent.data + target.value.slice(end);\r\n }\r\n }\r\n\r\n const { errors } = this.tools.validation.process({\r\n rules: entry.rules,\r\n value: nextVal,\r\n type: \"beforeinput\",\r\n context: this.buildContext(entry.needsContext, entry.key, fieldValues, {\r\n applied: true,\r\n value: nextVal,\r\n }),\r\n });\r\n\r\n if (errors.length > 0 && event.cancelable) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n entry.beforeInputHandler = beforeInputHandler;\r\n field.addEventListener(\"beforeinput\", beforeInputHandler);\r\n events.push({\r\n eventElement: field,\r\n eventType: \"beforeinput\",\r\n eventCallback: beforeInputHandler,\r\n });\r\n }\r\n\r\n field.classList.add(\"-inited\");\r\n fieldEntries.push(entry);\r\n fieldValues[key] = this.getFieldValue(field);\r\n }\r\n\r\n private unregisterField(\r\n field: FormField,\r\n fieldEntries: FieldEntry[],\r\n fieldValues: Record<string, any>,\r\n events: RegisteredEvent[]\r\n ): void {\r\n const index = fieldEntries.findIndex((entry) => entry.field === field);\r\n if (index === -1) return;\r\n const entry = fieldEntries[index];\r\n if (entry.inputHandler) {\r\n field.removeEventListener(entry.inputEventType, entry.inputHandler);\r\n }\r\n if (entry.beforeInputHandler) {\r\n field.removeEventListener(\"beforeinput\", entry.beforeInputHandler);\r\n }\r\n delete fieldValues[entry.key];\r\n fieldEntries.splice(index, 1);\r\n for (let i = events.length - 1; i >= 0; i--) {\r\n const registered = events[i];\r\n if (registered.eventElement !== field) continue;\r\n if (\r\n registered.eventCallback === entry.inputHandler ||\r\n (entry.beforeInputHandler && registered.eventCallback === entry.beforeInputHandler)\r\n ) {\r\n events.splice(i, 1);\r\n }\r\n }\r\n field.classList.remove(\"-inited\");\r\n }\r\n\r\n private collectInteractiveFieldsFromNode(node: Node): FormField[] {\r\n const elements: Element[] = [];\r\n if (node instanceof Element) {\r\n if (node.hasAttribute(\"string-input\")) {\r\n elements.push(node);\r\n }\r\n elements.push(...Array.from(node.querySelectorAll(\"[string-input]\")));\r\n } else if (node instanceof DocumentFragment) {\r\n elements.push(...Array.from(node.querySelectorAll(\"[string-input]\")));\r\n }\r\n\r\n return elements\r\n .filter((el) => !this.isServiceFieldAttribute(el.getAttribute(\"string-input\") || \"\"))\r\n .filter((el): el is FormField => this.isFormFieldElement(el));\r\n }\r\n\r\n private isRadioField(field: FormField): field is HTMLInputElement {\r\n return field instanceof HTMLInputElement && field.type === \"radio\";\r\n }\r\n\r\n private handleMutationAdditions(nodes: NodeList): void {\r\n nodes.forEach((node) => {\r\n const fields = this.collectInteractiveFieldsFromNode(node);\r\n fields.forEach((field) => {\r\n const state = this.getFormStateByContainment(field);\r\n if (!state) return;\r\n this.registerField(field, state.form, state.entries, state.values, state.events);\r\n });\r\n });\r\n }\r\n\r\n private handleMutationRemovals(nodes: NodeList): void {\r\n nodes.forEach((node) => {\r\n const fields = this.collectInteractiveFieldsFromNode(node);\r\n fields.forEach((field) => {\r\n const state = this.getFormStateByReference(field);\r\n if (!state) return;\r\n this.unregisterField(field, state.entries, state.values, state.events);\r\n });\r\n });\r\n }\r\n\r\n private getFormStateByContainment(field: FormField): FormState | null {\r\n const owner = this.objects.find(\r\n (object) =>\r\n object.htmlElement instanceof HTMLFormElement && object.htmlElement.contains(field)\r\n );\r\n if (!owner) return null;\r\n return this.buildFormState(owner);\r\n }\r\n\r\n private getFormStateByReference(field: FormField): FormState | null {\r\n for (const object of this.objects) {\r\n const entries = object.getProperty<FieldEntry[]>(\"form-field-entries\");\r\n if (!entries) continue;\r\n if (entries.some((entry) => entry.field === field)) {\r\n return this.buildFormState(object, entries);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private buildFormState(object: StringObject, entries?: FieldEntry[]): FormState | null {\r\n const element = object.htmlElement;\r\n if (!(element instanceof HTMLFormElement)) {\r\n return null;\r\n }\r\n const stateEntries = entries ?? object.getProperty<FieldEntry[]>(\"form-field-entries\");\r\n const values = object.getProperty<Record<string, any>>(\"form-field-values\");\r\n const events = object.getProperty<Array<RegisteredEvent>>(\"form-events\");\r\n if (!stateEntries || !values || !events) {\r\n return null;\r\n }\r\n return {\r\n object,\r\n form: element,\r\n entries: stateEntries,\r\n values,\r\n events,\r\n };\r\n }\r\n\r\n private registerFieldIndex(field: FormField, idx: number): number {\r\n const existing = field.getAttribute(\"data-string-form-index\");\r\n if (existing !== null) {\r\n return Number(existing);\r\n }\r\n field.setAttribute(\"data-string-form-index\", String(idx));\r\n return idx;\r\n }\r\n\r\n private getFieldIndex(field: FormField, fallbackIdx: number): number {\r\n const existing = field.getAttribute(\"data-string-form-index\");\r\n if (existing !== null) {\r\n const parsed = Number(existing);\r\n return Number.isNaN(parsed) ? fallbackIdx : parsed;\r\n }\r\n return this.registerFieldIndex(field, fallbackIdx);\r\n }\r\n\r\n private shouldValidateField(field: FormField): boolean {\r\n if (field.disabled) return false;\r\n if (field instanceof HTMLInputElement && field.type === \"hidden\") return false;\r\n return true;\r\n }\r\n\r\n private supportsBeforeInputValidation(rules: RuleParserResult[]): boolean {\r\n return rules.some((rule) => StringForm.beforeInputRuleKeys.has(rule.key));\r\n }\r\n\r\n private requiresContext(rules: RuleParserResult[]): boolean {\r\n return rules.some((rule) => StringForm.crossFieldRuleKeys.has(rule.key));\r\n }\r\n\r\n private buildContext(\r\n needsContext: boolean,\r\n fieldKey: string,\r\n fieldValues: Record<string, any>,\r\n override?: { applied: boolean; value: any }\r\n ): ValidationContext {\r\n if (!needsContext) {\r\n return { fieldKey };\r\n }\r\n\r\n const needsOverride = Boolean(override?.applied);\r\n const values = needsOverride ? { ...fieldValues, [fieldKey]: override!.value } : fieldValues;\r\n\r\n return {\r\n fieldKey,\r\n values,\r\n getValue: (lookupKey: string) => {\r\n if (needsOverride && lookupKey === fieldKey) {\r\n return override!.value;\r\n }\r\n return values[lookupKey];\r\n },\r\n };\r\n }\r\n\r\n private static readonly beforeInputRuleKeys = new Set([\r\n \"number\",\r\n \"integer\",\r\n \"email\",\r\n \"phone\",\r\n \"letters\",\r\n \"lettersSpaces\",\r\n \"lettersNumbers\",\r\n \"alpha\",\r\n \"alpha_num\",\r\n \"alpha_dash\",\r\n \"digits\",\r\n \"url\",\r\n \"pattern\",\r\n ]);\r\n\r\n private static readonly crossFieldRuleKeys = new Set([\"same\", \"different\", \"after\", \"before\"]);\r\n\r\n private static readonly serviceAttributePrefixes = [\"error\", \"group\"];\r\n\r\n getInputKey(field: FormField, idx: number): string {\r\n return (\r\n this.tools.domAttribute.process({\r\n element: field,\r\n key: \"id\",\r\n }) ||\r\n field.getAttribute(\"name\") ||\r\n field.getAttribute(\"id\") ||\r\n `input-${idx}`\r\n );\r\n }\r\n\r\n getFieldValue(field: FormField): any {\r\n if (field instanceof HTMLInputElement) {\r\n if (field.type === \"checkbox\") {\r\n if (field.name) {\r\n const form = field.form || field.closest(\"form\");\r\n const checked = form\r\n ? Array.from(\r\n form.querySelectorAll<HTMLInputElement>(\r\n `input[type=\"checkbox\"][name=\"${field.name}\"]:checked`\r\n )\r\n )\r\n : [field];\r\n if (checked.length > 1) return checked.map((el) => el.value);\r\n return checked.length === 1 ? checked[0].value : \"\";\r\n }\r\n return field.checked;\r\n }\r\n if (field.type === \"radio\") {\r\n if (field.name) {\r\n const form = field.form || field.closest(\"form\");\r\n const checked = form?.querySelector<HTMLInputElement>(\r\n `input[type=\"radio\"][name=\"${field.name}\"]:checked`\r\n );\r\n return checked ? checked.value : \"\";\r\n }\r\n return field.checked ? field.value : \"\";\r\n }\r\n if (field.type === \"file\") {\r\n if (field.files && field.files.length > 0) {\r\n return field.multiple ? Array.from(field.files) : field.files[0];\r\n }\r\n return field.value;\r\n }\r\n return field.value;\r\n }\r\n if (field instanceof HTMLSelectElement) {\r\n if (field.multiple) {\r\n return Array.from(field.selectedOptions).map((opt) => opt.value);\r\n }\r\n return field.value;\r\n }\r\n if (field instanceof HTMLTextAreaElement) {\r\n return field.value;\r\n }\r\n return \"\";\r\n }\r\n\r\n private isServiceFieldAttribute(attr: string): boolean {\r\n return StringForm.serviceAttributePrefixes.some((type) => attr.startsWith(`${type}[`));\r\n }\r\n\r\n private isFormFieldElement(element: Element): element is FormField {\r\n return (\r\n element instanceof HTMLInputElement ||\r\n element instanceof HTMLSelectElement ||\r\n element instanceof HTMLTextAreaElement\r\n );\r\n }\r\n\r\n private getInputEventType(field: FormField): \"input\" | \"change\" {\r\n if (\r\n field instanceof HTMLSelectElement ||\r\n (field instanceof HTMLInputElement && (field.type === \"checkbox\" || field.type === \"radio\"))\r\n ) {\r\n return \"change\";\r\n }\r\n return \"input\";\r\n }\r\n}\r\n","import { StringObject } from \"../../objects/StringObject\";\r\n\r\ntype CenterState = {\r\n cx: number;\r\n cy: number;\r\n valid: boolean;\r\n ro?: ResizeObserver;\r\n el?: HTMLElement;\r\n};\r\n\r\nexport class CenterCache {\r\n private map = new WeakMap<StringObject, CenterState>();\r\n private all: Set<StringObject> = new Set();\r\n\r\n attach(obj: StringObject) {\r\n if (this.map.has(obj)) return;\r\n const el = obj.htmlElement;\r\n const st: CenterState = { cx: 0, cy: 0, valid: false, el };\r\n st.ro = new ResizeObserver(() => {\r\n st.valid = false;\r\n });\r\n st.ro.observe(el);\r\n this.map.set(obj, st);\r\n this.all.add(obj);\r\n }\r\n\r\n detach(obj: StringObject) {\r\n const st = this.map.get(obj);\r\n if (!st) return;\r\n st.ro?.disconnect();\r\n this.map.delete(obj);\r\n this.all.delete(obj);\r\n }\r\n\r\n invalidate(id: string) {\r\n this.all.forEach((o) => {\r\n if (o.id === id) {\r\n const st = this.map.get(o);\r\n if (st) st.valid = false;\r\n }\r\n });\r\n }\r\n\r\n invalidateAll() {\r\n this.all.forEach((o) => {\r\n const st = this.map.get(o);\r\n if (st) st.valid = false;\r\n });\r\n }\r\n\r\n getCenter(obj: StringObject): { cx: number; cy: number } {\r\n const st = this.map.get(obj);\r\n if (!st || !st.el) return { cx: 0, cy: 0 };\r\n if (!st.valid) {\r\n const r = st.el.getBoundingClientRect();\r\n st.cx = r.left + r.width / 2;\r\n st.cy = r.top + r.height / 2;\r\n st.valid = true;\r\n }\r\n return { cx: st.cx, cy: st.cy };\r\n }\r\n}\r\n","import { StringObject } from \"../../objects/StringObject\";\n\ntype HoverState = { enter?: () => void; leave?: () => void };\n\nexport class HoverTracker {\n private active = new Set<StringObject>();\n private subs = new WeakMap<StringObject, HoverState>();\n\n track(obj: StringObject) {\n if (this.subs.has(obj)) return;\n const el = obj.htmlElement;\n\n const enter = () => this.active.add(obj);\n const leave = () => this.active.delete(obj);\n\n el.addEventListener(\"pointerenter\", enter);\n el.addEventListener(\"pointerleave\", leave);\n this.subs.set(obj, { enter, leave });\n }\n\n untrack(obj: StringObject) {\n const st = this.subs.get(obj);\n if (!st) return;\n const el = obj.htmlElement;\n if (st.enter) el.removeEventListener(\"pointerenter\", st.enter);\n if (st.leave) el.removeEventListener(\"pointerleave\", st.leave);\n this.active.delete(obj);\n this.subs.delete(obj);\n }\n\n isActive(obj: StringObject) {\n return this.active.has(obj);\n }\n activeObjects(): StringObject[] {\n return Array.from(this.active);\n }\n}\n","import { StringContext } from \"../../core/StringContext\";\nimport { StringData } from \"../../core/StringData\";\nimport { StringModule } from \"../../core/StringModule\";\nimport { StringObject } from \"../../objects/StringObject\";\n\nexport class StringScroller extends StringModule {\n constructor(context: StringContext) {\n super(context);\n this.htmlKey = \"scroller\";\n }\n\n onObjectConnected(object: StringObject): void {\n let isScrollInited = object.getProperty(\"scroller-inited\");\n if (isScrollInited == null || isScrollInited == \"\") {\n object.setProperty(\"scroller-inited\", \"inited\");\n let wheelEvent = (event: Event) => {\n this.events.emit(`wheel`, event);\n };\n object.setProperty(\"scroller-wheel-event\", wheelEvent);\n object.htmlElement.addEventListener(\"wheel\", wheelEvent);\n }\n }\n onObjectDisconnected(object: StringObject): void {\n object.setProperty(\"scroller-inited\", \"\");\n object.htmlElement.removeEventListener(\"wheel\", object.getProperty(\"scroller-wheel-event\"));\n }\n}\n","export function parsePartOf(value: string): { id: string; start: number; end: number } | null {\n const match = value.match(/([^[]+)\\[([\\d.]+)-([\\d.]+)\\]/);\n if (!match) return null;\n return {\n id: match[1],\n start: parseFloat(match[2]),\n end: parseFloat(match[3]),\n };\n}\n","import { StringContext } from \"../../core/StringContext\";\nimport { StringModule } from \"../../core/StringModule\";\nimport { StringObject } from \"../../objects/StringObject\";\nimport { parsePartOf } from \"../../utils/ParsePartOf\";\n\nfunction remap(value: number, from1: number, to1: number, from2: number, to2: number): number {\n return from2 + ((to2 - from2) * (value - from1)) / (to1 - from1);\n}\n\nexport class StringProgressPart extends StringModule {\n constructor(context: StringContext) {\n super(context);\n this.htmlKey = \"progress-part\";\n this.attributesToMap = [\n ...this.attributesToMap,\n { key: \"part-of\", type: \"string\", fallback: \"\" },\n ];\n }\n\n onObjectConnected(object: StringObject): void {\n let partOfId = object.getProperty(\"part-of\");\n let partOfData = parsePartOf(partOfId as string);\n if (partOfData) {\n object.setProperty(\"part-of-id\", partOfData.id);\n object.setProperty(\"start\", partOfData.start);\n object.setProperty(\"end\", partOfData.end);\n let progressEvent = (progress: number) => {\n if (partOfData) {\n const sliceProgress = remap(progress, partOfData?.start, partOfData?.end, 0, 1);\n const clampedProgress = Math.max(0, Math.min(1, sliceProgress));\n object.htmlElement.style.setProperty(\"--progress-slice\", clampedProgress.toString());\n this.events.emit(`object:progress-slice:${object.id}`, clampedProgress);\n }\n };\n object.setProperty(\"progress-event\", progressEvent);\n this.events.on(`object:progress:${partOfData.id}`, progressEvent);\n }\n }\n\n onObjectDisconnected(object: StringObject): void {\n let partOfId = object.getProperty(\"part-of-id\");\n if (partOfId) {\n this.events.off(`object:progress:${partOfId}`, object.getProperty<any>(\"progress-event\"));\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","CursorReactiveModule","StringAnchor","StringCursor","StringData","StringDelayLerpTracker","StringFPSTracker","StringForm","StringGlide","StringImpulse","StringLazy","StringLerp","StringLerpTracker","StringLoading","StringMagnetic","StringModule","StringObject","StringParallax","StringPositionTracker","StringProgress","StringProgressPart","StringResponsive","StringScrollbar","StringScroller","StringSequence","StringSplit","StringSpotlight","StringTune","StringVideoAutoplay","frameDOM","styleTxn","CursorController","smoothing","context","now","dt","targetX","targetY","smoothedX","smoothedY","stepX","stepY","distance","data","lerp","t","x","y","EventManager","eventName","callback","id","fullEvent","payload","set","value","visible","toLifecycleArgs","lifecycle","data","arg","arg2","ModuleManager","module","type","m","_data","added","removed","modules","args","i","StringMirrorObject","id","element","parent","key","value","easing","rawProgress","fallback","StringObject","id","element","EventManager","key","value","module","mirror","ObjectManager","data","modules","events","tools","el","idAttr","key","object","StringObject","keysAttr","s","attributes","m","q","item","id","obj","mirror","copyFromId","element","parent","existingId","existing","mirrorId","StringMirrorObject","easingAttr","attr","start","end","progressCallback","entries","e","outsideProp","outsideAttrValue","outsideAttrNormalized","outsideAttrFlag","isOutsideContainer","observerRoot","progressObserver","mutations","mutation","node","child","copyFrom","childCopyFrom","isCanRebuild","scrollPos","inviewStart","inviewEnd","wasInView","isNowInView","direction","distToStart","distToEnd","ScrollController","context","scrollDirection","rule","id","position","StringScrollDefault","ScrollController","context","delta","e","scrollTop","plusDelta","position","StringScrollDisable","ScrollController","context","e","SCROLL_CLASS_NAMES","StringScrollSmooth","ScrollController","context","newDirection","SCROLL_CLASS_NAMES","absVelocity","e","scrollDirection","atTop","atBottom","position","ScrollManager","context","StringScrollSmooth","StringScrollDefault","StringScrollDisable","mode","newMode","engine","events","rule","id","CursorState","RenderState","ScrollState","SystemState","TimeState","ViewportState","StringData","ScrollState","ViewportState","CursorState","RenderState","TimeState","SystemState","ModuleLifecyclePermissions","StringModule","context","ModuleLifecyclePermissions","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","parsedBreakpoint","breakpoints","item","val","id","index","applyFn","copyFn","mirror","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","boundingRect","parts","s","sum","part","v","isNegative","result","AdaptiveLerpTool","value","inMin","inMax","outMin","outMax","t","HORIZONTAL_KEYWORDS","VERTICAL_KEYWORDS","OriginParserTool","value","raw","options","s","index","parts","single","parsed","first","second","firstIsVerticalOnly","secondIsHorizontalOnly","val","axis","num","ColorParserTool","value","str","hex","ch","r","g","b","a","rgbMatch","v","hslMatch","h","l","s","hue2rgb","p","q","t","EasingFunctionTool","easing","def","match","x1","y1","x2","y2","t","cx","bx","ax","cy","by","ay","sampleCurveX","sampleCurveY","sampleCurveDerivativeX","solveCurveX","x","epsilon","t0","t1","t2","d2","i","MagneticPullTool","distance","radius","strength","proximity","LerpColorTool","from","to","progress","LerpVector2Tool","from","to","progress","TransformScaleParserTool","value","str","matrixValues","matrixNumbers","scaleValue","scaleNumbers","scaleXValue","scaleNumber","scale3dValue","matrix3dValues","error","SplitOptionsParserTool","attributeValue","options","part","trimmedPart","match","prefix","optionType","fullOptionKey","params","p","parsedParam","result","param","randomMatch","RuleParserTool","value","result","current","depth","i","c","ruleStr","match","key","params","s","colonIndex","paramsString","ValidationTool","v","params","normalized","digitCount","context","targetKey","otherValue","value","min","max","length","limit","rules","type","errors","rule","beforeInputValidatorFn","inputValidatorFn","inputValid","beforeInputValid","key","files","allowed","p","file","limitKb","maxBytes","item","mime","ext","name","parts","mode","target","currentDate","referenceDate","token","contextualValue","today","date","timestamp","pattern","allowEmpty","stringValue","source","flags","trimmed","lastSlashIndex","a","b","segments","segment","num","hextetPattern","DefaultToolsContainer","DOMAttributeTool","RecordAttributeTool","TransformNullifyTool","BoundingClientRectTool","RelativePositionTool","UnitParserTool","LerpTool","AdaptiveLerpTool","OriginParserTool","ColorParserTool","ValidationTool","EasingFunctionTool","MagneticPullTool","LerpColorTool","LerpVector2Tool","TransformScaleParserTool","SplitOptionsParserTool","RuleParserTool","isCoarsePointer","mm","touch","narrow","StyleTxn","el","vars","currentVars","k","v","props","currentProps","fn","alreadyOpen","error","style","styleTxn","targetStates","CURSOR_EPSILON","DEFAULT_CURSOR_ID","CURSOR_PORTAL_SELECTOR","CURSOR_PORTAL_CONTENT_SELECTOR","MIN_FRAME_DELTA","getTargetState","object","state","StringCursor","StringModule","context","value","isCoarsePointer","globalId","element","attributes","data","now","dt","cursorX","cursorY","isOver","isDisabled","baseLerp","frameLerp","dimensions","halfWidth","halfHeight","width","height","cx","cy","elementX","elementY","px","py","dx","dy","lerpedX","lerpedY","updatedX","updatedY","pixelChanged","alignment","offsetX","offsetY","mouseX","mouseY","targetX","targetY","newMouseX","newMouseY","stepX","stepY","smoothedX","smoothedY","prev","bucket","portal","cursorClass","added","removed","node","id","customLerp","content","existing","attrSources","source","raw","clamped","nodes","cb","ids","selected","normalized","portals","fallbackBucket","currentX","currentY","factor","fpsAdjustedLerp","safeDt","normalizedVelocityX","normalizedVelocityY","nextX","nextY","x","y","roundedX","roundedY","valueX","valueY","el","styleTxn","base","clampedBase","frames","adjusted","fallbackWidth","fallbackHeight","rawHalfWidth","rawHalfHeight","mousePos","size","obj","StringImpulse","StringModule","context","object","observer","_e","cursorVelocityX","cursorVelocityY","mouseX","mouseY","rect","w","side01","positionStrength","isContinuousPush","isLatched","objectVelocityX","objectVelocityY","rotationStrength","centerX","centerY","relativeX","relativeY","torque","angularVelocityDeg","originValue","x","y","attrName","dataAttrName","mutations","mutation","newValue","normalizedX","normalizedY","_","objectItem","isUnderCursor","i","offsetX","offsetY","velocityX","velocityY","positionTension","positionFriction","maxVelocity","maxOffset","velocityDecay","angleDeg","rotationTension","rotationFriction","maxAngularVelocityDeg","maxRotationAngleDeg","sleepEpsilon","isPositionAsleep","isRotationAsleep","positionUpdateThreshold","rotationUpdateThreshold","prevCssX","prevCssY","prevCssRot","cssTranslateX","cssTranslateY","cssRotateDeg","needsPositionUpdate","needsRotationUpdate","el","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","FrameDOM","fn","mQueue","i","e","wQueue","frameDOM","CursorReactiveModule","StringModule","context","isCoarsePointer","object","id","obj","data","allowFallback","near","target","mx","my","targets","maxDistanceSq","cx","cy","dx","dy","d2","frameDOM","styleTxn","TAU","RAD2DEG","clamp01","v","shortestArc","from","to","d","spotState","getSpot","o","s","StringSpotlight","CursorReactiveModule","context","id","obj","el","attrs","frameDOM","styleTxn","data","targets","object","options","dx","dy","dist","DEADZONE","distMax","lerp","nextA","degRaw","angleEps","distEps","angleChanged","distChanged","cssDeg","cssDist","ASPECT_CLASS","isSvgSource","src","lower","parsePng","b","d","parseJpeg","o","m","len","parseWebp","i","chunkHeader","chunkSize","dataOffset","w","h","b0","b1","b2","b3","tryParseDims","buffer","ct","c","fetchImageStreamWithDims","opts","onDims","res","reader","PROBE_CAP","TRY_STEP","probe","probeLen","lastTriedLen","chunks","dims","announced","done","value","part","toCopy","view","full","blob","blobUrl","StringLazy","StringModule","context","img","object","element","state","listener","data","raw","inView","crossOrigin","referrerPolicy","ac","finalize","loaded","onLoad","onError","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","startPosition","differencePosition","rawProgress","easing","progress","windowSize","data","key","progressStr","parentEasing","el","styleTxn","mirror","eased","clearCustomProperty","StringParallax","StringProgress","context","object","progress","factor","start","end","sign","screenSize","translation","globalId","element","attributes","bias","windowSize","data","isDesktop","transformData","el","styleTxn","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","getWholeWordSplitClass","word","first","ch","cls","BuildDOMTree","layoutLines","options","fontMetrics","fragment","localCharIndex","hasLine","hasOption","hasChar","wordsCount","line","charsCount","w","linesCount","wordsGlobalCount","extraProps","li","isLastInLayout","container","wordsForLine","SPLIT_ELEMENT_CLASS","applyStyles","wi","isLast","original","wordText","c","hasWord","wordEl","wholeWordClass","char","charIndex","charNode","charEl","nextChar","kerning","splitClassChar","textNode","lineText","el","calculatedValues","val","isOptionEnabled","varName","generateVariableName","type","align","group","item","norm","key","tokenCounter","BuildTokens","nodes","tokens","pushWithMeta","t","extra","processNode","node","carryMeta","el","tag","classes","extraMeta","child","text","id","n","FontMetrics","element","canvas","cs","font","char","width","charA","charB","pair","key","widthWithKerning","widthWithoutKerning","kerning","word","totalWidth","i","prevChar","splitTokensByBr","tokens","result","chunk","token","LayoutMeasurer","container","fontMetrics","wrapper","computed","spaceMeasurer","spaceWidth","measured","chunks","isAfterElement","lastTokenWasSpace","prevMeasuredWasText","wordSpans","tokenInfo","raw","hadLeadingSpace","hadTrailingSpace","words","w","word","wIdx","span","node","info","idx","domRect","rect","accurateWidth","measuredToken","prev","LINE_TOLERANCE","SplitMeasuredTokens","measured","container","fontMetrics","lines","currentLine","y","charIndexGlobal","wordIndexGlobal","mt","token","isBefore","isAfter","wordText","splitClass","joinPrev","chars","currentXInWord","i","ch","prev","charWidth","kerning","charRect","pc","lastChar","currentY","baselineY","target","charsBeforeAll","acc","w","baseInWord","c","mergeRects","wordIndexInLine","charsBefore","processedWord","rect","rects","left","r","top","right","bottom","StringSplit","StringModule","context","object","element","isAlreadySplit","originalHtml","attr","options","fragment","result","extraProps","value","key","restoreAfter","fontMetrics","FontMetrics","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","ATTR_FPS","StringFPSTracker","StringModule","context","_data","visible","fps","fpsStr","el","mutations","needsRescan","mutation","node","styleId","style","StringLerpTracker","StringModule","context","data","v","ctx","w","h","val","i","x","y","position","ATTR_VAL","ATTR_VAL_PCT","ATTR_DIR","StringPositionTracker","StringModule","context","data","current","target","contentHeight","windowHeight","val","maxScroll","valPct","direction","valStr","el","pctStr","visible","mutations","needsRescan","mutation","node","styleId","style","Debounce","func","delay","timeoutId","args","context","StringFPS","time","fps","now","elapsed","callback","StringVideoAutoplay","StringModule","context","object","videoElement","started","element","err","SequenceState","SequenceProgressVars","_StringSequence","StringModule","context","e","data","current","max","target","dir","els","el","trigger","parsed","object","get","k","seq","attr","key","match","slider","value","settings","global","group","obj","sliders","p","step","sequence","enteringDuration","leavingDuration","active","m","attrKey","seqAttr","v","easing","idx","transitionProgress","direction","duration","instant","toStep","customDuration","fromStep","prevLeaving","enteringGroup","leavingGroup","progress","prev","leaving","enteringProg","leavingProg","state","rawProgress","currentState","currentDir","styleTxn","SequenceProgressVars","t","elapsed","SequenceState","StringSequence","_StringForm","StringModule","context","globalId","object","element","attributes","existingEvents","evt","form","fieldEntries","fieldValues","field","idx","submitCallback","event","allValid","data","processedRadioKeys","entry","key","rules","needsContext","value","valid","errors","firstInvalidEntry","added","removed","phase","errorBlock","groupBlock","message","span","eventSuffix","el","ruleString","events","preferredIndex","registeredIndex","supportsRealtime","inputEventType","inputHandler","target","beforeInputHandler","inputEvent","start","end","nextVal","index","i","registered","node","elements","nodes","state","owner","entries","stateEntries","values","existing","fallbackIdx","parsed","rule","fieldKey","override","needsOverride","lookupKey","checked","opt","attr","type","StringForm","CenterCache","obj","el","st","id","o","HoverTracker","obj","el","enter","leave","st","StringScroller","StringModule","context","object","isScrollInited","wheelEvent","event","parsePartOf","value","match","remap","value","from1","to1","from2","to2","StringProgressPart","StringModule","context","object","partOfId","partOfData","parsePartOf","progressEvent","progress","sliceProgress","clampedProgress","StringTune","_StringTune","StringFPS","Debounce","DefaultToolsContainer","StringData","EventManager","ModuleManager","ObjectManager","CenterCache","HoverTracker","CursorController","ScrollManager","time","value","container","speed","mode","visible","type","objectClass","settings","effectiveSettings","module","eventName","callback","id","data","rule","fps","observerContainerMutation","mutationsList","observer","mutation","config","StringInview","htmlFontSize","fontSizeNumber","element","connectTargetId","event","frameDOM","styleTxn","force","scroll","width","height","newScrollHeight","newContainerTopPosition","rect","transformScale","isDesktop","widthChanged","heightChanged","scrollHeightChanged","shouldRebuild","selector","offset","scrollTop","position"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/controllers/CursorController.ts","../src/core/managers/EventManager.ts","../src/core/managers/ModuleManager.ts","../src/objects/StringMirrorObject.ts","../src/objects/StringObject.ts","../src/core/managers/DOMBatcher.ts","../src/models/IModuleLifecyclePermissions.ts","../src/core/StringModule.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/SystemState.ts","../src/states/TimeState.ts","../src/states/ViewportState.ts","../src/core/StringData.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/EasingFunctionTool.ts","../src/tools/MagneticPullTool.ts","../src/tools/LerpColorTool.ts","../src/tools/LerpVector2Tool.ts","../src/tools/TransformScaleParserTool.ts","../src/tools/SplitOptionsParserTool.ts","../src/tools/RuleParserTool.ts","../src/tools/ValidationTool.ts","../src/core/StringToolsContainer.ts","../src/utils/isCoarsePointer.ts","../src/utils/style-txn.ts","../src/modules/cursor/StringCursor.ts","../src/modules/cursor/StringImpulse.ts","../src/modules/cursor/StringMagnetic.ts","../src/utils/frame-dom.ts","../src/modules/cursor/CursorReactiveModule.ts","../src/modules/cursor/StringSpotlight.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/CanvasKerningApplier.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","../src/modules/input/StringForm.ts","../src/core/managers/CenterCache.ts","../src/core/managers/HoverTracker.ts","../src/modules/scroll/StringScroller.ts","../src/utils/ParsePartOf.ts","../src/modules/scroll/StringProgressPart.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 { StringImpulse } from \"./modules/cursor/StringImpulse\";\r\nimport { StringMagnetic } from \"./modules/cursor/StringMagnetic\";\r\nimport { StringSpotlight } from \"./modules/cursor/StringSpotlight\";\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\nimport { StringForm } from \"./modules/input/StringForm\";\r\nimport { ISettingsChangeData } from \"./models/event/ISettingsChangeData\";\r\nimport { CenterCache } from \"./core/managers/CenterCache\";\r\nimport { HoverTracker } from \"./core/managers/HoverTracker\";\r\nimport { CursorReactiveModule } from \"./modules/cursor/CursorReactiveModule\";\r\nimport { StringScroller } from \"./modules/scroll/StringScroller\";\r\nimport { parsePartOf } from \"./utils/ParsePartOf\";\r\nimport { StringProgressPart } from \"./modules/scroll/StringProgressPart\";\r\nimport { frameDOM } from \"./utils/frame-dom\";\r\nimport { styleTxn } from \"./utils/style-txn\";\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 private onContainerTransitionEndBind: any;\r\n private onResizeObserverBind: any;\r\n private pendingScroll: boolean = false;\r\n private lastScrollEmitted: number = NaN;\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 /** Caches the center positions of string objects. */\r\n private centers: CenterCache;\r\n\r\n /** Tracks hover states of string objects. */\r\n private hoverManager: HoverTracker;\r\n\r\n private observerContainerResize: ResizeObserver | null = null;\r\n\r\n public canRebuild: boolean = true;\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 this.objectManager.checkInview();\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 this.observerContainerResize?.unobserve(this.context.data.scroll.container);\r\n\r\n this.data.scroll.elementContainer.removeEventListener(\r\n \"transitionend\",\r\n this.onContainerTransitionEndBind\r\n );\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.data.scroll.elementContainer.addEventListener(\r\n \"transitionend\",\r\n this.onContainerTransitionEndBind\r\n );\r\n this.observerContainerResize?.observe(this.context.data.scroll.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 scrollPosition() {\r\n return this.data.scroll.current;\r\n }\r\n\r\n public get scrollHeight() {\r\n return this.data.viewport.contentHeight;\r\n }\r\n\r\n public get containerHeight() {\r\n return this.data.viewport.windowHeight;\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 public set FPSTrackerVisible(visible: boolean) {\r\n this.data.system.fpsTracker = visible;\r\n this.eventManager.emit(\"tracker:fps:visible\", visible);\r\n }\r\n\r\n public set PositionTrackerVisible(visible: boolean) {\r\n this.data.system.positionTracker = visible;\r\n this.eventManager.emit(\"tracker:position:visible\", visible);\r\n }\r\n\r\n public set domBatcherEnabled(enabled: boolean) {\r\n this.objectManager.setDOMBatcherEnabled(enabled);\r\n }\r\n\r\n public set intersectionObserverEnabled(enabled: boolean) {\r\n this.objectManager.setIntersectionObserverEnabled(enabled);\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 this.tools\r\n );\r\n\r\n this.centers = new CenterCache();\r\n this.hoverManager = new HoverTracker();\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 centers: this.centers,\r\n hover: this.hoverManager,\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 \"global-class\": false,\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 \"cursor-lerp\": \"0.75\",\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 \"position-strength\": 3,\r\n \"position-tension\": 0.05,\r\n \"position-friction\": 0.15,\r\n \"position-max-velocity\": 10,\r\n \"position-update-threshold\": 0.1,\r\n \"rotation-strength\": 0.75,\r\n \"rotation-tension\": 0.06,\r\n \"rotation-friction\": 0.18,\r\n \"rotation-max-angular-velocity\": 6,\r\n \"rotation-max-angle\": 18,\r\n \"rotation-update-threshold\": 0.15,\r\n \"max-offset\": 220,\r\n \"sleep-epsilon\": 0.01,\r\n \"continuous-push\": true,\r\n });\r\n\r\n this.onContainerTransitionEndBind = this.onContainerTransitionEnd.bind(this);\r\n\r\n this.onResizeObserverBind = this.onResizeObserverEvent.bind(this);\r\n this.observerContainerResize = new ResizeObserver(this.onResizeObserverBind);\r\n this.observerContainerResize.observe(this.context.data.scroll.container);\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.eventManager.on(`wheel`, this.onWheelBind);\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 centers: this.centers,\r\n hover: this.hoverManager,\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(\"scroll\", this.onScrollBind);\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 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\" || 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(this.context.data.scroll.container, config);\r\n\r\n this.use(StringInview);\r\n\r\n const htmlFontSize = window.getComputedStyle(document.documentElement).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.querySelectorAll(\"[string-copy-from],[data-string-copy-from]\").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\r\n if (connectTargetId && connectTargetId.length > 0) {\r\n this.objectManager.linkMirror(connectTargetId, element as HTMLElement);\r\n }\r\n });\r\n // document.querySelectorAll(\"[string-part-of],[data-string-part-of]\").forEach((element) => {\r\n // let partOfTargetId = this.tools.domAttribute.process({\r\n // element: element as HTMLElement,\r\n // key: \"part-of\",\r\n // fallback: \"\",\r\n // });\r\n // let partOfData = parsePartOf(partOfTargetId as string);\r\n // if (partOfData) {\r\n // if (partOfData.id && partOfData.id.length > 0) {\r\n // if (this.objectManager.all.has(partOfData.id)) {\r\n // let partOfObject = new StringObject(\"\", element as HTMLElement);\r\n // partOfObject.setProperty(\"part-of-id\", partOfData.id);\r\n // partOfObject.setProperty(\"start\", partOfData.start);\r\n // partOfObject.setProperty(\"end\", partOfData.end);\r\n\r\n // this.objectManager.all.get(partOfData.id)!.partOf.push(partOfObject);\r\n // } else {\r\n // this.objectManager.enqueuePartOf(partOfData.id, element as HTMLElement);\r\n // }\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 isDesktop: this.data.viewport.windowWidth > 1024,\r\n widthChanged: true,\r\n heightChanged: true,\r\n scrollHeightChanged: true,\r\n isForceRebuild: false,\r\n });\r\n }\r\n\r\n private onResizeObserverEvent() {\r\n this.debouncedResize();\r\n }\r\n\r\n private onContainerTransitionEnd(event: TransitionEvent) {\r\n if (event.target === this.context.data.scroll.container) {\r\n this.onResize();\r\n this.moduleManager.onResize();\r\n this.moduleManager.onScroll();\r\n this.moduleManager.onFrame();\r\n }\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 frameDOM.measure(() => {\r\n this.moduleManager.onMouseMoveMeasure();\r\n });\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(\"[string-isolation],[data-string-isolation]\");\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 this.eventManager.emit(`scroll:start`, null);\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 this.eventManager.emit(`scroll:stop`, null);\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(data: ISettingsChangeData) {\r\n this.cursorController.onSettingsChange(data);\r\n this.objectManager.onSettingsChange(data);\r\n this.moduleManager.onSettingsChange(data);\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\r\n this.context.centers.invalidateAll();\r\n\r\n this.scrollManager.get().onScroll(e);\r\n this.pendingScroll = true;\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\r\n if (this.pendingScroll || this.data.scroll.current !== this.lastScrollEmitted) {\r\n this.pendingScroll = false;\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 frameDOM.measure(() => {\r\n this.moduleManager.onScrollMeasure();\r\n });\r\n this.lastScrollEmitted = this.data.scroll.current;\r\n }\r\n\r\n frameDOM.mutate(() => {\r\n styleTxn.begin();\r\n this.moduleManager.onMutate();\r\n styleTxn.commit();\r\n });\r\n\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(force: boolean = false): void {\r\n if (this.canRebuild == false) {\r\n return;\r\n }\r\n\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 =\r\n window.getComputedStyle(container).scale == \"none\"\r\n ? transformScale\r\n : Number(window.getComputedStyle(container).scale);\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current * this.context.data.viewport.transformScale;\r\n const isDesktop = width > 1024;\r\n\r\n const widthChanged = this.prevWidth !== width;\r\n const heightChanged = this.prevHeight !== height;\r\n const scrollHeightChanged = this.context.data.viewport.contentHeight !== newScrollHeight;\r\n\r\n const shouldRebuild = widthChanged || (isDesktop && heightChanged) || scrollHeightChanged;\r\n\r\n this.context.data.scroll.topPosition = Math.floor(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(document.documentElement).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 (widthChanged || (typeof force === \"boolean\" && force)) {\r\n this.moduleManager.onResizeWidth();\r\n }\r\n if (shouldRebuild || (typeof force === \"boolean\" && force)) {\r\n if (this.context.data.scroll.container.scrollTop > 0) {\r\n this.context.data.scroll.current = this.context.data.scroll.container.scrollTop;\r\n this.context.data.scroll.target = this.context.data.scroll.container.scrollTop;\r\n }\r\n\r\n this.scrollManager.updateResponsiveMode();\r\n this.moduleManager.onResize();\r\n this.onSettingsChange({\r\n isDesktop,\r\n widthChanged,\r\n heightChanged,\r\n scrollHeightChanged,\r\n isForceRebuild: force === true,\r\n });\r\n this.objectManager.invalidateInviewIndex();\r\n this.moduleManager.onScroll();\r\n this.moduleManager.onScrollMeasure();\r\n this.moduleManager.onFrame();\r\n this.objectManager.checkInview();\r\n }\r\n }\r\n\r\n /**\r\n * Scrolls the container to the specified element identified by a CSS selector, applying an optional offset.\r\n *\r\n * Calculates the vertical position of the target element relative to the scroll container and updates the scroll delta accordingly.\r\n * If the element is not found, a warning is logged to the console.\r\n *\r\n * @param selector - The CSS selector string used to identify the target element.\r\n * @param offset - Optional. The number of pixels to offset from the target element's top position. Defaults to 0.\r\n */\r\n public scrollToElement(selector: string, offset: number = 0) {\r\n const element = document.querySelector(selector);\r\n if (element) {\r\n const rect = element.getBoundingClientRect();\r\n const scrollTop =\r\n rect.top + window.pageYOffset - this.data.scroll.container.clientTop - offset;\r\n this.context.data.scroll.delta = scrollTop - this.data.scroll.current;\r\n } else {\r\n console.warn(`Element not found: ${selector}`);\r\n }\r\n }\r\n\r\n public scrollTo(position: number) {\r\n this.scrollManager.get().scrollTo(position);\r\n }\r\n\r\n public invalidateCenter(id: string): void {\r\n this.centers.invalidate(id);\r\n }\r\n\r\n /**\r\n * Forces center cache recalculation for all tracked objects.\r\n * Useful when DOM geometry changes outside of StringTune's control.\r\n */\r\n public invalidateCenters(): void {\r\n this.centers.invalidateAll();\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(\"scroll\", this.onScrollBind);\r\n this.data.scroll.container?.removeEventListener(\"wheel\", this.onWheelBind);\r\n this.data.scroll.elementContainer.removeEventListener(\r\n \"transitionend\",\r\n this.onContainerTransitionEndBind\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 this.eventManager.off(`wheel`, this.onWheelBind);\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 StringForm,\r\n StringImpulse,\r\n StringMagnetic,\r\n StringParallax,\r\n StringPositionTracker,\r\n StringProgress,\r\n StringResponsive,\r\n StringSpotlight,\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 StringScroller,\r\n StringProgressPart,\r\n CursorReactiveModule,\r\n frameDOM,\r\n styleTxn,\r\n type ScrollMarkRule as ScrollTriggerRule,\r\n type StringContext,\r\n};\r\n\r\n// Export performance utilities\r\nexport { DOMBatcher } from \"./core/managers/DOMBatcher\";\r\n","import { ISettingsChangeData } from \"../../models/event/ISettingsChangeData\";\r\nimport { 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 private lastMouseX: number = 0;\r\n private lastMouseY: number = 0;\r\n private lastMouseTime: number = 0;\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\r\n this.onSettingsChange({\r\n isDesktop: context.data.viewport.windowWidth > 1024,\r\n isForceRebuild: false,\r\n widthChanged: true,\r\n heightChanged: true,\r\n scrollHeightChanged: true,\r\n });\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 const now = performance.now();\r\n const dt = now - this.lastMouseTime;\r\n\r\n if (dt > 0) {\r\n this.context.data.cursor.velocityX = (e.clientX - this.lastMouseX) / dt;\r\n this.context.data.cursor.velocityY = (e.clientY - this.lastMouseY) / dt;\r\n }\r\n\r\n this.lastMouseX = e.clientX;\r\n this.lastMouseY = e.clientY;\r\n this.lastMouseTime = now;\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({\r\n from: smoothedX,\r\n to: targetX,\r\n progress: this.smoothingFactor,\r\n });\r\n const stepY = this.context.tools.lerp.process({\r\n from: smoothedY,\r\n to: targetY,\r\n progress: this.smoothingFactor,\r\n });\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(data: ISettingsChangeData): void {\r\n let lerp = Number(this.context.settings[\"cursor-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 private stateEvents: Set<string> = new Set();\r\n private lastPayloads: Record<string, any> = {};\r\n\r\n constructor() {\r\n this.stateEvents.add(\"screen:mobile\");\r\n this.stateEvents.add(\"screen:tablet\");\r\n this.stateEvents.add(\"screen:laptop\");\r\n this.stateEvents.add(\"screen:desktop\");\r\n this.stateEvents.add(\"start\");\r\n }\r\n\r\n /**\r\n * Marks an event as stateful so the last payload is cached and replayed to new listeners.\r\n * Optionally seeds the initial payload.\r\n */\r\n registerStateEvent(eventName: string, initialPayload?: any): void {\r\n this.stateEvents.add(eventName);\r\n if (initialPayload !== undefined) {\r\n this.lastPayloads[eventName] = initialPayload;\r\n }\r\n }\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>(eventName: string, callback: EventCallback<T>, id?: string | null): 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 if (this.stateEvents.has(fullEvent) && this.lastPayloads[fullEvent] !== undefined) {\r\n callback(this.lastPayloads[fullEvent]);\r\n }\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>(eventName: string, callback: EventCallback<T>, id?: string): 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 if (this.stateEvents.has(eventName)) {\r\n this.lastPayloads[eventName] = payload;\r\n }\r\n const set = this.listeners[eventName];\r\n if (!set) return;\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 { ISettingsChangeData } from \"../../models/event/ISettingsChangeData\";\r\nimport { IStringModule } from \"../IStringModule\";\r\nimport { StringModule } from \"../StringModule\";\r\n\r\ntype LifecycleName =\r\n | \"destroy\"\r\n | \"onInit\"\r\n | \"onFrame\"\r\n | \"onMutate\"\r\n | \"onScrollMeasure\"\r\n | \"onMouseMoveMeasure\"\r\n | \"onScroll\"\r\n | \"onResizeWidth\"\r\n | \"onResize\"\r\n | \"onMouseMove\"\r\n | \"onWheel\"\r\n | \"onDirectionChange\"\r\n | \"onScrollStart\"\r\n | \"onScrollStop\"\r\n | \"onAxisChange\"\r\n | \"onDeviceChange\"\r\n | \"onScrollConfigChange\"\r\n | \"onSettingsChange\"\r\n | \"onDOMMutate\";\r\n\r\nfunction toLifecycleArgs(\r\n lifecycle: LifecycleName,\r\n data: StringData,\r\n arg?: unknown,\r\n arg2?: unknown\r\n): unknown[] {\r\n switch (lifecycle) {\r\n case \"onFrame\":\r\n case \"onMutate\":\r\n case \"onScrollMeasure\":\r\n case \"onMouseMoveMeasure\":\r\n case \"onScroll\":\r\n return [data];\r\n case \"onMouseMove\":\r\n case \"onWheel\":\r\n return arg ? [arg] : [];\r\n case \"onDOMMutate\":\r\n return arg && arg2 ? [arg, arg2] : [];\r\n case \"onSettingsChange\":\r\n return [];\r\n default:\r\n return [];\r\n }\r\n}\r\n\r\nexport class ModuleManager {\r\n private modules: StringModule[] = [];\r\n private uiModules: StringModule[] = [];\r\n private allModules: StringModule[] = [];\r\n\r\n constructor(private data: StringData) {}\r\n\r\n register(module: StringModule): void {\r\n if (module.type === 1) {\r\n this.modules.push(module);\r\n } else if (module.type === 2) {\r\n this.uiModules.push(module);\r\n }\r\n\r\n this.rebuildAllModules();\r\n }\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 onInit(): void {\r\n this.callAll(\"onInit\");\r\n }\r\n\r\n onFrame(): void {\r\n this.callAll(\"onFrame\");\r\n }\r\n\r\n onMutate(): void {\r\n this.callAll(\"onMutate\");\r\n }\r\n\r\n onScrollMeasure(): void {\r\n this.callAll(\"onScrollMeasure\");\r\n }\r\n\r\n onMouseMoveMeasure(): void {\r\n this.callAll(\"onMouseMoveMeasure\");\r\n }\r\n\r\n onScroll(): void {\r\n this.callAll(\"onScroll\");\r\n }\r\n\r\n onResizeWidth(): void {\r\n this.callAll(\"onResizeWidth\");\r\n }\r\n\r\n onResize(): void {\r\n this.callAll(\"onResize\");\r\n }\r\n\r\n onMouseMove(e: MouseEvent): void {\r\n this.callAll(\"onMouseMove\", e);\r\n }\r\n\r\n onWheel(e: WheelEvent): void {\r\n this.callAll(\"onWheel\", e);\r\n }\r\n\r\n onDirectionChange(): void {\r\n this.callAll(\"onDirectionChange\");\r\n }\r\n\r\n onScrollStart(): void {\r\n this.callAll(\"onScrollStart\");\r\n }\r\n\r\n onScrollStop(): void {\r\n this.callAll(\"onScrollStop\");\r\n }\r\n\r\n onAxisChange(): void {\r\n this.callAll(\"onAxisChange\");\r\n }\r\n\r\n onDeviceChange(): void {\r\n this.callAll(\"onDeviceChange\");\r\n }\r\n\r\n onScrollConfigChange(): void {\r\n this.callAll(\"onScrollConfigChange\");\r\n }\r\n\r\n onSettingsChange(_data: ISettingsChangeData): void {\r\n this.callAll(\"onSettingsChange\");\r\n }\r\n\r\n onDOMMutate(added: NodeList, removed: NodeList): void {\r\n this.callAll(\"onDOMMutate\", added, removed);\r\n }\r\n\r\n destroy(): void {\r\n this.callAll(\"destroy\");\r\n this.modules = [];\r\n this.uiModules = [];\r\n this.allModules = [];\r\n }\r\n\r\n get all(): IStringModule[] {\r\n return this.allModules;\r\n }\r\n\r\n get core(): IStringModule[] {\r\n return this.modules;\r\n }\r\n\r\n get ui(): IStringModule[] {\r\n return this.uiModules;\r\n }\r\n\r\n private callAll(lifecycle: LifecycleName, arg?: unknown, arg2?: unknown): void {\r\n this.callLifecycle(this.modules, lifecycle, arg, arg2);\r\n this.callLifecycle(this.uiModules, lifecycle, arg, arg2);\r\n }\r\n\r\n private callLifecycle(\r\n modules: StringModule[],\r\n lifecycle: LifecycleName,\r\n arg?: unknown,\r\n arg2?: unknown\r\n ): void {\r\n if (modules.length === 0) {\r\n return;\r\n }\r\n\r\n const args = toLifecycleArgs(lifecycle, this.data, arg, arg2);\r\n\r\n for (let i = 0; i < modules.length; i++) {\r\n const module = modules[i];\r\n if (!module) continue;\r\n\r\n (module as any)[lifecycle](...args);\r\n }\r\n }\r\n\r\n private rebuildAllModules(): void {\r\n this.allModules = [...this.modules, ...this.uiModules];\r\n }\r\n}\r\n","import type { StringObject } from \"./StringObject\";\n\nexport type MirrorEasingFn = (value: number) => number;\n\n/**\n * Lightweight wrapper that mirrors a primary StringObject while keeping\n * its own easing and state. Intended for elements linked via\n * `[string-copy-from]`.\n */\nexport class StringMirrorObject {\n public readonly id: string;\n public readonly htmlElement: HTMLElement;\n\n private properties = new Map<string, any>();\n private easingFn?: MirrorEasingFn;\n\n constructor(id: string, element: HTMLElement, private parent: StringObject) {\n this.id = id;\n this.htmlElement = element;\n }\n\n public get parentObject(): StringObject {\n return this.parent;\n }\n\n public setProperty<T>(key: string, value: T): void {\n this.properties.set(key, value);\n }\n\n public getProperty<T>(key: string): T {\n return this.properties.get(key) ?? null;\n }\n\n public setEasing(easing: MirrorEasingFn | null | undefined): void {\n this.easingFn = easing ?? undefined;\n }\n\n public getEasing(): MirrorEasingFn | undefined {\n return this.easingFn;\n }\n\n /**\n * Returns eased progress using mirror easing (if set) or fallback.\n */\n public applyProgress(rawProgress: number, fallback?: MirrorEasingFn): number {\n const easing = this.easingFn ?? fallback;\n return easing ? easing(rawProgress) : rawProgress;\n }\n}\n","import { IStringModule } from \"../core/IStringModule\";\nimport { EventManager } from \"../core/managers/EventManager\";\nimport { StringMirrorObject } from \"./StringMirrorObject\";\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 /**\n * Mirror objects linked via `string-copy-from`.\n */\n private mirrors = new Map<string, StringMirrorObject>();\n\r\n /**\n * Internal key-value store of dynamic object properties (like offsets, progress, etc.).\n */\n private properties: Map<string, any> = new Map();\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();\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 /**\n * Retrieves a previously stored property value.\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) => {\n module.removeObject(this.id);\n });\n }\n\n /**\n * Shows the object, applies visual class and notifies connected modules.\n */\n public show(): void {\n this.htmlElement.classList.add(\"-inview\");\n }\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 {\n if (!this.modules.includes(module)) {\n this.modules.push(module);\n }\n }\n\n public addMirror(mirror: StringMirrorObject): void {\n this.mirrors.set(mirror.id, mirror);\n }\n\n public removeMirror(id: string): void {\n this.mirrors.delete(id);\n }\n\n public get mirrorObjects(): StringMirrorObject[] {\n return Array.from(this.mirrors.values());\n }\n\n public get connects(): HTMLElement[] {\n return this.mirrorObjects.map((mirror) => mirror.htmlElement);\n }\n}\n","import { StringObject } from \"../../objects/StringObject\";\r\nimport { StringModule } from \"../StringModule\";\r\n\r\ninterface BatchTask {\r\n priority: number;\r\n execute: () => void;\r\n}\r\n\r\ninterface ModuleBatchContext {\r\n module: StringModule;\r\n object: StringObject;\r\n element: HTMLElement;\r\n attributes: Record<string, any>;\r\n globalId: number;\r\n windowSize: number;\r\n}\r\n\r\nexport class DOMBatcher {\r\n private readQueue: BatchTask[] = [];\r\n private writeQueue: BatchTask[] = [];\r\n private computeQueue: BatchTask[] = [];\r\n private isProcessing = false;\r\n private pendingFrame: number | null = null;\r\n private rectCache = new WeakMap<HTMLElement, DOMRect>();\r\n private dimensionCache = new WeakMap<HTMLElement, { width: number; height: number }>();\r\n\r\n public scheduleRead(task: () => void, priority: number = 0): void {\r\n this.readQueue.push({ priority, execute: task });\r\n this.scheduleFlush();\r\n }\r\n\r\n public scheduleCompute(task: () => void, priority: number = 0): void {\r\n this.computeQueue.push({ priority, execute: task });\r\n this.scheduleFlush();\r\n }\r\n\r\n public scheduleWrite(task: () => void, priority: number = 0): void {\r\n this.writeQueue.push({ priority, execute: task });\r\n this.scheduleFlush();\r\n }\r\n\r\n public batchModuleInitialization(contexts: ModuleBatchContext[]): void {\r\n contexts.forEach(({ module, object, element, attributes, globalId }) => {\r\n this.scheduleRead(() => {\r\n const rect = element.getBoundingClientRect();\r\n this.rectCache.set(element, rect);\r\n this.dimensionCache.set(element, {\r\n width: element.offsetWidth || element.clientWidth || rect.width,\r\n height: element.offsetHeight || element.clientHeight || rect.height,\r\n });\r\n module.initializeObject(globalId, object, element, attributes);\r\n }, 1);\r\n });\r\n\r\n contexts.forEach(({ module, object, windowSize }) => {\r\n this.scheduleCompute(() => {\r\n module.calculatePositions(object, windowSize);\r\n }, 2);\r\n });\r\n\r\n contexts.forEach(({ module, object }) => {\r\n this.scheduleWrite(() => {\r\n module.connectObject(object);\r\n module.addObject(object.id, object);\r\n }, 3);\r\n });\r\n }\r\n\r\n public getCachedRect(element: HTMLElement): DOMRect | undefined {\r\n return this.rectCache.get(element);\r\n }\r\n\r\n public getCachedDimensions(element: HTMLElement): { width: number; height: number } | undefined {\r\n return this.dimensionCache.get(element);\r\n }\r\n\r\n private scheduleFlush(): void {\r\n if (this.pendingFrame !== null || this.isProcessing) {\r\n return;\r\n }\r\n this.pendingFrame = requestAnimationFrame(() => {\r\n this.flush();\r\n });\r\n }\r\n\r\n private flush(): void {\r\n this.isProcessing = true;\r\n this.pendingFrame = null;\r\n const sortByPriority = (a: BatchTask, b: BatchTask) => b.priority - a.priority;\r\n\r\n try {\r\n const reads = [...this.readQueue].sort(sortByPriority);\r\n reads.forEach((task) => {\r\n try {\r\n task.execute();\r\n } catch (error) {\r\n console.error(\"[DOMBatcher] Read task error:\", error);\r\n }\r\n });\r\n this.readQueue = [];\r\n\r\n const computes = [...this.computeQueue].sort(sortByPriority);\r\n computes.forEach((task) => {\r\n try {\r\n task.execute();\r\n } catch (error) {\r\n console.error(\"[DOMBatcher] Compute task error:\", error);\r\n }\r\n });\r\n this.computeQueue = [];\r\n\r\n const writes = [...this.writeQueue].sort(sortByPriority);\r\n writes.forEach((task) => {\r\n try {\r\n task.execute();\r\n } catch (error) {\r\n console.error(\"[DOMBatcher] Write task error:\", error);\r\n }\r\n });\r\n this.writeQueue = [];\r\n } finally {\r\n this.rectCache = new WeakMap();\r\n this.dimensionCache = new WeakMap();\r\n this.isProcessing = false;\r\n }\r\n }\r\n\r\n public flushSync(): void {\r\n if (this.pendingFrame !== null) {\r\n cancelAnimationFrame(this.pendingFrame);\r\n this.pendingFrame = null;\r\n }\r\n this.flush();\r\n }\r\n\r\n public clear(): void {\r\n if (this.pendingFrame !== null) {\r\n cancelAnimationFrame(this.pendingFrame);\r\n this.pendingFrame = null;\r\n }\r\n this.readQueue = [];\r\n this.writeQueue = [];\r\n this.computeQueue = [];\r\n this.rectCache = new WeakMap();\r\n this.dimensionCache = new WeakMap();\r\n }\r\n}\r\n","export interface ModuleLifecyclePermissionsItem {\n rebuild: {\n width: boolean;\n height: boolean;\n scrollHeight: boolean;\n };\n}\nexport class ModuleLifecyclePermissions {\n desktop: ModuleLifecyclePermissionsItem = {\n rebuild: {\n width: true,\n height: true,\n scrollHeight: true,\n },\n };\n mobile: ModuleLifecyclePermissionsItem = {\n rebuild: {\n width: true,\n height: true,\n scrollHeight: true,\n },\n };\n}\n","import { IStringModule } from \"./IStringModule\";\r\nimport { StringObject } from \"../objects/StringObject\";\r\nimport { StringMirrorObject } from \"../objects/StringMirrorObject\";\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\nimport { ModuleLifecyclePermissions } from \"../models/IModuleLifecyclePermissions\";\r\nimport { CenterCache } from \"./managers/CenterCache\";\r\nimport { HoverTracker } from \"./managers/HoverTracker\";\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 /**\r\n * Cache for storing and managing object centers.\r\n */\r\n protected centers: CenterCache;\r\n\r\n /**\r\n * Tracker for managing hover states of objects.\r\n */\r\n protected hover: HoverTracker;\r\n\r\n public permissions: ModuleLifecyclePermissions = new ModuleLifecyclePermissions();\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 this.centers = context.centers;\r\n this.hover = context.hover;\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: \"outside-container\", type: \"boolean\", fallback: this.settings[\"outside-container\"] },\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: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n const top = boundingRect.top;\r\n return (\r\n Math.floor(top) +\r\n this.data.scroll.container.scrollTop * this.data.viewport.transformScale\r\n );\r\n },\r\n },\r\n {\r\n key: \"end\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n const top = boundingRect.top;\r\n const height = boundingRect.height;\r\n return top + height - this.data.scroll.transformedCurrent;\r\n },\r\n },\r\n {\r\n key: \"size\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n return boundingRect.height;\r\n },\r\n },\r\n {\r\n key: \"half-width\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n return boundingRect.width / 2;\r\n },\r\n },\r\n {\r\n key: \"half-height\",\r\n type: \"number\",\r\n fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\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\" ? fallback(element, object, boundingRect) : fallback;\r\n const raw = this.tools.domAttribute.process({\r\n element,\r\n key,\r\n fallback: attributes[key] ?? this.settings[key] ?? resolvedFallback,\r\n });\r\n\r\n let parsed = this.parseAttribute(raw, type, {\r\n element,\r\n boundingRect,\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>(\"start-position\", startPosition - this.data.scroll.topPosition);\r\n object.setProperty<number>(\"end-position\", endPosition - this.data.scroll.topPosition);\r\n object.setProperty<number>(\"difference-position\", endPosition - startPosition);\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 object.getProperty<number>(\"start-position\") + inviewTop\r\n );\r\n object.setProperty<number>(\r\n \"inview-end-position\",\r\n object.getProperty<number>(\"end-position\") + 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 boundingRect?: DOMRect;\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 context.boundingRect != 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 boundingRect: context.boundingRect,\r\n baseRem: context.baseRem,\r\n });\r\n } else {\r\n return 0;\r\n }\r\n\r\n case \"breakpoint-dimension\":\r\n if (\r\n context.element != null &&\r\n context.viewportHeight != null &&\r\n context.baseRem != null &&\r\n context.boundingRect != null\r\n ) {\r\n let parsedBreakpoint = value.trim().split(\"|\");\r\n let breakpoints: Array<{ breakpoint: number; value: number }> = [];\r\n for (const item of parsedBreakpoint) {\r\n if (item.includes(\":\")) {\r\n const [key, val] = item.split(\":\");\r\n breakpoints.push({\r\n breakpoint: parseInt(key),\r\n value: this.tools.unitParser.process({\r\n value: `${val}|`,\r\n element: context.element,\r\n viewportHeight: context.viewportHeight,\r\n boundingRect: context.boundingRect,\r\n baseRem: context.baseRem,\r\n }),\r\n });\r\n } else {\r\n breakpoints.push({\r\n breakpoint: 0,\r\n value: this.tools.unitParser.process({\r\n value: item,\r\n element: context.element,\r\n viewportHeight: context.viewportHeight,\r\n boundingRect: context.boundingRect,\r\n baseRem: context.baseRem,\r\n }),\r\n });\r\n }\r\n }\r\n return breakpoints;\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 this.onObjectDisconnected(object);\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 * Called when an object is disconnected. Can be overridden to clean up styles or logic.\r\n * @param object The disconnected object.\r\n */\r\n onObjectDisconnected(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 copyFn: (el: HTMLElement, mirror?: StringMirrorObject) => void = applyFn\r\n ) {\r\n if (object.getProperty(\"self-disable\") !== true) {\r\n applyFn(object.htmlElement);\r\n }\r\n object.mirrorObjects.forEach((mirror) => copyFn(mirror.htmlElement, mirror));\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 onMutate(data: StringData): void {}\r\n onScrollMeasure(data: StringData): void {}\r\n onMouseMoveMeasure(data: StringData): void {}\r\n /** Called when the window or layout is resized. */\r\n onResize(): void {}\r\n\r\n /** Called when the layout is resized width. */\r\n onResizeWidth(): 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 { ModuleManager } from \"./ModuleManager\";\r\nimport { StringData } from \"../StringData\";\r\nimport { StringMirrorObject } from \"../../objects/StringMirrorObject\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EventManager } from \"./EventManager\";\r\nimport { ISettingsChangeData } from \"../../models/event/ISettingsChangeData\";\r\nimport { StringToolsContainer } from \"../StringToolsContainer\";\r\nimport { DOMBatcher } from \"./DOMBatcher\";\r\nimport { StringModule } from \"../StringModule\";\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 mirrors = new Map<string, StringMirrorObject>();\r\n private mirrorId = 1;\r\n private globalId = 1;\r\n private domBatcher = new DOMBatcher();\r\n private domBatcherEnabled = false;\r\n private inviewStarts: Array<{ pos: number; object: StringObject }> = [];\r\n private inviewEnds: Array<{ pos: number; object: StringObject }> = [];\r\n private inviewActive = new Set<StringObject>();\r\n private inviewStartIdx = 0;\r\n private inviewEndIdx = 0;\r\n private inviewIndexDirty = true;\r\n private lastInviewScrollPos = 0;\r\n private intersectionObserverEnabled = true;\r\n\r\n constructor(\r\n private data: StringData,\r\n private modules: ModuleManager,\r\n private events: EventManager,\r\n private tools: StringToolsContainer\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) ? this.objects.get(idAttr)! : new StringObject(idAttr, el);\r\n\r\n el.setAttribute(key, object.id);\r\n\r\n const keysAttr = el.getAttribute(\"string\") ?? el.getAttribute(\"data-string\");\r\n\r\n if (keysAttr) {\r\n object.keys = (keysAttr ?? \"\")\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter(Boolean);\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 (\"setupCoreProperties\" in m && typeof m[\"setupCoreProperties\"] === \"function\") {\r\n (m as any).setupCoreProperties(object, el, attributes);\r\n }\r\n });\r\n\r\n // Try connecting to modules\r\n const connectableModules = this.modules.core.filter(\r\n (m): m is StringModule => m instanceof StringModule && m.canConnect(object)\r\n );\r\n if (this.domBatcherEnabled && connectableModules.length > 0) {\r\n const batchContexts = connectableModules.map((module) => ({\r\n module,\r\n object,\r\n element: el,\r\n attributes,\r\n globalId: this.globalId,\r\n windowSize: this.data.viewport.windowHeight,\r\n }));\r\n this.domBatcher.batchModuleInitialization(batchContexts);\r\n this.domBatcher.scheduleWrite(() => {\r\n this.initObservers(object, el);\r\n this.checkInviewForObject(object);\r\n });\r\n } else {\r\n connectableModules.forEach((m) => {\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 this.initObservers(object, el);\r\n this.checkInviewForObject(object);\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) => this.attachMirrorToObject(object, item.element));\r\n this.connectQueue = this.connectQueue.filter((q) => q.id !== object.id);\r\n this.inviewIndexDirty = true;\r\n }\r\n\r\n public setDOMBatcherEnabled(enabled: boolean): void {\r\n this.domBatcherEnabled = enabled;\r\n if (!enabled) {\r\n this.domBatcher.flushSync();\r\n }\r\n }\r\n\r\n public setIntersectionObserverEnabled(enabled: boolean): void {\r\n if (this.intersectionObserverEnabled === enabled) return;\r\n this.intersectionObserverEnabled = enabled;\r\n this.objects.forEach((object) => {\r\n object.getProperty<IntersectionObserver>(\"observer-progress\")?.disconnect();\r\n if (enabled) {\r\n this.initObservers(object, object.htmlElement);\r\n }\r\n });\r\n }\r\n\r\n public invalidateInviewIndex(): void {\r\n this.inviewIndexDirty = true;\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 obj.mirrorObjects.forEach((mirror) => {\r\n const mirrorIds = this.getMirrorIds(mirror.htmlElement);\r\n this.setMirrorIds(\r\n mirror.htmlElement,\r\n mirrorIds.filter((id) => id !== mirror.id)\r\n );\r\n this.mirrors.delete(mirror.id);\r\n\r\n const copyFromId =\r\n mirror.htmlElement.getAttribute(\"string-copy-from\") ??\r\n mirror.htmlElement.getAttribute(\"data-string-copy-from\");\r\n if (copyFromId) {\r\n this.enqueueConnection(copyFromId, mirror.htmlElement);\r\n }\r\n });\r\n\r\n this.objects.delete(id);\r\n this.inviewActive.delete(obj);\r\n this.inviewIndexDirty = true;\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 // Split by | to handle multiple IDs\r\n const ids = id\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter((s) => s.length > 0);\r\n\r\n ids.forEach((singleId) => {\r\n if (this.connectQueue.some((item) => item.id === singleId && item.element === element)) {\r\n return;\r\n }\r\n this.connectQueue.push({ id: singleId, element });\r\n });\r\n }\r\n\r\n public linkMirror(id: string, element: HTMLElement): void {\r\n // Split by | to handle multiple IDs\r\n const ids = id\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter((s) => s.length > 0);\r\n\r\n ids.forEach((singleId) => {\r\n const parent = this.objects.get(singleId);\r\n if (parent) {\r\n this.attachMirrorToObject(parent, element);\r\n } else {\r\n this.enqueueConnection(singleId, element);\r\n }\r\n });\r\n }\r\n\r\n private attachMirrorToObject(object: StringObject, element: HTMLElement): StringMirrorObject {\r\n const existingIds = this.getMirrorIds(element);\r\n for (const id of existingIds) {\r\n const existing = this.mirrors.get(id);\r\n if (existing && existing.parentObject === object) {\r\n return existing;\r\n }\r\n }\r\n\r\n const mirrorId = `string-mirror-${this.mirrorId++}`;\r\n const mirror = new StringMirrorObject(mirrorId, element, object);\r\n this.setMirrorIds(element, [...existingIds, mirrorId]);\r\n object.addMirror(mirror);\r\n this.mirrors.set(mirrorId, mirror);\r\n\r\n const easingAttr =\r\n element.getAttribute(\"string-easing\") ?? element.getAttribute(\"data-string-easing\");\r\n if (easingAttr && easingAttr.trim().length > 0) {\r\n mirror.setEasing(this.tools.easingFunction.process({ easing: easingAttr }));\r\n mirror.setProperty(\"easing\", easingAttr);\r\n }\r\n return mirror;\r\n }\r\n\r\n private detachMirrorByElement(element: HTMLElement): void {\r\n const ids = this.getMirrorIds(element);\r\n if (ids.length === 0) return;\r\n ids.forEach((id) => this.detachMirrorById(id));\r\n this.clearMirrorIds(element);\r\n }\r\n\r\n private detachMirrorById(mirrorId: string): void {\r\n const mirror = this.mirrors.get(mirrorId);\r\n if (!mirror) return;\r\n mirror.parentObject.removeMirror(mirrorId);\r\n this.mirrors.delete(mirrorId);\r\n }\r\n\r\n private getMirrorIds(element: HTMLElement): string[] {\r\n const raw =\r\n element.getAttribute(\"string-mirror-id\") ?? element.getAttribute(\"data-string-mirror-id\");\r\n if (!raw) return [];\r\n return raw\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter((s) => s.length > 0);\r\n }\r\n\r\n private setMirrorIds(element: HTMLElement, ids: string[]): void {\r\n if (ids.length === 0) {\r\n this.clearMirrorIds(element);\r\n return;\r\n }\r\n element.setAttribute(\"string-mirror-id\", ids.join(\"|\"));\r\n }\r\n\r\n private clearMirrorIds(element: HTMLElement): void {\r\n element.removeAttribute(\"string-mirror-id\");\r\n element.removeAttribute(\"data-string-mirror-id\");\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 if (!this.intersectionObserverEnabled) {\r\n return;\r\n }\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 outsideProp = obj.getProperty<boolean>(\"outside-container\");\r\n const outsideAttrValue =\r\n el.getAttribute(\"string-outside-container\") ??\r\n el.getAttribute(\"data-string-outside-container\");\r\n const outsideAttrNormalized =\r\n outsideAttrValue != null ? outsideAttrValue.trim().toLowerCase() : null;\r\n const outsideAttrFlag =\r\n outsideAttrNormalized === \"\" ||\r\n outsideAttrNormalized === \"true\" ||\r\n outsideAttrNormalized === \"1\";\r\n const isOutsideContainer = outsideProp != null ? outsideProp === true : outsideAttrFlag;\r\n const observerRoot =\r\n this.data.scroll.container === document.body || isOutsideContainer\r\n ? null\r\n : this.data.scroll.container;\r\n\r\n const progressObserver = new IntersectionObserver(progressCallback, {\r\n root: observerRoot,\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 this.detachMirrorByElement(element);\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.querySelectorAll(\"[string],[data-string]\").forEach((child) => {\r\n if (this.isFixed(child as HTMLElement)) return;\r\n this.handleRemoved(child as HTMLElement);\r\n });\r\n\r\n element\r\n .querySelectorAll(\"[string-copy-from],[data-string-copy-from]\")\r\n .forEach((child) => this.detachMirrorByElement(child as HTMLElement));\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 (element.hasAttribute(\"string\") && !element.hasAttribute(\"string-inited\")) {\r\n this.add(element);\r\n }\r\n\r\n element\r\n .querySelectorAll(\"[string]:not([string-inited]),[data-string]:not([string-inited])\")\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\r\n if (copyFrom) {\r\n this.linkMirror(copyFrom, element);\r\n }\r\n\r\n element\r\n .querySelectorAll(\"[string-copy-from],[data-string-copy-from]\")\r\n .forEach((child) => {\r\n const childCopyFrom =\r\n child.getAttribute(\"string-copy-from\") ??\r\n child.getAttribute(\"data-string-copy-from\");\r\n if (childCopyFrom) {\r\n this.linkMirror(childCopyFrom, child as HTMLElement);\r\n }\r\n });\r\n });\r\n\r\n if (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0) {\r\n this.modules.onDOMMutate(mutation.addedNodes, mutation.removedNodes);\r\n }\r\n\r\n // Let modules know about DOM rebuild\r\n this.modules.all.forEach((m) => m.onDOMRebuild());\r\n }\r\n });\r\n });\r\n\r\n observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Removes an object and its observers.\r\n */\r\n private handleRemoved(el: HTMLElement): void {\r\n const id = el.getAttribute(\"string-id\") ?? el.getAttribute(\"data-string-id\");\r\n if (!id) return;\r\n\r\n const copyFrom =\r\n el.getAttribute(\"string-copy-from\") ?? 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(data: ISettingsChangeData) {\r\n this.objects.forEach((object) => {\r\n this.modules.core.forEach((m) => {\r\n let isCanRebuild = false;\r\n if (data.isDesktop) {\r\n if (m.permissions.desktop.rebuild.scrollHeight && data.scrollHeightChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.desktop.rebuild.width && data.widthChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.desktop.rebuild.height && data.heightChanged) {\r\n isCanRebuild = true;\r\n }\r\n } else {\r\n if (m.permissions.mobile.rebuild.scrollHeight && data.scrollHeightChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.mobile.rebuild.width && data.widthChanged) {\r\n isCanRebuild = true;\r\n }\r\n if (m.permissions.mobile.rebuild.height && data.heightChanged) {\r\n isCanRebuild = true;\r\n }\r\n }\r\n\r\n if (isCanRebuild || data.isForceRebuild) {\r\n if (m.canConnect(object)) {\r\n const attributes = this.getAllAttributes(object.htmlElement);\r\n m.initializeObject(this.globalId, object, object.htmlElement, attributes);\r\n m.calculatePositions(object, this.data.viewport.windowHeight);\r\n m.connectObject(object);\r\n }\r\n }\r\n });\r\n });\r\n this.inviewIndexDirty = true;\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 const scrollPos = this.data.scroll.transformedCurrent;\r\n this.updateInviewWindow(scrollPos);\r\n this.inviewActive.forEach((object) => {\r\n this.checkInviewForObject(object);\r\n });\r\n }\r\n\r\n private checkInviewForObject(object: StringObject) {\r\n const scrollPos = this.data.scroll.transformedCurrent;\r\n if (!this.intersectionObserverEnabled) {\r\n const activeStart = object.getProperty<number>(\"start-position\");\r\n const activeEnd = object.getProperty<number>(\"end-position\");\r\n if (activeStart != null && activeEnd != null) {\r\n const activeMin = Math.min(activeStart, activeEnd);\r\n const activeMax = Math.max(activeStart, activeEnd);\r\n const wasActive = object.getProperty<boolean>(\"is-active\") ?? false;\r\n const isActive = scrollPos >= activeMin && scrollPos <= activeMax;\r\n if (isActive !== wasActive) {\r\n object.setProperty(\"is-active\", isActive);\r\n this.events.emit(`object:activate:${object.id}`, isActive);\r\n isActive ? object.enter() : object.leave();\r\n }\r\n }\r\n }\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\r\n const start = Math.min(inviewStart, inviewEnd);\r\n const end = Math.max(inviewStart, inviewEnd);\r\n const isNowInView = scrollPos >= start && scrollPos <= end;\r\n\r\n let direction: \"enter-top\" | \"enter-bottom\" | \"exit-top\" | \"exit-bottom\" | null = null;\r\n if (!wasInView && isNowInView) {\r\n const distToStart = Math.abs(scrollPos - start);\r\n const distToEnd = Math.abs(end - scrollPos);\r\n direction = distToStart <= distToEnd ? \"enter-top\" : \"enter-bottom\";\r\n } else if (wasInView && !isNowInView) {\r\n direction = scrollPos < start ? \"exit-top\" : \"exit-bottom\";\r\n }\r\n if (isNowInView !== wasInView) {\r\n object.setProperty(\"is-inview\", isNowInView);\r\n this.events.emit(`object:inview:${object.id}`, {\r\n inView: isNowInView,\r\n direction,\r\n });\r\n isNowInView ? object.show() : object.hide();\r\n }\r\n }\r\n\r\n private updateInviewWindow(scrollPos: number) {\r\n const buffer = this.data.viewport.windowHeight;\r\n const windowMin = scrollPos - buffer;\r\n const windowMax = scrollPos + this.data.viewport.windowHeight + buffer;\r\n\r\n if (this.inviewIndexDirty || scrollPos < this.lastInviewScrollPos) {\r\n this.rebuildInviewIndex(windowMin, windowMax);\r\n }\r\n\r\n while (\r\n this.inviewStartIdx < this.inviewStarts.length &&\r\n this.inviewStarts[this.inviewStartIdx].pos <= windowMax\r\n ) {\r\n this.inviewActive.add(this.inviewStarts[this.inviewStartIdx].object);\r\n this.inviewStartIdx++;\r\n }\r\n\r\n while (\r\n this.inviewEndIdx < this.inviewEnds.length &&\r\n this.inviewEnds[this.inviewEndIdx].pos < windowMin\r\n ) {\r\n this.inviewActive.delete(this.inviewEnds[this.inviewEndIdx].object);\r\n this.inviewEndIdx++;\r\n }\r\n\r\n this.lastInviewScrollPos = scrollPos;\r\n }\r\n\r\n private rebuildInviewIndex(windowMin: number, windowMax: number) {\r\n this.inviewStarts = [];\r\n this.inviewEnds = [];\r\n\r\n this.objects.forEach((object) => {\r\n const start = object.getProperty<number>(\"inview-start-position\");\r\n const end = object.getProperty<number>(\"inview-end-position\");\r\n if (start == null || end == null) return;\r\n this.inviewStarts.push({ pos: Math.min(start, end), object });\r\n this.inviewEnds.push({ pos: Math.max(start, end), object });\r\n });\r\n\r\n this.inviewStarts.sort((a, b) => a.pos - b.pos);\r\n this.inviewEnds.sort((a, b) => a.pos - b.pos);\r\n\r\n this.inviewActive.clear();\r\n\r\n this.inviewStartIdx = this.upperBound(this.inviewStarts, windowMax);\r\n this.inviewEndIdx = this.upperBound(this.inviewEnds, windowMin - 1);\r\n\r\n for (let i = 0; i < this.inviewStartIdx; i++) {\r\n this.inviewActive.add(this.inviewStarts[i].object);\r\n }\r\n for (let i = 0; i < this.inviewEndIdx; i++) {\r\n this.inviewActive.delete(this.inviewEnds[i].object);\r\n }\r\n\r\n this.inviewIndexDirty = false;\r\n }\r\n\r\n private upperBound(list: Array<{ pos: number }>, value: number): number {\r\n let low = 0;\r\n let high = list.length;\r\n while (low < high) {\r\n const mid = (low + high) >>> 1;\r\n if (list[mid].pos <= value) low = mid + 1;\r\n else high = mid;\r\n }\r\n return low;\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(0, this.context.data.scroll.current);\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(this.context.data.scroll.current, 0);\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Creates a new ScrollController instance.\r\n * @param context Shared context containing data and settings.\r\n */\r\n constructor(context: StringContext) {\r\n this.document = document;\r\n this.context = context;\r\n }\r\n\r\n /**\r\n * Called when scroll direction changes (up ↔ down).\r\n * Override this callback in subclasses or instances.\r\n */\r\n public onChangeDirection = () => {};\r\n\r\n /**\r\n * Called when scroll starts (user input).\r\n * Override this callback in subclasses or instances.\r\n */\r\n public onScrollStart = () => {};\r\n\r\n /**\r\n * Called when scroll ends.\r\n * Override this callback in subclasses or instances.\r\n */\r\n public onScrollStop = () => {};\r\n\r\n /**\r\n * Scroll-to function called on each frame.\r\n * This will be reassigned depending on scroll direction.\r\n */\r\n public onCalcUpdate: () => void = () => {\r\n this.context.data.scroll.scrollContainer?.scrollTo(0, this.context.data.scroll.current);\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((rule) => rule.id !== id);\r\n }\r\n\r\n public scrollTo(position: number) {}\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 public scrollTo(position: number) {\r\n this.context.data.scroll.target = position;\r\n this.context.data.scroll.delta = 1;\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","/**\r\n * CSS class names applied to `<html>` element based on scroll direction.\r\n */\r\nexport const SCROLL_CLASS_NAMES = {\r\n SCROLL_FORWARD: \"-scroll-forward\",\r\n SCROLL_BACKWARD: \"-scroll-backward\",\r\n SCROLLING_FORWARD: \"-scrolling-forward\",\r\n SCROLLING_BACKWARD: \"-scrolling-backward\",\r\n} as const;\r\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 this.context.events.emit(`scroll:direction:change`, this.context.data.scroll.isScrollingDown);\r\n\r\n if (this.context.settings[\"global-class\"]) {\r\n document.documentElement.classList.toggle(SCROLL_CLASS_NAMES.SCROLLING_FORWARD, newDirection);\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLLING_BACKWARD,\r\n !newDirection\r\n );\r\n document.documentElement.classList.toggle(SCROLL_CLASS_NAMES.SCROLL_FORWARD, newDirection);\r\n document.documentElement.classList.toggle(SCROLL_CLASS_NAMES.SCROLL_BACKWARD, !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 = this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.target = this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current * 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 = this.context.data.scroll.delta * this.context.data.scroll.speedAccelerate;\r\n\r\n this.context.data.scroll.target = Math.min(\r\n Math.max(0, this.context.data.scroll.target + this.scrollForce),\r\n this.context.data.scroll.bottomPosition\r\n );\r\n this.context.data.scroll.delta -= this.scrollForce;\r\n\r\n this.context.data.scroll.lerped =\r\n (this.context.data.scroll.target - this.context.data.scroll.current) *\r\n this.context.data.scroll.speed;\r\n\r\n const absVelocity = Math.abs(this.context.data.scroll.lerped);\r\n if (this.context.data.scroll.lerped > 0) {\r\n this.context.data.scroll.current = Math.ceil(\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 * 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 === this.context.data.scroll.bottomPosition &&\r\n scrollDirection > 0;\r\n\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 public scrollTo(position: number) {\r\n this.context.data.scroll.target = position;\r\n this.context.data.scroll.delta = 1;\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 < 1024;\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 * Velocity in X direction, calculated from smoothed position.\r\n */\r\n velocityX: number = 0;\r\n\r\n /**\r\n * Velocity in Y direction, calculated from smoothed position.\r\n */\r\n velocityY: 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","export class SystemState {\n fpsTracker: boolean = false;\n positionTracker: boolean = false;\n}\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 { SystemState } from \"../states/SystemState\";\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 system = new SystemState();\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 boundingRect: DOMRect;\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, boundingRect }: UnitParserInput): number {\r\n const parts = value\r\n .split(\"|\")\r\n .map((s) => s.trim())\r\n .filter(Boolean);\r\n\r\n let sum = 0;\r\n for (const part of parts) {\r\n let v = part;\r\n let isNegative = false;\r\n if (v.startsWith(\"-\")) {\r\n isNegative = true;\r\n v = v.slice(1);\r\n }\r\n let result = 0;\r\n if (v === \"selfHeight\") {\r\n result = element.offsetHeight;\r\n } else if (v.endsWith(\"px\")) {\r\n result = parseFloat(v);\r\n } else if (v.endsWith(\"%\")) {\r\n result = (parseFloat(v) / 100) * viewportHeight;\r\n } else if (v.endsWith(\"rem\")) {\r\n result = parseFloat(v) * baseRem;\r\n } else if (v.endsWith(\"sh\")) {\r\n result = (parseFloat(v) * boundingRect.height) / 100;\r\n } else {\r\n result = parseFloat(v);\r\n }\r\n\r\n sum += isNegative ? -result : result;\r\n }\r\n\r\n return sum;\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 * Input for parsing origin to normalized coordinates.\r\n * Supports formats like `'left top'`, `'center center'`, `'50% 50%'`, `'35% 76%'`.\r\n */\r\ninterface OriginToNormalizedInput {\r\n /** Raw origin string, e.g. `'left top'`, `'center'`, `'50% 25%'`. */\r\n value: string;\r\n}\r\n\r\n/**\r\n * Output: normalized origin coordinates (0-1 range).\r\n */\r\ninterface NormalizedOrigin {\r\n /** Normalized X coordinate (0 = left, 0.5 = center, 1 = right). */\r\n x: number;\r\n /** Normalized Y coordinate (0 = top, 0.5 = center, 1 = bottom). */\r\n y: number;\r\n}\r\n\r\n/** Keyword mappings for horizontal axis. */\r\nconst HORIZONTAL_KEYWORDS: Record<string, number> = {\r\n left: 0,\r\n center: 0.5,\r\n right: 1,\r\n};\r\n\r\n/** Keyword mappings for vertical axis. */\r\nconst VERTICAL_KEYWORDS: Record<string, number> = {\r\n top: 0,\r\n center: 0.5,\r\n bottom: 1,\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 * Also provides `toNormalized()` method to convert origin strings to `{ x, y }` coordinates.\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 if (!value) return \"center\";\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 /**\r\n * Parses an origin string to normalized `{ x, y }` coordinates (0-1 range).\r\n *\r\n * Supported formats:\r\n * - Single keyword: `'center'`, `'top'`, `'left'`, etc.\r\n * - Two keywords: `'left top'`, `'right bottom'`, `'center center'`\r\n * - Percentages: `'50% 50%'`, `'0% 100%'`, `'35% 76%'`\r\n * - Mixed: `'left 25%'`, `'50% top'`\r\n *\r\n * @param input - The origin string to parse.\r\n * @returns Normalized `{ x, y }` coordinates.\r\n */\r\n toNormalized({ value }: OriginToNormalizedInput): NormalizedOrigin {\r\n const raw = this.process({ value });\r\n const parts = raw.toLowerCase().split(/\\s+/).filter(Boolean);\r\n\r\n if (parts.length === 0) {\r\n return { x: 0.5, y: 0.5 };\r\n }\r\n\r\n if (parts.length === 1) {\r\n const single = parts[0];\r\n const parsed = this.parseValue(single);\r\n\r\n // If it's a horizontal keyword, use center for Y\r\n if (single in HORIZONTAL_KEYWORDS && !(single in VERTICAL_KEYWORDS)) {\r\n return { x: parsed, y: 0.5 };\r\n }\r\n // If it's a vertical keyword, use center for X\r\n if (single in VERTICAL_KEYWORDS && !(single in HORIZONTAL_KEYWORDS)) {\r\n return { x: 0.5, y: parsed };\r\n }\r\n // 'center' or percentage applies to both\r\n return { x: parsed, y: parsed };\r\n }\r\n\r\n // Two parts: determine which is X and which is Y\r\n const [first, second] = parts;\r\n\r\n // Check if keywords need to be swapped (e.g., \"top left\" → x=left, y=top)\r\n const firstIsVerticalOnly = first in VERTICAL_KEYWORDS && !(first in HORIZONTAL_KEYWORDS);\r\n const secondIsHorizontalOnly = second in HORIZONTAL_KEYWORDS && !(second in VERTICAL_KEYWORDS);\r\n\r\n if (firstIsVerticalOnly || secondIsHorizontalOnly) {\r\n // Swap: first is Y, second is X\r\n return {\r\n x: this.parseValue(second, \"horizontal\"),\r\n y: this.parseValue(first, \"vertical\"),\r\n };\r\n }\r\n\r\n // Default order: first is X, second is Y\r\n return {\r\n x: this.parseValue(first, \"horizontal\"),\r\n y: this.parseValue(second, \"vertical\"),\r\n };\r\n }\r\n\r\n /**\r\n * Parses a single value (keyword or percentage) to a normalized number.\r\n */\r\n private parseValue(val: string, axis?: \"horizontal\" | \"vertical\"): number {\r\n // Check keywords\r\n if (axis === \"horizontal\" && val in HORIZONTAL_KEYWORDS) {\r\n return HORIZONTAL_KEYWORDS[val];\r\n }\r\n if (axis === \"vertical\" && val in VERTICAL_KEYWORDS) {\r\n return VERTICAL_KEYWORDS[val];\r\n }\r\n if (val in HORIZONTAL_KEYWORDS) {\r\n return HORIZONTAL_KEYWORDS[val];\r\n }\r\n if (val in VERTICAL_KEYWORDS) {\r\n return VERTICAL_KEYWORDS[val];\r\n }\r\n\r\n // Parse percentage\r\n if (val.endsWith(\"%\")) {\r\n const num = parseFloat(val);\r\n if (!isNaN(num)) {\r\n return num / 100;\r\n }\r\n }\r\n\r\n // Parse plain number (treat as percentage)\r\n const num = parseFloat(val);\r\n if (!isNaN(num)) {\r\n // If it's a small number (0-1), treat as normalized\r\n // If it's larger, treat as percentage\r\n return num > 1 ? num / 100 : num;\r\n }\r\n\r\n // Default to center\r\n return 0.5;\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\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 { IStringTool } from \"../core/IStringTool\";\n\nexport interface RuleParserInput {\n value: string;\n}\n\nexport interface RuleParserResult {\n key: string;\n params?: string[];\n}\n\nexport default class RuleParserTool implements IStringTool<RuleParserInput, RuleParserResult[]> {\n process({ value }: RuleParserInput): RuleParserResult[] {\n const result: string[] = [];\n let current = \"\";\n let depth = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value[i];\n if (c === \"(\") depth++;\n if (c === \")\") depth--;\n if (c === \"|\" && depth === 0) {\n if (current.trim()) result.push(current.trim());\n current = \"\";\n } else {\n current += c;\n }\n }\n if (current.trim()) result.push(current.trim());\n\n return result.map((ruleStr) => {\n const match = ruleStr.match(/^(\\w+)(?:\\((.*)\\))?$/);\n if (match) {\n const [, key, params] = match;\n if (params) {\n return { key, params: params.split(\",\").map((s) => s.trim()) };\n }\n return { key };\n }\n\n const colonIndex = ruleStr.indexOf(\":\");\n if (colonIndex !== -1) {\n const key = ruleStr.slice(0, colonIndex).trim();\n const paramsString = ruleStr.slice(colonIndex + 1).trim();\n const params = paramsString ? paramsString.split(\",\").map((s) => s.trim()) : undefined;\n return { key, params };\n }\n\n return { key: ruleStr };\n });\n }\n}\n","import { IStringTool } from \"../core/IStringTool\";\r\nimport { RuleParserResult } from \"./RuleParserTool\";\r\n\r\nexport interface ValidationContext {\r\n fieldKey?: string;\r\n values?: Record<string, any>;\r\n getValue?: (key: string) => any;\r\n}\r\n\r\nexport interface ValidateInput {\r\n rules: RuleParserResult[];\r\n value: any;\r\n type?: \"input\" | \"beforeinput\";\r\n context?: ValidationContext;\r\n}\r\n\r\nexport interface ValidationResult {\r\n valid: boolean;\r\n errors: string[];\r\n}\r\n\r\ntype ValidatorFn = (value: any, params?: string[], context?: ValidationContext) => boolean;\r\n\r\nexport class ValidationTool implements IStringTool<ValidateInput, ValidationResult> {\r\n process({ rules, value, type = \"input\", context }: ValidateInput): ValidationResult {\r\n const errors: string[] = [];\r\n for (const rule of rules) {\r\n var beforeInputValidatorFn: ValidatorFn | null = null;\r\n var inputValidatorFn: ValidatorFn | null = null;\r\n var inputValid = true;\r\n var beforeInputValid = true;\r\n\r\n if (type == \"input\") {\r\n inputValidatorFn = this.inputValidators[rule.key];\r\n if (!inputValidatorFn) continue;\r\n }\r\n if (type == \"beforeinput\") {\r\n beforeInputValidatorFn = this.beforeInputValidators[rule.key];\r\n if (!beforeInputValidatorFn) continue;\r\n }\r\n\r\n if (inputValidatorFn) {\r\n inputValid = inputValidatorFn(value, rule.params, context);\r\n }\r\n if (beforeInputValidatorFn) {\r\n beforeInputValid = beforeInputValidatorFn(value, rule.params, context);\r\n }\r\n\r\n if (!beforeInputValid) {\r\n errors.push(this.getErrorMessage(rule.key, rule.params));\r\n }\r\n if (!inputValid) {\r\n errors.push(this.getErrorMessage(rule.key, rule.params));\r\n }\r\n }\r\n return { valid: errors.length === 0, errors };\r\n }\r\n\r\n inputValidators: Record<string, ValidatorFn> = {\r\n required: (v) => v != null && String(v).trim() !== \"\",\r\n min: (v, params) => typeof v === \"string\" && v.length >= Number(params?.[0] ?? 0),\r\n max: (v, params) =>\r\n typeof v === \"string\" && v.length <= Number(params?.[0] ?? Number.MAX_SAFE_INTEGER),\r\n checked: (v) => {\r\n if (Array.isArray(v)) {\r\n return v.length > 0;\r\n }\r\n if (v === true || v === \"true\" || v === 1 || v === \"1\") {\r\n return true;\r\n }\r\n if (typeof v === \"string\") {\r\n const normalized = v.trim().toLowerCase();\r\n if (normalized === \"false\" || normalized === \"0\") {\r\n return false;\r\n }\r\n return normalized.length > 0;\r\n }\r\n return !!v;\r\n },\r\n email: (v) => typeof v === \"string\" && /^[\\w.-]+@([\\w-]+\\.)+[\\w-]{2,}$/.test(v),\r\n phone: (v) => {\r\n if (typeof v !== \"string\") return false;\r\n const normalized = v.trim();\r\n if (normalized === \"\") return false;\r\n if (!/^[0-9()\\s+-.]+$/.test(normalized)) return false;\r\n const digitCount = normalized.replace(/\\D/g, \"\").length;\r\n return digitCount >= 7 && digitCount <= 15;\r\n },\r\n number: (v) => typeof v === \"string\" && /^-?\\d+(\\.\\d+)?$/.test(v),\r\n integer: (v) => typeof v === \"string\" && /^-?\\d+$/.test(v),\r\n url: (v) =>\r\n typeof v === \"string\" &&\r\n /^(https?:\\/\\/)?([\\w\\-]+\\.)+[\\w\\-]+(\\/[\\w\\-._~:\\/?#[\\]@!$&'()*+,;=]*)?$/.test(v),\r\n regex: (v, params) => this.testByRegex(v, params?.[0]),\r\n alpha: (v) => this.testByRegex(v, \"^[A-Za-z]+$\", true),\r\n alpha_num: (v) => this.testByRegex(v, \"^[A-Za-z0-9]+$\", true),\r\n alpha_dash: (v) => this.testByRegex(v, \"^[A-Za-z0-9_-]+$\", true),\r\n same: (v, params, context) => {\r\n const targetKey = params?.[0];\r\n const otherValue = this.getContextValue(context, targetKey);\r\n if (targetKey && otherValue === undefined) return false;\r\n return this.areValuesEqual(v, otherValue);\r\n },\r\n different: (v, params, context) => {\r\n const targetKey = params?.[0];\r\n const otherValue = this.getContextValue(context, targetKey);\r\n if (targetKey && otherValue === undefined) return false;\r\n return !this.areValuesEqual(v, otherValue);\r\n },\r\n range: (v, params) => {\r\n if (v == null || v === \"\") return true;\r\n const value = Number(v);\r\n const min = Number(params?.[0]);\r\n const max = Number(params?.[1]);\r\n if (Number.isNaN(value) || Number.isNaN(min) || Number.isNaN(max)) {\r\n return false;\r\n }\r\n return value >= min && value <= max;\r\n },\r\n digits: (v, params) => {\r\n if (typeof v !== \"string\") return false;\r\n const length = Number(params?.[0] ?? 0);\r\n if (length <= 0) return false;\r\n return new RegExp(`^\\\\d{${length}}$`).test(v);\r\n },\r\n ip: (v) => typeof v === \"string\" && (this.isIPv4(v) || this.isIPv6(v)),\r\n mimes: (v, params) => this.validateMimes(v, params),\r\n max_size: (v, params) => {\r\n const limit = Number(params?.[0]);\r\n if (!limit || limit <= 0) return true;\r\n return this.validateMaxSize(v, limit);\r\n },\r\n after: (v, params, context) => this.compareDates(v, params, context, \"after\"),\r\n before: (v, params, context) => this.compareDates(v, params, context, \"before\"),\r\n };\r\n\r\n beforeInputValidators: Record<string, ValidatorFn> = {\r\n number: (v) => /^-?\\d*\\.?\\d*$/.test(v),\r\n integer: (v) => /^-?\\d*$/.test(v),\r\n email: (v) => /^[\\w@.\\-+]*$/.test(v),\r\n phone: (v) => /^[0-9()\\s+-.]*$/.test(v),\r\n letters: (v) => /^[a-zA-Z]*$/.test(v),\r\n lettersSpaces: (v) => /^[a-zA-Z\\s]*$/.test(v),\r\n lettersNumbers: (v) => /^[a-zA-Z0-9]*$/.test(v),\r\n alpha: (v) => /^[A-Za-z]*$/.test(v),\r\n alpha_num: (v) => /^[A-Za-z0-9]*$/.test(v),\r\n alpha_dash: (v) => /^[A-Za-z0-9_-]*$/.test(v),\r\n digits: (v, params) => {\r\n const length = Number(params?.[0] ?? 0);\r\n if (length <= 0) return /^\\d*$/.test(v);\r\n return new RegExp(`^\\\\d{0,${length}}$`).test(v);\r\n },\r\n url: (v) => /^[a-zA-Z0-9\\-._~:\\/?#\\[\\]@!$&'()*+,;=%]*$/.test(v),\r\n pattern: (v, params) => {\r\n try {\r\n return new RegExp(params?.[0] || \"\").test(v);\r\n } catch {\r\n return true;\r\n }\r\n },\r\n };\r\n\r\n getErrorMessage(key: string, params?: string[]): string {\r\n switch (key) {\r\n case \"required\":\r\n return \"This field is required\";\r\n case \"email\":\r\n return \"Invalid email address\";\r\n case \"min\":\r\n return `Minimum ${params?.[0]} characters`;\r\n case \"max\":\r\n return `Maximum ${params?.[0]} characters`;\r\n case \"phone\":\r\n return \"Invalid phone number\";\r\n case \"number\":\r\n return \"Only numbers are allowed\";\r\n case \"integer\":\r\n return \"Only whole numbers are allowed\";\r\n case \"url\":\r\n return \"Invalid URL address\";\r\n case \"checked\":\r\n return \"You must accept\";\r\n case \"regex\":\r\n return \"Value does not match the required pattern\";\r\n case \"alpha\":\r\n return \"Only letters are allowed\";\r\n case \"alpha_num\":\r\n return \"Only letters and numbers are allowed\";\r\n case \"alpha_dash\":\r\n return \"Only letters, numbers, dashes, and underscores are allowed\";\r\n case \"same\":\r\n return \"Values do not match\";\r\n case \"different\":\r\n return \"Values must be different\";\r\n case \"range\":\r\n return `Value must be between ${params?.[0]} and ${params?.[1]}`;\r\n case \"digits\":\r\n return `Value must contain exactly ${params?.[0]} digits`;\r\n case \"ip\":\r\n return \"Invalid IP address\";\r\n case \"mimes\":\r\n return `Allowed file types: ${params?.join(\", \")}`;\r\n case \"max_size\":\r\n return `File must be smaller than ${params?.[0]} KB`;\r\n case \"after\":\r\n return `Date must be after ${params?.[0]}`;\r\n case \"before\":\r\n return `Date must be before ${params?.[0]}`;\r\n default:\r\n return \"Invalid value\";\r\n }\r\n }\r\n\r\n private validateMimes(value: any, params?: string[]): boolean {\r\n if (!params || params.length === 0) return true;\r\n const files = this.extractFiles(value);\r\n if (files.length === 0) return true;\r\n const allowed = params.map((p) => p.trim().toLowerCase());\r\n return files.every((file) => this.isMimeAllowed(file, allowed));\r\n }\r\n\r\n private validateMaxSize(value: any, limitKb: number): boolean {\r\n const files = this.extractFiles(value);\r\n if (files.length === 0) return true;\r\n const maxBytes = limitKb * 1024;\r\n return files.every((file) => {\r\n if (typeof file.size !== \"number\") return true;\r\n return file.size <= maxBytes;\r\n });\r\n }\r\n\r\n private extractFiles(value: any): Array<{ name?: string; size?: number; type?: string }> {\r\n if (!value) return [];\r\n const files: Array<{ name?: string; size?: number; type?: string }> = [];\r\n\r\n if (typeof File !== \"undefined\" && value instanceof File) {\r\n files.push(value);\r\n return files;\r\n }\r\n\r\n if (typeof FileList !== \"undefined\" && value instanceof FileList) {\r\n return Array.from(value);\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n value.forEach((item) => {\r\n files.push(...this.extractFiles(item));\r\n });\r\n return files;\r\n }\r\n\r\n if (typeof value === \"object\" && (\"name\" in value || \"size\" in value || \"type\" in value)) {\r\n files.push(value as any);\r\n return files;\r\n }\r\n\r\n if (typeof value === \"string\" && value !== \"\") {\r\n files.push({ name: value });\r\n }\r\n\r\n return files;\r\n }\r\n\r\n private isMimeAllowed(file: { name?: string; type?: string }, allowed: string[]): boolean {\r\n const mime = (file.type || \"\").toLowerCase();\r\n const ext = this.getFileExtension(file.name);\r\n return allowed.some((rule) => {\r\n const normalized = rule.replace(/^\\./, \"\").toLowerCase();\r\n if (!normalized) return false;\r\n if (normalized.includes(\"/\")) {\r\n return mime === normalized;\r\n }\r\n return ext === normalized;\r\n });\r\n }\r\n\r\n private getFileExtension(name?: string): string {\r\n if (!name) return \"\";\r\n const parts = name.split(\".\");\r\n if (parts.length <= 1) return \"\";\r\n return (parts.pop() || \"\").toLowerCase();\r\n }\r\n\r\n private compareDates(\r\n value: any,\r\n params: string[] | undefined,\r\n context: ValidationContext | undefined,\r\n mode: \"before\" | \"after\"\r\n ): boolean {\r\n if (value == null || value === \"\") return true;\r\n const target = params?.[0];\r\n if (!target) return true;\r\n const currentDate = this.toDate(value);\r\n const referenceDate = this.resolveDateReference(target, context);\r\n if (!currentDate || !referenceDate) return false;\r\n return mode === \"after\"\r\n ? currentDate.getTime() > referenceDate.getTime()\r\n : currentDate.getTime() < referenceDate.getTime();\r\n }\r\n\r\n private resolveDateReference(token: string, context?: ValidationContext): Date | null {\r\n const contextualValue = this.getContextValue(context, token);\r\n if (contextualValue !== undefined) {\r\n return this.toDate(contextualValue);\r\n }\r\n if (token.toLowerCase() === \"now\") {\r\n return new Date();\r\n }\r\n if (token.toLowerCase() === \"today\") {\r\n const today = new Date();\r\n today.setHours(0, 0, 0, 0);\r\n return today;\r\n }\r\n return this.toDate(token);\r\n }\r\n\r\n private toDate(value: any): Date | null {\r\n if (value == null || value === \"\") return null;\r\n if (value instanceof Date) {\r\n return Number.isNaN(value.getTime()) ? null : value;\r\n }\r\n if (typeof value === \"number\") {\r\n const date = new Date(value);\r\n return Number.isNaN(date.getTime()) ? null : date;\r\n }\r\n if (typeof value === \"string\") {\r\n const timestamp = Date.parse(value);\r\n if (!Number.isNaN(timestamp)) {\r\n return new Date(timestamp);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private testByRegex(value: any, pattern?: string, allowEmpty = false): boolean {\r\n if (pattern == null || pattern === \"\") return true;\r\n const stringValue = typeof value === \"string\" ? value : value == null ? \"\" : String(value);\r\n if (allowEmpty && stringValue === \"\") return true;\r\n try {\r\n const { source, flags } = this.normalizeRegex(pattern);\r\n return new RegExp(source, flags).test(stringValue);\r\n } catch {\r\n return true;\r\n }\r\n }\r\n\r\n private normalizeRegex(pattern: string): { source: string; flags: string } {\r\n const trimmed = pattern.trim();\r\n if (trimmed.startsWith(\"/\") && trimmed.lastIndexOf(\"/\") > 0) {\r\n const lastSlashIndex = trimmed.lastIndexOf(\"/\");\r\n const source = trimmed.slice(1, lastSlashIndex);\r\n const flags = trimmed.slice(lastSlashIndex + 1);\r\n return { source, flags };\r\n }\r\n return { source: trimmed, flags: \"\" };\r\n }\r\n\r\n private getContextValue(context: ValidationContext | undefined, key?: string): any {\r\n if (!context || !key) return undefined;\r\n if (context.values && Object.prototype.hasOwnProperty.call(context.values, key)) {\r\n return context.values[key];\r\n }\r\n if (context.getValue) {\r\n return context.getValue(key);\r\n }\r\n return undefined;\r\n }\r\n\r\n private areValuesEqual(a: any, b: any): boolean {\r\n if (Array.isArray(a) || Array.isArray(b)) {\r\n return JSON.stringify(a) === JSON.stringify(b);\r\n }\r\n return a === b;\r\n }\r\n\r\n private isIPv4(value: string): boolean {\r\n const segments = value.split(\".\");\r\n if (segments.length !== 4) return false;\r\n return segments.every((segment) => {\r\n if (!/^\\d+$/.test(segment)) return false;\r\n const num = Number(segment);\r\n return num >= 0 && num <= 255;\r\n });\r\n }\r\n\r\n private isIPv6(value: string): boolean {\r\n if (!value) return false;\r\n if (value === \"::\") return true;\r\n const parts = value.split(\"::\");\r\n if (parts.length > 2) return false;\r\n\r\n const hextetPattern = /^[0-9a-fA-F]{1,4}$/;\r\n const segments = value.split(\":\");\r\n if (parts.length === 2) {\r\n return (\r\n segments.every((segment) => segment === \"\" || hextetPattern.test(segment)) &&\r\n segments.length <= 8\r\n );\r\n }\r\n return segments.length === 8 && segments.every((segment) => hextetPattern.test(segment));\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 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\nimport RuleParserTool from \"../tools/RuleParserTool\";\r\nimport { ValidationTool } from \"../tools/ValidationTool\";\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 ruleParser: RuleParserTool;\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 public ruleParser = new RuleParserTool();\r\n}\r\n","export function isCoarsePointer(): boolean {\n const mm =\n typeof window !== \"undefined\" && typeof window.matchMedia === \"function\"\n ? window.matchMedia(\"(pointer: coarse)\").matches\n : false;\n const touch = typeof navigator !== \"undefined\" ? (navigator.maxTouchPoints || 0) > 0 : false;\n const narrow = typeof window !== \"undefined\" ? window.innerWidth <= 768 : false;\n return mm || touch || narrow;\n}\n","type StyleValue = string | number;\ntype StyleVars = Record<string, StyleValue>;\ntype StyleProps = Record<string, StyleValue>;\n\nclass StyleTxn {\n private pendingVars = new Map<Element, StyleVars>();\n private pendingProps = new Map<Element, StyleProps>();\n private isOpen = false;\n\n public begin(): void {\n if (this.isOpen) return;\n this.isOpen = true;\n }\n\n public setVars(el: Element, vars: StyleVars): void {\n if (!this.isOpen) {\n console.warn(\"StyleTxn: call begin() first to set custom properties.\");\n return;\n }\n const currentVars = this.pendingVars.get(el) ?? {};\n for (const [k, v] of Object.entries(vars)) {\n if (currentVars[k] === v) continue;\n currentVars[k] = v;\n }\n this.pendingVars.set(el, currentVars);\n }\n\n public setProps(el: Element, props: StyleProps): void {\n if (!this.isOpen) {\n console.warn(\"StyleTxn: call begin() first to set standard properties.\");\n return;\n }\n const currentProps = this.pendingProps.get(el) ?? {};\n for (const [k, v] of Object.entries(props)) {\n if (currentProps[k] === v) continue;\n currentProps[k] = v;\n }\n\n this.pendingProps.set(el, currentProps);\n }\n\n public run(fn: () => void): void {\n const alreadyOpen = this.isOpen;\n if (!alreadyOpen) {\n this.begin();\n }\n try {\n fn();\n if (!alreadyOpen) {\n this.commit();\n }\n } catch (error) {\n if (!alreadyOpen) {\n this.cancel();\n }\n throw error;\n }\n }\n\n public commit(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n\n for (const [el, vars] of this.pendingVars) {\n const style = (el as HTMLElement).style;\n for (const [k, v] of Object.entries(vars)) {\n style.setProperty(k, String(v));\n }\n }\n this.pendingVars.clear();\n\n for (const [el, props] of this.pendingProps) {\n const style = (el as HTMLElement).style;\n for (const [k, v] of Object.entries(props)) {\n (style as any)[k] = String(v);\n }\n }\n this.pendingProps.clear();\n }\n\n public cancel(): void {\n this.pendingVars.clear();\n this.pendingProps.clear();\n this.isOpen = false;\n }\n}\n\nexport const styleTxn = new StyleTxn();\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\nimport { isCoarsePointer } from \"../../utils/isCoarsePointer\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\ntype CursorTargetState = {\r\n prevX: number;\r\n prevY: number;\r\n};\r\n\r\ntype CursorObjectDimensions = {\r\n width: number;\r\n height: number;\r\n halfWidth: number;\r\n halfHeight: number;\r\n};\r\n\r\ntype CursorPrevSnapshot = {\r\n x: number;\r\n y: number;\r\n stepX: number;\r\n stepY: number;\r\n};\r\n\r\ntype CursorPortal = {\r\n id: string;\r\n element: HTMLElement;\r\n content: HTMLElement | null;\r\n prev: CursorPrevSnapshot;\r\n hoverCount: number;\r\n showTimer: ReturnType<typeof setTimeout> | null;\r\n lerp: number | null;\r\n};\r\n\r\nconst targetStates = new WeakMap<StringObject, CursorTargetState>();\r\nconst CURSOR_EPSILON = 0.0005;\r\nconst DEFAULT_CURSOR_ID = \"default\";\r\nconst CURSOR_PORTAL_SELECTOR = \"[string-cursor],[data-string-cursor]\";\r\nconst CURSOR_PORTAL_CONTENT_SELECTOR = \"[string-cursor-content],[data-string-cursor-content]\";\r\nconst MIN_FRAME_DELTA = 1 / 240;\r\n\r\nfunction getTargetState(object: StringObject): CursorTargetState {\r\n let state = targetStates.get(object);\r\n if (!state) {\r\n state = { prevX: Number.NaN, prevY: Number.NaN };\r\n targetStates.set(object, state);\r\n }\r\n return state;\r\n}\r\n\r\n/**\r\n * StringCursor Module\r\n *\r\n * Handles cursor tracking and hover states for StringTune objects.\r\n *\r\n * Safari Navigation Fix:\r\n * Safari has an issue where mouseleave events are not fired when navigation occurs\r\n * (especially with NuxtLink/router navigation). This module includes several\r\n * workarounds to ensure proper cleanup:\r\n *\r\n * 1. MutationObserver - detects when elements are removed from DOM\r\n * 2. beforeunload/pagehide - captures traditional navigation\r\n * 3. visibilitychange - captures modern SPA navigation\r\n * 4. DOM existence checks - prevents operations on removed elements\r\n */\r\nexport class StringCursor extends StringModule {\r\n private cursorPrev: CursorPrevSnapshot = {\r\n x: Number.NaN,\r\n y: Number.NaN,\r\n stepX: Number.NaN,\r\n stepY: Number.NaN,\r\n };\r\n private cursorPortals: Map<string, CursorPortal[]> = new Map();\r\n private hoveredObjects: Set<StringObject> = new Set();\r\n private globalListenersBound = false;\r\n private boundBeforeUnload = () => this.cleanupHoverTargets();\r\n private boundPageHide = () => this.cleanupHoverTargets();\r\n private boundVisibilityChange = () => {\r\n if (document.hidden) {\r\n this.cleanupHoverTargets();\r\n }\r\n };\r\n protected enabled = true;\r\n\r\n private lastFrameTime: number = 0;\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"cursor\";\r\n\r\n this.permissions.mobile.rebuild.height = false;\r\n this.permissions.mobile.rebuild.width = false;\r\n this.permissions.mobile.rebuild.scrollHeight = false;\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: \"cursor-target\",\r\n type: \"string\",\r\n fallback: this.settings[\"cursor-target\"] ?? DEFAULT_CURSOR_ID,\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: \"cursor-enter\",\r\n type: { type: \"enum\", values: [\"snap\", \"smooth\"] },\r\n fallback: \"snap\",\r\n },\r\n {\r\n key: \"cursor-leave\",\r\n type: { type: \"enum\", values: [\"snap\", \"smooth\"] },\r\n fallback: \"smooth\",\r\n },\r\n {\r\n key: \"cursor-leave-hold\",\r\n type: \"boolean\",\r\n fallback: false,\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 key: \"cursor-vars\",\r\n type: \"string\",\r\n fallback: \"\",\r\n },\r\n ];\r\n\r\n if (isCoarsePointer()) {\r\n this.enabled = false;\r\n }\r\n\r\n this.collectCursorPortals();\r\n if (this.enabled) {\r\n this.bindGlobalLifecycleListeners();\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 object.setProperty(\"__cursor-vars\", this.parseCursorVars(object.getProperty(\"cursor-vars\")));\r\n\r\n // Cache initial dimensions to avoid repeated DOM reads\r\n const rect = element.getBoundingClientRect();\r\n object.setProperty(\"cached-width\", rect.width || element.offsetWidth || 1);\r\n object.setProperty(\"cached-height\", rect.height || element.offsetHeight || 1);\r\n }\r\n\r\n onResize(): void {\r\n super.onResize();\r\n\r\n // Re-cache dimensions on resize to keep them accurate\r\n this.objects.forEach((object) => {\r\n const rect = object.htmlElement.getBoundingClientRect();\r\n object.setProperty(\"cached-width\", rect.width || object.htmlElement.offsetWidth || 1);\r\n object.setProperty(\"cached-height\", rect.height || object.htmlElement.offsetHeight || 1);\r\n });\r\n }\r\n\r\n onMutate(data: StringData): void {\r\n if (!this.enabled) return;\r\n\r\n const now = performance.now();\r\n\r\n let dt = this.lastFrameTime ? (now - this.lastFrameTime) / 1000 : 0.016;\r\n this.lastFrameTime = now;\r\n if (dt > 0.1) dt = 0.1;\r\n if (dt < MIN_FRAME_DELTA) dt = MIN_FRAME_DELTA;\r\n\r\n const cursorX = this.data.cursor.targetX;\r\n const cursorY = this.data.cursor.targetY;\r\n\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 baseLerp = object.getProperty<number>(\"lerp\") ?? 0.15;\r\n const frameLerp = this.getFrameAdjustedLerp(baseLerp, dt);\r\n\r\n const dimensions = this.getObjectDimensions(object);\r\n const { halfWidth, halfHeight, width, height } = dimensions;\r\n\r\n if (isOver && !isDisabled) {\r\n const { cx, cy } = this.centers.getCenter(object);\r\n const elementX = cursorX - (cx - halfWidth);\r\n const elementY = cursorY - (cy - halfHeight);\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 = object.getProperty<boolean>(\"is-mouse-move\") ?? false;\r\n const enterMode = object.getProperty<string>(\"cursor-enter\") ?? \"snap\";\r\n if (!isMoving) {\r\n object.setProperty(\"is-mouse-move\", true);\r\n if (enterMode === \"snap\") {\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 }\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: frameLerp,\r\n });\r\n const lerpedY = this.tools.lerp.process({\r\n from: py,\r\n to: elementY,\r\n progress: frameLerp,\r\n });\r\n\r\n const updatedX = px + lerpedX;\r\n const updatedY = py + lerpedY;\r\n const pixelChanged =\r\n Math.abs(updatedX - px) > CURSOR_EPSILON || Math.abs(updatedY - py) > CURSOR_EPSILON;\r\n\r\n object.setProperty(\"mouse-pixel-x\", updatedX);\r\n object.setProperty(\"mouse-pixel-y\", updatedY);\r\n\r\n const alignment = object.getProperty<string>(\"alignment\") ?? \"center\";\r\n const offsetX = this.calculateOffset(alignment, updatedX, width);\r\n const offsetY = this.calculateOffset(alignment, updatedY, height);\r\n\r\n object.setProperty(\"mouse-x\", offsetX);\r\n object.setProperty(\"mouse-y\", offsetY);\r\n\r\n const coordsChanged = this.setMouseCoordinates(object, offsetX, offsetY, updatedX, updatedY);\r\n\r\n if (coordsChanged) {\r\n this.events.emit(`cursor:move:${object.id}`, {\r\n x: offsetX,\r\n y: offsetY,\r\n });\r\n }\r\n if (pixelChanged) {\r\n this.events.emit(`cursor:pixel:${object.id}`, {\r\n x: updatedX,\r\n y: updatedY,\r\n });\r\n }\r\n } else {\r\n object.setProperty(\"mouse-pixel-x\", elementX);\r\n object.setProperty(\"mouse-pixel-y\", elementY);\r\n if (object.getProperty<boolean>(\"is-mouse-move\")) {\r\n object.setProperty(\"is-mouse-move\", false);\r\n this.events.emit(`cursor:end:${object.id}`, null);\r\n }\r\n const alignment = object.getProperty<string>(\"alignment\") ?? \"center\";\r\n const offsetX = this.calculateOffset(alignment, elementX, width);\r\n const offsetY = this.calculateOffset(alignment, elementY, height);\r\n this.setMouseCoordinates(object, offsetX, offsetY, elementX, elementY);\r\n }\r\n } else {\r\n const holdOnLeave = object.getProperty<boolean>(\"cursor-leave-hold\") ?? false;\r\n if (holdOnLeave) {\r\n if (object.getProperty<boolean>(\"is-mouse-move\")) {\r\n object.setProperty(\"is-mouse-move\", false);\r\n this.events.emit(`cursor:end:${object.id}`, null);\r\n }\r\n return;\r\n }\r\n\r\n const leaveMode = object.getProperty<string>(\"cursor-leave\") ?? \"smooth\";\r\n if (leaveMode === \"snap\") {\r\n object.setProperty(\"is-mouse-move\", false);\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 this.setMouseCoordinates(object, 0, 0, 0, 0);\r\n return;\r\n }\r\n\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 targetX = this.calculateOffset(\"center\", halfWidth, width);\r\n const targetY = this.calculateOffset(\"center\", halfHeight, height);\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: frameLerp,\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: frameLerp,\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 this.setMouseCoordinates(object, 0, 0, 0, 0);\r\n } else {\r\n this.setMouseCoordinates(object, newMouseX, newMouseY);\r\n }\r\n }\r\n }\r\n });\r\n\r\n if (this.cursorPortals.size > 0) {\r\n const { stepX, stepY, smoothedX, smoothedY } = this.data.cursor;\r\n const prev = this.cursorPrev;\r\n const cursorChanged =\r\n !Number.isFinite(prev.x) ||\r\n Math.abs(smoothedX - prev.x) > CURSOR_EPSILON ||\r\n Math.abs(smoothedY - prev.y) > CURSOR_EPSILON ||\r\n Math.abs(stepX - prev.stepX) > CURSOR_EPSILON ||\r\n Math.abs(stepY - prev.stepY) > CURSOR_EPSILON;\r\n\r\n if (cursorChanged) {\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.cursorPrev = { x: smoothedX, y: smoothedY, stepX, stepY };\r\n }\r\n\r\n const targetX = this.data.cursor.targetX;\r\n const targetY = this.data.cursor.targetY;\r\n this.cursorPortals.forEach((bucket) => {\r\n bucket.forEach((portal) => {\r\n this.updatePortalPosition(portal, targetX, targetY, dt);\r\n });\r\n });\r\n }\r\n }\r\n\r\n onObjectConnected(object: StringObject) {\r\n const element = object.htmlElement;\r\n this.centers.attach(object);\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(\"enter\", object.getProperty<(object: StringObject) => void>(\"onEnterEvent\"));\r\n object.setProperty(\"onLeaveEvent\", this.onLeaveObject.bind(this));\r\n object.events.on(\"leave\", object.getProperty<(object: StringObject) => void>(\"onLeaveEvent\"));\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 if (!document.contains(object.htmlElement)) {\r\n return;\r\n }\r\n\r\n object.setProperty(\"is-mouse-over\", true);\r\n this.hoveredObjects.add(object);\r\n\r\n const cursorClass = this.getCursorClass(object);\r\n\r\n this.withPortalsForObject(object, (portal) => {\r\n if (cursorClass) {\r\n portal.element.classList.add(cursorClass);\r\n }\r\n this.incrementPortalHover(portal);\r\n });\r\n\r\n object.htmlElement.addEventListener(\"mouseleave\", object.getProperty(\"mouseleave\"));\r\n }\r\n\r\n onMouseLeave(object: StringObject) {\r\n object.setProperty(\"is-mouse-over\", false);\r\n this.hoveredObjects.delete(object);\r\n\r\n const cursorClass = this.getCursorClass(object);\r\n\r\n this.withPortalsForObject(object, (portal) => {\r\n if (cursorClass) {\r\n portal.element.classList.remove(cursorClass);\r\n }\r\n this.decrementPortalHover(portal);\r\n });\r\n\r\n if (document.contains(object.htmlElement)) {\r\n object.htmlElement.removeEventListener(\"mouseleave\", object.getProperty(\"mouseleave\"));\r\n }\r\n }\r\n\r\n private onEnterObject(object: StringObject) {\r\n object.htmlElement.addEventListener(\"mouseenter\", object.getProperty(\"mouseenter\"));\r\n }\r\n\r\n private onLeaveObject(object: StringObject) {\r\n object.htmlElement.removeEventListener(\"mouseenter\", object.getProperty(\"mouseenter\"));\r\n object.htmlElement.removeEventListener(\"mouseleave\", object.getProperty(\"mouseleave\"));\r\n }\r\n\r\n private safariNavigationCleanup(object: StringObject): void {\r\n if (object.getProperty<boolean>(\"is-mouse-over\")) {\r\n this.onMouseLeave(object);\r\n }\r\n }\r\n\r\n private onElementRemovedFromDOM(object: StringObject): void {\r\n if (object.getProperty<boolean>(\"is-mouse-over\")) {\r\n this.onMouseLeave(object);\r\n }\r\n }\r\n\r\n onObjectDisconnected(object: StringObject): void {\r\n if (object.getProperty<boolean>(\"is-mouse-over\")) {\r\n this.onMouseLeave(object);\r\n }\r\n }\r\n\r\n onDOMRebuild(): void {\r\n if (!this.enabled) return;\r\n this.collectCursorPortals();\r\n }\r\n\r\n onDOMMutate(added: NodeList, removed: NodeList): void {\r\n if (!this.enabled) return;\r\n if (this.shouldRefreshPortals(added) || this.shouldRefreshPortals(removed)) {\r\n this.collectCursorPortals();\r\n }\r\n if (removed.length > 0) {\r\n this.handleRemovedNodes(removed);\r\n }\r\n }\r\n\r\n private collectCursorPortals(): void {\r\n this.cursorPortals.clear();\r\n const nodes = document.querySelectorAll(CURSOR_PORTAL_SELECTOR);\r\n nodes.forEach((node) => {\r\n if (!(node instanceof HTMLElement)) return;\r\n const id = this.resolvePortalId(node);\r\n const customLerp = this.resolvePortalLerp(node);\r\n const content = node.matches(CURSOR_PORTAL_CONTENT_SELECTOR)\r\n ? node\r\n : (node.querySelector(CURSOR_PORTAL_CONTENT_SELECTOR) as HTMLElement | null);\r\n\r\n const targetX = this.data.cursor.targetX;\r\n const targetY = this.data.cursor.targetY;\r\n const portal: CursorPortal = {\r\n id,\r\n element: node,\r\n content,\r\n prev: { x: targetX, y: targetY, stepX: 0, stepY: 0 },\r\n hoverCount: 0,\r\n showTimer: null,\r\n lerp: customLerp,\r\n };\r\n\r\n const existing = this.cursorPortals.get(id);\r\n if (existing) {\r\n existing.push(portal);\r\n } else {\r\n this.cursorPortals.set(id, [portal]);\r\n }\r\n });\r\n }\r\n\r\n private resolvePortalId(element: HTMLElement): string {\r\n const attrSources = [\r\n element.getAttribute(\"data-string-cursor\"),\r\n element.getAttribute(\"string-cursor\"),\r\n element.getAttribute(\"data-string-cursor-id\"),\r\n element.getAttribute(\"string-cursor-id\"),\r\n ];\r\n\r\n for (const source of attrSources) {\r\n if (source && source.trim().length > 0) {\r\n return source.trim();\r\n }\r\n }\r\n\r\n return DEFAULT_CURSOR_ID;\r\n }\r\n\r\n private resolvePortalLerp(element: HTMLElement): number | null {\r\n const raw =\r\n element.getAttribute(\"data-string-cursor-lerp\") ??\r\n element.getAttribute(\"string-cursor-lerp\") ??\r\n this.settings[\"cursor-lerp\"];\r\n if (!raw) {\r\n return null;\r\n }\r\n\r\n const value = parseFloat(raw);\r\n if (!Number.isFinite(value)) {\r\n return null;\r\n }\r\n\r\n const clamped = Math.min(1, Math.max(0.01, value));\r\n return this.tools.adaptiveLerp.process({\r\n value: clamped,\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 private shouldRefreshPortals(nodes: NodeList): boolean {\r\n for (const node of Array.from(nodes)) {\r\n if (!(node instanceof Element)) continue;\r\n if (node.matches(CURSOR_PORTAL_SELECTOR)) {\r\n return true;\r\n }\r\n if (node.querySelector(CURSOR_PORTAL_SELECTOR)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n private withPortalsForObject(\r\n object: StringObject | null,\r\n cb: (portal: CursorPortal) => void\r\n ): void {\r\n const portals = this.getPortalsForObject(object);\r\n portals.forEach((portal) => cb(portal));\r\n }\r\n\r\n private getPortalsForObject(object: StringObject | null): CursorPortal[] {\r\n if (this.cursorPortals.size === 0) {\r\n return [];\r\n }\r\n\r\n const ids = this.extractPortalIds(object);\r\n const selected: CursorPortal[] = [];\r\n\r\n ids.forEach((id) => {\r\n if (id === \"*\") {\r\n this.cursorPortals.forEach((bucket) => {\r\n bucket.forEach((portal) => selected.push(portal));\r\n });\r\n return;\r\n }\r\n\r\n const normalized = id.length > 0 ? id : DEFAULT_CURSOR_ID;\r\n const portals = this.cursorPortals.get(normalized);\r\n if (portals) {\r\n portals.forEach((portal) => selected.push(portal));\r\n }\r\n });\r\n\r\n if (selected.length === 0) {\r\n const fallbackBucket =\r\n this.cursorPortals.get(DEFAULT_CURSOR_ID) ?? this.cursorPortals.values().next().value;\r\n if (fallbackBucket && fallbackBucket.length > 0) {\r\n fallbackBucket.forEach((portal: any) => selected.push(portal));\r\n }\r\n }\r\n\r\n return selected;\r\n }\r\n\r\n private extractPortalIds(object: StringObject | null): string[] {\r\n if (!object) return [DEFAULT_CURSOR_ID];\r\n const raw = object.getProperty<string>(\"cursor-target\");\r\n if (typeof raw !== \"string\" || raw.trim().length === 0) {\r\n return [DEFAULT_CURSOR_ID];\r\n }\r\n\r\n return raw\r\n .split(/[,|]/)\r\n .map((value) => value.trim())\r\n .filter(Boolean);\r\n }\r\n\r\n private incrementPortalHover(portal: CursorPortal): void {\r\n portal.hoverCount++;\r\n portal.element.classList.remove(\"-show\");\r\n this.restartPortalShowTimer(portal);\r\n }\r\n\r\n private decrementPortalHover(portal: CursorPortal): void {\r\n portal.hoverCount = Math.max(0, portal.hoverCount - 1);\r\n if (portal.hoverCount === 0) {\r\n this.clearPortalShowTimer(portal);\r\n portal.element.classList.remove(\"-show\");\r\n }\r\n }\r\n\r\n private restartPortalShowTimer(portal: CursorPortal): void {\r\n this.clearPortalShowTimer(portal);\r\n if (!portal.element.isConnected) {\r\n portal.showTimer = null;\r\n return;\r\n }\r\n portal.element.classList.add(\"-show\");\r\n portal.showTimer = null;\r\n }\r\n\r\n private clearPortalShowTimer(portal: CursorPortal): void {\r\n if (portal.showTimer) {\r\n clearTimeout(portal.showTimer);\r\n portal.showTimer = null;\r\n }\r\n }\r\n\r\n private updatePortalPosition(\r\n portal: CursorPortal,\r\n targetX: number,\r\n targetY: number,\r\n dt: number\r\n ): void {\r\n if (!portal.element.isConnected) return;\r\n\r\n const prev = portal.prev;\r\n\r\n const currentX = Number.isFinite(prev.x) ? prev.x : targetX;\r\n const currentY = Number.isFinite(prev.y) ? prev.y : targetY;\r\n\r\n const factor = portal.lerp ?? 0.1;\r\n const fpsAdjustedLerp = this.getFrameAdjustedLerp(factor, dt);\r\n\r\n const stepX = (targetX - currentX) * fpsAdjustedLerp;\r\n const stepY = (targetY - currentY) * fpsAdjustedLerp;\r\n\r\n const safeDt = dt > 1e-4 ? dt : 1 / 60;\r\n const normalizedVelocityX = stepX / (safeDt * 60);\r\n const normalizedVelocityY = stepY / (safeDt * 60);\r\n\r\n if (Math.abs(stepX) < CURSOR_EPSILON && Math.abs(stepY) < CURSOR_EPSILON) {\r\n return;\r\n }\r\n\r\n const nextX = currentX + stepX;\r\n const nextY = currentY + stepY;\r\n\r\n portal.element.style.setProperty(\"--x\", nextX.toFixed(2));\r\n portal.element.style.setProperty(\"--y\", nextY.toFixed(2));\r\n\r\n portal.element.style.setProperty(\"--x-lerp\", normalizedVelocityX.toFixed(3));\r\n portal.element.style.setProperty(\"--y-lerp\", normalizedVelocityY.toFixed(3));\r\n\r\n prev.x = nextX;\r\n prev.y = nextY;\r\n prev.stepX = stepX;\r\n prev.stepY = stepY;\r\n }\r\n\r\n private handleRemovedNodes(nodes: NodeList): void {\r\n if (this.hoveredObjects.size === 0) {\r\n return;\r\n }\r\n Array.from(this.hoveredObjects).forEach((object) => {\r\n if (!object.htmlElement.isConnected) {\r\n this.onElementRemovedFromDOM(object);\r\n }\r\n });\r\n }\r\n\r\n private cleanupHoverTargets(): void {\r\n if (this.hoveredObjects.size === 0) {\r\n return;\r\n }\r\n Array.from(this.hoveredObjects).forEach((object) => this.safariNavigationCleanup(object));\r\n }\r\n\r\n private bindGlobalLifecycleListeners(): void {\r\n if (this.globalListenersBound) {\r\n return;\r\n }\r\n window.addEventListener(\"beforeunload\", this.boundBeforeUnload);\r\n window.addEventListener(\"pagehide\", this.boundPageHide);\r\n document.addEventListener(\"visibilitychange\", this.boundVisibilityChange);\r\n this.globalListenersBound = true;\r\n }\r\n\r\n private unbindGlobalLifecycleListeners(): void {\r\n if (!this.globalListenersBound) {\r\n return;\r\n }\r\n window.removeEventListener(\"beforeunload\", this.boundBeforeUnload);\r\n window.removeEventListener(\"pagehide\", this.boundPageHide);\r\n document.removeEventListener(\"visibilitychange\", this.boundVisibilityChange);\r\n this.globalListenersBound = false;\r\n }\r\n\r\n private setMouseCoordinates(\r\n object: StringObject,\r\n x: number,\r\n y: number,\r\n pixelX?: number,\r\n pixelY?: number\r\n ): boolean {\r\n if (object.getProperty(\"cursor-target-style-disable\")) {\r\n return false;\r\n }\r\n\r\n const state = getTargetState(object);\r\n const roundedX =\r\n Math.abs(x) < CURSOR_EPSILON &&\r\n Number.isFinite(state.prevX) &&\r\n Math.abs(state.prevX) < CURSOR_EPSILON\r\n ? state.prevX\r\n : Math.round(x * 100) / 100;\r\n const roundedY =\r\n Math.abs(y) < CURSOR_EPSILON &&\r\n Number.isFinite(state.prevY) &&\r\n Math.abs(state.prevY) < CURSOR_EPSILON\r\n ? state.prevY\r\n : Math.round(y * 100) / 100;\r\n\r\n if (\r\n Number.isFinite(state.prevX) &&\r\n Math.abs(roundedX - state.prevX) <= CURSOR_EPSILON &&\r\n Number.isFinite(state.prevY) &&\r\n Math.abs(roundedY - state.prevY) <= CURSOR_EPSILON\r\n ) {\r\n return false;\r\n }\r\n\r\n state.prevX = roundedX;\r\n state.prevY = roundedY;\r\n\r\n const valueX = roundedX.toFixed(2);\r\n const valueY = roundedY.toFixed(2);\r\n\r\n const vars = object.getProperty<Set<string>>(\"__cursor-vars\");\r\n const extraVars: Record<string, string> = { \"--x\": valueX, \"--y\": valueY };\r\n\r\n if (vars && vars.size > 0) {\r\n const px =\r\n Number.isFinite(pixelX) ? (pixelX as number) : object.getProperty<number>(\"mouse-pixel-x\");\r\n const py =\r\n Number.isFinite(pixelY) ? (pixelY as number) : object.getProperty<number>(\"mouse-pixel-y\");\r\n const prevPx = object.getProperty<number>(\"__prev-x-px\");\r\n const prevPy = object.getProperty<number>(\"__prev-y-px\");\r\n\r\n const dx = Number.isFinite(prevPx) ? px - prevPx : 0;\r\n const dy = Number.isFinite(prevPy) ? py - prevPy : 0;\r\n\r\n object.setProperty(\"__prev-x-px\", px);\r\n object.setProperty(\"__prev-y-px\", py);\r\n\r\n const angle = dx === 0 && dy === 0 ? 0 : Math.atan2(dy, dx);\r\n const angleDeg = (angle * 180) / Math.PI;\r\n\r\n if (vars.has(\"xpx\")) extraVars[\"--x-px\"] = px.toFixed(2);\r\n if (vars.has(\"ypx\")) extraVars[\"--y-px\"] = py.toFixed(2);\r\n if (vars.has(\"dx\")) extraVars[\"--dx\"] = dx.toFixed(3);\r\n if (vars.has(\"dy\")) extraVars[\"--dy\"] = dy.toFixed(3);\r\n if (vars.has(\"angle\")) extraVars[\"--angle\"] = angle.toFixed(4);\r\n if (vars.has(\"angle-deg\")) extraVars[\"--angle-deg\"] = angleDeg.toFixed(2);\r\n }\r\n\r\n styleTxn.run(() => {\r\n this.applyToElementAndConnects(object, (el) => {\r\n styleTxn.setVars(el, extraVars);\r\n });\r\n });\r\n\r\n return true;\r\n }\r\n\r\n private parseCursorVars(value: string | null | undefined): Set<string> {\r\n if (!value) return new Set();\r\n return new Set(\r\n value\r\n .split(/[|,]/)\r\n .map((v) => v.trim().toLowerCase())\r\n .filter((v) => v.length > 0)\r\n );\r\n }\r\n\r\n private getFrameAdjustedLerp(base: number, dt: number): number {\r\n const clampedBase = Math.min(0.99, Math.max(0.001, base));\r\n if (!Number.isFinite(dt) || dt <= 0) {\r\n return clampedBase;\r\n }\r\n\r\n const normalizedDt = Math.max(dt, MIN_FRAME_DELTA);\r\n const frames = normalizedDt * 60;\r\n const adjusted = 1 - Math.pow(1 - clampedBase, frames);\r\n return Math.min(0.999, Math.max(0.0001, adjusted));\r\n }\r\n\r\n private getObjectDimensions(object: StringObject): CursorObjectDimensions {\r\n // Try to use cached dimensions first (set during resize/init)\r\n const cachedWidth = object.getProperty<number>(\"cached-width\");\r\n const cachedHeight = object.getProperty<number>(\"cached-height\");\r\n\r\n // If cache exists, use it to avoid DOM reads every frame\r\n if (\r\n typeof cachedWidth === \"number\" &&\r\n typeof cachedHeight === \"number\" &&\r\n cachedWidth > 0 &&\r\n cachedHeight > 0\r\n ) {\r\n const halfWidth = cachedWidth / 2;\r\n const halfHeight = cachedHeight / 2;\r\n return {\r\n width: cachedWidth,\r\n height: cachedHeight,\r\n halfWidth,\r\n halfHeight,\r\n };\r\n }\r\n\r\n // Fallback: read from DOM (only if cache not available)\r\n const element = object.htmlElement;\r\n const fallbackWidth = element.offsetWidth || element.clientWidth || element.scrollWidth || 1;\r\n const fallbackHeight =\r\n element.offsetHeight || element.clientHeight || element.scrollHeight || 1;\r\n\r\n const rawHalfWidth = object.getProperty<number>(\"half-width\");\r\n const rawHalfHeight = object.getProperty<number>(\"half-height\");\r\n\r\n const halfWidth =\r\n typeof rawHalfWidth === \"number\" && Number.isFinite(rawHalfWidth)\r\n ? rawHalfWidth\r\n : fallbackWidth / 2;\r\n const halfHeight =\r\n typeof rawHalfHeight === \"number\" && Number.isFinite(rawHalfHeight)\r\n ? rawHalfHeight\r\n : fallbackHeight / 2;\r\n\r\n const width = halfWidth > 0 ? halfWidth * 2 : fallbackWidth;\r\n const height = halfHeight > 0 ? halfHeight * 2 : fallbackHeight;\r\n\r\n // Cache for next frame\r\n object.setProperty(\"cached-width\", width);\r\n object.setProperty(\"cached-height\", height);\r\n\r\n return { width, height, halfWidth, halfHeight };\r\n }\r\n\r\n private calculateOffset(alignment: string, mousePos: number, size: number): 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 override removeObject(id: string): void {\r\n if (!this.enabled) return super.removeObject(id);\r\n const obj = this.objectMapOnPage.get(id);\r\n if (obj) {\r\n this.centers.detach(obj);\r\n }\r\n super.removeObject(id);\r\n }\r\n\r\n override destroy(): void {\r\n this.unbindGlobalLifecycleListeners();\r\n this.hoveredObjects.clear();\r\n super.destroy();\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 StringImpulse extends StringModule {\r\n private originObservers = new WeakMap<StringObject, MutationObserver>();\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"impulse\";\r\n\r\n this.attributesToMap.push(\r\n { key: \"position-strength\", type: \"number\", fallback: this.settings[\"position-strength\"] },\r\n { key: \"position-tension\", type: \"number\", fallback: this.settings[\"position-tension\"] },\r\n { key: \"position-friction\", type: \"number\", fallback: this.settings[\"position-friction\"] },\r\n {\r\n key: \"position-max-velocity\",\r\n type: \"number\",\r\n fallback: this.settings[\"position-max-velocity\"],\r\n },\r\n {\r\n key: \"position-update-threshold\",\r\n type: \"number\",\r\n fallback: this.settings[\"position-update-threshold\"],\r\n },\r\n\r\n // rotate\r\n { key: \"rotation-strength\", type: \"number\", fallback: this.settings[\"rotation-strength\"] },\r\n { key: \"rotation-tension\", type: \"number\", fallback: this.settings[\"rotation-tension\"] },\r\n { key: \"rotation-friction\", type: \"number\", fallback: this.settings[\"rotation-friction\"] },\r\n {\r\n key: \"rotation-max-angular-velocity\",\r\n type: \"number\",\r\n fallback: this.settings[\"rotation-max-angular-velocity\"],\r\n },\r\n { key: \"rotation-max-angle\", type: \"number\", fallback: this.settings[\"rotation-max-angle\"] },\r\n {\r\n key: \"rotation-update-threshold\",\r\n type: \"number\",\r\n fallback: this.settings[\"rotation-update-threshold\"],\r\n },\r\n\r\n { key: \"max-offset\", type: \"number\", fallback: this.settings[\"max-offset\"] },\r\n { key: \"sleep-epsilon\", type: \"number\", fallback: this.settings[\"sleep-epsilon\"] },\r\n { key: \"continuous-push\", type: \"boolean\", fallback: this.settings[\"continuous-push\"] },\r\n {\r\n key: \"rotation-origin\",\r\n type: \"string\",\r\n fallback: this.settings[\"rotation-origin\"] ?? \"center center\",\r\n }\r\n );\r\n }\r\n\r\n override onObjectConnected(object: StringObject): void {\r\n super.onObjectConnected(object);\r\n\r\n object.setProperty(\"offset-x\", 0);\r\n object.setProperty(\"offset-y\", 0);\r\n object.setProperty(\"velocity-x\", 0);\r\n object.setProperty(\"velocity-y\", 0);\r\n\r\n object.setProperty(\"angle-deg\", 0);\r\n object.setProperty(\"ang-vel-deg\", 0);\r\n\r\n object.setProperty(\"__prev-css-x\", 0);\r\n object.setProperty(\"__prev-css-y\", 0);\r\n object.setProperty(\"__prev-css-rot\", 0);\r\n\r\n object.setProperty(\"__push-latch\", false);\r\n object.setProperty(\"__rotate-latch\", false);\r\n\r\n // Cache parsed rotation origin\r\n this.cacheRotationOrigin(object);\r\n\r\n // Watch for rotation-origin attribute changes\r\n this.observeRotationOrigin(object);\r\n\r\n this.hover.track(object);\r\n this.centers.attach(object);\r\n }\r\n\r\n override onObjectDisconnected(object: StringObject): void {\r\n this.hover.untrack(object);\r\n this.centers.detach(object);\r\n\r\n // Cleanup rotation-origin observer\r\n const observer = this.originObservers.get(object);\r\n if (observer) {\r\n observer.disconnect();\r\n this.originObservers.delete(object);\r\n }\r\n }\r\n\r\n override onMouseMove(_e?: MouseEvent): void {\r\n if (!_e) return;\r\n\r\n const cursorVelocityX = this.data.cursor.velocityX;\r\n const cursorVelocityY = this.data.cursor.velocityY;\r\n if (cursorVelocityX === 0 && cursorVelocityY === 0) return;\r\n\r\n const mouseX = this.data.cursor.targetX;\r\n const mouseY = this.data.cursor.targetY;\r\n\r\n for (const object of this.objects) {\r\n const rect = object.htmlElement.getBoundingClientRect();\r\n const isUnderCursor =\r\n mouseX >= rect.left && mouseX <= rect.right && mouseY >= rect.top && mouseY <= rect.bottom;\r\n\r\n if (isUnderCursor) {\r\n {\r\n const w = rect.width || 1;\r\n const side01 = Math.max(0, Math.min(1, (this.data.cursor.targetX - rect.left) / w));\r\n this.events.emit(`object:impulse:${object.id}:side`, { value: side01 });\r\n }\r\n\r\n const positionStrength = object.getProperty<number>(\"position-strength\") || 0;\r\n if (positionStrength !== 0) {\r\n const isContinuousPush = object.getProperty<boolean>(\"continuous-push\") ?? true;\r\n const isLatched = object.getProperty<boolean>(\"__push-latch\") === true;\r\n if (isContinuousPush || !isLatched) {\r\n let objectVelocityX = object.getProperty<number>(\"velocity-x\") || 0;\r\n let objectVelocityY = object.getProperty<number>(\"velocity-y\") || 0;\r\n objectVelocityX += cursorVelocityX * positionStrength;\r\n objectVelocityY += cursorVelocityY * positionStrength;\r\n object.setProperty(\"velocity-x\", objectVelocityX);\r\n object.setProperty(\"velocity-y\", objectVelocityY);\r\n if (!isContinuousPush) object.setProperty(\"__push-latch\", true);\r\n }\r\n }\r\n\r\n const rotationStrength = object.getProperty<number>(\"rotation-strength\") ?? 0.75;\r\n if (rotationStrength !== 0) {\r\n const isContinuousPush = object.getProperty<boolean>(\"continuous-push\") ?? true;\r\n const isLatched = object.getProperty<boolean>(\"__rotate-latch\") === true;\r\n\r\n if (isContinuousPush || !isLatched) {\r\n const { centerX, centerY } = this.getRotationOriginFromRect(object, rect);\r\n const relativeX = mouseX - centerX;\r\n const relativeY = mouseY - centerY;\r\n const torque = relativeX * cursorVelocityY - relativeY * cursorVelocityX;\r\n\r\n let angularVelocityDeg = object.getProperty<number>(\"ang-vel-deg\") || 0;\r\n angularVelocityDeg += torque * rotationStrength * 0.02;\r\n object.setProperty(\"ang-vel-deg\", angularVelocityDeg);\r\n if (!isContinuousPush) object.setProperty(\"__rotate-latch\", true);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Parses and caches the rotation origin for an object.\r\n * Called once on object connection and when attribute changes.\r\n */\r\n private cacheRotationOrigin(object: StringObject): void {\r\n const originValue = object.getProperty<string>(\"rotation-origin\") ?? \"center center\";\r\n const { x, y } = this.tools.originParser.toNormalized({ value: originValue });\r\n object.setProperty(\"__rotation-origin-x\", x);\r\n object.setProperty(\"__rotation-origin-y\", y);\r\n }\r\n\r\n /**\r\n * Observes changes to the rotation-origin attribute and re-caches when changed.\r\n */\r\n private observeRotationOrigin(object: StringObject): void {\r\n const attrName = \"string-rotation-origin\";\r\n const dataAttrName = \"data-string-rotation-origin\";\r\n\r\n const observer = new MutationObserver((mutations) => {\r\n for (const mutation of mutations) {\r\n if (\r\n mutation.type === \"attributes\" &&\r\n (mutation.attributeName === attrName || mutation.attributeName === dataAttrName)\r\n ) {\r\n // Re-read attribute and update cache\r\n const newValue =\r\n object.htmlElement.getAttribute(attrName) ??\r\n object.htmlElement.getAttribute(dataAttrName);\r\n if (newValue !== null) {\r\n object.setProperty(\"rotation-origin\", newValue);\r\n }\r\n this.cacheRotationOrigin(object);\r\n break;\r\n }\r\n }\r\n });\r\n\r\n observer.observe(object.htmlElement, {\r\n attributes: true,\r\n attributeFilter: [attrName, dataAttrName],\r\n });\r\n\r\n this.originObservers.set(object, observer);\r\n }\r\n\r\n /**\r\n * Calculates the rotation origin point using cached normalized values and provided rect.\r\n * Avoids re-parsing origin string and extra getBoundingClientRect calls.\r\n */\r\n private getRotationOriginFromRect(\r\n object: StringObject,\r\n rect: DOMRect\r\n ): { centerX: number; centerY: number } {\r\n const normalizedX = object.getProperty<number>(\"__rotation-origin-x\") ?? 0.5;\r\n const normalizedY = object.getProperty<number>(\"__rotation-origin-y\") ?? 0.5;\r\n\r\n return {\r\n centerX: rect.left + rect.width * normalizedX,\r\n centerY: rect.top + rect.height * normalizedY,\r\n };\r\n }\r\n\r\n onFrame(_: StringData): void {\r\n const mouseX = this.data.cursor.targetX;\r\n const mouseY = this.data.cursor.targetY;\r\n\r\n for (const objectItem of this.objects) {\r\n const rect = objectItem.htmlElement.getBoundingClientRect();\r\n const isUnderCursor =\r\n mouseX >= rect.left && mouseX <= rect.right && mouseY >= rect.top && mouseY <= rect.bottom;\r\n\r\n if (!isUnderCursor && objectItem.getProperty<boolean>(\"__push-latch\") === true) {\r\n objectItem.setProperty(\"__push-latch\", false);\r\n }\r\n if (!isUnderCursor && objectItem.getProperty<boolean>(\"__rotate-latch\") === true) {\r\n objectItem.setProperty(\"__rotate-latch\", false);\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.objects.length; i++) {\r\n const object = this.objects[i];\r\n\r\n let offsetX = object.getProperty<number>(\"offset-x\") || 0;\r\n let offsetY = object.getProperty<number>(\"offset-y\") || 0;\r\n let velocityX = object.getProperty<number>(\"velocity-x\") || 0;\r\n let velocityY = object.getProperty<number>(\"velocity-y\") || 0;\r\n\r\n const positionTension = object.getProperty<number>(\"position-tension\") ?? 0.05;\r\n const positionFriction = object.getProperty<number>(\"position-friction\") ?? 0.15;\r\n const maxVelocity = object.getProperty<number>(\"position-max-velocity\") ?? 120;\r\n const maxOffset = object.getProperty<number>(\"max-offset\") ?? 220;\r\n\r\n velocityX -= positionTension * offsetX;\r\n velocityY -= positionTension * offsetY;\r\n\r\n const velocityDecay = 1 - positionFriction;\r\n velocityX *= velocityDecay;\r\n velocityY *= velocityDecay;\r\n\r\n if (velocityX > maxVelocity) velocityX = maxVelocity;\r\n else if (velocityX < -maxVelocity) velocityX = -maxVelocity;\r\n if (velocityY > maxVelocity) velocityY = maxVelocity;\r\n else if (velocityY < -maxVelocity) velocityY = -maxVelocity;\r\n\r\n offsetX += velocityX;\r\n offsetY += velocityY;\r\n\r\n if (offsetX > maxOffset) offsetX = maxOffset;\r\n else if (offsetX < -maxOffset) offsetX = -maxOffset;\r\n if (offsetY > maxOffset) offsetY = maxOffset;\r\n else if (offsetY < -maxOffset) offsetY = -maxOffset;\r\n\r\n let angleDeg = object.getProperty<number>(\"angle-deg\") || 0;\r\n let angularVelocityDeg = object.getProperty<number>(\"ang-vel-deg\") || 0;\r\n\r\n const rotationTension = object.getProperty<number>(\"rotation-tension\") ?? 0.06;\r\n const rotationFriction = object.getProperty<number>(\"rotation-friction\") ?? 0.18;\r\n const maxAngularVelocityDeg =\r\n object.getProperty<number>(\"rotation-max-angular-velocity\") ?? 6;\r\n const maxRotationAngleDeg = object.getProperty<number>(\"rotation-max-angle\") ?? 18;\r\n\r\n angularVelocityDeg -= rotationTension * angleDeg;\r\n angularVelocityDeg *= 1 - rotationFriction;\r\n\r\n if (angularVelocityDeg > maxAngularVelocityDeg) angularVelocityDeg = maxAngularVelocityDeg;\r\n else if (angularVelocityDeg < -maxAngularVelocityDeg)\r\n angularVelocityDeg = -maxAngularVelocityDeg;\r\n\r\n angleDeg += angularVelocityDeg;\r\n\r\n if (angleDeg > maxRotationAngleDeg) {\r\n angleDeg = maxRotationAngleDeg;\r\n angularVelocityDeg *= 0.35;\r\n } else if (angleDeg < -maxRotationAngleDeg) {\r\n angleDeg = -maxRotationAngleDeg;\r\n angularVelocityDeg *= 0.35;\r\n }\r\n\r\n const sleepEpsilon = object.getProperty<number>(\"sleep-epsilon\") ?? 0.01;\r\n const isPositionAsleep =\r\n velocityX * velocityX + velocityY * velocityY < sleepEpsilon * sleepEpsilon &&\r\n offsetX * offsetX + offsetY * offsetY < sleepEpsilon * sleepEpsilon;\r\n\r\n const isRotationAsleep =\r\n Math.abs(angularVelocityDeg) < sleepEpsilon && Math.abs(angleDeg) < sleepEpsilon;\r\n\r\n if (isPositionAsleep) {\r\n if (velocityX || velocityY || offsetX || offsetY) {\r\n object.setProperty(\"offset-x\", 0);\r\n object.setProperty(\"offset-y\", 0);\r\n object.setProperty(\"velocity-x\", 0);\r\n object.setProperty(\"velocity-y\", 0);\r\n offsetX = offsetY = velocityX = velocityY = 0;\r\n }\r\n } else {\r\n object.setProperty(\"offset-x\", offsetX);\r\n object.setProperty(\"offset-y\", offsetY);\r\n object.setProperty(\"velocity-x\", velocityX);\r\n object.setProperty(\"velocity-y\", velocityY);\r\n }\r\n\r\n if (isRotationAsleep) {\r\n if (angleDeg || angularVelocityDeg) {\r\n object.setProperty(\"angle-deg\", 0);\r\n object.setProperty(\"ang-vel-deg\", 0);\r\n angleDeg = angularVelocityDeg = 0;\r\n }\r\n } else {\r\n object.setProperty(\"angle-deg\", angleDeg);\r\n object.setProperty(\"ang-vel-deg\", angularVelocityDeg);\r\n }\r\n\r\n const positionUpdateThreshold =\r\n object.getProperty<number>(\"position-update-threshold\") ?? 0.1;\r\n const rotationUpdateThreshold =\r\n object.getProperty<number>(\"rotation-update-threshold\") ?? 0.15;\r\n\r\n const prevCssX = object.getProperty<number>(\"__prev-css-x\") || 0;\r\n const prevCssY = object.getProperty<number>(\"__prev-css-y\") || 0;\r\n const prevCssRot = object.getProperty<number>(\"__prev-css-rot\") || 0;\r\n\r\n const cssTranslateX = Math.round(offsetX * 10) / 10;\r\n const cssTranslateY = Math.round(offsetY * 10) / 10;\r\n const cssRotateDeg = Math.round(angleDeg * 10) / 10;\r\n\r\n const needsPositionUpdate =\r\n Math.abs(cssTranslateX - prevCssX) > positionUpdateThreshold ||\r\n Math.abs(cssTranslateY - prevCssY) > positionUpdateThreshold;\r\n\r\n const needsRotationUpdate = Math.abs(cssRotateDeg - prevCssRot) > rotationUpdateThreshold;\r\n\r\n if (needsPositionUpdate || needsRotationUpdate) {\r\n this.applyToElementAndConnects(object, (el) => {\r\n if (needsPositionUpdate) {\r\n el.style.setProperty(\"--push-x\", String(cssTranslateX));\r\n el.style.setProperty(\"--push-y\", String(cssTranslateY));\r\n this.events.emit(`object:impulse:${object.id}:move`, {\r\n x: cssTranslateX,\r\n y: cssTranslateY,\r\n });\r\n }\r\n if (needsRotationUpdate) {\r\n el.style.setProperty(\"--push-rotation\", String(cssRotateDeg));\r\n this.events.emit(`object:impulse:${object.id}:rotate`, { rotation: cssRotateDeg });\r\n }\r\n });\r\n\r\n if (needsPositionUpdate) {\r\n object.setProperty(\"__prev-css-x\", cssTranslateX);\r\n object.setProperty(\"__prev-css-y\", cssTranslateY);\r\n }\r\n if (needsRotationUpdate) {\r\n object.setProperty(\"__prev-css-rot\", cssRotateDeg);\r\n }\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\nexport class StringMagnetic extends StringModule {\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"magnetic\";\r\n\r\n this.permissions.mobile.rebuild.height = false;\r\n this.permissions.mobile.rebuild.width = false;\r\n this.permissions.mobile.rebuild.scrollHeight = false;\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 = rect.left + rect.width / 2;\r\n const centerY = rect.top + rect.height / 2;\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 = object.getProperty<number>(\"magnetic-target-x\") ?? 0;\r\n let targetMagneticY = 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(\"magnetic-x\", object.getProperty(\"magnetic-target-x\"));\r\n }\r\n if (lerpY > -0.01 && lerpY < 0.01) {\r\n lerpY = 0;\r\n object.setProperty(\"magnetic-y\", object.getProperty(\"magnetic-target-y\"));\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","type Job = () => void;\n\nclass FrameDOM {\n private measureQueue: Job[] = [];\n private mutateQueue: Job[] = [];\n private scheduled = false;\n\n public measure(fn: Job): void {\n this.measureQueue.push(fn);\n this.schedule();\n }\n\n public mutate(fn: Job): void {\n this.mutateQueue.push(fn);\n this.schedule();\n }\n\n private schedule(): void {\n if (this.scheduled) {\n return;\n }\n\n this.scheduled = true;\n requestAnimationFrame(() => {\n const mQueue = this.measureQueue;\n this.measureQueue = [];\n for (let i = 0; i < mQueue.length; i++) {\n try {\n mQueue[i]();\n } catch (e) {\n console.error(\"Error in frameDOM measure task:\", e);\n }\n }\n\n const wQueue = this.mutateQueue;\n this.mutateQueue = [];\n for (let i = 0; i < wQueue.length; i++) {\n try {\n wQueue[i]();\n } catch (e) {\n console.error(\"Error in frameDOM mutate task:\", e);\n }\n }\n\n this.scheduled = false;\n });\n }\n}\n\nexport const frameDOM = new FrameDOM();\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\nimport { frameDOM } from \"../../utils/frame-dom\";\r\nimport { isCoarsePointer } from \"../../utils/isCoarsePointer\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\nexport abstract class CursorReactiveModule extends StringModule {\r\n protected nearOnly = true;\r\n protected useAllObjects = false;\r\n protected maxDistanceMultiplier = 1;\r\n protected updateThreshold = 0.1;\r\n\r\n protected enabled = true;\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n if (isCoarsePointer()) {\r\n this.enabled = false;\r\n }\r\n }\r\n\r\n override onObjectConnected(object: StringObject): void {\r\n if (!this.enabled) return;\r\n super.onObjectConnected(object);\r\n this.centers.attach(object);\r\n this.hover.track(object);\r\n }\r\n\r\n override removeObject(id: string): void {\r\n if (!this.enabled) return super.removeObject(id);\r\n const obj = this.objectMapOnPage.get(id);\r\n if (obj) {\r\n this.centers.detach(obj);\r\n this.hover.untrack(obj);\r\n }\r\n super.removeObject(id);\r\n }\r\n\r\n override onScroll(): void {\r\n if (!this.enabled) return;\r\n this.centers.invalidateAll();\r\n this.scheduleCursorUpdate();\r\n }\r\n\r\n override onMouseMoveMeasure(data: StringData) {\r\n if (!this.enabled) return;\r\n super.onMouseMoveMeasure(data);\r\n this.refreshPointerState();\r\n }\r\n\r\n override onScrollMeasure(data: StringData) {\r\n if (!this.enabled) return;\r\n super.onScrollMeasure(data);\r\n this.refreshPointerState();\r\n }\r\n\r\n protected getCursorTargets(allowFallback = false): StringObject[] {\r\n if (!this.enabled) return [];\r\n const near = this.hover.activeObjects();\r\n if (this.nearOnly && near.length) return near;\r\n if (this.useAllObjects) return this.objectsOnPage;\r\n if (this.objects.length > 0) return this.objects;\r\n return allowFallback ? this.objectsOnPage : this.objects;\r\n }\r\n\r\n protected refreshPointerState(target?: StringObject, allowFallback = false): void {\r\n if (!this.enabled) return;\r\n\r\n const mx = this.data.cursor.targetX;\r\n const my = this.data.cursor.targetY;\r\n const targets = target ? [target] : this.getCursorTargets(allowFallback);\r\n\r\n const maxDistanceSq =\r\n !this.nearOnly && this.maxDistanceMultiplier > 0\r\n ? Math.pow(this.data.viewport.windowWidth * this.maxDistanceMultiplier, 2)\r\n : null;\r\n\r\n for (const obj of targets) {\r\n const { cx, cy } = this.centers.getCenter(obj);\r\n const dx = mx - cx;\r\n const dy = my - cy;\r\n const d2 = dx * dx + dy * dy;\r\n\r\n if (this.nearOnly) {\r\n const far = d2 > this.data.viewport.windowWidth * this.data.viewport.windowWidth;\r\n if (far && !this.hover.isActive(obj)) continue;\r\n } else if (maxDistanceSq !== null && d2 > maxDistanceSq) {\r\n continue;\r\n }\r\n\r\n obj.setProperty(\"dx\", dx);\r\n obj.setProperty(\"dy\", dy);\r\n obj.setProperty(\"dist\", Math.sqrt(d2));\r\n }\r\n }\r\n\r\n private scrollUpdateScheduled = false;\r\n\r\n protected scheduleCursorUpdate(): void {\r\n if (!this.enabled || this.scrollUpdateScheduled) return;\r\n this.scrollUpdateScheduled = true;\r\n\r\n frameDOM.measure(() => {\r\n this.refreshPointerState();\r\n frameDOM.mutate(() => {\r\n this.scrollUpdateScheduled = false;\r\n styleTxn.run(() => {\r\n this.onCursorScrollUpdate();\r\n });\r\n });\r\n });\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-empty-function\r\n protected onCursorScrollUpdate(): void {}\r\n}\r\n","import { StringData } from \"../../core/StringData\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { frameDOM } from \"../../utils/frame-dom\";\r\nimport { isCoarsePointer } from \"../../utils/isCoarsePointer\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\nimport { CursorReactiveModule } from \"./CursorReactiveModule\";\r\n\r\nconst TAU = Math.PI * 2;\r\nconst RAD2DEG = 180 / Math.PI;\r\nconst clamp01 = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);\r\n\r\nconst shortestArc = (from: number, to: number) => {\r\n let d = (to - from) % TAU;\r\n if (d > Math.PI) d -= TAU;\r\n if (d < -Math.PI) d += TAU;\r\n return from + d;\r\n};\r\n\r\ntype SpotlightState = {\r\n angle: number;\r\n dist: number;\r\n tAngle: number;\r\n tDist: number;\r\n prevDeg: number;\r\n prevDist: number;\r\n};\r\n\r\nconst spotState = new WeakMap<StringObject, SpotlightState>();\r\nconst getSpot = (o: StringObject): SpotlightState => {\r\n let s = spotState.get(o);\r\n if (!s) {\r\n s = { angle: 0, dist: 0, tAngle: 0, tDist: 0, prevDeg: NaN, prevDist: NaN };\r\n spotState.set(o, s);\r\n }\r\n return s;\r\n};\r\n\r\nexport class StringSpotlight extends CursorReactiveModule {\r\n constructor(context: any) {\r\n super(context);\r\n this.htmlKey = \"spotlight\";\r\n\r\n this.nearOnly = false;\r\n this.useAllObjects = false;\r\n this.maxDistanceMultiplier = 1;\r\n\r\n this.attributesToMap.push(\r\n {\r\n key: \"lerp\",\r\n type: \"number\",\r\n fallback: this.settings[\"lerp\"],\r\n transform: (v: number) =>\r\n clamp01(\r\n this.tools.adaptiveLerp.process({\r\n value: v,\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 { key: \"angle-threshold\", type: \"number\", fallback: 0.2 },\r\n { key: \"distance-threshold\", type: \"number\", fallback: 0.5 },\r\n { key: \"deadzone\", type: \"number\", fallback: 4 },\r\n { key: \"dist-max\", type: \"number\", fallback: 0 }\r\n );\r\n }\r\n\r\n initializeObject(\r\n id: number,\r\n obj: StringObject,\r\n el: HTMLElement,\r\n attrs: Record<string, any>\r\n ): void {\r\n super.initializeObject(id, obj, el, attrs);\r\n\r\n obj.setProperty(\"spotlight-angle-rad\", 0);\r\n obj.setProperty(\"spotlight-distance\", 0);\r\n obj.setProperty(\"spotlight-angle-rad-target\", 0);\r\n obj.setProperty(\"spotlight-distance-target\", 0);\r\n\r\n frameDOM.measure(() => {\r\n this.refreshPointerState(obj, /*allowFallback=*/ true);\r\n frameDOM.mutate(() => {\r\n styleTxn.run(() => {\r\n this.updateSpotlightState(obj, {\r\n forceImmediate: true,\r\n forceEmit: true,\r\n bypassDeadzone: true,\r\n });\r\n });\r\n });\r\n });\r\n }\r\n\r\n override onMutate(data: StringData): void {\r\n if (this.enabled) {\r\n super.onMutate(data);\r\n const targets = this.getCursorTargets(/*allowFallback=*/ false);\r\n const list = targets.length > 0 ? targets : this.getCursorTargets(/*allowFallback=*/ true);\r\n list.forEach((object) => {\r\n this.updateSpotlightState(object);\r\n });\r\n }\r\n }\r\n\r\n protected onCursorScrollUpdate(): void {\r\n const targets = this.getCursorTargets(/*allowFallback=*/ false);\r\n const list = targets.length > 0 ? targets : this.getCursorTargets(/*allowFallback=*/ true);\r\n\r\n list.forEach((object) => {\r\n this.updateSpotlightState(object, { bypassDeadzone: true });\r\n });\r\n }\r\n\r\n private updateSpotlightState(\r\n object: StringObject,\r\n options: { forceImmediate?: boolean; forceEmit?: boolean; bypassDeadzone?: boolean } = {}\r\n ): void {\r\n const dx = object.getProperty<number>(\"dx\");\r\n const dy = object.getProperty<number>(\"dy\");\r\n const dist = object.getProperty<number>(\"dist\");\r\n\r\n if (!Number.isFinite(dx) || !Number.isFinite(dy) || !Number.isFinite(dist)) {\r\n return;\r\n }\r\n\r\n const s = getSpot(object);\r\n\r\n const DEADZONE = object.getProperty<number>(\"deadzone\") ?? 4;\r\n if (options.bypassDeadzone || dist! > DEADZONE) {\r\n s.tAngle = Math.atan2(dy!, dx!);\r\n }\r\n\r\n const distMax = object.getProperty<number>(\"dist-max\") ?? 0;\r\n s.tDist = distMax > 0 ? Math.min(dist!, distMax) : dist!;\r\n\r\n object.setProperty(\"spotlight-distance-target\", s.tDist);\r\n object.setProperty(\"spotlight-angle-rad-target\", s.tAngle);\r\n\r\n if (options.forceImmediate) {\r\n s.angle = s.tAngle;\r\n s.dist = s.tDist;\r\n } else {\r\n const lerp = clamp01(object.getProperty<number>(\"lerp\") ?? 0.15);\r\n const nextA = shortestArc(s.angle, s.tAngle);\r\n s.angle += (nextA - s.angle) * lerp;\r\n s.dist += (s.tDist - s.dist) * lerp;\r\n }\r\n\r\n object.setProperty(\"spotlight-angle-rad\", s.angle);\r\n object.setProperty(\"spotlight-distance\", s.dist);\r\n\r\n const degRaw = s.angle * RAD2DEG - 90;\r\n\r\n const angleEps = object.getProperty<number>(\"angle-threshold\") ?? 0.2;\r\n const distEps = object.getProperty<number>(\"distance-threshold\") ?? 0.5;\r\n\r\n const angleChanged =\r\n options.forceEmit || Number.isNaN(s.prevDeg) || Math.abs(degRaw - s.prevDeg) > angleEps;\r\n const distChanged =\r\n options.forceEmit || Number.isNaN(s.prevDist) || Math.abs(s.dist - s.prevDist) > distEps;\r\n\r\n if (angleChanged || distChanged) {\r\n const cssDeg = Math.round(degRaw * 10) / 10;\r\n const cssDist = Math.round(s.dist * 10) / 10;\r\n\r\n styleTxn.run(() => {\r\n this.applyToElementAndConnects(object, (el) => {\r\n styleTxn.setVars(el, {\r\n \"--spotlight-angle\": String(cssDeg),\r\n \"--spotlight-angle-deg\": `${cssDeg}deg`,\r\n \"--spotlight-distance\": String(cssDist),\r\n });\r\n });\r\n });\r\n\r\n s.prevDeg = degRaw;\r\n s.prevDist = s.dist;\r\n\r\n this.events.emit(`spotlight:update:${object.id}`, {\r\n distance: cssDist,\r\n angleDeg: cssDeg,\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\nconst ASPECT_CLASS = \"-aspect-ready\";\r\n\r\ntype Dims = { width: number; height: number };\r\n\r\nfunction isSvgSource(src: string): boolean {\r\n if (!src) return false;\r\n const lower = src.toLowerCase();\r\n if (lower.endsWith(\".svg\")) return true;\r\n if (lower.startsWith(\"data:image/svg\")) return true;\r\n return false;\r\n}\r\n\r\ninterface LazyImageState {\r\n src: string;\r\n aspectReady: boolean;\r\n contentReady: boolean;\r\n aspectLoading: boolean;\r\n contentLoading: boolean;\r\n pendingActivation: boolean;\r\n width?: number;\r\n height?: number;\r\n aspectPromise?: Promise<void>;\r\n unsubscribe?: () => void;\r\n rangeAttempted: boolean;\r\n blobUrl?: string;\r\n controller?: AbortController;\r\n\r\n fetching: boolean;\r\n allowSrcFallback?: boolean;\r\n}\r\n\r\nfunction parsePng(b: ArrayBuffer): Dims {\r\n const d = new DataView(b);\r\n if (b.byteLength < 24) return { width: 0, height: 0 };\r\n if (d.getUint32(0) !== 0x89504e47 || d.getUint32(4) !== 0x0d0a1a0a)\r\n return { width: 0, height: 0 };\r\n if (d.getUint32(12) !== 13 || d.getUint32(16) !== 0x49484452) return { width: 0, height: 0 };\r\n return { width: d.getUint32(20, false), height: d.getUint32(24, false) };\r\n}\r\n\r\nfunction parseJpeg(b: ArrayBuffer): Dims {\r\n const d = new DataView(b);\r\n if (d.getUint16(0) !== 0xffd8) return { width: 0, height: 0 };\r\n let o = 2;\r\n while (o + 9 < b.byteLength) {\r\n const m = d.getUint16(o);\r\n o += 2;\r\n if (m === 0xffda || m === 0xffd9) break;\r\n const len = d.getUint16(o);\r\n if (len < 2 || o + len > b.byteLength) break;\r\n if (\r\n (m >= 0xffc0 && m <= 0xffc3) ||\r\n (m >= 0xffc5 && m <= 0xffc7) ||\r\n (m >= 0xffc9 && m <= 0xffcb) ||\r\n (m >= 0xffcd && m <= 0xffcf)\r\n ) {\r\n return { height: d.getUint16(o + 3), width: d.getUint16(o + 5) };\r\n }\r\n o += len;\r\n }\r\n return { width: 0, height: 0 };\r\n}\r\n\r\nfunction parseWebp(b: ArrayBuffer): Dims {\r\n const d = new DataView(b);\r\n if (b.byteLength < 16) return { width: 0, height: 0 };\r\n\r\n if (d.getUint32(0, true) !== 0x46464952 || d.getUint32(8, true) !== 0x50424557)\r\n return { width: 0, height: 0 };\r\n\r\n let i = 12;\r\n while (i + 8 <= b.byteLength) {\r\n const chunkHeader = d.getUint32(i, false);\r\n const chunkSize = d.getUint32(i + 4, true);\r\n const dataOffset = i + 8;\r\n\r\n if (chunkHeader === 0x56503858) {\r\n const w = (d.getUint16(dataOffset + 4, true) | (d.getUint8(dataOffset + 6) << 16)) + 1;\r\n const h = (d.getUint16(dataOffset + 7, true) | (d.getUint8(dataOffset + 9) << 16)) + 1;\r\n return { width: w, height: h };\r\n }\r\n\r\n if (chunkHeader === 0x56503820) {\r\n if (\r\n dataOffset + 10 <= b.byteLength &&\r\n d.getUint8(dataOffset + 3) === 0x9d &&\r\n d.getUint8(dataOffset + 4) === 0x01 &&\r\n d.getUint8(dataOffset + 5) === 0x2a\r\n ) {\r\n const w = d.getUint16(dataOffset + 6, true) & 0x3fff;\r\n const h = d.getUint16(dataOffset + 8, true) & 0x3fff;\r\n return { width: w, height: h };\r\n }\r\n }\r\n\r\n if (chunkHeader === 0x5650384c) {\r\n if (dataOffset + 5 <= b.byteLength && d.getUint8(dataOffset) === 0x2f) {\r\n const b0 = d.getUint8(dataOffset + 1);\r\n const b1 = d.getUint8(dataOffset + 2);\r\n const b2 = d.getUint8(dataOffset + 3);\r\n const b3 = d.getUint8(dataOffset + 4);\r\n\r\n const w = 1 + (((b1 & 0x3f) << 8) | b0);\r\n const h = 1 + (((b3 & 0x0f) << 10) | (b2 << 2) | ((b1 & 0xc0) >> 6));\r\n return { width: w, height: h };\r\n }\r\n }\r\n\r\n i = dataOffset + chunkSize + (chunkSize & 1);\r\n }\r\n return { width: 0, height: 0 };\r\n}\r\n\r\nfunction tryParseDims(buffer: ArrayBuffer, ct?: string | null): Dims {\r\n const c = (ct || \"\").toLowerCase();\r\n if (c.includes(\"png\")) return parsePng(buffer);\r\n if (c.includes(\"jpeg\") || c.includes(\"jpg\")) return parseJpeg(buffer);\r\n if (c.includes(\"webp\")) return parseWebp(buffer);\r\n let d = parsePng(buffer);\r\n if (d.width) return d;\r\n d = parseJpeg(buffer);\r\n if (d.width) return d;\r\n d = parseWebp(buffer);\r\n if (d.width) return d;\r\n return { width: 0, height: 0 };\r\n}\r\n\r\nasync function fetchImageStreamWithDims(\r\n src: string,\r\n opts?: {\r\n credentials?: RequestCredentials;\r\n referrerPolicy?: ReferrerPolicy;\r\n signal?: AbortSignal;\r\n },\r\n onDims?: (d: Dims) => void\r\n): Promise<{\r\n dims: { width: number; height: number } | null;\r\n blobUrl: string;\r\n contentType?: string | null;\r\n}> {\r\n const res = await fetch(src, {\r\n mode: \"cors\",\r\n credentials: opts?.credentials ?? \"omit\",\r\n referrerPolicy: opts?.referrerPolicy,\r\n signal: opts?.signal,\r\n cache: \"default\",\r\n });\r\n if (!res.ok || !res.body) throw new Error(`HTTP ${res.status}`);\r\n\r\n const ct = res.headers.get(\"content-type\");\r\n const reader = res.body.getReader();\r\n\r\n const PROBE_CAP = 1048576;\r\n const TRY_STEP = 4096;\r\n\r\n const probe = new Uint8Array(PROBE_CAP);\r\n let probeLen = 0;\r\n let lastTriedLen = 0;\r\n\r\n const chunks: ArrayBuffer[] = [];\r\n let dims: Dims | null = null;\r\n let announced = false;\r\n\r\n for (;;) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n if (!value) continue;\r\n\r\n const part = value.buffer.slice(value.byteOffset, value.byteOffset + value.byteLength);\r\n chunks.push(part);\r\n\r\n if (!dims && probeLen < PROBE_CAP) {\r\n const toCopy = Math.min(value.byteLength, PROBE_CAP - probeLen);\r\n if (toCopy > 0) {\r\n probe.set(value.subarray(0, toCopy), probeLen);\r\n probeLen += toCopy;\r\n }\r\n if (probeLen - lastTriedLen >= TRY_STEP) {\r\n const view = probeLen === probe.byteLength ? probe : probe.slice(0, probeLen);\r\n const d = tryParseDims(view.buffer, ct);\r\n if (d.width && d.height) {\r\n dims = d;\r\n if (!announced && onDims) {\r\n onDims(dims);\r\n announced = true;\r\n }\r\n }\r\n lastTriedLen = probeLen;\r\n }\r\n }\r\n }\r\n\r\n if (!dims) {\r\n const full = await new Response(new Blob(chunks)).arrayBuffer();\r\n const d = tryParseDims(full, ct);\r\n if (d.width && d.height) {\r\n dims = d;\r\n if (!announced && onDims) {\r\n onDims(dims);\r\n announced = true;\r\n }\r\n }\r\n }\r\n\r\n const blob = new Blob(chunks, { type: ct || \"application/octet-stream\" });\r\n const blobUrl = URL.createObjectURL(blob);\r\n return { dims, blobUrl, contentType: ct };\r\n}\r\n\r\nexport class StringLazy extends StringModule {\r\n private isStartLoaded = false;\r\n private loadingCount = 0;\r\n private imageStates = new WeakMap<HTMLImageElement, LazyImageState>();\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"lazy\";\r\n }\r\n\r\n onInit(): void {\r\n const images = document.querySelectorAll(\"img[string-lazy], img[data-string-lazy]\");\r\n images.forEach((img) => this.ensureState(img as HTMLImageElement));\r\n this.isStartLoaded = true;\r\n }\r\n\r\n onObjectConnected(object: StringObject): void {\r\n const element = object.htmlElement;\r\n if (!(element instanceof HTMLImageElement)) return;\r\n const state = this.ensureState(element);\r\n\r\n if (!state.aspectReady && !state.aspectLoading) {\r\n this.prepareAspectRatio(element);\r\n }\r\n\r\n const listener = (data: { inView: boolean } | undefined) => {\r\n this.handleInView(element, state, !!data?.inView);\r\n };\r\n if (state.unsubscribe) state.unsubscribe();\r\n this.events.on(`object:inview:${object.id}`, listener);\r\n state.unsubscribe = () => this.events.off(`object:inview:${object.id}`, listener);\r\n if (this.isStartLoaded && (object.getProperty<boolean>(\"is-inview\") ?? false)) {\r\n this.handleInView(element, state, true);\r\n }\r\n }\r\n\r\n onObjectDisconnected(object: StringObject): void {\r\n const element = object.htmlElement;\r\n if (!(element instanceof HTMLImageElement)) return;\r\n const state = this.imageStates.get(element);\r\n if (!state) return;\r\n state.pendingActivation = false;\r\n if (state.controller) state.controller.abort();\r\n if (state.blobUrl) URL.revokeObjectURL(state.blobUrl);\r\n if (state.unsubscribe) {\r\n state.unsubscribe();\r\n state.unsubscribe = undefined;\r\n }\r\n }\r\n\r\n private ensureState(img: HTMLImageElement): LazyImageState {\r\n let state = this.imageStates.get(img);\r\n if (!state) {\r\n const src = this.readSource(img);\r\n state = {\r\n src,\r\n aspectReady: false,\r\n contentReady: false,\r\n aspectLoading: false,\r\n contentLoading: false,\r\n pendingActivation: false,\r\n rangeAttempted: false,\r\n fetching: false,\r\n };\r\n this.imageStates.set(img, state);\r\n if (!img.classList.contains(\"lazyLoad\")) img.classList.add(\"lazyLoad\");\r\n if (img.dataset && !img.dataset.stringLazySrc && src) img.dataset.stringLazySrc = src;\r\n return state;\r\n }\r\n if (!state.src) state.src = this.readSource(img);\r\n return state;\r\n }\r\n\r\n private readSource(img: HTMLImageElement): string {\r\n const raw = this.tools.domAttribute.process({ element: img, key: this.htmlKey, fallback: \"\" });\r\n if (typeof raw === \"string\") return raw;\r\n if (raw == null) return \"\";\r\n return String(raw);\r\n }\r\n\r\n private handleInView(img: HTMLImageElement, state: LazyImageState, inView: boolean): void {\r\n state.pendingActivation = inView;\r\n if (!inView) return;\r\n if (state.aspectReady) {\r\n this.maybeActivateImage(img, state);\r\n } else if (!state.aspectLoading) {\r\n this.prepareAspectRatio(img);\r\n }\r\n }\r\n\r\n private async prepareAspectRatio(img: HTMLImageElement): Promise<void> {\r\n const state = this.ensureState(img);\r\n if (!state.src || state.aspectLoading || state.aspectReady) return;\r\n\r\n if (isSvgSource(state.src)) {\r\n state.aspectReady = true;\r\n state.allowSrcFallback = true;\r\n this.maybeActivateImage(img, state);\r\n return;\r\n }\r\n\r\n state.aspectLoading = true;\r\n state.fetching = true;\r\n\r\n const crossOrigin = img.getAttribute(\"crossorigin\");\r\n const referrerPolicy = img.getAttribute(\"referrerpolicy\") as ReferrerPolicy | null;\r\n const ac = new AbortController();\r\n state.controller = ac;\r\n\r\n try {\r\n const { blobUrl } = await fetchImageStreamWithDims(\r\n state.src,\r\n {\r\n credentials: crossOrigin === \"use-credentials\" ? \"include\" : \"omit\",\r\n referrerPolicy: referrerPolicy || undefined,\r\n signal: ac.signal,\r\n },\r\n\r\n (d) => {\r\n if (d.width > 0 && d.height > 0 && !state.aspectReady) {\r\n img.style.aspectRatio = `${d.width} / ${d.height}`;\r\n img.classList.add(ASPECT_CLASS);\r\n state.width = d.width;\r\n state.height = d.height;\r\n state.aspectReady = true;\r\n }\r\n }\r\n );\r\n\r\n state.blobUrl = blobUrl;\r\n\r\n if (!state.aspectReady && state.width && state.height) {\r\n img.style.aspectRatio = `${state.width} / ${state.height}`;\r\n img.classList.add(ASPECT_CLASS);\r\n state.aspectReady = true;\r\n }\r\n } catch {\r\n state.allowSrcFallback = true;\r\n state.aspectReady = true;\r\n } finally {\r\n state.fetching = false;\r\n state.aspectLoading = false;\r\n\r\n this.maybeActivateImage(img, state);\r\n }\r\n }\r\n\r\n private maybeActivateImage(img: HTMLImageElement, state: LazyImageState): void {\r\n if (!state.pendingActivation || state.contentReady || state.contentLoading) return;\r\n if (!state.aspectReady || !state.src) return;\r\n\r\n if (state.fetching && !state.blobUrl) return;\r\n\r\n if (state.blobUrl || state.allowSrcFallback) {\r\n this.activateImage(img, state);\r\n }\r\n }\r\n\r\n private activateImage(img: HTMLImageElement, state: LazyImageState): void {\r\n state.contentLoading = true;\r\n this.loadingCount++;\r\n const finalize = (loaded: boolean) => {\r\n if (!state.contentLoading) return;\r\n state.contentLoading = false;\r\n state.pendingActivation = false;\r\n this.loadingCount = Math.max(0, this.loadingCount - 1);\r\n if (loaded) {\r\n state.contentReady = true;\r\n img.classList.add(\"-loaded\");\r\n }\r\n if (this.loadingCount === 0) this.events.emit(\"image:load:all\", null);\r\n };\r\n const onLoad = () => finalize(true);\r\n const onError = () => finalize(false);\r\n img.addEventListener(\"load\", onLoad, { once: true });\r\n img.addEventListener(\"error\", onError, { once: true });\r\n img.decoding = \"async\";\r\n img.loading = img.loading || \"lazy\";\r\n\r\n if (state.blobUrl) {\r\n img.removeAttribute(\"srcset\");\r\n img.removeAttribute(\"sizes\");\r\n img.src = state.blobUrl;\r\n } else {\r\n img.src = state.src;\r\n }\r\n\r\n if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {\r\n img.removeEventListener(\"load\", onLoad);\r\n img.removeEventListener(\"error\", onError);\r\n finalize(true);\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: 1023,\r\n }),\r\n [DeviceType.Laptop]: new StringResponsiveQueryDevice({\r\n min: 1024,\r\n max: 1365,\r\n }),\r\n [DeviceType.Desktop]: new StringResponsiveQueryDevice({ min: 1366 }),\r\n };\r\n\r\n private isMobileMedia: boolean = false;\r\n private isTabletMedia: boolean = false;\r\n private isLaptopMedia: boolean = false;\r\n private isDesktopMedia: boolean = false;\r\n\r\n private matchMedias: { [key in DeviceType]: MediaQueryList } = {\r\n [DeviceType.Mobile]: window.matchMedia(this.queries[DeviceType.Mobile].mediaQuery),\r\n [DeviceType.Tablet]: window.matchMedia(this.queries[DeviceType.Tablet].mediaQuery),\r\n [DeviceType.Laptop]: window.matchMedia(this.queries[DeviceType.Laptop].mediaQuery),\r\n [DeviceType.Desktop]: window.matchMedia(this.queries[DeviceType.Desktop].mediaQuery),\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.tablet.min == undefined ? null : config.tablet.min,\r\n config.tablet.max ?? null\r\n );\r\n this.matchMedias[DeviceType.Tablet] = window.matchMedia(\r\n this.queries[DeviceType.Tablet].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.laptop.min == undefined ? null : config.laptop.min,\r\n config.laptop.max ?? null\r\n );\r\n this.matchMedias[DeviceType.Laptop] = window.matchMedia(\r\n this.queries[DeviceType.Laptop].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.desktop.min == undefined ? null : config.desktop.min,\r\n config.desktop.max ?? null\r\n );\r\n this.matchMedias[DeviceType.Desktop] = window.matchMedia(\r\n this.queries[DeviceType.Desktop].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 && this.queries[DeviceType.Mobile].enable;\r\n const isTabletMedia =\r\n this.matchMedias[DeviceType.Tablet].matches && this.queries[DeviceType.Tablet].enable;\r\n const isLaptopMedia =\r\n this.matchMedias[DeviceType.Laptop].matches && this.queries[DeviceType.Laptop].enable;\r\n const isDesktopMedia =\r\n this.matchMedias[DeviceType.Desktop].matches && this.queries[DeviceType.Desktop].enable;\r\n\r\n if (this.isMobileMedia != isMobileMedia) {\r\n this.events.emit(\"screen:mobile\", isMobileMedia);\r\n }\r\n if (this.isTabletMedia != isTabletMedia) {\r\n this.events.emit(\"screen:tablet\", isTabletMedia);\r\n }\r\n if (this.isLaptopMedia != isLaptopMedia) {\r\n this.events.emit(\"screen:laptop\", isLaptopMedia);\r\n }\r\n if (this.isDesktopMedia != isDesktopMedia) {\r\n this.events.emit(\"screen:desktop\", isDesktopMedia);\r\n }\r\n\r\n this.isMobileMedia = isMobileMedia;\r\n this.isTabletMedia = isTabletMedia;\r\n this.isLaptopMedia = isLaptopMedia;\r\n this.isDesktopMedia = isDesktopMedia;\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 }\r\n if (element.hasAttribute(\"string-tablet\") && isTabletMedia) {\r\n showElement = true;\r\n }\r\n if (element.hasAttribute(\"string-laptop\") && isLaptopMedia) {\r\n showElement = true;\r\n }\r\n if (element.hasAttribute(\"string-desktop\") && isDesktopMedia) {\r\n showElement = true;\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\"] ?? 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 = -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 > 1024) {\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(\"--glide\", this.data.scroll.displacement.toString());\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(MAX_DISPLACEMENT, this.acceleration + ACCELERATION_STEP);\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(MIN_VELOCITY, this.data.scroll.lerped * this.displacement * this.acceleration)\r\n );\r\n this.objects.forEach((object) => {\r\n this.applyToElementAndConnects(object, (el) => {\r\n el.style.setProperty(\"--glide\", this.data.scroll.displacement.toString());\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 { StringMirrorObject } from \"../../objects/StringMirrorObject\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\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 private hasInitializedCSS = false;\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"lerp\";\r\n }\r\n\r\n /**\r\n * Initialize lerp value when object connects.\r\n */\r\n onObjectConnected(object: StringObject): void {\r\n super.onObjectConnected(object);\r\n // Initialize with 0\r\n object.setProperty<number>(\"lerp\", 0);\r\n }\r\n\r\n /**\r\n * Called on resize - use this to apply initial values after mirrors are created.\r\n */\r\n onResize(): void {\r\n super.onResize();\r\n // Only apply initial CSS on first resize (after mirrors are created)\r\n if (!this.hasInitializedCSS && this.objectsOnPage.length > 0) {\r\n this.hasInitializedCSS = true;\r\n styleTxn.run(() => {\r\n this.objectsOnPage.forEach((object) => {\r\n this.updateObjectLerp(object, true);\r\n });\r\n });\r\n }\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.recomputeLerp(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.recomputeLerp(object, velocity);\r\n });\r\n }\r\n\r\n /**\r\n * Computes the lerp value for the object.\r\n */\r\n private recomputeLerp(object: StringObject, velocity: number): void {\r\n const prevLerp = object.getProperty<number>(\"lerp\");\r\n\r\n if (prevLerp === velocity) {\r\n return;\r\n }\r\n\r\n object.setProperty<number>(\"lerp\", velocity);\r\n // Update immediately when lerp value changes\r\n this.updateObjectLerp(object);\r\n }\r\n\r\n /**\r\n * Applies the lerp value to the object and its mirrors.\r\n */\r\n onMutate(): void {\r\n styleTxn.run(() => {\r\n this.objects.forEach((object) => {\r\n this.updateObjectLerp(object);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Updates the CSS variable on the object and connected elements.\r\n */\r\n private updateObjectLerp(object: StringObject, force = false): void {\r\n const lerp = object.getProperty<number>(\"lerp\");\r\n const prevLerp = object.getProperty<number>(\"lerp-applied\");\r\n\r\n if (!force && prevLerp === lerp) {\r\n return;\r\n }\r\n\r\n object.setProperty<number>(\"lerp-applied\", lerp);\r\n\r\n const lerpStr = lerp?.toString() ?? \"0\";\r\n\r\n this.events.emit(`object:lerp:${object.id}`, lerp);\r\n\r\n styleTxn.run(() => {\r\n this.applyToElementAndConnects(\r\n object,\r\n (el) => {\r\n styleTxn.setVars(el, { \"--lerp\": lerpStr });\r\n },\r\n (el: HTMLElement, mirror?: StringMirrorObject) => {\r\n if (!mirror) return;\r\n styleTxn.setVars(el, { \"--lerp\": lerpStr });\r\n }\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Cleans up the CSS variable when object is disconnected.\r\n */\r\n onObjectDisconnected(object: StringObject): void {\r\n super.onObjectDisconnected(object);\r\n\r\n const clearCustomProperty = (el: HTMLElement) => {\r\n el.style.removeProperty(\"--lerp\");\r\n };\r\n\r\n clearCustomProperty(object.htmlElement);\r\n object.mirrorObjects.forEach((mirror) => {\r\n clearCustomProperty(mirror.htmlElement);\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 { StringMirrorObject } from \"../../objects/StringMirrorObject\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EasingFunctionOutput } from \"../../tools/EasingFunctionTool\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\nexport class StringProgress extends StringModule {\r\n protected updateScheduled = false;\r\n\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 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 private recomputeProgress(object: StringObject): void {\r\n const startPosition = object.getProperty<number>(\"start-position\") ?? 0;\r\n const differencePosition = object.getProperty<number>(\"difference-position\") ?? 0;\r\n\r\n let rawProgress = 0;\r\n rawProgress = Math.min(\r\n 1,\r\n Math.max(0, (this.data.scroll.transformedCurrent - startPosition) / differencePosition)\r\n );\r\n\r\n const prevRawProgress = object.getProperty<number>(\"progress-raw\");\r\n\r\n if (prevRawProgress === rawProgress) {\r\n return;\r\n }\r\n\r\n object.setProperty<number>(\"progress-raw\", rawProgress);\r\n\r\n const easing = object.getProperty<EasingFunctionOutput>(\"easing\");\r\n const progress = typeof easing === \"function\" ? easing(rawProgress) : rawProgress;\r\n object.setProperty<number>(\"progress\", progress);\r\n }\r\n\r\n calculatePositions(object: StringObject, windowSize: number) {\r\n super.calculatePositions(object, windowSize);\r\n this.recomputeProgress(object);\r\n }\r\n\r\n onScroll(data: StringData): void {\r\n super.onScroll(data);\r\n }\r\n\r\n onObjectConnected(object: StringObject) {\r\n super.onObjectConnected(object);\r\n }\r\n\r\n onScrollMeasure(data: StringData) {\r\n this.objects.forEach((object) => {\r\n this.recomputeProgress(object);\r\n });\r\n }\r\n\r\n onMutate() {\r\n styleTxn.run(() => {\r\n this.objects.forEach((object) => {\r\n this.updateObjectProgress(object);\r\n });\r\n });\r\n }\r\n\r\n private updateObjectProgress(object: StringObject): void {\r\n const key = object.getProperty<string>(\"key\");\r\n const progress = object.getProperty<number>(\"progress\");\r\n const prevProgress = object.getProperty<number>(\"progress-applied\");\r\n\r\n if (prevProgress === progress) {\r\n return;\r\n }\r\n\r\n object.setProperty<number>(\"progress-applied\", progress);\r\n\r\n const rawProgress = object.getProperty<number>(\"progress-raw\") ?? progress;\r\n const progressStr = progress.toString();\r\n const parentEasing = object.getProperty<EasingFunctionOutput>(\"easing\");\r\n\r\n this.events.emit(`object:progress:${object.id}`, progress);\r\n this.applyToElementAndConnects(\r\n object,\r\n (el) => {\r\n if (key) {\r\n styleTxn.setVars(el, { [key]: progressStr });\r\n }\r\n },\r\n (el: HTMLElement, mirror?: StringMirrorObject) => {\r\n if (!mirror) return;\r\n const eased = mirror.applyProgress(\r\n rawProgress,\r\n typeof parentEasing === \"function\" ? parentEasing : undefined\r\n );\r\n mirror.setProperty(\"progress\", eased);\r\n if (key) {\r\n styleTxn.setVars(el, { [key]: eased.toString() });\r\n }\r\n }\r\n );\r\n }\r\n\r\n onObjectDisconnected(object: StringObject): void {\r\n super.onObjectDisconnected(object);\r\n const key = object.getProperty<string>(\"key\");\r\n if (!key) return;\r\n\r\n const clearCustomProperty = (el: HTMLElement) => {\r\n el.style.removeProperty(key);\r\n };\r\n\r\n clearCustomProperty(object.htmlElement);\r\n object.mirrorObjects.forEach((mirror) => {\r\n clearCustomProperty(mirror.htmlElement);\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 { frameDOM } from \"../../utils/frame-dom\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\nimport { StringProgress } from \"./StringProgress\";\r\n\r\ntype ParallaxTransformResult = { transform: string };\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 private updateScheduledTransform = false;\r\n private calculateParallaxForObject: (object: StringObject) => ParallaxTransformResult | null;\r\n\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 this.calculateParallaxForObject = this.calculateDesktopParallax;\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(\"parallax-sign\", Math.sign(object.getProperty<number>(\"parallax\")));\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 calculatePositions(object: StringObject, windowSize: number) {\r\n super.calculatePositions(object, windowSize);\r\n object.setProperty(\"transform-value\", this.calculateParallaxForObject(object));\r\n }\r\n\r\n override onScroll(data: StringData): void {\r\n super.onScroll(data);\r\n }\r\n\r\n override onResize(): void {\r\n const isDesktop = window.innerWidth > 1024;\r\n this.calculateParallaxForObject = isDesktop\r\n ? this.calculateDesktopParallax\r\n : this.calculateMobileParallax;\r\n }\r\n\r\n onScrollMeasure(data: StringData) {\r\n super.onScrollMeasure(data);\r\n this.objects.forEach((object) => {\r\n object.setProperty(\"transform-value\", this.calculateParallaxForObject(object));\r\n });\r\n }\r\n\r\n onMutate() {\r\n styleTxn.run(() => {\r\n this.objects.forEach((object) => {\r\n const transformData = object.getProperty<ParallaxTransformResult>(\"transform-value\");\r\n this.applyToElementAndConnects(object, (el) => {\r\n styleTxn.setProps(el, transformData);\r\n });\r\n });\r\n });\r\n }\r\n\r\n private calculateDesktopParallax = (object: StringObject): ParallaxTransformResult => {\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 / this.data.viewport.transformScale;\r\n const translation = sign * factor * (screenSize * start + progress * screenSize * end);\r\n\r\n this.events.emit(`object:parallax:${object.id}`, translation);\r\n\r\n return { transform: `translate3d(0, ${translation}px, 0)` };\r\n };\r\n\r\n private calculateMobileParallax = (object: StringObject): ParallaxTransformResult => {\r\n this.events.emit(`object:parallax:${object.id}`, 0);\r\n return { transform: `translate3d(0, 0px, 0)` };\r\n };\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 = {\r\n BEFORE_ELEMENT: \"-before-element\",\r\n AFTER_ELEMENT: \"-after-element\",\r\n} as const;\r\n","import { CalculatedValue } from \"../../models/text/CalculatedValue\";\r\nimport { LayoutLine } from \"./SplitMeasuredTokens\";\r\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\r\nimport { SPLIT_ELEMENT_CLASS } from \"../../models/text/SplitElementClass\";\r\nimport { FontMetrics } from \"./CanvasKerningApplier\";\r\n\r\nfunction getWholeWordSplitClass(word: any): string[] {\r\n if (!word || !Array.isArray(word.chars) || word.chars.length === 0) return [];\r\n const first = (word.chars[0] as any).splitClass ?? [];\r\n if (first.length === 0) return [];\r\n for (const ch of word.chars) {\r\n const cls = (ch as any).splitClass ?? [];\r\n if (cls.length !== first.length) return [];\r\n for (let i = 0; i < cls.length; i++) {\r\n if (cls[i] !== first[i]) return [];\r\n }\r\n }\r\n return first;\r\n}\r\n\r\nexport function BuildDOMTree(\r\n layoutLines: LayoutLine[],\r\n options: ISplitOptions,\r\n fontMetrics: FontMetrics\r\n): { fragment: DocumentFragment; extraProps: Map<string, string> } {\r\n const fragment = document.createDocumentFragment();\r\n let localCharIndex = 0;\r\n\r\n const hasLine =\r\n hasOption(options, \"line\") || hasOption(options, \"charLine\") || hasOption(options, \"wordLine\");\r\n\r\n const hasChar =\r\n hasOption(options, \"char\") || hasOption(options, \"charLine\") || hasOption(options, \"charWord\");\r\n\r\n let wordsCount = 0;\r\n layoutLines.forEach((line) => (wordsCount += line.words.length));\r\n wordsCount--;\r\n\r\n let charsCount = 0;\r\n layoutLines.forEach((line) => line.words.forEach((w) => (charsCount += w.chars.length)));\r\n\r\n const linesCount = layoutLines.length;\r\n const wordsGlobalCount = wordsCount + 1;\r\n\r\n const extraProps = new Map<string, string>();\r\n\r\n layoutLines.forEach((line, li) => {\r\n const isLastInLayout = li === layoutLines.length - 1;\r\n\r\n let container: HTMLElement | DocumentFragment = fragment;\r\n const wordsForLine: string[] = [];\r\n\r\n if (hasLine) {\r\n container = document.createElement(\"span\");\r\n container.setAttribute(\"aria-hidden\", \"true\");\r\n container.classList.add(\"-s-line\");\r\n if (line.isBeforeElement)\r\n (container as HTMLElement).classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\r\n if (line.isAfterElement)\r\n (container as HTMLElement).classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\r\n (container as HTMLElement).style.setProperty(\"--line-index\", String(line.lineIndex));\r\n (container as HTMLElement).style.setProperty(\"--word-total\", String(line.words.length));\r\n applyStyles(container as HTMLElement, (line as any).calculatedValues, options);\r\n }\r\n\r\n line.words.forEach((word, wi) => {\r\n if (hasLine) {\r\n wordsCount = line.words.length - 1;\r\n }\r\n const isLast = wi === wordsCount;\r\n const isElementWord = word.chars.length === 1 && word.chars[0].token.type === \"element\";\r\n if (isElementWord) {\r\n const original = word.chars[0].token.node.cloneNode(true) as HTMLElement;\r\n container.appendChild(original);\r\n return;\r\n }\r\n\r\n const wordText = word.chars.map((c) => c.char).join(\"\");\r\n if (wordText) {\r\n wordsForLine.push(wordText);\r\n }\r\n\r\n const hasWord =\r\n hasOption(options, \"word\") ||\r\n hasOption(options, \"charWord\") ||\r\n hasOption(options, \"wordLine\");\r\n\r\n const wordEl = hasWord ? document.createElement(\"span\") : (container as HTMLElement);\r\n\r\n const wholeWordClass = getWholeWordSplitClass(word);\r\n\r\n if (hasWord) {\r\n wordEl.setAttribute(\"aria-hidden\", \"true\");\r\n wordEl.classList.add(\"-s-word\");\r\n if (word.isBeforeElement) wordEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\r\n if (word.isAfterElement) wordEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\r\n wordEl.style.setProperty(\"--word-index\", String(word.wordIndexGlobal));\r\n wordEl.style.setProperty(\"--char-total\", String(word.chars.length));\r\n wordEl.setAttribute(\"data-split-content\", wordText);\r\n applyStyles(wordEl, (word as any).calculatedValues, options);\r\n\r\n if (wholeWordClass.length) {\r\n wordEl.classList.add(...wholeWordClass);\r\n }\r\n }\r\n\r\n if (hasChar) {\r\n word.chars.forEach((char, charIndex) => {\r\n if (char.char === \" \" || char.char === \"\\t\") return;\r\n\r\n const charNode = document.createElement(\"span\");\r\n charNode.setAttribute(\"aria-hidden\", \"true\");\r\n const charEl = charNode as HTMLElement;\r\n\r\n charEl.classList.add(\"-s-char\");\r\n if (char.isBeforeElement) charEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\r\n if (char.isAfterElement) charEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\r\n\r\n charEl.textContent = char.char;\r\n charEl.setAttribute(\"data-split-content\", char.char);\r\n charEl.style.setProperty(\"--char-index\", String(localCharIndex++));\r\n\r\n const nextChar = word.chars[charIndex + 1];\r\n if (nextChar) {\r\n const kerning = fontMetrics.getKerning(char.char, nextChar.char);\r\n if (Math.abs(kerning) > 0.01) {\r\n charEl.style.setProperty(\"--kerning\", `${kerning.toFixed(2)}px`);\r\n charEl.style.marginRight = `var(--kerning)`;\r\n }\r\n }\r\n\r\n applyStyles(charEl, (char as any).calculatedValues, options);\r\n\r\n const splitClassChar: string[] = (char as any).splitClass ?? [];\r\n if (splitClassChar.length && !wholeWordClass.length) {\r\n charEl.classList.add(...splitClassChar);\r\n }\r\n\r\n wordEl.appendChild(charNode);\r\n });\r\n } else {\r\n const textNode = document.createTextNode(wordText);\r\n wordEl.appendChild(textNode);\r\n }\r\n\r\n if (hasWord) {\r\n container.appendChild(wordEl);\r\n }\r\n\r\n if (hasLine) {\r\n if (!isLast) {\r\n wordEl.appendChild(document.createTextNode(\"\\u00a0\"));\r\n } else if (!isLastInLayout) {\r\n container.appendChild(document.createElement(\"br\"));\r\n }\r\n } else {\r\n if (!isLast) {\r\n wordEl.appendChild(document.createTextNode(\"\\u00a0\"));\r\n }\r\n }\r\n });\r\n\r\n if (hasLine) {\r\n const lineText = wordsForLine.join(\" \");\r\n (container as HTMLElement).setAttribute(\"data-split-content\", lineText);\r\n fragment.appendChild(container as HTMLElement);\r\n }\r\n });\r\n\r\n if (hasChar) {\r\n extraProps.set(\"--char-global-total\", String(charsCount));\r\n }\r\n if (\r\n hasOption(options, \"word\") ||\r\n hasOption(options, \"charWord\") ||\r\n hasOption(options, \"wordLine\")\r\n ) {\r\n extraProps.set(\"--word-global-total\", String(wordsGlobalCount));\r\n }\r\n if (hasLine) {\r\n extraProps.set(\"--line-global-total\", String(linesCount));\r\n }\r\n\r\n return { fragment, extraProps };\r\n}\r\n\r\nfunction applyStyles(\r\n el: HTMLElement,\r\n calculatedValues: CalculatedValue[] | undefined,\r\n options: ISplitOptions\r\n) {\r\n if (!calculatedValues) return;\r\n for (const val of calculatedValues) {\r\n if (!isOptionEnabled(val.type, val.align, options)) continue;\r\n const varName = generateVariableName(val.type, val.align);\r\n el.style.setProperty(varName, String(val.value));\r\n }\r\n}\r\n\r\nfunction isOptionEnabled(type: string, align: string, options: ISplitOptions): boolean {\r\n const group = options[type as keyof ISplitOptions] ?? [];\r\n return (\r\n Array.isArray(group) &&\r\n group.some((item) =>\r\n align.startsWith(\"random\") ? item.align.startsWith(\"random\") : item.align === align\r\n )\r\n );\r\n}\r\n\r\nfunction generateVariableName(type: string, align: string): string {\r\n const norm = align.startsWith(\"random\") ? \"random\" : align;\r\n return `--${type}-${norm}`;\r\n}\r\n\r\nfunction hasOption(options: ISplitOptions, key: keyof ISplitOptions): boolean {\r\n return Array.isArray(options[key]) && options[key]!.length > 0;\r\n}\r\n","export type Token =\r\n | {\r\n type: \"text\";\r\n id: string;\r\n node: Text;\r\n content: string;\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"space\";\r\n id: string;\r\n node: Text;\r\n content: string;\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"element\";\r\n id: string;\r\n node: HTMLElement;\r\n tagName: string;\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"br\";\r\n id: string;\r\n node: HTMLElement;\r\n tagName: \"br\";\r\n meta?: Record<string, any>;\r\n }\r\n | {\r\n type: \"other\";\r\n id: string;\r\n node: Node;\r\n meta?: Record<string, any>;\r\n };\r\n\r\nlet tokenCounter = 0;\r\n\r\nexport function BuildTokens(nodes: NodeListOf<ChildNode>): Token[] {\r\n tokenCounter = 0;\r\n const tokens: Token[] = [];\r\n\r\n const pushWithMeta = (t: Token, extra: Record<string, any> | undefined) => {\r\n if (extra && Object.keys(extra).length) {\r\n t.meta = { ...(t.meta || {}), ...extra };\r\n }\r\n tokens.push(t);\r\n };\r\n\r\n const processNode = (node: ChildNode, carryMeta?: Record<string, any>) => {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === \"split-class\") {\r\n const classes = (el.getAttribute(\"class\") ?? \"\").split(/\\s+/).filter(Boolean);\r\n const extraMeta = {\r\n ...(carryMeta || {}),\r\n splitClass: [...((carryMeta?.splitClass as string[]) ?? []), ...classes],\r\n };\r\n el.childNodes.forEach((child) => processNode(child as ChildNode, extraMeta));\r\n return;\r\n }\r\n\r\n if (tag === \"br\") {\r\n pushWithMeta(\r\n {\r\n type: \"br\",\r\n id: `br_${tokenCounter++}`,\r\n node: el,\r\n tagName: \"br\",\r\n },\r\n carryMeta\r\n );\r\n return;\r\n }\r\n\r\n pushWithMeta(\r\n {\r\n type: \"element\",\r\n id: `el_${tokenCounter++}`,\r\n node: el,\r\n tagName: tag,\r\n },\r\n carryMeta\r\n );\r\n return;\r\n }\r\n\r\n if (node.nodeType === Node.TEXT_NODE) {\r\n const text = node.nodeValue ?? \"\";\r\n const id = `text_${tokenCounter++}`;\r\n if (text.trim()) {\r\n pushWithMeta({ type: \"text\", id, node: node as Text, content: text }, carryMeta);\r\n } else {\r\n pushWithMeta({ type: \"space\", id, node: node as Text, content: text }, carryMeta);\r\n }\r\n return;\r\n }\r\n\r\n pushWithMeta({ type: \"other\", id: `node_${tokenCounter++}`, node }, carryMeta);\r\n };\r\n\r\n nodes.forEach((n) => processNode(n as ChildNode));\r\n return tokens;\r\n}\r\n","type PairKey = `${string}|${string}`;\n\nexport class FontMetrics {\n private ctx: CanvasRenderingContext2D;\n private font: string = \"\";\n private cache = {\n kerning: new Map<PairKey, number>(),\n charWidth: new Map<string, number>(),\n };\n\n constructor(element: HTMLElement) {\n const canvas = document.createElement(\"canvas\");\n this.ctx = canvas.getContext(\"2d\")!;\n this.setFontFromElement(element);\n }\n\n public setFontFromElement(element: HTMLElement): void {\n const cs = window.getComputedStyle(element);\n const font = `${cs.fontStyle} ${cs.fontVariant} ${cs.fontWeight} ${cs.fontSize}/${cs.lineHeight} ${cs.fontFamily}`;\n if (font !== this.font) {\n this.font = font;\n this.ctx.font = this.font;\n this.cache.kerning.clear();\n this.cache.charWidth.clear();\n }\n }\n\n public getCharWidth(char: string): number {\n if (this.cache.charWidth.has(char)) {\n return this.cache.charWidth.get(char)!;\n }\n const width = this.ctx.measureText(char).width;\n this.cache.charWidth.set(char, width);\n return width;\n }\n\n public getKerning(charA: string, charB: string): number {\n const pair = `${charA}${charB}`;\n const key: PairKey = `${this.font}|${pair}`;\n\n if (this.cache.kerning.has(key)) {\n return this.cache.kerning.get(key)!;\n }\n\n const widthWithKerning = this.ctx.measureText(pair).width;\n const widthWithoutKerning = this.getCharWidth(charA) + this.getCharWidth(charB);\n\n const kerning = widthWithKerning - widthWithoutKerning;\n\n this.cache.kerning.set(key, kerning);\n return kerning;\n }\n\n public measureWord(word: string): number {\n let totalWidth = 0;\n for (let i = 0; i < word.length; i++) {\n const char = word[i];\n totalWidth += this.getCharWidth(char);\n\n if (i > 0) {\n const prevChar = word[i - 1];\n totalWidth += this.getKerning(prevChar, char);\n }\n }\n return totalWidth;\n }\n}\n","import { Token } from \"./BuildTokens\";\r\nimport { FontMetrics } from \"./CanvasKerningApplier\";\r\n\r\nexport type MeasuredToken = {\r\n token: Token;\r\n rect: DOMRect;\r\n};\r\n\r\nfunction splitTokensByBr(tokens: Token[]): Token[][] {\r\n const result: Token[][] = [];\r\n let chunk: Token[] = [];\r\n for (const token of tokens) {\r\n if (token.type === \"br\") {\r\n if (chunk.length) result.push(chunk);\r\n result.push([token]);\r\n chunk = [];\r\n } else {\r\n chunk.push(token);\r\n }\r\n }\r\n if (chunk.length) result.push(chunk);\r\n return result;\r\n}\r\n\r\nexport function LayoutMeasurer(\r\n tokens: Token[],\r\n container: HTMLElement,\r\n fontMetrics: FontMetrics\r\n): MeasuredToken[] {\r\n const wrapper = document.createElement(\"div\");\r\n const computed = window.getComputedStyle(container);\r\n\r\n wrapper.style.position = \"absolute\";\r\n wrapper.style.visibility = \"hidden\";\r\n wrapper.style.pointerEvents = \"none\";\r\n wrapper.style.width = container.clientWidth + \"px\";\r\n wrapper.style.padding = computed.padding;\r\n wrapper.style.font = computed.font;\r\n wrapper.style.letterSpacing = computed.letterSpacing;\r\n wrapper.style.lineHeight = computed.lineHeight;\r\n wrapper.style.fontVariant = computed.fontVariant;\r\n wrapper.style.fontStretch = computed.fontStretch;\r\n wrapper.style.wordBreak = computed.wordBreak;\r\n wrapper.style.wordWrap = computed.wordWrap;\r\n wrapper.style.whiteSpace = computed.whiteSpace;\r\n\r\n const spaceMeasurer = document.createElement(\"span\");\r\n spaceMeasurer.textContent = \"\\u00a0\";\r\n wrapper.appendChild(spaceMeasurer);\r\n const spaceWidth = spaceMeasurer.getBoundingClientRect().width;\r\n wrapper.removeChild(spaceMeasurer);\r\n wrapper.style.width = container.clientWidth + spaceWidth + \"px\";\r\n wrapper.style.boxSizing = \"border-box\";\r\n\r\n container.appendChild(wrapper);\r\n\r\n const measured: MeasuredToken[] = [];\r\n const chunks = splitTokensByBr(tokens);\r\n\r\n let isAfterElement = false;\r\n let lastTokenWasSpace = false;\r\n let prevMeasuredWasText = false;\r\n\r\n for (const chunk of chunks) {\r\n if (chunk.length === 1 && chunk[0].type === \"br\") {\r\n measured.push({ token: chunk[0], rect: new DOMRect(0, 0, 0, 0) });\r\n continue;\r\n }\r\n if (chunk.length === 0) continue;\r\n\r\n wrapper.innerHTML = \"\";\r\n\r\n const wordSpans: HTMLSpanElement[] = [];\r\n const tokenInfo: Array<{\r\n token: Token;\r\n wordIndex?: number;\r\n hadLeadingSpace?: boolean;\r\n hadTrailingSpace?: boolean;\r\n }> = [];\r\n\r\n chunk.forEach((token) => {\r\n switch (token.type) {\r\n case \"text\": {\r\n const raw = token.content;\r\n const hadLeadingSpace = /^\\s/.test(raw);\r\n const hadTrailingSpace = /\\s$/.test(raw);\r\n\r\n const words = raw\r\n .trim()\r\n .split(/\\s+/)\r\n .filter((w) => w.length > 0);\r\n\r\n words.forEach((word, wIdx) => {\r\n const span = document.createElement(\"span\");\r\n span.style.display = \"inline-block\";\r\n span.textContent = word;\r\n wrapper.appendChild(span);\r\n\r\n if (wIdx < words.length - 1 || hadTrailingSpace) {\r\n wrapper.appendChild(document.createTextNode(\" \"));\r\n }\r\n\r\n wordSpans.push(span);\r\n tokenInfo.push({\r\n token: {\r\n type: \"text\",\r\n id: \"\",\r\n node: token.node,\r\n content: word,\r\n meta: {\r\n ...(token.meta || {}),\r\n joinPrev:\r\n wIdx === 0\r\n ? !hadLeadingSpace && !lastTokenWasSpace && prevMeasuredWasText\r\n : false,\r\n },\r\n },\r\n wordIndex: wordSpans.length - 1,\r\n hadLeadingSpace,\r\n hadTrailingSpace,\r\n });\r\n });\r\n\r\n lastTokenWasSpace = hadTrailingSpace;\r\n prevMeasuredWasText = true;\r\n break;\r\n }\r\n\r\n case \"element\": {\r\n const node = token.node.cloneNode(true);\r\n const span = document.createElement(\"span\");\r\n span.style.display = \"inline-block\";\r\n span.appendChild(node);\r\n wrapper.appendChild(span);\r\n wordSpans.push(span);\r\n tokenInfo.push({ token, wordIndex: wordSpans.length - 1 });\r\n isAfterElement = true;\r\n prevMeasuredWasText = false;\r\n lastTokenWasSpace = false;\r\n break;\r\n }\r\n\r\n case \"space\":\r\n lastTokenWasSpace = true;\r\n break;\r\n\r\n case \"other\":\r\n prevMeasuredWasText = false;\r\n lastTokenWasSpace = false;\r\n break;\r\n }\r\n });\r\n\r\n wrapper.offsetHeight;\r\n\r\n tokenInfo.forEach((info, idx) => {\r\n if (info.wordIndex !== undefined) {\r\n const span = wordSpans[info.wordIndex];\r\n const domRect = span.getBoundingClientRect();\r\n\r\n let rect: DOMRect;\r\n if (info.token.type === \"text\") {\r\n const accurateWidth = fontMetrics.measureWord(info.token.content);\r\n rect = new DOMRect(domRect.x, domRect.y, accurateWidth, domRect.height);\r\n } else {\r\n rect = domRect;\r\n }\r\n\r\n const measuredToken: MeasuredToken = {\r\n token: info.token,\r\n rect: rect,\r\n };\r\n\r\n if (isAfterElement && info.token.type === \"text\") {\r\n isAfterElement = false;\r\n measuredToken.token.meta = {\r\n ...(measuredToken.token.meta || {}),\r\n isAfterElement: true,\r\n };\r\n }\r\n\r\n measured.push(measuredToken);\r\n\r\n if (info.token.type === \"element\") {\r\n const prev = measured[measured.length - 2];\r\n if (prev?.token.type === \"text\") {\r\n prev.token.meta = { ...(prev.token.meta || {}), isBeforeElement: true };\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n container.removeChild(wrapper);\r\n return measured;\r\n}\r\n","import { MeasuredToken } from \"./LayoutMeasurer\";\r\nimport { Token } from \"./BuildTokens\";\r\nimport { FontMetrics } from \"./CanvasKerningApplier\";\r\n\r\nexport type ProcessedChar = {\r\n char: string;\r\n rect: DOMRect;\r\n token: Token;\r\n charIndexGlobal: number;\r\n charIndexInLine: number;\r\n charIndexInWord: number;\r\n isBeforeElement?: boolean;\r\n isAfterElement?: boolean;\r\n};\r\n\r\nexport type ProcessedWord = {\r\n chars: ProcessedChar[];\r\n rect: DOMRect;\r\n wordIndexGlobal: number;\r\n wordIndexInLine: number;\r\n isBeforeElement?: boolean;\r\n isAfterElement?: boolean;\r\n};\r\n\r\nexport type LayoutLine = {\r\n words: ProcessedWord[];\r\n rect: DOMRect;\r\n lineIndex: number;\r\n isBeforeElement?: boolean;\r\n isAfterElement?: boolean;\r\n};\r\n\r\nconst LINE_TOLERANCE = 5;\r\n\r\nexport function SplitMeasuredTokens(\r\n measured: MeasuredToken[],\r\n container: HTMLElement,\r\n fontMetrics: FontMetrics\r\n): LayoutLine[] {\r\n const lines: LayoutLine[] = [];\r\n let currentLine: LayoutLine | null = null;\r\n let y = 0;\r\n\r\n let charIndexGlobal = 0;\r\n let wordIndexGlobal = 0;\r\n\r\n measured.forEach((mt) => {\r\n const token = mt.token;\r\n const isBefore = token.meta?.isBeforeElement ?? false;\r\n const isAfter = token.meta?.isAfterElement ?? false;\r\n\r\n if (token.type === \"br\") {\r\n currentLine = null;\r\n return;\r\n }\r\n\r\n if (token.type === \"text\") {\r\n const wordText = token.content;\r\n const splitClass: string[] = (token.meta?.splitClass as string[]) ?? [];\r\n const joinPrev = !!token.meta?.joinPrev;\r\n\r\n const chars: ProcessedChar[] = [];\r\n let currentXInWord = 0;\r\n\r\n for (let i = 0; i < wordText.length; i++) {\r\n const ch = wordText[i];\r\n const prev = i > 0 ? wordText[i - 1] : null;\r\n\r\n const charWidth = fontMetrics.getCharWidth(ch);\r\n const kerning = prev ? fontMetrics.getKerning(prev, ch) : 0;\r\n\r\n currentXInWord += kerning;\r\n\r\n const charRect = new DOMRect(\r\n mt.rect.left + currentXInWord,\r\n mt.rect.top,\r\n charWidth,\r\n mt.rect.height\r\n );\r\n\r\n const pc: ProcessedChar = {\r\n char: ch,\r\n rect: charRect,\r\n token,\r\n charIndexInWord: i,\r\n charIndexInLine: 0,\r\n charIndexGlobal: charIndexGlobal++,\r\n };\r\n\r\n if (splitClass.length) (pc as any).splitClass = splitClass;\r\n\r\n chars.push(pc);\r\n currentXInWord += charWidth;\r\n }\r\n\r\n if (chars.length > 0) {\r\n const lastChar = chars[chars.length - 1];\r\n if (isBefore) lastChar.isBeforeElement = true;\r\n if (isAfter) lastChar.isAfterElement = true;\r\n }\r\n\r\n const currentY = Math.round(mt.rect.top);\r\n const baselineY = Math.round(y);\r\n const isNewLine = !currentLine || Math.abs(currentY - baselineY) > LINE_TOLERANCE;\r\n if (isNewLine) {\r\n y = currentY;\r\n currentLine = { words: [], rect: mt.rect, lineIndex: lines.length };\r\n lines.push(currentLine);\r\n }\r\n if (!currentLine) return;\r\n\r\n if (joinPrev && currentLine.words.length > 0) {\r\n const target = currentLine.words[currentLine.words.length - 1];\r\n\r\n const charsBeforeAll = currentLine.words.reduce((acc, w) => acc + w.chars.length, 0);\r\n const baseInWord = target.chars.length;\r\n\r\n chars.forEach((c, i) => {\r\n c.charIndexInLine = charsBeforeAll + i;\r\n c.charIndexInWord = baseInWord + i;\r\n });\r\n\r\n target.chars.push(...chars);\r\n target.rect = mergeRects([target.rect, mt.rect]);\r\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\r\n if (isBefore) target.isBeforeElement = true;\r\n if (isAfter) target.isAfterElement = true;\r\n return;\r\n }\r\n\r\n const wordIndexInLine = currentLine.words.length;\r\n const charsBefore = currentLine.words.reduce((acc, w) => acc + w.chars.length, 0);\r\n chars.forEach((c, i) => (c.charIndexInLine = charsBefore + i));\r\n\r\n const processedWord: ProcessedWord = {\r\n chars,\r\n rect: mt.rect,\r\n wordIndexGlobal: wordIndexGlobal++,\r\n wordIndexInLine,\r\n isBeforeElement: isBefore,\r\n isAfterElement: isAfter,\r\n };\r\n\r\n currentLine.words.push(processedWord);\r\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\r\n if (isBefore) currentLine.isBeforeElement = true;\r\n if (isAfter) currentLine.isAfterElement = true;\r\n return;\r\n }\r\n\r\n if (token.type === \"element\") {\r\n const rect = mt.rect;\r\n const currentY = Math.round(rect.top);\r\n const baselineY = Math.round(y);\r\n const isNewLine = !currentLine || Math.abs(currentY - baselineY) > LINE_TOLERANCE;\r\n\r\n if (isNewLine) {\r\n y = currentY;\r\n currentLine = { words: [], rect, lineIndex: lines.length };\r\n lines.push(currentLine);\r\n }\r\n if (!currentLine) return;\r\n\r\n const wordIndexInLine = currentLine.words.length;\r\n const charsBefore = currentLine.words.reduce((acc, w) => acc + w.chars.length, 0);\r\n\r\n const chars: ProcessedChar[] = [\r\n {\r\n char: \"[E]\",\r\n rect,\r\n token,\r\n charIndexInWord: 0,\r\n charIndexInLine: charsBefore,\r\n charIndexGlobal: charIndexGlobal++,\r\n },\r\n ];\r\n\r\n const processedWord: ProcessedWord = {\r\n chars,\r\n rect,\r\n wordIndexGlobal: wordIndexGlobal++,\r\n wordIndexInLine,\r\n isBeforeElement: false,\r\n isAfterElement: false,\r\n };\r\n\r\n currentLine.words.push(processedWord);\r\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\r\n }\r\n });\r\n\r\n return lines;\r\n}\r\n\r\nfunction mergeRects(rects: DOMRect[]): DOMRect {\r\n if (rects.length === 0) return new DOMRect(0, 0, 0, 0);\r\n const left = Math.min(...rects.map((r) => r.left));\r\n const top = Math.min(...rects.map((r) => r.top));\r\n const right = Math.max(...rects.map((r) => r.right));\r\n const bottom = Math.max(...rects.map((r) => r.bottom));\r\n return new DOMRect(left, top, right - left, bottom - top);\r\n}\r\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 { FontMetrics } from \"../../utils/text/CanvasKerningApplier\";\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 this.permissions.mobile.rebuild.height = false;\r\n this.permissions.mobile.rebuild.width = false;\r\n //this.permissions.mobile.rebuild.scrollHeight = false;\r\n }\r\n\r\n onResizeWidth(): 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\") ?? element.getAttribute(\"data-string-split\") ?? \"\";\r\n const options: ISplitOptions = this.tools.optionsParser.process({\r\n attributeValue: attr,\r\n });\r\n const { fragment, result, extraProps } = this.split(element, options);\r\n object.setProperty(\"nodes\", fragment.childNodes);\r\n element.setAttribute(\"aria-label\", originalHtml);\r\n element.innerHTML = \"\";\r\n element.appendChild(result);\r\n\r\n extraProps.forEach((value: string, key: string) => {\r\n element.style.setProperty(key, value);\r\n });\r\n\r\n const restoreAfter = element.getAttribute(\"string-split-restore-after\");\r\n if (restoreAfter && !isNaN(Number(restoreAfter))) {\r\n setTimeout(() => {\r\n element.innerHTML = originalHtml!;\r\n element.classList.add(\"-restored\");\r\n }, Number(restoreAfter));\r\n }\r\n }\r\n\r\n public split(element: HTMLElement, options: ISplitOptions) {\r\n const fontMetrics = new FontMetrics(element);\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, fontMetrics);\r\n const layoutLines: LayoutLine[] = SplitMeasuredTokens(measured, element, fontMetrics);\r\n this.applyCalculatedValues(layoutLines, options);\r\n const dom = BuildDOMTree(layoutLines, options, fontMetrics);\r\n return {\r\n fragment: frag,\r\n result: dom.fragment,\r\n extraProps: dom.extraProps,\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(opt: ISplitOptionItem, index: number, total: number): 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(lines: LayoutLine[], options: ISplitOptions): 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(opt, word.wordIndexInLine, line.words.length),\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(opt, char.charIndexGlobal, totalCharsGlobal),\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(opt, char.charIndexInWord, word.chars.length),\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(opt, char.charIndexInLine, totalCharsInLine),\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/** Attribute selector for FPS tracker elements */\r\nconst ATTR_FPS = \"data-fps\";\r\n\r\n/**\r\n * FPS Tracker Module.\r\n * Broadcasts frame rate to elements with `data-fps` attribute.\r\n * Also creates an optional debug display element.\r\n */\r\nexport class StringFPSTracker extends StringModule {\r\n private displayElement: HTMLDivElement | null = null;\r\n private intervalId: number = 0;\r\n private frameCount = 0;\r\n\r\n /** Cached elements with data-fps attribute */\r\n private fpsElements: Set<HTMLElement> = new Set();\r\n\r\n /** MutationObserver for DOM changes */\r\n private observer: MutationObserver | null = null;\r\n\r\n /** Last known FPS to avoid redundant updates */\r\n private lastFps = -1;\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, scans for elements, and starts interval.\r\n */\r\n onInit(): void {\r\n if (this.data.system.fpsTracker) {\r\n this.createDisplayElement();\r\n }\r\n\r\n // Listen for visibility toggle\r\n this.events.on(\"tracker:fps:visible\", this.onVisibilityChange.bind(this));\r\n\r\n this.scanElements();\r\n this.observeDOM();\r\n\r\n this.intervalId = window.setInterval(() => {\r\n this.updateFPS(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, observer, and interval.\r\n */\r\n destroy(): void {\r\n clearInterval(this.intervalId);\r\n this.observer?.disconnect();\r\n this.removeDisplayElement();\r\n this.fpsElements.clear();\r\n }\r\n\r\n /**\r\n * Handles visibility toggle from external API.\r\n */\r\n private onVisibilityChange(visible: boolean): void {\r\n if (visible) {\r\n this.createDisplayElement();\r\n } else {\r\n this.removeDisplayElement();\r\n }\r\n }\r\n\r\n /**\r\n * Removes the display element and its styles.\r\n */\r\n private removeDisplayElement(): void {\r\n this.displayElement?.remove();\r\n this.displayElement = null;\r\n }\r\n\r\n /**\r\n * Updates all tracked elements with current FPS.\r\n */\r\n private updateFPS(fps: number): void {\r\n if (fps === this.lastFps) return;\r\n this.lastFps = fps;\r\n\r\n const fpsStr = String(fps);\r\n\r\n // Update cached elements\r\n for (const el of this.fpsElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_FPS, fpsStr);\r\n }\r\n }\r\n\r\n // Update debug display\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_FPS, fpsStr);\r\n }\r\n\r\n this.events.emit(\"fps\", fps);\r\n }\r\n\r\n /**\r\n * Scans document for elements with data-fps attribute.\r\n */\r\n private scanElements(): void {\r\n this.fpsElements.clear();\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_FPS}]`).forEach((el) => {\r\n if (el !== this.displayElement) {\r\n this.fpsElements.add(el);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Observes DOM for added/removed elements with data-fps attribute.\r\n */\r\n private observeDOM(): void {\r\n this.observer = new MutationObserver((mutations) => {\r\n let needsRescan = false;\r\n\r\n for (const mutation of mutations) {\r\n // Check added nodes\r\n for (const node of Array.from(mutation.addedNodes)) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n if (el.hasAttribute(ATTR_FPS)) needsRescan = true;\r\n if (el.querySelector(`[${ATTR_FPS}]`)) needsRescan = true;\r\n }\r\n }\r\n\r\n // Check removed nodes - clean from cache\r\n for (const node of Array.from(mutation.removedNodes)) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n this.fpsElements.delete(node as HTMLElement);\r\n }\r\n }\r\n }\r\n\r\n if (needsRescan) {\r\n this.scanElements();\r\n }\r\n });\r\n\r\n this.observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Creates and styles the floating FPS display.\r\n */\r\n private createDisplayElement(): void {\r\n if (this.displayElement) return;\r\n\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.setAttribute(ATTR_FPS, \"0\");\r\n document.body.appendChild(el);\r\n\r\n // Inject dynamic CSS\r\n const styleId = \"string-fps-tracker-style\";\r\n if (!document.getElementById(styleId)) {\r\n const style = document.createElement(\"style\");\r\n style.id = styleId;\r\n style.innerHTML = `\r\n [${ATTR_FPS}]::before {\r\n content: 'FPS: ' attr(${ATTR_FPS});\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n }\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/** Attribute selectors for position tracker elements */\r\nconst ATTR_VAL = \"data-val\";\r\nconst ATTR_VAL_PCT = \"data-val-pct\";\r\nconst ATTR_DIR = \"data-dir\";\r\n\r\n/**\r\n * Tracker module that broadcasts scroll position to elements with data attributes.\r\n * Elements with `data-val`, `data-val-pct`, or `data-dir` will receive updates.\r\n * Also creates an optional debug display element.\r\n */\r\nexport class StringPositionTracker extends StringModule {\r\n private displayElement: HTMLDivElement | null = null;\r\n\r\n /** Cached elements by attribute type */\r\n private valElements: Set<HTMLElement> = new Set();\r\n private valPctElements: Set<HTMLElement> = new Set();\r\n private dirElements: Set<HTMLElement> = new Set();\r\n\r\n /** MutationObserver for DOM changes */\r\n private observer: MutationObserver | null = null;\r\n\r\n /** Last known values to avoid redundant updates */\r\n private lastVal = -1;\r\n private lastValPct = -1;\r\n private lastDir = \"\";\r\n\r\n /** Previous scroll position for direction detection */\r\n private previousCurrent = 0;\r\n\r\n /** Timeout for resetting direction to idle state */\r\n private idleTimeout: ReturnType<typeof setTimeout> | null = null;\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 debug element and scans for tracked elements.\r\n */\r\n onInit(): void {\r\n if (this.data.system.positionTracker) {\r\n this.createDisplayElement();\r\n }\r\n\r\n // Listen for visibility toggle\r\n this.events.on(\"tracker:position:visible\", this.onVisibilityChange.bind(this));\r\n\r\n this.scanElements();\r\n this.observeDOM();\r\n }\r\n\r\n /**\r\n * Called on scroll — updates all tracked elements with position data.\r\n */\r\n onScroll(data: StringData): void {\r\n const current = data.scroll.current;\r\n const target = data.scroll.target;\r\n const contentHeight = data.viewport.contentHeight;\r\n const windowHeight = data.viewport.windowHeight;\r\n\r\n const val = Math.round(current);\r\n const maxScroll = Math.max(1, contentHeight - windowHeight);\r\n const valPct = Math.round((current / maxScroll) * 100);\r\n\r\n // Determine scroll direction\r\n let direction: string;\r\n if (current !== target) {\r\n // Smooth scroll: compare current vs target (lerping)\r\n direction = current < target ? \"↓\" : \"↑\";\r\n } else if (current !== this.previousCurrent) {\r\n // Default scroll: compare with previous position\r\n direction = current > this.previousCurrent ? \"↓\" : \"↑\";\r\n } else {\r\n // No movement\r\n direction = this.lastDir || \"•\";\r\n }\r\n\r\n this.previousCurrent = current;\r\n\r\n // Reset idle timeout - will set direction to neutral after scroll stops\r\n if (this.idleTimeout) {\r\n clearTimeout(this.idleTimeout);\r\n }\r\n if (direction !== \"•\") {\r\n this.idleTimeout = setTimeout(() => {\r\n this.setDirection(\"•\");\r\n }, 150);\r\n }\r\n\r\n // Update data-val elements\r\n if (val !== this.lastVal) {\r\n this.lastVal = val;\r\n const valStr = String(val);\r\n for (const el of this.valElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_VAL, valStr);\r\n }\r\n }\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_VAL, valStr);\r\n }\r\n }\r\n\r\n // Update data-val-pct elements\r\n if (valPct !== this.lastValPct) {\r\n this.lastValPct = valPct;\r\n const pctStr = String(valPct);\r\n for (const el of this.valPctElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_VAL_PCT, pctStr);\r\n }\r\n }\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_VAL_PCT, pctStr);\r\n }\r\n }\r\n\r\n // Update data-dir elements\r\n this.setDirection(direction);\r\n\r\n this.events.emit(\"scroll-position\", { val, valPct, direction });\r\n }\r\n\r\n /**\r\n * Updates direction on all tracked elements.\r\n */\r\n private setDirection(direction: string): void {\r\n if (direction === this.lastDir) return;\r\n this.lastDir = direction;\r\n\r\n for (const el of this.dirElements) {\r\n if (el.isConnected) {\r\n el.setAttribute(ATTR_DIR, direction);\r\n }\r\n }\r\n if (this.displayElement) {\r\n this.displayElement.setAttribute(ATTR_DIR, direction);\r\n }\r\n }\r\n\r\n /**\r\n * Cleans up DOM observer and display element.\r\n */\r\n destroy(): void {\r\n if (this.idleTimeout) {\r\n clearTimeout(this.idleTimeout);\r\n }\r\n this.observer?.disconnect();\r\n this.removeDisplayElement();\r\n this.valElements.clear();\r\n this.valPctElements.clear();\r\n this.dirElements.clear();\r\n }\r\n\r\n /**\r\n * Handles visibility toggle from external API.\r\n */\r\n private onVisibilityChange(visible: boolean): void {\r\n if (visible) {\r\n this.createDisplayElement();\r\n } else {\r\n this.removeDisplayElement();\r\n }\r\n }\r\n\r\n /**\r\n * Removes the display element.\r\n */\r\n private removeDisplayElement(): void {\r\n this.displayElement?.remove();\r\n this.displayElement = null;\r\n }\r\n\r\n /**\r\n * Scans document for elements with tracking attributes.\r\n */\r\n private scanElements(): void {\r\n this.valElements.clear();\r\n this.valPctElements.clear();\r\n this.dirElements.clear();\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_VAL}]`).forEach((el) => {\r\n if (el !== this.displayElement) this.valElements.add(el);\r\n });\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_VAL_PCT}]`).forEach((el) => {\r\n if (el !== this.displayElement) this.valPctElements.add(el);\r\n });\r\n\r\n document.querySelectorAll<HTMLElement>(`[${ATTR_DIR}]`).forEach((el) => {\r\n if (el !== this.displayElement) this.dirElements.add(el);\r\n });\r\n }\r\n\r\n /**\r\n * Observes DOM for added/removed elements with tracking attributes.\r\n */\r\n private observeDOM(): void {\r\n this.observer = new MutationObserver((mutations) => {\r\n let needsRescan = false;\r\n\r\n for (const mutation of mutations) {\r\n // Check added nodes\r\n for (const node of Array.from(mutation.addedNodes)) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n if (this.hasTrackingAttr(el)) needsRescan = true;\r\n // Check descendants\r\n if (el.querySelector(`[${ATTR_VAL}],[${ATTR_VAL_PCT}],[${ATTR_DIR}]`)) {\r\n needsRescan = true;\r\n }\r\n }\r\n }\r\n\r\n // Check removed nodes - clean from cache\r\n for (const node of Array.from(mutation.removedNodes)) {\r\n if (node.nodeType === Node.ELEMENT_NODE) {\r\n const el = node as HTMLElement;\r\n this.valElements.delete(el);\r\n this.valPctElements.delete(el);\r\n this.dirElements.delete(el);\r\n }\r\n }\r\n }\r\n\r\n if (needsRescan) {\r\n this.scanElements();\r\n }\r\n });\r\n\r\n this.observer.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Checks if element has any tracking attribute.\r\n */\r\n private hasTrackingAttr(el: HTMLElement): boolean {\r\n return el.hasAttribute(ATTR_VAL) || el.hasAttribute(ATTR_VAL_PCT) || el.hasAttribute(ATTR_DIR);\r\n }\r\n\r\n /**\r\n * Creates and styles the floating position indicator.\r\n */\r\n private createDisplayElement(): void {\r\n if (this.displayElement) return;\r\n\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(ATTR_DIR, \"•\");\r\n el.setAttribute(ATTR_VAL, \"0\");\r\n el.setAttribute(ATTR_VAL_PCT, \"0\");\r\n document.body.appendChild(el);\r\n\r\n // Inject dynamic CSS\r\n const styleId = \"string-position-tracker-style\";\r\n if (!document.getElementById(styleId)) {\r\n const style = document.createElement(\"style\");\r\n style.id = styleId;\r\n style.innerHTML = `\r\n [${ATTR_DIR}][${ATTR_VAL}][${ATTR_VAL_PCT}]::before {\r\n content: attr(${ATTR_DIR}) ' | ' attr(${ATTR_VAL}) 'px (' attr(${ATTR_VAL_PCT}) '%)';\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n }\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","/**\r\n * Discrete state classes applied to sequence elements.\r\n */\r\nexport enum SequenceState {\r\n ACTIVE = \"-active\",\r\n ENTERING = \"-entering\",\r\n LEAVING = \"-leaving\",\r\n DISABLED = \"-disabled\",\r\n}\r\n\r\n/**\r\n * Event data for sequence transitions.\r\n */\r\nexport interface SequenceEventData {\r\n /** Slider identifier */\r\n slider: string;\r\n /** Current step index */\r\n step: number;\r\n /** Transition progress from 0 to 1 (optional, for manual scrubbing) */\r\n transitionProgress?: number;\r\n /** Direction of transition: 1 = forward, -1 = backward */\r\n direction?: 1 | -1;\r\n /** Custom duration for this transition in ms (overrides element's sequence-duration) */\r\n duration?: number;\r\n /** Skip animation and switch instantly */\r\n instant?: boolean;\r\n}\r\n\r\n/**\r\n * CSS custom property names for sequence.\r\n */\r\nexport const SequenceProgressVars = {\r\n /** Unified progress variable (0 to 1) */\r\n PROGRESS: \"--sequence-progress\",\r\n /** Direction of current transition (1 or -1) */\r\n DIRECTION: \"--sequence-direction\",\r\n} as const;\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport {\r\n SequenceState,\r\n SequenceEventData,\r\n SequenceProgressVars,\r\n} from \"../../models/slider/SequenceState\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EasingFunctionOutput } from \"../../tools/EasingFunctionTool\";\r\nimport { styleTxn } from \"../../utils/style-txn\";\r\n\r\ninterface TransitionState {\r\n fromStep: number;\r\n toStep: number;\r\n direction: 1 | -1;\r\n startTime: number;\r\n enteringDuration: number;\r\n leavingDuration: number;\r\n}\r\n\r\ninterface StepElements {\r\n objects: StringObject[];\r\n enteringDuration: number;\r\n leavingDuration: number;\r\n}\r\n\r\ninterface TriggerData {\r\n slider: string;\r\n step: number | \"next\" | \"prev\";\r\n loop: boolean;\r\n}\r\n\r\ninterface GlobalSliderSettings {\r\n enteringDuration?: number;\r\n leavingDuration?: number;\r\n enteringEasing?: string;\r\n leavingEasing?: string;\r\n activeStep?: number;\r\n}\r\n\r\ntype DurationKey = \"enteringDuration\" | \"leavingDuration\";\r\ntype EasingKey = \"enteringEasing\" | \"leavingEasing\";\r\n\r\nexport class StringSequence extends StringModule {\r\n private activeStep = new Map<string, number>();\r\n private leavingStep = new Map<string, number>();\r\n private transitions = new Map<string, TransitionState>();\r\n private elementIndex = new Map<string, StepElements>();\r\n private triggerElements = new Map<HTMLElement, TriggerData>();\r\n private globalSettings = new Map<string, GlobalSliderSettings>();\r\n private stateRegistered = new Set<string>();\r\n private lastEnteredStep = new Map<string, number>();\r\n private defaultDuration: number;\r\n private initialized = false;\r\n private static readonly ALL_STATES = Object.values(SequenceState);\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"sequence\";\r\n this.defaultDuration = this.settings[\"sequence-duration\"] ?? 600;\r\n\r\n this.attributesToMap = [\r\n ...this.attributesToMap,\r\n { key: \"sequence\", type: \"string\", fallback: \"\" },\r\n { key: \"sequence-trigger\", type: \"string\", fallback: \"\" },\r\n { key: \"entering-easing\", type: \"string\", fallback: \"\" },\r\n { key: \"leaving-easing\", type: \"string\", fallback: \"\" },\r\n { key: \"entering-duration\", type: \"string\", fallback: \"\" },\r\n { key: \"leaving-duration\", type: \"string\", fallback: \"\" },\r\n { key: \"sequence-duration\", type: \"string\", fallback: \"\" },\r\n { key: \"active-step\", type: \"string\", fallback: \"\" },\r\n ];\r\n }\r\n\r\n onInit(): void {\r\n super.onInit();\r\n this.events.on<SequenceEventData>(\"sequence\", this.onSequenceEvent.bind(this));\r\n this.scanStandaloneTriggers();\r\n }\r\n\r\n private scanStandaloneTriggers(): void {\r\n const els = document.querySelectorAll<HTMLElement>(\r\n \"[string-sequence-trigger]:not([string-inited])\"\r\n );\r\n for (const el of Array.from(els)) {\r\n const trigger = el.getAttribute(\"string-sequence-trigger\");\r\n const parsed = trigger ? this.parseTriggerKey(trigger) : null;\r\n if (parsed) {\r\n this.triggerElements.set(el, parsed);\r\n el.addEventListener(\"click\", this.onTriggerClick);\r\n }\r\n }\r\n }\r\n\r\n private parseGlobalSettingsFromObject(object: StringObject): void {\r\n const get = (k: string) => object.getProperty<string>(k);\r\n const seq = get(\"sequence-duration\");\r\n\r\n this.tryParseGlobalSetting(seq, \"enteringDuration\");\r\n this.tryParseGlobalSetting(seq, \"leavingDuration\");\r\n this.tryParseGlobalSetting(get(\"entering-duration\"), \"enteringDuration\");\r\n this.tryParseGlobalSetting(get(\"leaving-duration\"), \"leavingDuration\");\r\n this.tryParseGlobalSetting(get(\"entering-easing\"), \"enteringEasing\");\r\n this.tryParseGlobalSetting(get(\"leaving-easing\"), \"leavingEasing\");\r\n this.tryParseGlobalSetting(get(\"active-step\"), \"activeStep\");\r\n }\r\n\r\n private tryParseGlobalSetting(attr: string | null, key: keyof GlobalSliderSettings): void {\r\n if (!attr) return;\r\n const match = attr.match(/^(.+)\\[(.+)\\]$/);\r\n if (!match) return;\r\n\r\n const [, slider, value] = match;\r\n const settings = this.globalSettings.get(slider) ?? {};\r\n this.globalSettings.set(slider, settings);\r\n\r\n (settings as Record<string, string | number>)[key] =\r\n key === \"enteringEasing\" || key === \"leavingEasing\" ? value : parseFloat(value);\r\n\r\n this.applyGlobalSettingsToExistingObjects(slider);\r\n }\r\n\r\n private applyGlobalSettingsToExistingObjects(slider: string): void {\r\n const global = this.globalSettings.get(slider);\r\n if (!global) return;\r\n\r\n for (const [key, group] of this.elementIndex) {\r\n const parsed = this.parseSequenceKey(key);\r\n if (parsed?.slider !== slider) continue;\r\n\r\n if (global.enteringDuration !== undefined) group.enteringDuration = global.enteringDuration;\r\n if (global.leavingDuration !== undefined) group.leavingDuration = global.leavingDuration;\r\n\r\n for (const obj of group.objects) this.resolveEasings(obj, key);\r\n }\r\n }\r\n\r\n private initializeSliders(): void {\r\n const sliders = new Set<string>();\r\n for (const key of this.elementIndex.keys()) {\r\n const p = this.parseSequenceKey(key);\r\n if (p) sliders.add(p.slider);\r\n }\r\n\r\n for (const slider of sliders) {\r\n if (this.activeStep.has(slider)) continue;\r\n const global = this.globalSettings.get(slider);\r\n let step = global?.activeStep ?? 0;\r\n if (!this.elementIndex.has(`${slider}[${step}]`)) step = 0;\r\n this.switchInstant(slider, step, 1);\r\n }\r\n }\r\n\r\n private tryApplyPendingActiveStep(slider: string): void {\r\n if (this.activeStep.has(slider)) return;\r\n const step = this.globalSettings.get(slider)?.activeStep;\r\n if (step !== undefined && this.elementIndex.has(`${slider}[${step}]`)) {\r\n this.switchInstant(slider, step, 1);\r\n }\r\n }\r\n\r\n override canConnect(object: StringObject): boolean {\r\n return object.keys.includes(\"sequence\") || object.keys.includes(\"sequence-trigger\");\r\n }\r\n\r\n override onObjectConnected(object: StringObject): void {\r\n super.onObjectConnected(object);\r\n this.parseGlobalSettingsFromObject(object);\r\n\r\n let sequence = object.getProperty<string>(\"sequence\");\r\n const trigger = object.getProperty<string>(\"sequence-trigger\");\r\n\r\n if (!sequence && trigger) {\r\n const p = this.parseTriggerKey(trigger);\r\n if (p && typeof p.step === \"number\") {\r\n sequence = `${p.slider}[${p.step}]`;\r\n object.setProperty(\"sequence\", sequence);\r\n }\r\n }\r\n\r\n if (sequence) {\r\n const parsed = this.parseSequenceKey(sequence);\r\n if (parsed) {\r\n this.ensureStateEventRegistered(parsed.slider);\r\n let group = this.elementIndex.get(sequence);\r\n if (!group) {\r\n const { enteringDuration, leavingDuration } = this.resolveDurations(object, sequence);\r\n group = { objects: [], enteringDuration, leavingDuration };\r\n this.elementIndex.set(sequence, group);\r\n }\r\n group.objects.push(object);\r\n this.resolveEasings(object, sequence);\r\n\r\n const active = this.activeStep.get(parsed.slider);\r\n this.setState(\r\n object,\r\n active === parsed.step ? SequenceState.ACTIVE : SequenceState.DISABLED,\r\n active === parsed.step ? 1 : 0,\r\n 1\r\n );\r\n this.tryApplyPendingActiveStep(parsed.slider);\r\n }\r\n }\r\n\r\n if (trigger) {\r\n const p = this.parseTriggerKey(trigger);\r\n if (p) {\r\n this.triggerElements.set(object.htmlElement, p);\r\n object.htmlElement.addEventListener(\"click\", this.onTriggerClick);\r\n }\r\n }\r\n }\r\n\r\n private ensureStateEventRegistered(slider: string): void {\r\n if (this.stateRegistered.has(slider)) return;\r\n this.stateRegistered.add(slider);\r\n this.events.registerStateEvent?.(`sequence:active:${slider}`);\r\n }\r\n\r\n private parseTriggerKey(key: string): TriggerData | null {\r\n const m = key.match(/^(.+)\\[(next|prev|\\d+)(\\|loop)?\\]$/);\r\n if (!m) return null;\r\n const step = m[2] === \"next\" || m[2] === \"prev\" ? m[2] : parseInt(m[2], 10);\r\n return { slider: m[1], step, loop: m[3] === \"|loop\" };\r\n }\r\n\r\n private getMaxStep(slider: string): number {\r\n let max = -1;\r\n for (const key of this.elementIndex.keys()) {\r\n const p = this.parseSequenceKey(key);\r\n if (p?.slider === slider && p.step > max) max = p.step;\r\n }\r\n return max;\r\n }\r\n\r\n private resolveDuration(\r\n object: StringObject,\r\n slider: string,\r\n key: DurationKey,\r\n attrKey: string\r\n ): number {\r\n const attr = object.getProperty<string>(attrKey);\r\n const seqAttr = object.getProperty<string>(\"sequence-duration\");\r\n const global = this.globalSettings.get(slider)?.[key];\r\n\r\n if (attr && !attr.includes(\"[\")) {\r\n const v = parseFloat(attr);\r\n if (!isNaN(v)) return v;\r\n }\r\n if (seqAttr && !seqAttr.includes(\"[\")) {\r\n const v = parseFloat(seqAttr);\r\n if (!isNaN(v)) return v;\r\n }\r\n return global ?? this.defaultDuration;\r\n }\r\n\r\n private resolveDurations(object: StringObject, sequence: string) {\r\n const slider = this.parseSequenceKey(sequence)?.slider ?? \"\";\r\n return {\r\n enteringDuration: this.resolveDuration(\r\n object,\r\n slider,\r\n \"enteringDuration\",\r\n \"entering-duration\"\r\n ),\r\n leavingDuration: this.resolveDuration(object, slider, \"leavingDuration\", \"leaving-duration\"),\r\n };\r\n }\r\n\r\n private resolveEasing(\r\n object: StringObject,\r\n slider: string,\r\n key: EasingKey,\r\n attrKey: string\r\n ): void {\r\n let easing = object.getProperty<string | EasingFunctionOutput>(attrKey);\r\n if (!easing || (typeof easing === \"string\" && easing.includes(\"[\"))) {\r\n easing = this.globalSettings.get(slider)?.[key] ?? this.settings[\"easing\"] ?? \"ease-out\";\r\n }\r\n if (typeof easing === \"string\") {\r\n object.setProperty(attrKey, this.tools.easingFunction.process({ easing }));\r\n }\r\n }\r\n\r\n private resolveEasings(object: StringObject, sequence: string): void {\r\n const slider = this.parseSequenceKey(sequence)?.slider;\r\n if (!slider) return;\r\n this.resolveEasing(object, slider, \"enteringEasing\", \"entering-easing\");\r\n this.resolveEasing(object, slider, \"leavingEasing\", \"leaving-easing\");\r\n }\r\n\r\n override onObjectDisconnected(object: StringObject): void {\r\n super.onObjectDisconnected(object);\r\n\r\n const sequence = object.getProperty<string>(\"sequence\");\r\n if (sequence) {\r\n const group = this.elementIndex.get(sequence);\r\n if (group) {\r\n const idx = group.objects.indexOf(object);\r\n if (idx !== -1) group.objects.splice(idx, 1);\r\n if (!group.objects.length) this.elementIndex.delete(sequence);\r\n }\r\n }\r\n\r\n if (this.triggerElements.has(object.htmlElement)) {\r\n object.htmlElement.removeEventListener(\"click\", this.onTriggerClick);\r\n this.triggerElements.delete(object.htmlElement);\r\n }\r\n }\r\n\r\n private parseSequenceKey(key: string): { slider: string; step: number } | null {\r\n const m = key.match(/^(.+)\\[(\\d+)\\]$/);\r\n return m ? { slider: m[1], step: parseInt(m[2], 10) } : null;\r\n }\r\n\r\n private onTriggerClick = (e: Event): void => {\r\n const data = this.triggerElements.get(e.currentTarget as HTMLElement);\r\n if (!data) return;\r\n\r\n const current = this.activeStep.get(data.slider) ?? 0;\r\n const max = this.getMaxStep(data.slider);\r\n let target: number, dir: 1 | -1;\r\n\r\n if (data.step === \"next\") {\r\n target = current + 1;\r\n dir = 1;\r\n if (!this.elementIndex.has(`${data.slider}[${target}]`)) {\r\n if (data.loop && max >= 0) target = 0;\r\n else return;\r\n }\r\n } else if (data.step === \"prev\") {\r\n target = current - 1;\r\n dir = -1;\r\n if (target < 0) {\r\n if (data.loop && max >= 0) target = max;\r\n else return;\r\n }\r\n if (!this.elementIndex.has(`${data.slider}[${target}]`)) return;\r\n } else {\r\n target = data.step;\r\n if (current === target) return;\r\n dir = target > current ? 1 : -1;\r\n }\r\n\r\n this.startTransition(data.slider, target, dir);\r\n };\r\n\r\n private onSequenceEvent(data: SequenceEventData): void {\r\n const { slider, step, transitionProgress, direction = 1, duration, instant } = data;\r\n const current = this.activeStep.get(slider);\r\n\r\n if (current === step && transitionProgress === undefined) return;\r\n\r\n if (transitionProgress !== undefined) {\r\n this.handleScrub(slider, step, transitionProgress, direction);\r\n } else if (instant) {\r\n this.switchInstant(slider, step, direction);\r\n } else {\r\n this.startTransition(slider, step, direction, duration);\r\n }\r\n }\r\n\r\n private startTransition(\r\n slider: string,\r\n toStep: number,\r\n direction: 1 | -1,\r\n customDuration?: number\r\n ): void {\r\n const fromStep = this.activeStep.get(slider);\r\n const prevLeaving = this.leavingStep.get(slider);\r\n\r\n this.ensureStateEventRegistered(slider);\r\n\r\n if (prevLeaving !== undefined && prevLeaving !== fromStep) {\r\n this.setStepState(slider, prevLeaving, SequenceState.DISABLED, 0, direction);\r\n }\r\n\r\n const enteringGroup = this.elementIndex.get(`${slider}[${toStep}]`);\r\n const leavingGroup =\r\n fromStep !== undefined ? this.elementIndex.get(`${slider}[${fromStep}]`) : null;\r\n\r\n if (fromStep !== undefined) this.leavingStep.set(slider, fromStep);\r\n this.activeStep.set(slider, toStep);\r\n this.emitActiveState(slider, toStep);\r\n\r\n const transition: TransitionState = {\r\n fromStep: fromStep ?? toStep,\r\n toStep,\r\n direction,\r\n startTime: this.data.time.now,\r\n enteringDuration: customDuration ?? enteringGroup?.enteringDuration ?? this.defaultDuration,\r\n leavingDuration: customDuration ?? leavingGroup?.leavingDuration ?? this.defaultDuration,\r\n };\r\n\r\n this.transitions.set(slider, transition);\r\n this.emitTransitionStart(slider, transition);\r\n }\r\n\r\n private handleScrub(slider: string, step: number, progress: number, direction: 1 | -1): void {\r\n this.transitions.delete(slider);\r\n const current = this.activeStep.get(slider);\r\n\r\n if (current !== step) {\r\n const prev = this.leavingStep.get(slider);\r\n if (prev !== undefined) this.setStepState(slider, prev, SequenceState.DISABLED, 0, direction);\r\n if (current !== undefined) this.leavingStep.set(slider, current);\r\n this.activeStep.set(slider, step);\r\n this.emitActiveState(slider, step);\r\n }\r\n\r\n const fromStep = this.leavingStep.get(slider) ?? current ?? step;\r\n this.applyProgress(slider, fromStep, step, progress, progress, direction);\r\n }\r\n\r\n private switchInstant(slider: string, step: number, direction: 1 | -1): void {\r\n this.transitions.delete(slider);\r\n const current = this.activeStep.get(slider);\r\n const leaving = this.leavingStep.get(slider);\r\n\r\n if (leaving !== undefined)\r\n this.setStepState(slider, leaving, SequenceState.DISABLED, 0, direction);\r\n if (current !== undefined && current !== step)\r\n this.setStepState(slider, current, SequenceState.DISABLED, 0, direction);\r\n\r\n this.activeStep.set(slider, step);\r\n this.leavingStep.delete(slider);\r\n this.setStepState(slider, step, SequenceState.ACTIVE, 1, direction);\r\n\r\n this.emitActiveState(slider, step);\r\n if (leaving !== undefined && leaving !== step)\r\n this.emitStepLeave(slider, leaving, direction, true);\r\n else if (current !== undefined && current !== step)\r\n this.emitStepLeave(slider, current, direction, true);\r\n this.emitStepEnter(slider, step, direction, true);\r\n\r\n const transition: TransitionState = {\r\n fromStep: current ?? step,\r\n toStep: step,\r\n direction,\r\n startTime: this.data.time.now,\r\n enteringDuration: 0,\r\n leavingDuration: 0,\r\n };\r\n this.emitTransitionStart(slider, transition);\r\n this.emitTransitionEnd(slider, step, current ?? step, direction, true);\r\n }\r\n\r\n private applyProgress(\r\n slider: string,\r\n fromStep: number,\r\n toStep: number,\r\n enteringProg: number,\r\n leavingProg: number,\r\n direction: 1 | -1\r\n ): void {\r\n const active = this.activeStep.get(slider)!;\r\n const leaving = this.leavingStep.get(slider);\r\n\r\n this.setStepState(\r\n slider,\r\n active,\r\n enteringProg >= 1 ? SequenceState.ACTIVE : SequenceState.ENTERING,\r\n enteringProg,\r\n direction\r\n );\r\n\r\n if (leaving !== undefined && leaving !== active) {\r\n if (leavingProg >= 1) {\r\n this.setStepState(slider, leaving, SequenceState.DISABLED, 0, direction);\r\n this.leavingStep.delete(slider);\r\n this.emitStepLeave(slider, leaving, direction, false);\r\n } else {\r\n this.setStepState(slider, leaving, SequenceState.LEAVING, leavingProg, direction);\r\n }\r\n }\r\n\r\n this.emitTransitionProgress(slider, fromStep, toStep, enteringProg, leavingProg, direction);\r\n\r\n if (enteringProg >= 1) {\r\n this.emitStepEnter(slider, active, direction, false);\r\n }\r\n }\r\n\r\n private setStepState(\r\n slider: string,\r\n step: number,\r\n state: SequenceState,\r\n progress: number,\r\n direction: 1 | -1\r\n ): void {\r\n const group = this.elementIndex.get(`${slider}[${step}]`);\r\n if (group) for (const obj of group.objects) this.setState(obj, state, progress, direction);\r\n }\r\n\r\n private setState(\r\n object: StringObject,\r\n state: SequenceState,\r\n rawProgress: number,\r\n direction: 1 | -1\r\n ): void {\r\n const el = object.htmlElement;\r\n const currentState = object.getProperty<SequenceState>(\"_state\");\r\n const currentDir = object.getProperty<number>(\"_direction\");\r\n\r\n const easing = object.getProperty<EasingFunctionOutput>(\r\n state === SequenceState.LEAVING ? \"leaving-easing\" : \"entering-easing\"\r\n );\r\n const progress = typeof easing === \"function\" ? easing(rawProgress) : rawProgress;\r\n\r\n if (currentState !== state) {\r\n el.classList.remove(...StringSequence.ALL_STATES);\r\n el.classList.add(state);\r\n object.setProperty(\"_state\", state);\r\n }\r\n\r\n if (currentDir !== direction) {\r\n object.setProperty(\"_direction\", direction);\r\n styleTxn.run(() =>\r\n styleTxn.setVars(el, { [SequenceProgressVars.DIRECTION]: direction.toString() })\r\n );\r\n }\r\n }\r\n\r\n onFrame(data: StringData): void {\r\n super.onFrame(data);\r\n\r\n if (!this.initialized) {\r\n this.initialized = true;\r\n this.initializeSliders();\r\n }\r\n\r\n for (const [slider, t] of this.transitions) {\r\n const elapsed = data.time.now - t.startTime;\r\n const enteringProg = Math.min(1, elapsed / t.enteringDuration);\r\n const leavingProg = Math.min(1, elapsed / t.leavingDuration);\r\n\r\n this.applyProgress(slider, t.fromStep, t.toStep, enteringProg, leavingProg, t.direction);\r\n\r\n if (enteringProg >= 1 && leavingProg >= 1) {\r\n this.emitTransitionEnd(slider, t.toStep, t.fromStep, t.direction, false);\r\n this.transitions.delete(slider);\r\n }\r\n }\r\n }\r\n\r\n private emitTransitionStart(slider: string, t: TransitionState): void {\r\n const payload = {\r\n slider,\r\n from: t.fromStep,\r\n to: t.toStep,\r\n direction: t.direction,\r\n enteringDuration: t.enteringDuration,\r\n leavingDuration: t.leavingDuration,\r\n startedAt: t.startTime,\r\n };\r\n this.events.emit(\"sequence:transition:start\", payload);\r\n this.events.emit(`sequence:transition:start:${slider}`, payload);\r\n }\r\n\r\n private emitTransitionProgress(\r\n slider: string,\r\n from: number,\r\n to: number,\r\n entering: number,\r\n leaving: number,\r\n direction: 1 | -1\r\n ): void {\r\n const payload = { slider, from, to, entering, leaving, direction };\r\n this.events.emit(\"sequence:transition:progress\", payload);\r\n this.events.emit(`sequence:transition:progress:${slider}`, payload);\r\n }\r\n\r\n private emitTransitionEnd(\r\n slider: string,\r\n to: number,\r\n from: number,\r\n direction: 1 | -1,\r\n instant: boolean\r\n ): void {\r\n const payload = { slider, from, to, direction, instant };\r\n this.events.emit(\"sequence:transition:end\", payload);\r\n this.events.emit(`sequence:transition:end:${slider}`, payload);\r\n }\r\n\r\n private emitStepEnter(slider: string, step: number, direction: 1 | -1, instant: boolean): void {\r\n if (!instant && this.lastEnteredStep.get(slider) === step) return;\r\n this.lastEnteredStep.set(slider, step);\r\n const payload = { slider, step, direction, instant };\r\n this.events.emit(\"sequence:step:enter\", payload);\r\n this.events.emit(`sequence:step:enter:${slider}`, payload);\r\n }\r\n\r\n private emitStepLeave(\r\n slider: string,\r\n step: number | null,\r\n direction: 1 | -1,\r\n instant: boolean\r\n ): void {\r\n if (step === null || step === undefined) return;\r\n const payload = { slider, step, direction, instant };\r\n this.events.emit(\"sequence:step:leave\", payload);\r\n this.events.emit(`sequence:step:leave:${slider}`, payload);\r\n }\r\n\r\n private emitActiveState(slider: string, step: number): void {\r\n const payload = { slider, step };\r\n this.events.emit(\"sequence:active\", payload);\r\n this.events.emit(`sequence:active:${slider}`, payload);\r\n }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { RuleParserResult } from \"../../tools/RuleParserTool\";\r\nimport type { ValidationContext } from \"../../tools/ValidationTool\";\r\n\r\ntype FormField = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\r\n\r\ninterface RegisteredEvent {\r\n eventElement: EventTarget;\r\n eventType: string;\r\n eventCallback: EventListenerOrEventListenerObject;\r\n}\r\n\r\ninterface FieldEntry {\r\n field: FormField;\r\n key: string;\r\n rules: RuleParserResult[];\r\n supportsRealtime: boolean;\r\n needsContext: boolean;\r\n inputEventType: \"input\" | \"change\";\r\n inputHandler: EventListener;\r\n beforeInputHandler?: EventListener;\r\n}\r\n\r\ntype FormState = {\r\n object: StringObject;\r\n form: HTMLFormElement;\r\n entries: FieldEntry[];\r\n values: Record<string, any>;\r\n events: RegisteredEvent[];\r\n};\r\n\r\nexport class StringForm extends StringModule {\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"form\";\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\r\n const existingEvents = object.getProperty<Array<RegisteredEvent>>(\"form-events\") ?? [];\r\n existingEvents.forEach((evt) => {\r\n evt.eventElement.removeEventListener(evt.eventType, evt.eventCallback);\r\n });\r\n existingEvents.length = 0;\r\n object.setProperty(\"form-events\", existingEvents);\r\n\r\n super.onObjectConnected(object);\r\n const form = object.htmlElement as HTMLFormElement;\r\n\r\n const fieldEntries: FieldEntry[] = [];\r\n const fieldValues: Record<string, any> = {};\r\n\r\n this.getInteractiveFields(form).forEach((field, idx) =>\r\n this.registerField(field, form, fieldEntries, fieldValues, existingEvents, idx)\r\n );\r\n\r\n const submitCallback = (event: Event) => {\r\n event.preventDefault();\r\n let allValid = true;\r\n const data: Record<string, any> = {};\r\n const processedRadioKeys = new Set<string>();\r\n for (const entry of fieldEntries) {\r\n const field = entry.field;\r\n if (!field.isConnected || !this.shouldValidateField(field)) continue;\r\n if (this.isRadioField(field)) {\r\n if (processedRadioKeys.has(entry.key)) {\r\n continue;\r\n }\r\n processedRadioKeys.add(entry.key);\r\n }\r\n const { key, rules, needsContext } = entry;\r\n const value = this.getFieldValue(field);\r\n data[key] = value;\r\n fieldValues[key] = value;\r\n\r\n const { valid, errors } = this.tools.validation.process({\r\n rules,\r\n value,\r\n context: this.buildContext(needsContext, key, fieldValues),\r\n });\r\n\r\n this.applyValidationState(form, field, key, valid, errors, \"submit\");\r\n\r\n if (!valid) {\r\n allValid = false;\r\n }\r\n }\r\n\r\n if (allValid) {\r\n this.events.emit(`form:submit:${object.id}`, data);\r\n } else {\r\n const processedRadioKeys = new Set<string>();\r\n const firstInvalidEntry = fieldEntries.find((entry) => {\r\n const field = entry.field;\r\n if (!field.isConnected || !this.shouldValidateField(field)) return false;\r\n if (this.isRadioField(field)) {\r\n if (processedRadioKeys.has(entry.key)) {\r\n return false;\r\n }\r\n processedRadioKeys.add(entry.key);\r\n }\r\n const { key, rules, needsContext } = entry;\r\n const value = this.getFieldValue(field);\r\n fieldValues[key] = value;\r\n const { valid } = this.tools.validation.process({\r\n rules,\r\n value,\r\n context: this.buildContext(needsContext, key, fieldValues),\r\n });\r\n return !valid;\r\n });\r\n if (firstInvalidEntry?.field && typeof firstInvalidEntry.field.focus === \"function\") {\r\n firstInvalidEntry.field.focus();\r\n }\r\n this.events.emit(`form:invalid:${object.id}`);\r\n }\r\n };\r\n\r\n form.addEventListener(\"submit\", submitCallback);\r\n existingEvents.push({ eventElement: form, eventType: \"submit\", eventCallback: submitCallback });\r\n\r\n object.setProperty(\"form-field-entries\", fieldEntries);\r\n object.setProperty(\"form-field-values\", fieldValues);\r\n }\r\n\r\n onObjectConnected(object: StringObject) {}\r\n\r\n onDOMMutate(added: NodeList, removed: NodeList): void {\r\n if (this.objects.length === 0) {\r\n return;\r\n }\r\n\r\n if (added.length > 0) {\r\n this.handleMutationAdditions(added);\r\n }\r\n\r\n if (removed.length > 0) {\r\n this.handleMutationRemovals(removed);\r\n }\r\n }\r\n\r\n private applyValidationState(\r\n form: HTMLFormElement,\r\n field: FormField,\r\n key: string,\r\n valid: boolean,\r\n errors: string[],\r\n phase: \"live\" | \"submit\"\r\n ): void {\r\n const errorBlock = form.querySelector(`[string-input=\"error[${key}]\"]`);\r\n const groupBlock = form.querySelector(`[string-input=\"group[${key}]\"]`);\r\n if (errorBlock) {\r\n errorBlock.innerHTML = \"\";\r\n errors.forEach((message) => {\r\n const span = document.createElement(\"span\");\r\n span.textContent = message;\r\n errorBlock.appendChild(span);\r\n });\r\n }\r\n if (phase === \"live\") {\r\n field.classList.toggle(\"-invalid\", !valid);\r\n field.classList.remove(\"-error\");\r\n } else {\r\n field.classList.remove(\"-invalid\");\r\n field.classList.toggle(\"-error\", !valid);\r\n }\r\n field.classList.toggle(\"-valid\", valid);\r\n if (groupBlock) {\r\n if (phase === \"live\") {\r\n groupBlock.classList.toggle(\"-invalid\", !valid);\r\n groupBlock.classList.remove(\"-error\");\r\n } else {\r\n groupBlock.classList.remove(\"-invalid\");\r\n groupBlock.classList.toggle(\"-error\", !valid);\r\n }\r\n groupBlock.classList.toggle(\"-valid\", valid);\r\n }\r\n\r\n const eventSuffix = valid ? \"valid\" : phase === \"live\" ? \"invalid\" : \"error\";\r\n this.events.emit(`form:field:${eventSuffix}:${key}`, {\r\n key,\r\n field,\r\n errors,\r\n phase,\r\n valid,\r\n });\r\n }\r\n\r\n private getInteractiveFields(form: HTMLFormElement): FormField[] {\r\n return Array.from(form.querySelectorAll(\"[string-input]\"))\r\n .filter((el) => !this.isServiceFieldAttribute(el.getAttribute(\"string-input\") || \"\"))\r\n .filter((el): el is FormField => this.isFormFieldElement(el))\r\n .map((el) => el as FormField);\r\n }\r\n\r\n private getFieldRules(field: FormField): RuleParserResult[] {\r\n const ruleString =\r\n this.tools.domAttribute.process({\r\n element: field,\r\n key: \"input\",\r\n }) ?? \"\";\r\n return this.tools.ruleParser.process({ value: ruleString });\r\n }\r\n\r\n private registerField(\r\n field: FormField,\r\n form: HTMLFormElement,\r\n fieldEntries: FieldEntry[],\r\n fieldValues: Record<string, any>,\r\n events: RegisteredEvent[],\r\n preferredIndex?: number\r\n ): void {\r\n if (!this.isFormFieldElement(field)) return;\r\n if (field.closest(\"form\") !== form) return;\r\n if (fieldEntries.some((entry) => entry.field === field)) return;\r\n\r\n const registeredIndex = this.registerFieldIndex(field, preferredIndex ?? fieldEntries.length);\r\n const key = this.getInputKey(field, registeredIndex);\r\n const rules = this.getFieldRules(field);\r\n const supportsRealtime = this.supportsBeforeInputValidation(rules);\r\n const needsContext = this.requiresContext(rules);\r\n const inputEventType = this.getInputEventType(field);\r\n\r\n const entry: FieldEntry = {\r\n field,\r\n key,\r\n rules,\r\n supportsRealtime,\r\n needsContext,\r\n inputEventType,\r\n inputHandler: () => undefined,\r\n };\r\n\r\n const inputHandler = (event: Event) => {\r\n const target = (event.currentTarget || event.target) as FormField | null;\r\n if (!target || !target.isConnected || !this.shouldValidateField(target)) {\r\n return;\r\n }\r\n const value = this.getFieldValue(target);\r\n fieldValues[entry.key] = value;\r\n const context = this.buildContext(entry.needsContext, entry.key, fieldValues);\r\n\r\n const { valid, errors } = this.tools.validation.process({\r\n rules: entry.rules,\r\n value,\r\n context,\r\n });\r\n\r\n this.applyValidationState(form, target, entry.key, valid, errors, \"live\");\r\n };\r\n\r\n entry.inputHandler = inputHandler;\r\n field.addEventListener(inputEventType, inputHandler);\r\n events.push({ eventElement: field, eventType: inputEventType, eventCallback: inputHandler });\r\n\r\n if (\r\n supportsRealtime &&\r\n (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement)\r\n ) {\r\n const beforeInputHandler = (event: Event) => {\r\n const inputEvent = event as InputEvent;\r\n if (inputEvent.isComposing || inputEvent.inputType?.startsWith(\"insertComposition\")) {\r\n return;\r\n }\r\n const target = (event.currentTarget || event.target) as FormField | null;\r\n if (\r\n !target ||\r\n !(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) ||\r\n !target.isConnected\r\n ) {\r\n return;\r\n }\r\n\r\n const start = target.selectionStart ?? 0;\r\n const end = target.selectionEnd ?? 0;\r\n let nextVal = target.value;\r\n\r\n switch (inputEvent.inputType) {\r\n case \"deleteContentBackward\":\r\n nextVal =\r\n start === end && start > 0\r\n ? target.value.slice(0, start - 1) + target.value.slice(end)\r\n : target.value.slice(0, start) + target.value.slice(end);\r\n break;\r\n case \"deleteContentForward\":\r\n nextVal =\r\n start === end && start < target.value.length\r\n ? target.value.slice(0, start) + target.value.slice(start + 1)\r\n : target.value.slice(0, start) + target.value.slice(end);\r\n break;\r\n case \"insertFromPaste\":\r\n case \"insertFromDrop\":\r\n case \"insertReplacementText\":\r\n nextVal =\r\n target.value.slice(0, start) + (inputEvent.data || \"\") + target.value.slice(end);\r\n break;\r\n default:\r\n if (typeof inputEvent.data === \"string\") {\r\n nextVal = target.value.slice(0, start) + inputEvent.data + target.value.slice(end);\r\n }\r\n }\r\n\r\n const { errors } = this.tools.validation.process({\r\n rules: entry.rules,\r\n value: nextVal,\r\n type: \"beforeinput\",\r\n context: this.buildContext(entry.needsContext, entry.key, fieldValues, {\r\n applied: true,\r\n value: nextVal,\r\n }),\r\n });\r\n\r\n if (errors.length > 0 && event.cancelable) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n entry.beforeInputHandler = beforeInputHandler;\r\n field.addEventListener(\"beforeinput\", beforeInputHandler);\r\n events.push({\r\n eventElement: field,\r\n eventType: \"beforeinput\",\r\n eventCallback: beforeInputHandler,\r\n });\r\n }\r\n\r\n field.classList.add(\"-inited\");\r\n fieldEntries.push(entry);\r\n fieldValues[key] = this.getFieldValue(field);\r\n }\r\n\r\n private unregisterField(\r\n field: FormField,\r\n fieldEntries: FieldEntry[],\r\n fieldValues: Record<string, any>,\r\n events: RegisteredEvent[]\r\n ): void {\r\n const index = fieldEntries.findIndex((entry) => entry.field === field);\r\n if (index === -1) return;\r\n const entry = fieldEntries[index];\r\n if (entry.inputHandler) {\r\n field.removeEventListener(entry.inputEventType, entry.inputHandler);\r\n }\r\n if (entry.beforeInputHandler) {\r\n field.removeEventListener(\"beforeinput\", entry.beforeInputHandler);\r\n }\r\n delete fieldValues[entry.key];\r\n fieldEntries.splice(index, 1);\r\n for (let i = events.length - 1; i >= 0; i--) {\r\n const registered = events[i];\r\n if (registered.eventElement !== field) continue;\r\n if (\r\n registered.eventCallback === entry.inputHandler ||\r\n (entry.beforeInputHandler && registered.eventCallback === entry.beforeInputHandler)\r\n ) {\r\n events.splice(i, 1);\r\n }\r\n }\r\n field.classList.remove(\"-inited\");\r\n }\r\n\r\n private collectInteractiveFieldsFromNode(node: Node): FormField[] {\r\n const elements: Element[] = [];\r\n if (node instanceof Element) {\r\n if (node.hasAttribute(\"string-input\")) {\r\n elements.push(node);\r\n }\r\n elements.push(...Array.from(node.querySelectorAll(\"[string-input]\")));\r\n } else if (node instanceof DocumentFragment) {\r\n elements.push(...Array.from(node.querySelectorAll(\"[string-input]\")));\r\n }\r\n\r\n return elements\r\n .filter((el) => !this.isServiceFieldAttribute(el.getAttribute(\"string-input\") || \"\"))\r\n .filter((el): el is FormField => this.isFormFieldElement(el));\r\n }\r\n\r\n private isRadioField(field: FormField): field is HTMLInputElement {\r\n return field instanceof HTMLInputElement && field.type === \"radio\";\r\n }\r\n\r\n private handleMutationAdditions(nodes: NodeList): void {\r\n nodes.forEach((node) => {\r\n const fields = this.collectInteractiveFieldsFromNode(node);\r\n fields.forEach((field) => {\r\n const state = this.getFormStateByContainment(field);\r\n if (!state) return;\r\n this.registerField(field, state.form, state.entries, state.values, state.events);\r\n });\r\n });\r\n }\r\n\r\n private handleMutationRemovals(nodes: NodeList): void {\r\n nodes.forEach((node) => {\r\n const fields = this.collectInteractiveFieldsFromNode(node);\r\n fields.forEach((field) => {\r\n const state = this.getFormStateByReference(field);\r\n if (!state) return;\r\n this.unregisterField(field, state.entries, state.values, state.events);\r\n });\r\n });\r\n }\r\n\r\n private getFormStateByContainment(field: FormField): FormState | null {\r\n const owner = this.objects.find(\r\n (object) =>\r\n object.htmlElement instanceof HTMLFormElement && object.htmlElement.contains(field)\r\n );\r\n if (!owner) return null;\r\n return this.buildFormState(owner);\r\n }\r\n\r\n private getFormStateByReference(field: FormField): FormState | null {\r\n for (const object of this.objects) {\r\n const entries = object.getProperty<FieldEntry[]>(\"form-field-entries\");\r\n if (!entries) continue;\r\n if (entries.some((entry) => entry.field === field)) {\r\n return this.buildFormState(object, entries);\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private buildFormState(object: StringObject, entries?: FieldEntry[]): FormState | null {\r\n const element = object.htmlElement;\r\n if (!(element instanceof HTMLFormElement)) {\r\n return null;\r\n }\r\n const stateEntries = entries ?? object.getProperty<FieldEntry[]>(\"form-field-entries\");\r\n const values = object.getProperty<Record<string, any>>(\"form-field-values\");\r\n const events = object.getProperty<Array<RegisteredEvent>>(\"form-events\");\r\n if (!stateEntries || !values || !events) {\r\n return null;\r\n }\r\n return {\r\n object,\r\n form: element,\r\n entries: stateEntries,\r\n values,\r\n events,\r\n };\r\n }\r\n\r\n private registerFieldIndex(field: FormField, idx: number): number {\r\n const existing = field.getAttribute(\"data-string-form-index\");\r\n if (existing !== null) {\r\n return Number(existing);\r\n }\r\n field.setAttribute(\"data-string-form-index\", String(idx));\r\n return idx;\r\n }\r\n\r\n private getFieldIndex(field: FormField, fallbackIdx: number): number {\r\n const existing = field.getAttribute(\"data-string-form-index\");\r\n if (existing !== null) {\r\n const parsed = Number(existing);\r\n return Number.isNaN(parsed) ? fallbackIdx : parsed;\r\n }\r\n return this.registerFieldIndex(field, fallbackIdx);\r\n }\r\n\r\n private shouldValidateField(field: FormField): boolean {\r\n if (field.disabled) return false;\r\n if (field instanceof HTMLInputElement && field.type === \"hidden\") return false;\r\n return true;\r\n }\r\n\r\n private supportsBeforeInputValidation(rules: RuleParserResult[]): boolean {\r\n return rules.some((rule) => StringForm.beforeInputRuleKeys.has(rule.key));\r\n }\r\n\r\n private requiresContext(rules: RuleParserResult[]): boolean {\r\n return rules.some((rule) => StringForm.crossFieldRuleKeys.has(rule.key));\r\n }\r\n\r\n private buildContext(\r\n needsContext: boolean,\r\n fieldKey: string,\r\n fieldValues: Record<string, any>,\r\n override?: { applied: boolean; value: any }\r\n ): ValidationContext {\r\n if (!needsContext) {\r\n return { fieldKey };\r\n }\r\n\r\n const needsOverride = Boolean(override?.applied);\r\n const values = needsOverride ? { ...fieldValues, [fieldKey]: override!.value } : fieldValues;\r\n\r\n return {\r\n fieldKey,\r\n values,\r\n getValue: (lookupKey: string) => {\r\n if (needsOverride && lookupKey === fieldKey) {\r\n return override!.value;\r\n }\r\n return values[lookupKey];\r\n },\r\n };\r\n }\r\n\r\n private static readonly beforeInputRuleKeys = new Set([\r\n \"number\",\r\n \"integer\",\r\n \"email\",\r\n \"phone\",\r\n \"letters\",\r\n \"lettersSpaces\",\r\n \"lettersNumbers\",\r\n \"alpha\",\r\n \"alpha_num\",\r\n \"alpha_dash\",\r\n \"digits\",\r\n \"url\",\r\n \"pattern\",\r\n ]);\r\n\r\n private static readonly crossFieldRuleKeys = new Set([\"same\", \"different\", \"after\", \"before\"]);\r\n\r\n private static readonly serviceAttributePrefixes = [\"error\", \"group\"];\r\n\r\n getInputKey(field: FormField, idx: number): string {\r\n return (\r\n this.tools.domAttribute.process({\r\n element: field,\r\n key: \"id\",\r\n }) ||\r\n field.getAttribute(\"name\") ||\r\n field.getAttribute(\"id\") ||\r\n `input-${idx}`\r\n );\r\n }\r\n\r\n getFieldValue(field: FormField): any {\r\n if (field instanceof HTMLInputElement) {\r\n if (field.type === \"checkbox\") {\r\n if (field.name) {\r\n const form = field.form || field.closest(\"form\");\r\n const checked = form\r\n ? Array.from(\r\n form.querySelectorAll<HTMLInputElement>(\r\n `input[type=\"checkbox\"][name=\"${field.name}\"]:checked`\r\n )\r\n )\r\n : [field];\r\n if (checked.length > 1) return checked.map((el) => el.value);\r\n return checked.length === 1 ? checked[0].value : \"\";\r\n }\r\n return field.checked;\r\n }\r\n if (field.type === \"radio\") {\r\n if (field.name) {\r\n const form = field.form || field.closest(\"form\");\r\n const checked = form?.querySelector<HTMLInputElement>(\r\n `input[type=\"radio\"][name=\"${field.name}\"]:checked`\r\n );\r\n return checked ? checked.value : \"\";\r\n }\r\n return field.checked ? field.value : \"\";\r\n }\r\n if (field.type === \"file\") {\r\n if (field.files && field.files.length > 0) {\r\n return field.multiple ? Array.from(field.files) : field.files[0];\r\n }\r\n return field.value;\r\n }\r\n return field.value;\r\n }\r\n if (field instanceof HTMLSelectElement) {\r\n if (field.multiple) {\r\n return Array.from(field.selectedOptions).map((opt) => opt.value);\r\n }\r\n return field.value;\r\n }\r\n if (field instanceof HTMLTextAreaElement) {\r\n return field.value;\r\n }\r\n return \"\";\r\n }\r\n\r\n private isServiceFieldAttribute(attr: string): boolean {\r\n return StringForm.serviceAttributePrefixes.some((type) => attr.startsWith(`${type}[`));\r\n }\r\n\r\n private isFormFieldElement(element: Element): element is FormField {\r\n return (\r\n element instanceof HTMLInputElement ||\r\n element instanceof HTMLSelectElement ||\r\n element instanceof HTMLTextAreaElement\r\n );\r\n }\r\n\r\n private getInputEventType(field: FormField): \"input\" | \"change\" {\r\n if (\r\n field instanceof HTMLSelectElement ||\r\n (field instanceof HTMLInputElement && (field.type === \"checkbox\" || field.type === \"radio\"))\r\n ) {\r\n return \"change\";\r\n }\r\n return \"input\";\r\n }\r\n}\r\n","import { StringObject } from \"../../objects/StringObject\";\r\n\r\ntype CenterState = {\r\n cx: number;\r\n cy: number;\r\n valid: boolean;\r\n ro?: ResizeObserver;\r\n el?: HTMLElement;\r\n};\r\n\r\nexport class CenterCache {\r\n private map = new WeakMap<StringObject, CenterState>();\r\n private all: Set<StringObject> = new Set();\r\n\r\n attach(obj: StringObject) {\r\n if (this.map.has(obj)) return;\r\n const el = obj.htmlElement;\r\n const st: CenterState = { cx: 0, cy: 0, valid: false, el };\r\n st.ro = new ResizeObserver(() => {\r\n st.valid = false;\r\n });\r\n st.ro.observe(el);\r\n this.map.set(obj, st);\r\n this.all.add(obj);\r\n }\r\n\r\n detach(obj: StringObject) {\r\n const st = this.map.get(obj);\r\n if (!st) return;\r\n st.ro?.disconnect();\r\n this.map.delete(obj);\r\n this.all.delete(obj);\r\n }\r\n\r\n invalidate(id: string) {\r\n this.all.forEach((o) => {\r\n if (o.id === id) {\r\n const st = this.map.get(o);\r\n if (st) st.valid = false;\r\n }\r\n });\r\n }\r\n\r\n invalidateAll() {\r\n this.all.forEach((o) => {\r\n const st = this.map.get(o);\r\n if (st) st.valid = false;\r\n });\r\n }\r\n\r\n getCenter(obj: StringObject): { cx: number; cy: number } {\r\n const st = this.map.get(obj);\r\n if (!st || !st.el) return { cx: 0, cy: 0 };\r\n if (!st.valid) {\r\n const r = st.el.getBoundingClientRect();\r\n st.cx = r.left + r.width / 2;\r\n st.cy = r.top + r.height / 2;\r\n st.valid = true;\r\n }\r\n return { cx: st.cx, cy: st.cy };\r\n }\r\n}\r\n","import { StringObject } from \"../../objects/StringObject\";\n\ntype HoverState = { enter?: () => void; leave?: () => void };\n\nexport class HoverTracker {\n private active = new Set<StringObject>();\n private subs = new WeakMap<StringObject, HoverState>();\n\n track(obj: StringObject) {\n if (this.subs.has(obj)) return;\n const el = obj.htmlElement;\n\n const enter = () => this.active.add(obj);\n const leave = () => this.active.delete(obj);\n\n el.addEventListener(\"pointerenter\", enter);\n el.addEventListener(\"pointerleave\", leave);\n this.subs.set(obj, { enter, leave });\n }\n\n untrack(obj: StringObject) {\n const st = this.subs.get(obj);\n if (!st) return;\n const el = obj.htmlElement;\n if (st.enter) el.removeEventListener(\"pointerenter\", st.enter);\n if (st.leave) el.removeEventListener(\"pointerleave\", st.leave);\n this.active.delete(obj);\n this.subs.delete(obj);\n }\n\n isActive(obj: StringObject) {\n return this.active.has(obj);\n }\n activeObjects(): StringObject[] {\n return Array.from(this.active);\n }\n}\n","import { StringContext } from \"../../core/StringContext\";\nimport { StringData } from \"../../core/StringData\";\nimport { StringModule } from \"../../core/StringModule\";\nimport { StringObject } from \"../../objects/StringObject\";\n\nexport class StringScroller extends StringModule {\n constructor(context: StringContext) {\n super(context);\n this.htmlKey = \"scroller\";\n }\n\n onObjectConnected(object: StringObject): void {\n let isScrollInited = object.getProperty(\"scroller-inited\");\n if (isScrollInited == null || isScrollInited == \"\") {\n object.setProperty(\"scroller-inited\", \"inited\");\n let wheelEvent = (event: Event) => {\n this.events.emit(`wheel`, event);\n };\n object.setProperty(\"scroller-wheel-event\", wheelEvent);\n object.htmlElement.addEventListener(\"wheel\", wheelEvent);\n }\n }\n onObjectDisconnected(object: StringObject): void {\n object.setProperty(\"scroller-inited\", \"\");\n object.htmlElement.removeEventListener(\"wheel\", object.getProperty(\"scroller-wheel-event\"));\n }\n}\n","export function parsePartOf(value: string): { id: string; start: number; end: number } | null {\n const match = value.match(/([^[]+)\\[([\\d.]+)-([\\d.]+)\\]/);\n if (!match) return null;\n return {\n id: match[1],\n start: parseFloat(match[2]),\n end: parseFloat(match[3]),\n };\n}\n","import { StringContext } from \"../../core/StringContext\";\nimport { StringModule } from \"../../core/StringModule\";\nimport { StringObject } from \"../../objects/StringObject\";\nimport { parsePartOf } from \"../../utils/ParsePartOf\";\n\nfunction remap(value: number, from1: number, to1: number, from2: number, to2: number): number {\n return from2 + ((to2 - from2) * (value - from1)) / (to1 - from1);\n}\n\nexport class StringProgressPart extends StringModule {\n constructor(context: StringContext) {\n super(context);\n this.htmlKey = \"progress-part\";\n this.attributesToMap = [\n ...this.attributesToMap,\n { key: \"part-of\", type: \"string\", fallback: \"\" },\n ];\n }\n\n onObjectConnected(object: StringObject): void {\n let partOfId = object.getProperty(\"part-of\");\n let partOfData = parsePartOf(partOfId as string);\n if (partOfData) {\n object.setProperty(\"part-of-id\", partOfData.id);\n object.setProperty(\"start\", partOfData.start);\n object.setProperty(\"end\", partOfData.end);\n let progressEvent = (progress: number) => {\n if (partOfData) {\n const sliceProgress = remap(progress, partOfData?.start, partOfData?.end, 0, 1);\n const clampedProgress = Math.max(0, Math.min(1, sliceProgress));\n object.htmlElement.style.setProperty(\"--progress-slice\", clampedProgress.toString());\n this.events.emit(`object:progress-slice:${object.id}`, clampedProgress);\n }\n };\n object.setProperty(\"progress-event\", progressEvent);\n this.events.on(`object:progress:${partOfData.id}`, progressEvent);\n }\n }\n\n onObjectDisconnected(object: StringObject): void {\n let partOfId = object.getProperty(\"part-of-id\");\n if (partOfId) {\n this.events.off(`object:progress:${partOfId}`, object.getProperty<any>(\"progress-event\"));\n }\n }\n}\n"],"mappings":"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","names":["index_exports","__export","CursorReactiveModule","DOMBatcher","StringAnchor","StringCursor","StringData","StringDelayLerpTracker","StringFPSTracker","StringForm","StringGlide","StringImpulse","StringLazy","StringLerp","StringLerpTracker","StringLoading","StringMagnetic","StringModule","StringObject","StringParallax","StringPositionTracker","StringProgress","StringProgressPart","StringResponsive","StringScrollbar","StringScroller","StringSequence","StringSplit","StringSpotlight","StringTune","StringVideoAutoplay","frameDOM","styleTxn","CursorController","smoothing","context","now","dt","targetX","targetY","smoothedX","smoothedY","stepX","stepY","distance","data","lerp","t","x","y","EventManager","eventName","initialPayload","callback","id","fullEvent","payload","set","value","visible","toLifecycleArgs","lifecycle","data","arg","arg2","ModuleManager","module","type","m","_data","added","removed","modules","args","i","StringMirrorObject","id","element","parent","key","value","easing","rawProgress","fallback","StringObject","id","element","EventManager","key","value","module","mirror","DOMBatcher","task","priority","contexts","module","object","element","attributes","globalId","rect","windowSize","sortByPriority","a","b","error","ModuleLifecyclePermissions","StringModule","context","ModuleLifecyclePermissions","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","parsedBreakpoint","breakpoints","item","val","id","index","applyFn","copyFn","mirror","data","event","added","removed","ObjectManager","data","modules","events","tools","DOMBatcher","el","idAttr","key","object","StringObject","keysAttr","s","attributes","m","connectableModules","StringModule","batchContexts","module","q","item","enabled","id","obj","mirror","mirrorIds","copyFromId","element","singleId","parent","existingIds","existing","mirrorId","StringMirrorObject","easingAttr","ids","raw","attr","start","end","progressCallback","entries","e","outsideProp","outsideAttrValue","outsideAttrNormalized","outsideAttrFlag","isOutsideContainer","observerRoot","progressObserver","mutations","mutation","node","child","copyFrom","childCopyFrom","isCanRebuild","scrollPos","activeStart","activeEnd","activeMin","activeMax","wasActive","isActive","inviewStart","inviewEnd","wasInView","isNowInView","direction","distToStart","distToEnd","buffer","windowMin","windowMax","a","b","i","list","value","low","high","mid","ScrollController","context","scrollDirection","rule","id","position","StringScrollDefault","ScrollController","context","delta","e","scrollTop","plusDelta","position","StringScrollDisable","ScrollController","context","e","SCROLL_CLASS_NAMES","StringScrollSmooth","ScrollController","context","newDirection","SCROLL_CLASS_NAMES","absVelocity","e","scrollDirection","atTop","atBottom","position","ScrollManager","context","StringScrollSmooth","StringScrollDefault","StringScrollDisable","mode","newMode","engine","events","rule","id","CursorState","RenderState","ScrollState","SystemState","TimeState","ViewportState","StringData","ScrollState","ViewportState","CursorState","RenderState","TimeState","SystemState","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","boundingRect","parts","s","sum","part","v","isNegative","result","AdaptiveLerpTool","value","inMin","inMax","outMin","outMax","t","HORIZONTAL_KEYWORDS","VERTICAL_KEYWORDS","OriginParserTool","value","raw","options","s","index","parts","single","parsed","first","second","firstIsVerticalOnly","secondIsHorizontalOnly","val","axis","num","ColorParserTool","value","str","hex","ch","r","g","b","a","rgbMatch","v","hslMatch","h","l","s","hue2rgb","p","q","t","EasingFunctionTool","easing","def","match","x1","y1","x2","y2","t","cx","bx","ax","cy","by","ay","sampleCurveX","sampleCurveY","sampleCurveDerivativeX","solveCurveX","x","epsilon","t0","t1","t2","d2","i","MagneticPullTool","distance","radius","strength","proximity","LerpColorTool","from","to","progress","LerpVector2Tool","from","to","progress","TransformScaleParserTool","value","str","matrixValues","matrixNumbers","scaleValue","scaleNumbers","scaleXValue","scaleNumber","scale3dValue","matrix3dValues","error","SplitOptionsParserTool","attributeValue","options","part","trimmedPart","match","prefix","optionType","fullOptionKey","params","p","parsedParam","result","param","randomMatch","RuleParserTool","value","result","current","depth","i","c","ruleStr","match","key","params","s","colonIndex","paramsString","ValidationTool","v","params","normalized","digitCount","context","targetKey","otherValue","value","min","max","length","limit","rules","type","errors","rule","beforeInputValidatorFn","inputValidatorFn","inputValid","beforeInputValid","key","files","allowed","p","file","limitKb","maxBytes","item","mime","ext","name","parts","mode","target","currentDate","referenceDate","token","contextualValue","today","date","timestamp","pattern","allowEmpty","stringValue","source","flags","trimmed","lastSlashIndex","a","b","segments","segment","num","hextetPattern","DefaultToolsContainer","DOMAttributeTool","RecordAttributeTool","TransformNullifyTool","BoundingClientRectTool","RelativePositionTool","UnitParserTool","LerpTool","AdaptiveLerpTool","OriginParserTool","ColorParserTool","ValidationTool","EasingFunctionTool","MagneticPullTool","LerpColorTool","LerpVector2Tool","TransformScaleParserTool","SplitOptionsParserTool","RuleParserTool","isCoarsePointer","mm","touch","narrow","StyleTxn","el","vars","currentVars","k","v","props","currentProps","fn","alreadyOpen","error","style","styleTxn","targetStates","CURSOR_EPSILON","DEFAULT_CURSOR_ID","CURSOR_PORTAL_SELECTOR","CURSOR_PORTAL_CONTENT_SELECTOR","MIN_FRAME_DELTA","getTargetState","object","state","StringCursor","StringModule","context","value","isCoarsePointer","globalId","element","attributes","rect","data","now","dt","cursorX","cursorY","isOver","isDisabled","baseLerp","frameLerp","dimensions","halfWidth","halfHeight","width","height","cx","cy","elementX","elementY","px","py","dx","dy","isMoving","enterMode","lerpedX","lerpedY","updatedX","updatedY","pixelChanged","alignment","offsetX","offsetY","mouseX","mouseY","targetX","targetY","newMouseX","newMouseY","stepX","stepY","smoothedX","smoothedY","prev","bucket","portal","cursorClass","added","removed","node","id","customLerp","content","existing","attrSources","source","raw","clamped","nodes","cb","ids","selected","normalized","portals","fallbackBucket","currentX","currentY","factor","fpsAdjustedLerp","safeDt","normalizedVelocityX","normalizedVelocityY","nextX","nextY","x","y","pixelX","pixelY","roundedX","roundedY","valueX","valueY","vars","extraVars","prevPx","prevPy","angle","angleDeg","styleTxn","el","v","base","clampedBase","frames","adjusted","cachedWidth","cachedHeight","fallbackWidth","fallbackHeight","rawHalfWidth","rawHalfHeight","mousePos","size","obj","StringImpulse","StringModule","context","object","observer","_e","cursorVelocityX","cursorVelocityY","mouseX","mouseY","rect","w","side01","positionStrength","isContinuousPush","isLatched","objectVelocityX","objectVelocityY","rotationStrength","centerX","centerY","relativeX","relativeY","torque","angularVelocityDeg","originValue","x","y","attrName","dataAttrName","mutations","mutation","newValue","normalizedX","normalizedY","_","objectItem","isUnderCursor","i","offsetX","offsetY","velocityX","velocityY","positionTension","positionFriction","maxVelocity","maxOffset","velocityDecay","angleDeg","rotationTension","rotationFriction","maxAngularVelocityDeg","maxRotationAngleDeg","sleepEpsilon","isPositionAsleep","isRotationAsleep","positionUpdateThreshold","rotationUpdateThreshold","prevCssX","prevCssY","prevCssRot","cssTranslateX","cssTranslateY","cssRotateDeg","needsPositionUpdate","needsRotationUpdate","el","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","FrameDOM","fn","mQueue","i","e","wQueue","frameDOM","CursorReactiveModule","StringModule","context","isCoarsePointer","object","id","obj","data","allowFallback","near","target","mx","my","targets","maxDistanceSq","cx","cy","dx","dy","d2","frameDOM","styleTxn","TAU","RAD2DEG","clamp01","v","shortestArc","from","to","d","spotState","getSpot","o","s","StringSpotlight","CursorReactiveModule","context","id","obj","el","attrs","frameDOM","styleTxn","data","targets","object","options","dx","dy","dist","DEADZONE","distMax","lerp","nextA","degRaw","angleEps","distEps","angleChanged","distChanged","cssDeg","cssDist","ASPECT_CLASS","isSvgSource","src","lower","parsePng","b","d","parseJpeg","o","m","len","parseWebp","i","chunkHeader","chunkSize","dataOffset","w","h","b0","b1","b2","b3","tryParseDims","buffer","ct","c","fetchImageStreamWithDims","opts","onDims","res","reader","PROBE_CAP","TRY_STEP","probe","probeLen","lastTriedLen","chunks","dims","announced","done","value","part","toCopy","view","full","blob","blobUrl","StringLazy","StringModule","context","img","object","element","state","listener","data","raw","inView","crossOrigin","referrerPolicy","ac","finalize","loaded","onLoad","onError","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","styleTxn","data","velocity","force","lerp","prevLerp","lerpStr","el","mirror","clearCustomProperty","StringProgress","StringModule","context","globalId","object","element","attributes","startPosition","differencePosition","rawProgress","easing","progress","windowSize","data","styleTxn","key","progressStr","parentEasing","el","mirror","eased","clearCustomProperty","StringParallax","StringProgress","context","object","progress","factor","start","end","sign","screenSize","translation","globalId","element","attributes","bias","windowSize","data","isDesktop","styleTxn","transformData","el","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","getWholeWordSplitClass","word","first","ch","cls","BuildDOMTree","layoutLines","options","fontMetrics","fragment","localCharIndex","hasLine","hasOption","hasChar","wordsCount","line","charsCount","w","linesCount","wordsGlobalCount","extraProps","li","isLastInLayout","container","wordsForLine","SPLIT_ELEMENT_CLASS","applyStyles","wi","isLast","original","wordText","c","hasWord","wordEl","wholeWordClass","char","charIndex","charNode","charEl","nextChar","kerning","splitClassChar","textNode","lineText","el","calculatedValues","val","isOptionEnabled","varName","generateVariableName","type","align","group","item","norm","key","tokenCounter","BuildTokens","nodes","tokens","pushWithMeta","t","extra","processNode","node","carryMeta","el","tag","classes","extraMeta","child","text","id","n","FontMetrics","element","canvas","cs","font","char","width","charA","charB","pair","key","widthWithKerning","widthWithoutKerning","kerning","word","totalWidth","i","prevChar","splitTokensByBr","tokens","result","chunk","token","LayoutMeasurer","container","fontMetrics","wrapper","computed","spaceMeasurer","spaceWidth","measured","chunks","isAfterElement","lastTokenWasSpace","prevMeasuredWasText","wordSpans","tokenInfo","raw","hadLeadingSpace","hadTrailingSpace","words","w","word","wIdx","span","node","info","idx","domRect","rect","accurateWidth","measuredToken","prev","LINE_TOLERANCE","SplitMeasuredTokens","measured","container","fontMetrics","lines","currentLine","y","charIndexGlobal","wordIndexGlobal","mt","token","isBefore","isAfter","wordText","splitClass","joinPrev","chars","currentXInWord","i","ch","prev","charWidth","kerning","charRect","pc","lastChar","currentY","baselineY","target","charsBeforeAll","acc","w","baseInWord","c","mergeRects","wordIndexInLine","charsBefore","processedWord","rect","rects","left","r","top","right","bottom","StringSplit","StringModule","context","object","element","isAlreadySplit","originalHtml","attr","options","fragment","result","extraProps","value","key","restoreAfter","fontMetrics","FontMetrics","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","ATTR_FPS","StringFPSTracker","StringModule","context","_data","visible","fps","fpsStr","el","mutations","needsRescan","mutation","node","styleId","style","StringLerpTracker","StringModule","context","data","v","ctx","w","h","val","i","x","y","position","ATTR_VAL","ATTR_VAL_PCT","ATTR_DIR","StringPositionTracker","StringModule","context","data","current","target","contentHeight","windowHeight","val","maxScroll","valPct","direction","valStr","el","pctStr","visible","mutations","needsRescan","mutation","node","styleId","style","Debounce","func","delay","timeoutId","args","context","StringFPS","time","fps","now","elapsed","callback","StringVideoAutoplay","StringModule","context","object","videoElement","started","element","err","SequenceState","SequenceProgressVars","_StringSequence","StringModule","context","e","data","current","max","target","dir","els","el","trigger","parsed","object","get","k","seq","attr","key","match","slider","value","settings","global","group","obj","sliders","p","step","sequence","enteringDuration","leavingDuration","active","m","attrKey","seqAttr","v","easing","idx","transitionProgress","direction","duration","instant","toStep","customDuration","fromStep","prevLeaving","enteringGroup","leavingGroup","transition","progress","prev","leaving","enteringProg","leavingProg","state","rawProgress","currentState","currentDir","styleTxn","SequenceProgressVars","t","elapsed","payload","from","to","entering","SequenceState","StringSequence","_StringForm","StringModule","context","globalId","object","element","attributes","existingEvents","evt","form","fieldEntries","fieldValues","field","idx","submitCallback","event","allValid","data","processedRadioKeys","entry","key","rules","needsContext","value","valid","errors","firstInvalidEntry","added","removed","phase","errorBlock","groupBlock","message","span","eventSuffix","el","ruleString","events","preferredIndex","registeredIndex","supportsRealtime","inputEventType","inputHandler","target","beforeInputHandler","inputEvent","start","end","nextVal","index","i","registered","node","elements","nodes","state","owner","entries","stateEntries","values","existing","fallbackIdx","parsed","rule","fieldKey","override","needsOverride","lookupKey","checked","opt","attr","type","StringForm","CenterCache","obj","el","st","id","o","HoverTracker","obj","el","enter","leave","st","StringScroller","StringModule","context","object","isScrollInited","wheelEvent","event","parsePartOf","value","match","remap","value","from1","to1","from2","to2","StringProgressPart","StringModule","context","object","partOfId","partOfData","parsePartOf","progressEvent","progress","sliceProgress","clampedProgress","StringTune","_StringTune","StringFPS","Debounce","DefaultToolsContainer","StringData","EventManager","ModuleManager","ObjectManager","CenterCache","HoverTracker","CursorController","ScrollManager","time","value","container","speed","mode","visible","enabled","type","objectClass","settings","effectiveSettings","module","eventName","callback","id","data","rule","fps","observerContainerMutation","mutationsList","observer","mutation","config","StringInview","htmlFontSize","fontSizeNumber","element","connectTargetId","event","frameDOM","styleTxn","force","scroll","width","height","newScrollHeight","newContainerTopPosition","rect","transformScale","isDesktop","widthChanged","heightChanged","scrollHeightChanged","shouldRebuild","selector","offset","scrollTop","position"]}
|