@fiddle-digital/string-tune 1.1.49 → 1.1.51-alpha.0

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.d.mts CHANGED
@@ -71,7 +71,8 @@ declare class RenderState {
71
71
  }
72
72
 
73
73
  type ScrollDirection = 'vertical' | 'horizontal';
74
- type ScrollMode = 'smooth' | 'disable' | 'default' | (string & {});
74
+ type BuiltInScrollMode = 'smooth' | 'disable' | 'default';
75
+ type ScrollMode = BuiltInScrollMode | string;
75
76
  /**
76
77
  * Describes current scroll-related state for all calculations and modules.
77
78
  */
@@ -455,6 +456,30 @@ declare class StringObject {
455
456
  * Internal key-value store of dynamic object properties (like offsets, progress, etc.).
456
457
  */
457
458
  private properties;
459
+ private eventNameCache;
460
+ private eventNameSuffixCache;
461
+ /**
462
+ * Direct properties for extremely hot, per-frame accessed metrics
463
+ * to avoid going through the Map and incurring overhead.
464
+ */
465
+ progress: number;
466
+ progressRaw: number;
467
+ startPosition: number;
468
+ differencePosition: number;
469
+ transformValue: {
470
+ transform: string;
471
+ } | null;
472
+ eventProgressName: string | null;
473
+ lerp: number;
474
+ glide: number;
475
+ isMagneting: boolean;
476
+ magneticX: number;
477
+ magneticY: number;
478
+ magneticTargetX: number;
479
+ magneticTargetY: number;
480
+ eventLerpName: string | null;
481
+ eventGlideName: string | null;
482
+ eventMagneticName: string | null;
458
483
  /**
459
484
  * Modules currently connected to this object.
460
485
  */
@@ -465,6 +490,12 @@ declare class StringObject {
465
490
  */
466
491
  events: EventManager;
467
492
  constructor(id: string, element: HTMLElement);
493
+ /**
494
+ * Returns a cached event name in one of these forms:
495
+ * - `${prefix}:${id}`
496
+ * - `${prefix}:${id}:${suffix}`
497
+ */
498
+ getScopedEventName(prefix: string, suffix?: string): string;
468
499
  /**
469
500
  * Stores a property value for this object.
470
501
  * @param key - Property name
@@ -505,7 +536,7 @@ declare class StringObject {
505
536
  * Connects a module to this object if not already connected.
506
537
  * @param module - The module to connect
507
538
  */
508
- connect(module: IStringModule): void;
539
+ connect(module: IStringModule): boolean;
509
540
  addMirror(mirror: StringMirrorObject): void;
510
541
  removeMirror(id: string): void;
511
542
  get mirrorObjects(): StringMirrorObject[];
@@ -542,6 +573,32 @@ interface ISettingsChangeData {
542
573
  scrollHeightChanged: boolean;
543
574
  }
544
575
 
576
+ type StyleValue = string | number;
577
+ type StyleVars = Record<string, StyleValue>;
578
+ type StyleProps = Record<string, StyleValue>;
579
+ declare class StyleTxn {
580
+ pendingVars: Map<Element, StyleVars>;
581
+ pendingProps: Map<Element, StyleProps>;
582
+ isOpen: boolean;
583
+ private canUseTypedOM;
584
+ private writeVar;
585
+ begin(): void;
586
+ setVars(el: Element, vars: StyleVars): void;
587
+ setVar(el: Element, key: string, value: StyleValue): void;
588
+ /**
589
+ * Directly sets a CSS custom property (variable) on an element using CSS Typed OM
590
+ * for improved performance. Falls back to string-based assignment if not supported.
591
+ * Note: This writes immediately. Use `begin()`, `setVar()`, `commit()` for batched writes.
592
+ */
593
+ setVarDirect(el: Element, key: string, value: StyleValue): void;
594
+ setProps(el: Element, props: StyleProps): void;
595
+ setProp(el: Element, key: string, value: StyleValue): void;
596
+ run(fn: () => void): void;
597
+ commit(): void;
598
+ cancel(): void;
599
+ }
600
+ declare const styleTxn: StyleTxn;
601
+
545
602
  /**
546
603
  * Base interface for injectable core tools in the String system.
547
604
  * Each tool takes input and returns output (transform, extract, calculate).
@@ -1001,6 +1058,7 @@ interface ISplitOptionItem {
1001
1058
  * Holds arrays of option definitions for each split type.
1002
1059
  */
1003
1060
  interface ISplitOptions {
1061
+ fit?: ISplitOptionItem[];
1004
1062
  line?: ISplitOptionItem[];
1005
1063
  word?: ISplitOptionItem[];
1006
1064
  char?: ISplitOptionItem[];
@@ -1075,7 +1133,8 @@ declare class ValidationTool implements IStringTool<ValidateInput, ValidationRes
1075
1133
  }
1076
1134
 
1077
1135
  /**
1078
- * Interface describing all available tools used inside modules.
1136
+ * Container holding references to all essential tools used within the library.
1137
+ * Dependency injection.
1079
1138
  */
1080
1139
  interface StringToolsContainer {
1081
1140
  /** Tool for reading DOM attributes (including data-*). */
@@ -1136,6 +1195,7 @@ interface StringToolsContainer {
1136
1195
  transformScaleParser: TransformScaleParserTool;
1137
1196
  optionsParser: SplitOptionsParserTool;
1138
1197
  ruleParser: RuleParserTool;
1198
+ styleTxn: typeof styleTxn;
1139
1199
  }
1140
1200
 
1141
1201
  type AttributeType = "string" | "number" | "boolean" | "json" | "dimension" | "breakpoint-dimension" | "tuple" | "easing" | "color" | {
@@ -1186,6 +1246,17 @@ declare class StringModule implements IStringModule {
1186
1246
  * Example: ["offset-top", "offset-bottom"]
1187
1247
  */
1188
1248
  protected attributesToMap: AttributeMapping[];
1249
+ /**
1250
+ * Defines CSS Custom Properties (Houdini) strictly required by this module.
1251
+ * ModuleManager will automatically register these properties on initialization
1252
+ * for Typed Object Model hardware acceleration.
1253
+ */
1254
+ cssProperties: Array<{
1255
+ name: string;
1256
+ syntax: string;
1257
+ initialValue: string;
1258
+ inherits: boolean;
1259
+ }>;
1189
1260
  /**
1190
1261
  * A map that associates string keys with `StringObject` instances.
1191
1262
  * This map is used to manage and track `StringObject` instances on a page.
@@ -1358,6 +1429,26 @@ declare class StringModule implements IStringModule {
1358
1429
  * @param applyFn The function that receives an HTMLElement and performs any update.
1359
1430
  */
1360
1431
  protected applyToElementAndConnects(object: StringObject, applyFn: (el: HTMLElement) => void, copyFn?: (el: HTMLElement, mirror?: StringMirrorObject) => void): void;
1432
+ /**
1433
+ * Directly applies a CSS variable to the object's element without closures.
1434
+ */
1435
+ protected applyVarToElement(object: StringObject, key: string, value: string | number): void;
1436
+ /**
1437
+ * Directly applies a standard CSS property to the object's element without closures.
1438
+ */
1439
+ protected applyPropToElement(object: StringObject, key: string, value: string | number): void;
1440
+ /**
1441
+ * Directly applies a CSS variable to all connected mirrors without closures.
1442
+ */
1443
+ protected applyVarToConnects(object: StringObject, key: string, value: string | number): void;
1444
+ /**
1445
+ * Directly applies a standard CSS property to all connected mirrors without closures.
1446
+ */
1447
+ protected applyPropToConnects(object: StringObject, key: string, value: string | number): void;
1448
+ /**
1449
+ * Returns a cached per-object event name to avoid building strings in hot paths.
1450
+ */
1451
+ protected getObjectEventName(object: StringObject, prefix: string, suffix?: string): string;
1361
1452
  /**
1362
1453
  * Cleans up internal state and detaches the module from the system.
1363
1454
  */
@@ -1438,7 +1529,7 @@ declare class ModuleManager {
1438
1529
  get core(): IStringModule[];
1439
1530
  get ui(): IStringModule[];
1440
1531
  private callAll;
1441
- private callLifecycle;
1532
+ private callLifecycleStrict;
1442
1533
  private rebuildAllModules;
1443
1534
  }
1444
1535
 
@@ -1449,6 +1540,7 @@ declare class ObjectManager {
1449
1540
  private tools;
1450
1541
  private objects;
1451
1542
  private connectQueue;
1543
+ private connectableModulesBuffer;
1452
1544
  private mirrors;
1453
1545
  private mirrorId;
1454
1546
  private globalId;
@@ -1462,6 +1554,7 @@ declare class ObjectManager {
1462
1554
  private inviewIndexDirty;
1463
1555
  private lastInviewScrollPos;
1464
1556
  private intersectionObserverEnabled;
1557
+ private domObserver;
1465
1558
  constructor(data: StringData, modules: ModuleManager, events: EventManager, tools: StringToolsContainer);
1466
1559
  /**
1467
1560
  * Returns the object map (read-only).
@@ -1542,6 +1635,8 @@ declare class ObjectManager {
1542
1635
  private updateInviewWindow;
1543
1636
  private rebuildInviewIndex;
1544
1637
  private upperBound;
1638
+ private splitPipeAndTrim;
1639
+ destroy(): void;
1545
1640
  }
1546
1641
 
1547
1642
  /**
@@ -1637,6 +1732,7 @@ declare class StringCursor extends StringModule {
1637
1732
  private bindGlobalLifecycleListeners;
1638
1733
  private unbindGlobalLifecycleListeners;
1639
1734
  private setMouseCoordinates;
1735
+ private writePortalVars;
1640
1736
  private parseCursorVars;
1641
1737
  private getFrameAdjustedLerp;
1642
1738
  private getObjectDimensions;
@@ -1666,6 +1762,7 @@ declare class StringImpulse extends StringModule {
1666
1762
  */
1667
1763
  private getRotationOriginFromRect;
1668
1764
  onFrame(_: StringData): void;
1765
+ onMutate(): void;
1669
1766
  }
1670
1767
 
1671
1768
  declare class StringMasonry extends StringModule {
@@ -1694,6 +1791,7 @@ declare class StringMagnetic extends StringModule {
1694
1791
  initializeObject(globalId: number, object: StringObject, element: HTMLElement, attributes: Record<string, any>): void;
1695
1792
  onMouseMove(e: MouseEvent): void;
1696
1793
  onFrame(data: StringData): void;
1794
+ onMutate(): void;
1697
1795
  }
1698
1796
 
1699
1797
  declare abstract class CursorReactiveModule extends StringModule {
@@ -1716,11 +1814,13 @@ declare abstract class CursorReactiveModule extends StringModule {
1716
1814
  }
1717
1815
 
1718
1816
  declare class StringSpotlight extends CursorReactiveModule {
1817
+ private readonly stepResult;
1719
1818
  constructor(context: any);
1720
1819
  initializeObject(id: number, obj: StringObject, el: HTMLElement, attrs: Record<string, any>): void;
1721
1820
  onMutate(data: StringData): void;
1722
1821
  protected onCursorScrollUpdate(): void;
1723
1822
  private updateSpotlightState;
1823
+ private writeSpotlightVars;
1724
1824
  }
1725
1825
 
1726
1826
  declare class StringLazy extends StringModule {
@@ -1793,6 +1893,7 @@ declare class StringGlide extends StringModule {
1793
1893
  private negativeVelocityMultiplier;
1794
1894
  private maxDisplacementValue;
1795
1895
  constructor(context: StringContext);
1896
+ initializeObject(globalId: number, object: StringObject, element: HTMLElement, attributes: Record<string, any>): void;
1796
1897
  private setupItem;
1797
1898
  private onUpdateDesktopEvent;
1798
1899
  private onUpdateMobileEvent;
@@ -1804,6 +1905,9 @@ declare class StringGlide extends StringModule {
1804
1905
  onScrollStart(): void;
1805
1906
  onScrollStop(): void;
1806
1907
  onFrame(data: StringData): void;
1908
+ onMutate(): void;
1909
+ private applyPendingGlideStyles;
1910
+ private flushPendingGlideStyles;
1807
1911
  }
1808
1912
 
1809
1913
  /**
@@ -1849,9 +1953,15 @@ declare class StringLerp extends StringModule {
1849
1953
 
1850
1954
  declare class StringProgress extends StringModule {
1851
1955
  protected updateScheduled: boolean;
1956
+ private batchStarts;
1957
+ private batchDiffs;
1958
+ private batchOut;
1852
1959
  constructor(context: StringContext);
1853
1960
  initializeObject(globalId: number, object: StringObject, element: HTMLElement, attributes: Record<string, any>): void;
1961
+ private sanitizeRawProgress;
1962
+ private applyRawProgress;
1854
1963
  private recomputeProgress;
1964
+ private ensureBatchCapacity;
1855
1965
  calculatePositions(object: StringObject, windowSize: number): void;
1856
1966
  onScroll(data: StringData): void;
1857
1967
  onObjectConnected(object: StringObject): void;
@@ -1896,6 +2006,7 @@ declare class StringScrollbar extends StringModule {
1896
2006
  private scrollbarState;
1897
2007
  private scrollbarStateHorizontal;
1898
2008
  private scrollbarStateVertical;
2009
+ private requestScrollTo;
1899
2010
  constructor(context: StringContext);
1900
2011
  destructor(): void;
1901
2012
  onInit(): void;
@@ -1924,6 +2035,38 @@ declare class StringSplit extends StringModule {
1924
2035
  result: DocumentFragment;
1925
2036
  extraProps: Map<string, string>;
1926
2037
  };
2038
+ private getFitContext;
2039
+ /**
2040
+ * Computes target font sizes to fill the container width and stores them on each line.
2041
+ *
2042
+ * With a line-level split (`line`, `wordLine`, `charLine`): sets `fitFontSize` on each
2043
+ * `LayoutLine` so that BuildDOMTree can expose `--fit-font-size` per `-s-line` span.
2044
+ * Each line may receive a different value, allowing text to fill 100% of the container
2045
+ * width independently per line.
2046
+ *
2047
+ * Without a line-level split: finds the widest line and returns a single
2048
+ * `--fit-font-size` in the extraProps map, to be applied to the container element.
2049
+ *
2050
+ * Formula: targetFontSize = currentFontSize * (contentWidth / lineWidth)
2051
+ */
2052
+ private applyFit;
2053
+ private refineFitFontSize;
2054
+ private solveRenderedFitFontSize;
2055
+ private measureScopeAtFontSize;
2056
+ private measureCharScopeWidth;
2057
+ private measureContentWidth;
2058
+ /**
2059
+ * Computes the target font size to fill `contentWidth`.
2060
+ *
2061
+ * Inter-word `\u00a0` nodes in the DOM are NOT wrapped in `-s-char` spans, so they
2062
+ * stay at the original font size and do not scale. The formula accounts for this by
2063
+ * subtracting total space width (fitWidth - browserWordWidthSum) from both sides:
2064
+ *
2065
+ * targetFontSize = currentFontSize * (contentWidth - spacesWidth) / (lineWidth - spacesWidth)
2066
+ *
2067
+ * For single-word lines spacesWidth = 0 and the formula reduces to the simple ratio.
2068
+ */
2069
+ private computeFitFontSize;
1927
2070
  /**
1928
2071
  * Computes a numeric value based on the provided split option, index, and total count.
1929
2072
  *
@@ -2309,6 +2452,95 @@ declare class StringScroller extends StringModule {
2309
2452
  onObjectDisconnected(object: StringObject): void;
2310
2453
  }
2311
2454
 
2455
+ /**
2456
+ * Module that provides smooth scrolling behavior for isolated containers.
2457
+ * Allows nested elements to have independent smooth scroll physics similar to the main window.
2458
+ *
2459
+ * Usage:
2460
+ * Add `string="scroll-container"` to any block element.
2461
+ * Optional: `string-lerp="0.1"` to controls the smoothing factor.
2462
+ */
2463
+ declare class StringScrollContainer extends StringModule {
2464
+ /**
2465
+ * WeakMap storing the state for each managed HTMLElement.
2466
+ */
2467
+ private states;
2468
+ /**
2469
+ * Initializes the StringScrollContainer module.
2470
+ * Registers the `lerp` attribute configuration.
2471
+ *
2472
+ * @param context The shared StringTune context.
2473
+ */
2474
+ constructor(context: StringContext);
2475
+ /**
2476
+ * Called when a new object with `string="scroll-container"` is initialized.
2477
+ * Sets up initial state, event listeners, and default styles.
2478
+ *
2479
+ * @param object The StringObject instance being connected.
2480
+ */
2481
+ onObjectConnected(object: StringObject): void;
2482
+ /**
2483
+ * Called when an object is removed from the DOM or disconnected.
2484
+ * Cleans up the state associated with the element.
2485
+ *
2486
+ * @param object The StringObject instance being disconnected.
2487
+ */
2488
+ onObjectDisconnected(object: StringObject): void;
2489
+ /**
2490
+ * Main animation loop for the module.
2491
+ * Updates the scroll position of active containers based on their target state.
2492
+ *
2493
+ * @param data Global frame data including time deltas.
2494
+ */
2495
+ onFrame(data: StringData): void;
2496
+ /**
2497
+ * Called when the window or layout is resized.
2498
+ * Recalculates scroll boundaries for all managed containers.
2499
+ */
2500
+ onResize(): void;
2501
+ /**
2502
+ * Recalculates the maximum scrollable distance for a container.
2503
+ *
2504
+ * @param el The scroll container element.
2505
+ * @param state The state object associated with the element.
2506
+ */
2507
+ private measure;
2508
+ /**
2509
+ * Handles the mouse wheel event to apply custom scroll physics.
2510
+ * Intercepts the event to prevent native scrolling and updates the target position.
2511
+ * Allows event propagation if scrolling past the boundaries (scroll chaining).
2512
+ *
2513
+ * @param e The WheelEvent triggered by the user.
2514
+ * @param el The target scroll container element.
2515
+ * @param state The state object associated with the element.
2516
+ */
2517
+ private handleWheel;
2518
+ /**
2519
+ * Placeholder for global wheel handler if needed by generic StringModule interface.
2520
+ * Specific handling is done via local event listeners in `handleWheel`.
2521
+ *
2522
+ * @param e Global WheelEvent.
2523
+ */
2524
+ onWheel(e: WheelEvent): void;
2525
+ /**
2526
+ * Handles native scroll events (dragbars, keyboard, touch).
2527
+ * Syncs the internal state with the native scroll position if the custom animation is not active.
2528
+ *
2529
+ * @param e The Scroll event.
2530
+ * @param el The target scroll container element.
2531
+ * @param state The state object associated with the element.
2532
+ */
2533
+ private onNativeScroll;
2534
+ /**
2535
+ * Updates the element's scrollTop property by interpolating towards the target.
2536
+ * Stops the animation if the difference is negligible.
2537
+ *
2538
+ * @param el The scroll container element.
2539
+ * @param state The state object associated with the element.
2540
+ */
2541
+ private updateScroll;
2542
+ }
2543
+
2312
2544
  declare class StringProgressPart extends StringModule {
2313
2545
  constructor(context: StringContext);
2314
2546
  onObjectConnected(object: StringObject): void;
@@ -2322,26 +2554,11 @@ declare class FrameDOM {
2322
2554
  private scheduled;
2323
2555
  measure(fn: Job): void;
2324
2556
  mutate(fn: Job): void;
2325
- private schedule;
2557
+ schedule(): void;
2558
+ flush(): void;
2326
2559
  }
2327
2560
  declare const frameDOM: FrameDOM;
2328
2561
 
2329
- type StyleValue = string | number;
2330
- type StyleVars = Record<string, StyleValue>;
2331
- type StyleProps = Record<string, StyleValue>;
2332
- declare class StyleTxn {
2333
- private pendingVars;
2334
- private pendingProps;
2335
- private isOpen;
2336
- begin(): void;
2337
- setVars(el: Element, vars: StyleVars): void;
2338
- setProps(el: Element, props: StyleProps): void;
2339
- run(fn: () => void): void;
2340
- commit(): void;
2341
- cancel(): void;
2342
- }
2343
- declare const styleTxn: StyleTxn;
2344
-
2345
2562
  declare class StringRandom extends StringModule {
2346
2563
  constructor(context: StringContext);
2347
2564
  onObjectConnected(object: StringObject): void;
@@ -2373,6 +2590,10 @@ declare class ScrollController {
2373
2590
  protected isBottomScrollDirection: boolean | null;
2374
2591
  protected isLastBottomScrollDirection: boolean;
2375
2592
  protected scrollTriggerRules: Array<ScrollMarkRule>;
2593
+ /** Tracks whether this controller is currently active */
2594
+ protected isActive: boolean;
2595
+ /** Last direction applied to DOM classes (for global-class toggles) */
2596
+ protected lastAppliedDirection: boolean | null;
2376
2597
  /**
2377
2598
  * Sets scroll direction and updates internal scroll logic.
2378
2599
  * @param scrollDirection Either 'vertical' or 'horizontal'.
@@ -2422,10 +2643,193 @@ declare class ScrollController {
2422
2643
  onScroll(e: any): void;
2423
2644
  disableScrollEvents(): void;
2424
2645
  enableScrollEvents(): void;
2646
+ /**
2647
+ * Called when this controller becomes the active scroll engine.
2648
+ * Ensures event bindings are attached only once.
2649
+ */
2650
+ activate(): void;
2651
+ /**
2652
+ * Called when this controller is deactivated.
2653
+ * Ensures event bindings are detached only once.
2654
+ */
2655
+ deactivate(): void;
2656
+ /**
2657
+ * Allows controllers to clean up resources on global destroy.
2658
+ */
2659
+ destroy(): void;
2660
+ /**
2661
+ * Updates scroll direction state, emits events, and toggles global classes.
2662
+ * Intended for reuse by custom scroll adapters.
2663
+ */
2664
+ protected updateScrollDirection(newDirection: boolean): void;
2665
+ protected clearScrollingClasses(): void;
2425
2666
  protected triggerScrollRules(): void;
2426
2667
  addScrollMark(rule: ScrollMarkRule): void;
2427
2668
  removeScrollMark(id: string): void;
2428
- scrollTo(position: number): void;
2669
+ scrollTo(position: number, immediate?: boolean): void;
2670
+ }
2671
+
2672
+ /**
2673
+ * StringGrid — developer utility module for layout grid overlays.
2674
+ *
2675
+ * Usage:
2676
+ * <div string="grid">...</div>
2677
+ *
2678
+ * No configuration attributes needed. All configuration happens
2679
+ * through the interactive HUD panel (hover top-right corner).
2680
+ *
2681
+ * Supports multiple grid types via the adapter pattern:
2682
+ * - Columns, Rows, Center
2683
+ * - Rule of Thirds, Phi Grid, Golden Rectangle, Harmonic Armature
2684
+ * - Extensible via `st.use(StringGrid, { adapters: [MyAdapter] })`
2685
+ */
2686
+ declare class StringGrid extends StringModule {
2687
+ private gridManager;
2688
+ private overlays;
2689
+ private huds;
2690
+ private elementMap;
2691
+ constructor(context: StringContext);
2692
+ onInit(): void;
2693
+ onObjectConnected(object: StringObject): void;
2694
+ onObjectDisconnected(object: StringObject): void;
2695
+ onResize(): void;
2696
+ destroy(): void;
2697
+ private handleAdd;
2698
+ private handleRemove;
2699
+ private handleToggle;
2700
+ private handleSettingChange;
2701
+ private renderElement;
2702
+ private refreshHUD;
2703
+ private destroyElement;
2704
+ private registerBuiltInAdapters;
2705
+ private registerExternalAdapters;
2706
+ private injectStyles;
2707
+ }
2708
+
2709
+ /**
2710
+ * Discriminated union of all UI field descriptors.
2711
+ * Each adapter returns an array of these to describe its settings panel.
2712
+ */
2713
+ type UIFieldDescriptor = UIFieldNumber | UIFieldRange | UIFieldColor | UIFieldSelect | UIFieldToggle | UIFieldDivider;
2714
+ interface UIFieldNumber {
2715
+ readonly type: "number";
2716
+ readonly key: string;
2717
+ readonly label: string;
2718
+ readonly default: number;
2719
+ readonly min?: number;
2720
+ readonly max?: number;
2721
+ readonly step?: number;
2722
+ }
2723
+ interface UIFieldRange {
2724
+ readonly type: "range";
2725
+ readonly key: string;
2726
+ readonly label: string;
2727
+ readonly default: number;
2728
+ readonly min: number;
2729
+ readonly max: number;
2730
+ readonly step?: number;
2731
+ /** When provided, a compact unit dropdown is shown next to the value input. */
2732
+ readonly units?: ReadonlyArray<{
2733
+ value: string;
2734
+ label: string;
2735
+ }>;
2736
+ /** Default unit value (used when no persisted unit exists). */
2737
+ readonly defaultUnit?: string;
2738
+ }
2739
+ interface UIFieldColor {
2740
+ readonly type: "color";
2741
+ readonly key: string;
2742
+ readonly label: string;
2743
+ readonly default: string;
2744
+ }
2745
+ interface UIFieldSelect {
2746
+ readonly type: "select";
2747
+ readonly key: string;
2748
+ readonly label: string;
2749
+ readonly default: string;
2750
+ readonly options: ReadonlyArray<{
2751
+ value: string;
2752
+ label: string;
2753
+ }>;
2754
+ }
2755
+ interface UIFieldToggle {
2756
+ readonly type: "toggle";
2757
+ readonly key: string;
2758
+ readonly label: string;
2759
+ readonly default: boolean;
2760
+ }
2761
+ interface UIFieldDivider {
2762
+ readonly type: "divider";
2763
+ readonly label?: string;
2764
+ }
2765
+
2766
+ /**
2767
+ * Abstract base class for all grid adapters.
2768
+ *
2769
+ * Each adapter is a self-contained unit that:
2770
+ * - Declares its own default settings
2771
+ * - Describes its UI schema for the settings panel
2772
+ * - Renders itself into an SVG overlay
2773
+ *
2774
+ * To create a new grid type, extend this class and implement
2775
+ * all abstract members. The system handles everything else.
2776
+ */
2777
+ declare abstract class GridAdapter {
2778
+ /** Unique type key used for serialization and registry lookup */
2779
+ abstract readonly type: string;
2780
+ /** Human-readable label shown in the HUD menu */
2781
+ abstract readonly label: string;
2782
+ /** SVG icon string (inline SVG markup) */
2783
+ abstract readonly icon: string;
2784
+ /**
2785
+ * Returns the default settings for this adapter.
2786
+ * These are used when a new grid instance is created.
2787
+ */
2788
+ abstract getDefaults(): Record<string, any>;
2789
+ /**
2790
+ * Returns the UI field descriptors that GridUIBuilder
2791
+ * uses to construct the settings panel.
2792
+ */
2793
+ abstract getUISchema(): UIFieldDescriptor[];
2794
+ /**
2795
+ * Renders the grid into the given SVG element.
2796
+ *
2797
+ * @param svg The SVG overlay element (same size as target)
2798
+ * @param width Element width in px
2799
+ * @param height Element height in px
2800
+ * @param settings Current settings for this instance
2801
+ */
2802
+ abstract render(svg: SVGSVGElement, width: number, height: number, settings: Record<string, any>): void;
2803
+ /**
2804
+ * Removes all elements previously rendered by this adapter.
2805
+ * Default implementation clears the adapter's group element.
2806
+ */
2807
+ clear(svg: SVGSVGElement, instanceId: string): void;
2808
+ /**
2809
+ * Creates or retrieves a <g> group element scoped to a grid instance.
2810
+ * All rendering should happen inside this group for clean cleanup.
2811
+ */
2812
+ protected getGroup(svg: SVGSVGElement, instanceId: string): SVGGElement;
2813
+ /**
2814
+ * Helper: creates an SVG line element.
2815
+ */
2816
+ protected createLine(x1: number, y1: number, x2: number, y2: number, color: string, opacity: number, strokeWidth?: number): SVGLineElement;
2817
+ /**
2818
+ * Helper: creates an SVG rect element.
2819
+ */
2820
+ protected createRect(x: number, y: number, width: number, height: number, fill: string, opacity: number): SVGRectElement;
2821
+ /**
2822
+ * Converts a value from the given unit to pixels.
2823
+ *
2824
+ * @param value Raw numeric value
2825
+ * @param unit "px" | "%" | "vw" | "vh"
2826
+ * @param dimension Reference dimension (element width or height) for "%" mode
2827
+ */
2828
+ protected resolveUnit(value: number, unit: string, dimension: number): number;
2829
+ /**
2830
+ * Helper: creates an SVG path element.
2831
+ */
2832
+ protected createPath(d: string, stroke: string, opacity: number, strokeWidth?: number, fill?: string): SVGPathElement;
2429
2833
  }
2430
2834
 
2431
2835
  interface ModuleBatchContext {
@@ -2476,10 +2880,14 @@ declare class StringTune {
2476
2880
  private onMouseMoveBind;
2477
2881
  /** Bound scroll to handler */
2478
2882
  private onScrollToBind;
2883
+ private onDOMChangedBind;
2479
2884
  private onContainerTransitionEndBind;
2480
2885
  private onResizeObserverBind;
2481
2886
  private pendingScroll;
2482
2887
  private lastScrollEmitted;
2888
+ private observerContainerMutation;
2889
+ private pendingResizeRaf;
2890
+ private pendingResizeForce;
2483
2891
  /** Singleton instance of StringTune */
2484
2892
  private static i;
2485
2893
  /** Root scrollable element (typically <body>) */
@@ -2598,7 +3006,7 @@ declare class StringTune {
2598
3006
  *
2599
3007
  * Example:
2600
3008
  * ```ts
2601
- * stringTune.registerScrollMode("lenis", (context) => new LenisAdapter(context));
3009
+ * stringTune.registerScrollMode("custom", (context) => new CustomAdapter(context));
2602
3010
  * ```
2603
3011
  */
2604
3012
  registerScrollMode(name: string, factory: ((context: StringContext) => ScrollController) | (new (context: StringContext) => ScrollController)): void;
@@ -2664,6 +3072,9 @@ declare class StringTune {
2664
3072
  setupSettings(settings: StringSettings): void;
2665
3073
  private onResizeObserverEvent;
2666
3074
  private onContainerTransitionEnd;
3075
+ private onDOMChanged;
3076
+ private observeContainerMutations;
3077
+ private queueResize;
2667
3078
  /**
2668
3079
  * Handles mouse move event and dispatches it to cursor and modules.
2669
3080
  * @param e Native mouse move event.
@@ -2713,8 +3124,11 @@ declare class StringTune {
2713
3124
  */
2714
3125
  onResize(force?: boolean): void;
2715
3126
  invalidateCenter(id: string): void;
2716
- scrollTo(position: number): void;
3127
+ scrollTo(value: number | {
3128
+ position: number;
3129
+ immediate?: boolean;
3130
+ }): void;
2717
3131
  destroy(): void;
2718
3132
  }
2719
3133
 
2720
- export { CursorReactiveModule, DOMBatcher, ScrollController, type ScrollMarkRule as ScrollTriggerRule, StringAnchor, type StringContext, StringCursor, StringData, StringDelayLerpTracker, StringFPSTracker, StringForm, StringGlide, StringImpulse, StringLazy, StringLerp, StringLerpTracker, StringLoading, StringMagnetic, StringMasonry, StringModule, StringObject, StringParallax, StringPositionTracker, StringProgress, StringProgressPart, StringRandom, StringResponsive, StringScrollbar, StringScroller, StringSequence, StringSplit, StringSpotlight, StringTune, StringVideoAutoplay, StringTune as default, frameDOM, styleTxn };
3134
+ export { CursorReactiveModule, DOMBatcher, GridAdapter, ScrollController, type ScrollMarkRule as ScrollTriggerRule, StringAnchor, type StringContext, StringCursor, StringData, StringDelayLerpTracker, StringFPSTracker, StringForm, StringGlide, StringGrid, StringImpulse, StringLazy, StringLerp, StringLerpTracker, StringLoading, StringMagnetic, StringMasonry, StringModule, StringObject, StringParallax, StringPositionTracker, StringProgress, StringProgressPart, StringRandom, StringResponsive, StringScrollContainer, StringScrollbar, StringScroller, StringSequence, StringSplit, StringSpotlight, StringTune, StringVideoAutoplay, StringTune as default, frameDOM, styleTxn };