@fiddle-digital/string-tune 1.1.50 → 1.1.51

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
@@ -1058,6 +1058,7 @@ interface ISplitOptionItem {
1058
1058
  * Holds arrays of option definitions for each split type.
1059
1059
  */
1060
1060
  interface ISplitOptions {
1061
+ fit?: boolean;
1061
1062
  line?: ISplitOptionItem[];
1062
1063
  word?: ISplitOptionItem[];
1063
1064
  char?: ISplitOptionItem[];
@@ -2034,6 +2035,38 @@ declare class StringSplit extends StringModule {
2034
2035
  result: DocumentFragment;
2035
2036
  extraProps: Map<string, string>;
2036
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;
2037
2070
  /**
2038
2071
  * Computes a numeric value based on the provided split option, index, and total count.
2039
2072
  *
@@ -2636,6 +2669,132 @@ declare class ScrollController {
2636
2669
  scrollTo(position: number, immediate?: boolean): void;
2637
2670
  }
2638
2671
 
2672
+ /**
2673
+ * Discriminated union of all UI field descriptors.
2674
+ * Each adapter returns an array of these to describe its settings panel.
2675
+ */
2676
+ type UIFieldDescriptor = UIFieldNumber | UIFieldRange | UIFieldColor | UIFieldSelect | UIFieldToggle | UIFieldDivider;
2677
+ interface UIFieldNumber {
2678
+ readonly type: "number";
2679
+ readonly key: string;
2680
+ readonly label: string;
2681
+ readonly default: number;
2682
+ readonly min?: number;
2683
+ readonly max?: number;
2684
+ readonly step?: number;
2685
+ }
2686
+ interface UIFieldRange {
2687
+ readonly type: "range";
2688
+ readonly key: string;
2689
+ readonly label: string;
2690
+ readonly default: number;
2691
+ readonly min: number;
2692
+ readonly max: number;
2693
+ readonly step?: number;
2694
+ /** When provided, a compact unit dropdown is shown next to the value input. */
2695
+ readonly units?: ReadonlyArray<{
2696
+ value: string;
2697
+ label: string;
2698
+ }>;
2699
+ /** Default unit value (used when no persisted unit exists). */
2700
+ readonly defaultUnit?: string;
2701
+ }
2702
+ interface UIFieldColor {
2703
+ readonly type: "color";
2704
+ readonly key: string;
2705
+ readonly label: string;
2706
+ readonly default: string;
2707
+ }
2708
+ interface UIFieldSelect {
2709
+ readonly type: "select";
2710
+ readonly key: string;
2711
+ readonly label: string;
2712
+ readonly default: string;
2713
+ readonly options: ReadonlyArray<{
2714
+ value: string;
2715
+ label: string;
2716
+ }>;
2717
+ }
2718
+ interface UIFieldToggle {
2719
+ readonly type: "toggle";
2720
+ readonly key: string;
2721
+ readonly label: string;
2722
+ readonly default: boolean;
2723
+ }
2724
+ interface UIFieldDivider {
2725
+ readonly type: "divider";
2726
+ readonly label?: string;
2727
+ }
2728
+
2729
+ /**
2730
+ * Abstract base class for all grid adapters.
2731
+ *
2732
+ * Each adapter is a self-contained unit that:
2733
+ * - Declares its own default settings
2734
+ * - Describes its UI schema for the settings panel
2735
+ * - Renders itself into an SVG overlay
2736
+ *
2737
+ * To create a new grid type, extend this class and implement
2738
+ * all abstract members. The system handles everything else.
2739
+ */
2740
+ declare abstract class GridAdapter {
2741
+ /** Unique type key used for serialization and registry lookup */
2742
+ abstract readonly type: string;
2743
+ /** Human-readable label shown in the HUD menu */
2744
+ abstract readonly label: string;
2745
+ /** SVG icon string (inline SVG markup) */
2746
+ abstract readonly icon: string;
2747
+ /**
2748
+ * Returns the default settings for this adapter.
2749
+ * These are used when a new grid instance is created.
2750
+ */
2751
+ abstract getDefaults(): Record<string, any>;
2752
+ /**
2753
+ * Returns the UI field descriptors that GridUIBuilder
2754
+ * uses to construct the settings panel.
2755
+ */
2756
+ abstract getUISchema(): UIFieldDescriptor[];
2757
+ /**
2758
+ * Renders the grid into the given SVG element.
2759
+ *
2760
+ * @param svg The SVG overlay element (same size as target)
2761
+ * @param width Element width in px
2762
+ * @param height Element height in px
2763
+ * @param settings Current settings for this instance
2764
+ */
2765
+ abstract render(svg: SVGSVGElement, width: number, height: number, settings: Record<string, any>): void;
2766
+ /**
2767
+ * Removes all elements previously rendered by this adapter.
2768
+ * Default implementation clears the adapter's group element.
2769
+ */
2770
+ clear(svg: SVGSVGElement, instanceId: string): void;
2771
+ /**
2772
+ * Creates or retrieves a <g> group element scoped to a grid instance.
2773
+ * All rendering should happen inside this group for clean cleanup.
2774
+ */
2775
+ protected getGroup(svg: SVGSVGElement, instanceId: string): SVGGElement;
2776
+ /**
2777
+ * Helper: creates an SVG line element.
2778
+ */
2779
+ protected createLine(x1: number, y1: number, x2: number, y2: number, color: string, opacity: number, strokeWidth?: number): SVGLineElement;
2780
+ /**
2781
+ * Helper: creates an SVG rect element.
2782
+ */
2783
+ protected createRect(x: number, y: number, width: number, height: number, fill: string, opacity: number): SVGRectElement;
2784
+ /**
2785
+ * Converts a value from the given unit to pixels.
2786
+ *
2787
+ * @param value Raw numeric value
2788
+ * @param unit "px" | "%" | "vw" | "vh"
2789
+ * @param dimension Reference dimension (element width or height) for "%" mode
2790
+ */
2791
+ protected resolveUnit(value: number, unit: string, dimension: number): number;
2792
+ /**
2793
+ * Helper: creates an SVG path element.
2794
+ */
2795
+ protected createPath(d: string, stroke: string, opacity: number, strokeWidth?: number, fill?: string): SVGPathElement;
2796
+ }
2797
+
2639
2798
  interface ModuleBatchContext {
2640
2799
  module: StringModule;
2641
2800
  object: StringObject;
@@ -2935,4 +3094,4 @@ declare class StringTune {
2935
3094
  destroy(): void;
2936
3095
  }
2937
3096
 
2938
- 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, StringScrollContainer, StringScrollbar, StringScroller, StringSequence, StringSplit, StringSpotlight, StringTune, StringVideoAutoplay, StringTune as default, frameDOM, styleTxn };
3097
+ export { CursorReactiveModule, DOMBatcher, GridAdapter, 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, StringScrollContainer, StringScrollbar, StringScroller, StringSequence, StringSplit, StringSpotlight, StringTune, StringVideoAutoplay, StringTune as default, frameDOM, styleTxn };
package/dist/index.d.ts CHANGED
@@ -1058,6 +1058,7 @@ interface ISplitOptionItem {
1058
1058
  * Holds arrays of option definitions for each split type.
1059
1059
  */
1060
1060
  interface ISplitOptions {
1061
+ fit?: boolean;
1061
1062
  line?: ISplitOptionItem[];
1062
1063
  word?: ISplitOptionItem[];
1063
1064
  char?: ISplitOptionItem[];
@@ -2034,6 +2035,38 @@ declare class StringSplit extends StringModule {
2034
2035
  result: DocumentFragment;
2035
2036
  extraProps: Map<string, string>;
2036
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;
2037
2070
  /**
2038
2071
  * Computes a numeric value based on the provided split option, index, and total count.
2039
2072
  *
@@ -2636,6 +2669,132 @@ declare class ScrollController {
2636
2669
  scrollTo(position: number, immediate?: boolean): void;
2637
2670
  }
2638
2671
 
2672
+ /**
2673
+ * Discriminated union of all UI field descriptors.
2674
+ * Each adapter returns an array of these to describe its settings panel.
2675
+ */
2676
+ type UIFieldDescriptor = UIFieldNumber | UIFieldRange | UIFieldColor | UIFieldSelect | UIFieldToggle | UIFieldDivider;
2677
+ interface UIFieldNumber {
2678
+ readonly type: "number";
2679
+ readonly key: string;
2680
+ readonly label: string;
2681
+ readonly default: number;
2682
+ readonly min?: number;
2683
+ readonly max?: number;
2684
+ readonly step?: number;
2685
+ }
2686
+ interface UIFieldRange {
2687
+ readonly type: "range";
2688
+ readonly key: string;
2689
+ readonly label: string;
2690
+ readonly default: number;
2691
+ readonly min: number;
2692
+ readonly max: number;
2693
+ readonly step?: number;
2694
+ /** When provided, a compact unit dropdown is shown next to the value input. */
2695
+ readonly units?: ReadonlyArray<{
2696
+ value: string;
2697
+ label: string;
2698
+ }>;
2699
+ /** Default unit value (used when no persisted unit exists). */
2700
+ readonly defaultUnit?: string;
2701
+ }
2702
+ interface UIFieldColor {
2703
+ readonly type: "color";
2704
+ readonly key: string;
2705
+ readonly label: string;
2706
+ readonly default: string;
2707
+ }
2708
+ interface UIFieldSelect {
2709
+ readonly type: "select";
2710
+ readonly key: string;
2711
+ readonly label: string;
2712
+ readonly default: string;
2713
+ readonly options: ReadonlyArray<{
2714
+ value: string;
2715
+ label: string;
2716
+ }>;
2717
+ }
2718
+ interface UIFieldToggle {
2719
+ readonly type: "toggle";
2720
+ readonly key: string;
2721
+ readonly label: string;
2722
+ readonly default: boolean;
2723
+ }
2724
+ interface UIFieldDivider {
2725
+ readonly type: "divider";
2726
+ readonly label?: string;
2727
+ }
2728
+
2729
+ /**
2730
+ * Abstract base class for all grid adapters.
2731
+ *
2732
+ * Each adapter is a self-contained unit that:
2733
+ * - Declares its own default settings
2734
+ * - Describes its UI schema for the settings panel
2735
+ * - Renders itself into an SVG overlay
2736
+ *
2737
+ * To create a new grid type, extend this class and implement
2738
+ * all abstract members. The system handles everything else.
2739
+ */
2740
+ declare abstract class GridAdapter {
2741
+ /** Unique type key used for serialization and registry lookup */
2742
+ abstract readonly type: string;
2743
+ /** Human-readable label shown in the HUD menu */
2744
+ abstract readonly label: string;
2745
+ /** SVG icon string (inline SVG markup) */
2746
+ abstract readonly icon: string;
2747
+ /**
2748
+ * Returns the default settings for this adapter.
2749
+ * These are used when a new grid instance is created.
2750
+ */
2751
+ abstract getDefaults(): Record<string, any>;
2752
+ /**
2753
+ * Returns the UI field descriptors that GridUIBuilder
2754
+ * uses to construct the settings panel.
2755
+ */
2756
+ abstract getUISchema(): UIFieldDescriptor[];
2757
+ /**
2758
+ * Renders the grid into the given SVG element.
2759
+ *
2760
+ * @param svg The SVG overlay element (same size as target)
2761
+ * @param width Element width in px
2762
+ * @param height Element height in px
2763
+ * @param settings Current settings for this instance
2764
+ */
2765
+ abstract render(svg: SVGSVGElement, width: number, height: number, settings: Record<string, any>): void;
2766
+ /**
2767
+ * Removes all elements previously rendered by this adapter.
2768
+ * Default implementation clears the adapter's group element.
2769
+ */
2770
+ clear(svg: SVGSVGElement, instanceId: string): void;
2771
+ /**
2772
+ * Creates or retrieves a <g> group element scoped to a grid instance.
2773
+ * All rendering should happen inside this group for clean cleanup.
2774
+ */
2775
+ protected getGroup(svg: SVGSVGElement, instanceId: string): SVGGElement;
2776
+ /**
2777
+ * Helper: creates an SVG line element.
2778
+ */
2779
+ protected createLine(x1: number, y1: number, x2: number, y2: number, color: string, opacity: number, strokeWidth?: number): SVGLineElement;
2780
+ /**
2781
+ * Helper: creates an SVG rect element.
2782
+ */
2783
+ protected createRect(x: number, y: number, width: number, height: number, fill: string, opacity: number): SVGRectElement;
2784
+ /**
2785
+ * Converts a value from the given unit to pixels.
2786
+ *
2787
+ * @param value Raw numeric value
2788
+ * @param unit "px" | "%" | "vw" | "vh"
2789
+ * @param dimension Reference dimension (element width or height) for "%" mode
2790
+ */
2791
+ protected resolveUnit(value: number, unit: string, dimension: number): number;
2792
+ /**
2793
+ * Helper: creates an SVG path element.
2794
+ */
2795
+ protected createPath(d: string, stroke: string, opacity: number, strokeWidth?: number, fill?: string): SVGPathElement;
2796
+ }
2797
+
2639
2798
  interface ModuleBatchContext {
2640
2799
  module: StringModule;
2641
2800
  object: StringObject;
@@ -2935,4 +3094,4 @@ declare class StringTune {
2935
3094
  destroy(): void;
2936
3095
  }
2937
3096
 
2938
- 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, StringScrollContainer, StringScrollbar, StringScroller, StringSequence, StringSplit, StringSpotlight, StringTune, StringVideoAutoplay, StringTune as default, frameDOM, styleTxn };
3097
+ export { CursorReactiveModule, DOMBatcher, GridAdapter, 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, StringScrollContainer, StringScrollbar, StringScroller, StringSequence, StringSplit, StringSpotlight, StringTune, StringVideoAutoplay, StringTune as default, frameDOM, styleTxn };