@wick-charts/vue 0.3.6 → 0.4.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.ts CHANGED
@@ -151,6 +151,28 @@ declare type __VLS_Props_3 = {
151
151
  intervals: number;
152
152
  };
153
153
  };
154
+ /**
155
+ * Viewport-level streaming behavior. Captured at mount only — changing
156
+ * this prop after the chart is created is ignored.
157
+ */
158
+ viewport?: {
159
+ /**
160
+ * Width of the visible window in data bars, set on the first data load
161
+ * to `maxVisibleBars * dataInterval`. While the dataset is smaller than
162
+ * this width, streaming ticks render into the empty right-side gap and
163
+ * the viewport stays put; once the data reaches the right edge, the
164
+ * viewport pans forward to keep the latest bar pinned (tail-scroll).
165
+ * Default: 200.
166
+ */
167
+ maxVisibleBars?: number;
168
+ /**
169
+ * Initial visible range applied before the first paint with data. Same
170
+ * shape as the imperative `chart.setVisibleRange` — pass a bar count
171
+ * (e.g. `35`), an explicit `{from, to}` window, or `{from, bars}` for
172
+ * a warm-up pair. Captured at mount.
173
+ */
174
+ initialRange?: VisibleRangeSpec;
175
+ };
154
176
  /** Show the chart background gradient. Defaults to true. */
155
177
  gradient?: boolean;
156
178
  /** Enable zoom, pan, and crosshair interactions. Defaults to true. */
@@ -166,16 +188,15 @@ declare type __VLS_Props_3 = {
166
188
  */
167
189
  headerLayout?: 'overlay' | 'inline';
168
190
  /**
169
- * Chart-level animation configuration. See `AnimationsConfig` for the full shape.
191
+ * Animation control. `true` / omitted uses built-in defaults; `false`
192
+ * disables every category. Per-series options on `<LineSeries>` /
193
+ * `<CandlestickSeries>` / `<BarSeries>` override these chart-level
194
+ * defaults unless the category here is explicitly `false`.
170
195
  *
171
- * Two layers — chart-level (this prop) sets defaults for every series; per-series
172
- * options on `<LineSeries>`/`<CandlestickSeries>`/`<BarSeries>` override that
173
- * default for that one series.
174
- *
175
- * Shorthands: `true` / omitted — built-in defaults; `false` — disables every
176
- * animation category; `{ points: false }` / `{ viewport: false }` disables a
177
- * category. Updating this prop calls `chart.setAnimations(...)` so the new
178
- * durations take effect on the next animation / render.
196
+ * **Init-only by reference identity.** A new `animations` reference
197
+ * recreates the underlying `ChartInstance`. Hoist the object outside
198
+ * the render scope — an inline literal tears the chart down on every
199
+ * re-render.
179
200
  */
180
201
  animations?: boolean | AnimationsConfig;
181
202
  /**
@@ -465,114 +486,230 @@ declare type __VLS_WithTemplateSlots_8<T, S> = T & {
465
486
  export declare const andromeda: ThemePreset;
466
487
 
467
488
  /**
468
- * Chart-level animation configuration. Two independent domains so per-series
469
- * defaults can't bleed into viewport-interaction timings.
470
- *
471
- * **Two layers — chart-level vs per-series.** The same data-animation knobs
472
- * live on both layers; remember which is which:
489
+ * Animation behavior knobs grouped by surface:
473
490
  *
474
- * | Field | Chart-level (here) | Per-series option |
475
- * | ----- | ------------------ | ----------------- |
476
- * | Entry duration | {@link AnimationsConfig.points}`.enterMs` | `<XSeries options={{ entryMs }}>` (canonical name; `enterMs` is a `@deprecated` alias) |
477
- * | Live smoothing | `points.smoothMs` | `options={{ smoothMs }}` |
478
- * | Line pulse period | `points.pulseMs` | `<LineSeries options={{ pulseMs }}>` |
491
+ * - `axis.y` — Y bound chase: pluggable curve, expand/contract/gesture
492
+ * settle times.
493
+ * - `axis.x` — X viewport: streaming settle + gesture override.
494
+ * - `axis.ticks` — axis tick label cross-fade.
495
+ * - `toggle` — series visibility (alpha fade + Y re-fit, locked to one
496
+ * duration so they finish on the same frame).
497
+ * - `series.{line,candlestick,bar,pie}` — per-series-type data tweens.
479
498
  *
480
- * Resolution: per-series option **wins** (it's the override). The chart-
481
- * level field acts as the default for every series that didn't set its own
482
- * override — *except* when the chart-level category is explicitly `false`,
483
- * which is a hard disable that overrides per-series too.
499
+ * Top-level `false` disables every animation category. `axis: false`
500
+ * disables both axes and ticks. `axis.y: false` / `axis.x: false` disables
501
+ * that axis only. Series-type-level `false` (`series: { line: false }`)
502
+ * disables that type only.
484
503
  *
485
- * - `points` — applied to data: entrance tween, live-tracking smoothing of
486
- * the last candle/bar/line value, line pulse cadence.
487
- * - `viewport` — applied to viewport interactions: post-gesture rebound,
488
- * Y-axis range chase, optional per-event ease for pan/zoom. Has no
489
- * per-series equivalent — these are chart-level only.
490
- *
491
- * All settling animations share a 250 ms default so the X re-fit, Y range
492
- * update, and last-bar live-track all settle on the same frame on a
493
- * streaming tick. Pulse cycle period (600 ms) and `inputResponseMs` (0,
494
- * opt-in) keep their own values.
504
+ * The per-series numeric fields (`entry` / `smooth` / `pulse`) also exist
505
+ * on individual series options (`<XSeries options={{ entryMs }}>`). The
506
+ * chart-level field acts as the default for any series that hasn't set its
507
+ * own override; an explicit `series.<type>: false` (or top-level `false`)
508
+ * is a hard disable that overrides per-series.
495
509
  */
496
510
  declare interface AnimationsConfig {
497
511
  /**
498
- * Data-series animations. `false` disables every point animation (entrance,
499
- * live-smoothing, pulse) across every series — overrides any per-series
500
- * option set on the same fields. An object overrides individual categories;
501
- * omitted fields fall back to the built-in defaults.
502
- *
503
- * Per-series options (`<LineSeries options={{ entryMs, smoothMs, pulseMs }}>`)
504
- * win over chart-level numeric values. The chart-level field becomes the
505
- * default for series that don't set their own.
512
+ * Axis-level animation. `false` collapses both axes and ticks to instant.
506
513
  */
507
- points?: false | {
514
+ axis?: false | {
508
515
  /**
509
- * Per-point entrance duration (ms). Default: 250.
510
- * Per-series equivalent: `<XSeries options={{ entryMs }}>` (note the
511
- * `y` — chart-level uses `enterMs`, per-series uses `entryMs` for
512
- * historical reasons; both refer to the same animation). `false` /
513
- * `0` disables.
516
+ * Y bound chase. `false` snaps Y instantly.
514
517
  */
515
- enterMs?: AnimationTime;
518
+ y?: false | {
519
+ /** Y curve. See {@link hermite}, {@link spring}, {@link snap}. */
520
+ curve?: TransitionFactory<YRange>;
521
+ /**
522
+ * Outward settle time — bound expanding to a new extreme.
523
+ *
524
+ * @default {@link DEFAULT_Y_SETTLE_MS}
525
+ */
526
+ settle?: AnimationTime;
527
+ /**
528
+ * Inward (contraction) settle — applied when a bound recedes
529
+ * after an extreme leaves the window (the "sticky-Y" hold).
530
+ *
531
+ * - `{ min, max }` — **dynamic**: the contract duration scales
532
+ * with the contraction magnitude, from `min` (a tiny recede)
533
+ * up to `max` (a full-range contraction). Big outliers ease
534
+ * off slowly while small receders finish quickly, so the axis
535
+ * doesn't crawl for seconds over a few pixels. Either side
536
+ * falls back to its default when omitted.
537
+ * - a scalar `AnimationTime` — **fixed**: `min === max`, every
538
+ * contraction takes the same time regardless of size (the
539
+ * legacy sticky feel). `false` snaps contractions instantly.
540
+ *
541
+ * @default `{ min:` {@link DEFAULT_Y_STICKY_MIN_MS}`, max:` {@link DEFAULT_Y_STICKY_MAX_MS}` }`
542
+ */
543
+ sticky?: AnimationTime | {
544
+ min?: AnimationTime;
545
+ max?: AnimationTime;
546
+ };
547
+ /**
548
+ * One-shot override during a user gesture (pan/zoom). Shorter
549
+ * than `sticky` so contractions during interaction converge in
550
+ * ~one frame per wheel tick.
551
+ *
552
+ * @default {@link DEFAULT_Y_GESTURE_MS}
553
+ */
554
+ gesture?: AnimationTime;
555
+ };
516
556
  /**
517
- * Live-value chase duration (ms) for the displayed last point on
518
- * `updateData` ticks. Animator-driven cubic ease — after this many ms
519
- * with no new updates, the displayed value reaches exactly the
520
- * actual last value. Default: 250. Per-series equivalent:
521
- * `options={{ smoothMs }}`. `false` / `0` snaps.
557
+ * X viewport. `false` snaps X instantly. The default critically-
558
+ * damped spring carries velocity across retargets so wheel-zoom
559
+ * sequences feel continuous and stream ticks blend smoothly into
560
+ * gesture motion.
522
561
  */
523
- smoothMs?: AnimationTime;
562
+ x?: false | {
563
+ /** X curve. See {@link spring}, {@link snap}. */
564
+ curve?: TransitionFactory<VisibleRange>;
565
+ /**
566
+ * Streaming settle time. Spring reaches ~99% of the target
567
+ * after this many ms. Used for streaming retargets; the
568
+ * streaming-cadence EMA tunes the effective value upward when
569
+ * data arrives slower than the baseline.
570
+ *
571
+ * @default {@link DEFAULT_X_SETTLE_MS}
572
+ */
573
+ settle?: AnimationTime;
574
+ /**
575
+ * One-shot override applied to user pan/zoom commits and to
576
+ * programmatic `fitContent`.
577
+ *
578
+ * @default {@link DEFAULT_X_GESTURE_MS}
579
+ */
580
+ gesture?: AnimationTime;
581
+ };
524
582
  /**
525
- * Pulse cycle period (ms) for the line last-point halo — periodic,
526
- * not a one-shot transition. Default: 600. Per-series equivalent:
527
- * `<LineSeries options={{ pulseMs }}>`. `false` / `0` disables.
583
+ * Axis tick label cross-fade. `false` makes tick relabel instant.
584
+ *
585
+ * @default {@link DEFAULT_TICKS_MS}
528
586
  */
529
- pulseMs?: AnimationTime;
587
+ ticks?: AnimationTime;
530
588
  };
531
589
  /**
532
- * Viewport interaction animations. `false` disables both rebound and Y-axis
533
- * smoothing — viewport changes snap instantly.
590
+ * Series-visibility toggle duration. Drives BOTH the renderer's alpha
591
+ * cross-fade and the engine's Y re-fit ease, so the two animations land
592
+ * on the same frame. `false` makes `setSeriesVisible` instant.
593
+ *
594
+ * @default {@link DEFAULT_TOGGLE_MS}
534
595
  */
535
- viewport?: false | {
536
- /** Rebound (snap-back) duration after pan/zoom overshoot (ms). Default: 350. */
537
- reboundMs?: AnimationTime;
596
+ toggle?: AnimationTime;
597
+ /**
598
+ * Per-series-type data animations. `false` disables every per-point
599
+ * animation across every series. Setting a single type to `false`
600
+ * (`series: { line: false }`) disables that type only.
601
+ *
602
+ * Per-series options (`<LineSeries options={{ entryMs, smoothMs, pulseMs }}>`)
603
+ * win over chart-level numeric values. The chart-level field becomes the
604
+ * default for series that don't set their own.
605
+ */
606
+ series?: false | {
538
607
  /**
539
- * Y-axis range transition duration in wall-clock milliseconds. The Y
540
- * min and max each ride their own {@link Animator} that retargets on
541
- * data updates and eases toward the new bound over this many ms.
542
- * Default `250` (shares the lockstep-arrival budget with viewport and
543
- * live-track). Inward contraction always eases. Outward expansion
544
- * eases when the per-point entrance is enabled (the entering candle's
545
- * fade masks the brief overshoot); when entrance is hard-disabled
546
- * (`points.enterMs === 0`), Y bounds snap outward to keep new
547
- * highs/lows from clipping at the canvas edge. `false` / `0` snaps
548
- * the Y range instantly on every update.
608
+ * Line-series tweens. `false` disables all line animations
609
+ * (entrance, live-smoothing, pulse).
549
610
  */
550
- yAxisMs?: AnimationTime;
611
+ line?: false | {
612
+ /**
613
+ * Per-point entrance duration. `false` disables the entrance
614
+ * (equivalent to `entryAnimation: 'none'`).
615
+ *
616
+ * @default {@link DEFAULT_LINE_ENTRY}
617
+ */
618
+ entry?: AnimationTime;
619
+ /**
620
+ * Last-value chase duration on `updateLastPoint`. `false` /
621
+ * `0` snaps to the target instantly.
622
+ *
623
+ * @default {@link DEFAULT_LINE_SMOOTH}
624
+ */
625
+ smooth?: AnimationTime;
626
+ /**
627
+ * Halo cycle period at the line tail. Periodic loop, not a
628
+ * one-shot. `false` / `0` turns the halo off entirely (drawing
629
+ * and animation loop).
630
+ *
631
+ * @default {@link DEFAULT_LINE_PULSE}
632
+ */
633
+ pulse?: AnimationTime;
634
+ };
551
635
  /**
552
- * Per-event ease applied to user pan/zoom commits. Logical state
553
- * advances synchronously (gesture math, edge detection, autoscroll
554
- * all read the committed target); the visual range eases over this
555
- * duration so back-to-back wheel/trackpad events interpolate
556
- * smoothly through the same animator.
557
- *
558
- * Default `0` (instant-apply, matches the long-standing pre-Phase-5
559
- * behaviour). Opt in via `inputResponseMs: 60` for an eased pan/zoom
560
- * feel — the default is conservative because the animated visual
561
- * range diverges from the committed target until the ease completes,
562
- * and existing consumers reading `chart.getVisibleRange()`
563
- * synchronously after a wheel/pan expect the new value.
636
+ * Candlestick tweens. `false` disables candle entrance + OHLC chase.
637
+ */
638
+ candlestick?: false | {
639
+ /**
640
+ * Per-candle entrance duration. `false` disables the entrance
641
+ * (equivalent to `entryAnimation: 'none'`).
642
+ *
643
+ * @default {@link DEFAULT_CANDLESTICK_ENTRY}
644
+ */
645
+ entry?: AnimationTime;
646
+ /**
647
+ * Live OHLC chase duration on `updateLastPoint`. `false` / `0`
648
+ * snaps to the target instantly.
649
+ *
650
+ * @default {@link DEFAULT_CANDLESTICK_SMOOTH}
651
+ */
652
+ smooth?: AnimationTime;
653
+ };
654
+ /**
655
+ * Bar-series tweens. `false` disables bar entrance + value chase.
564
656
  */
565
- inputResponseMs?: AnimationTime;
657
+ bar?: false | {
658
+ /**
659
+ * Per-bar entrance duration. `false` disables the entrance
660
+ * (equivalent to `entryAnimation: 'none'`).
661
+ *
662
+ * @default {@link DEFAULT_BAR_ENTRY}
663
+ */
664
+ entry?: AnimationTime;
665
+ /**
666
+ * Live value chase duration on `updateLastPoint`. `false` /
667
+ * `0` snaps to the target instantly.
668
+ *
669
+ * @default {@link DEFAULT_BAR_SMOOTH}
670
+ */
671
+ smooth?: AnimationTime;
672
+ };
673
+ /**
674
+ * Pie segment entry/update tweens. Parsed at config-time; the actual
675
+ * wiring lands in a later phase — providing a value here today is a
676
+ * no-op but the shape is stable.
677
+ */
678
+ pie?: false | {
679
+ /**
680
+ * Slice grow-in duration on first paint.
681
+ *
682
+ * @default {@link DEFAULT_PIE_ENTRY}
683
+ */
684
+ entry?: AnimationTime;
685
+ /**
686
+ * Slice resize duration when data changes.
687
+ *
688
+ * @default {@link DEFAULT_PIE_UPDATE}
689
+ */
690
+ update?: AnimationTime;
691
+ };
566
692
  };
567
693
  }
568
694
 
569
- /** Options passed when creating a new {@link ChartInstance}. */
570
695
  /**
571
- * Time-value or boolean used throughout the animation API. `false` disables
572
- * the category; a number configures its duration/time-constant in milliseconds
573
- * (`0` also disables, useful when the caller wants a number shape).
696
+ * Per-frame engine snapshot — same shape returned by the legacy
697
+ * `AnimationEngine.tick()` so existing consumers (chart render loop,
698
+ * `chart.getAnimationState()` public API, series overlay hooks) keep working.
574
699
  */
575
- declare type AnimationTime = number | false;
700
+ declare interface AnimationState {
701
+ readonly xRange: XRange;
702
+ readonly yRange: YRange;
703
+ readonly animating: boolean;
704
+ }
705
+
706
+ /**
707
+ * Public animation-time input. Accepts:
708
+ * - `number` — already milliseconds (`250`)
709
+ * - `string` in `<n>ms` or `<n>s` form (`"250ms"`, `"1s"`, `"2.5s"`)
710
+ * - `false` — disable (equivalent to `0`)
711
+ */
712
+ declare type AnimationTime = Milliseconds | string | false;
576
713
 
577
714
  /**
578
715
  * Build a 2-stop candle-body gradient around a single hex color — a lightened
@@ -621,6 +758,51 @@ export declare interface AxisConfig {
621
758
  x?: XAxisConfig;
622
759
  }
623
760
 
761
+ declare class AxisTickTracker {
762
+ #private;
763
+ constructor(opts?: AxisTickTrackerOptions);
764
+ /**
765
+ * Record the latest tick set. Diffs against the current set and either
766
+ * starts a `0 → 1` fade-in for new values or a `1 → 0` fade-out for
767
+ * dropped ones. Idempotent on element-wise equal arrays.
768
+ *
769
+ * Callers must invoke {@link tick} every frame to advance the animators —
770
+ * `snapshot()` reads the current state but does not advance time.
771
+ */
772
+ setCurrentTicks(next: readonly number[]): void;
773
+ /**
774
+ * Advance each tracked animator against `now`. Animators that settle
775
+ * at zero are dropped from the map; non-zero settled animators stay so
776
+ * a subsequent re-entering tick can pick them up without a flicker.
777
+ * Returns `true` while any animator is still in flight.
778
+ */
779
+ tick(now: number): boolean;
780
+ /**
781
+ * Build a renderer-ready snapshot from the tracker's own animator state.
782
+ * No external opacity map is consulted — `setCurrentTicks` + `tick(now)`
783
+ * are the only inputs.
784
+ */
785
+ snapshot(): TickTrackerSnapshot;
786
+ getCurrentTicks(): readonly number[];
787
+ getPreviousTicks(): readonly number[];
788
+ /**
789
+ * Reconfigure the cross-fade duration. Chart calls this after resolving
790
+ * `animations.axis.ticks` so the tracker honors the user's config
791
+ * without plumbing options through the scale constructors.
792
+ */
793
+ setFadeMs(ms: number): void;
794
+ /** Whether subsequent tick-set changes should fade-in or snap. */
795
+ markArmed(): void;
796
+ get isArmed(): boolean;
797
+ /** Drop all tracked ticks. Use after dataset swap so stale values don't linger. */
798
+ reset(): void;
799
+ }
800
+
801
+ declare interface AxisTickTrackerOptions {
802
+ /** Cross-fade duration in ms once {@link markArmed} has flipped. Defaults to {@link DEFAULT_TICKS_MS}. */
803
+ fadeMs?: number;
804
+ }
805
+
624
806
  export declare const ayuMirage: ThemePreset;
625
807
 
626
808
  /**
@@ -653,8 +835,6 @@ export declare interface BarSeriesOptions {
653
835
  * @see entryMs — cross-linked duration for this animation.
654
836
  */
655
837
  entryAnimation?: BarEntryAnimation;
656
- /** @deprecated Use {@link entryAnimation} instead. */
657
- enterAnimation?: BarEntryAnimation;
658
838
  /**
659
839
  * Per-bar entrance duration in milliseconds. Default: `250`.
660
840
  *
@@ -662,24 +842,19 @@ export declare interface BarSeriesOptions {
662
842
  * // Override for one series:
663
843
  * <BarSeries options={{ entryMs: 600 }} data={data} />
664
844
  *
665
- * // Or set the default for every series at once:
666
- * <ChartContainer animations={{ points: { enterMs: 600 } }}>
845
+ * // Or set the default for every bar series at once:
846
+ * <ChartContainer animations={{ series: { bar: { entry: 600 } } }}>
667
847
  * <BarSeries data={data} />
668
848
  * </ChartContainer>
669
849
  * ```
670
850
  *
671
- * Note: chart-level uses `enterMs`, per-series uses `entryMs` — same
672
- * animation, two names for historical reasons.
673
- *
674
851
  * `false` or `0` disables the entrance (equivalent to
675
- * `entryAnimation: 'none'`). A chart-level `animations.points: false` is a
676
- * hard disable that wins over this field.
852
+ * `entryAnimation: 'none'`). A chart-level `animations.series.bar: false`
853
+ * is a hard disable that wins over this field.
677
854
  *
678
855
  * @see BarSeriesOptions.entryAnimation
679
856
  */
680
857
  entryMs?: number | false;
681
- /** @deprecated Use {@link entryMs} instead. */
682
- enterMs?: number | false;
683
858
  /**
684
859
  * How long the displayed bar value takes to catch up to the actual one
685
860
  * on every `updateLastPoint`. Default: `250` ms.
@@ -689,21 +864,18 @@ export declare interface BarSeriesOptions {
689
864
  * <BarSeries options={{ smoothMs: 100 }} data={data} />
690
865
  *
691
866
  * // Chart-level default:
692
- * <ChartContainer animations={{ points: { smoothMs: 100 } }}>
867
+ * <ChartContainer animations={{ series: { bar: { smooth: 100 } } }}>
693
868
  * <BarSeries data={data} />
694
869
  * </ChartContainer>
695
870
  * ```
696
871
  *
697
872
  * `0` or `false` snaps the displayed value to the target on every tick
698
- * (no smoothing). A chart-level `animations.points: false` is a hard
873
+ * (no smoothing). A chart-level `animations.series.bar: false` is a hard
699
874
  * disable that wins over this field.
700
875
  */
701
876
  smoothMs?: number | false;
702
877
  }
703
878
 
704
- /** @deprecated Use {@link StackingMode} instead. */
705
- export declare type BarStacking = StackingMode;
706
-
707
879
  /**
708
880
  * Snapshot every visible series / layer at `time`. Used by hover overlays
709
881
  * (`InfoBar` in hover mode, `Tooltip`). Hidden series and hidden layers are
@@ -791,8 +963,6 @@ export declare interface CandlestickSeriesOptions {
791
963
  * @see entryMs — cross-linked duration for this animation.
792
964
  */
793
965
  entryAnimation?: CandlestickEntryAnimation;
794
- /** @deprecated Use {@link entryAnimation} instead. */
795
- enterAnimation?: CandlestickEntryAnimation;
796
966
  /**
797
967
  * Per-candle entrance duration in milliseconds. Default: `250`.
798
968
  *
@@ -800,24 +970,20 @@ export declare interface CandlestickSeriesOptions {
800
970
  * // Override for one series:
801
971
  * <CandlestickSeries options={{ entryMs: 600 }} data={data} />
802
972
  *
803
- * // Or set the default for every series at once:
804
- * <ChartContainer animations={{ points: { enterMs: 600 } }}>
973
+ * // Or set the default for every candlestick series at once:
974
+ * <ChartContainer animations={{ series: { candlestick: { entry: 600 } } }}>
805
975
  * <CandlestickSeries data={data} />
806
976
  * </ChartContainer>
807
977
  * ```
808
978
  *
809
- * Note: chart-level uses `enterMs`, per-series uses `entryMs` — same
810
- * animation, two names for historical reasons.
811
- *
812
979
  * `false` or `0` disables the entrance (equivalent to
813
- * `entryAnimation: 'none'`). A chart-level `animations.points: false` is a
814
- * hard disable that wins over this field.
980
+ * `entryAnimation: 'none'`). A chart-level
981
+ * `animations.series.candlestick: false` is a hard disable that wins over
982
+ * this field.
815
983
  *
816
984
  * @see CandlestickSeriesOptions.entryAnimation
817
985
  */
818
986
  entryMs?: number | false;
819
- /** @deprecated Use {@link entryMs} instead. */
820
- enterMs?: number | false;
821
987
  /**
822
988
  * How long the displayed OHLC takes to catch up to the actual last value
823
989
  * on every `updateLastPoint`. Default: `250` ms.
@@ -827,14 +993,14 @@ export declare interface CandlestickSeriesOptions {
827
993
  * <CandlestickSeries options={{ smoothMs: 100 }} data={data} />
828
994
  *
829
995
  * // Chart-level default:
830
- * <ChartContainer animations={{ points: { smoothMs: 100 } }}>
996
+ * <ChartContainer animations={{ series: { candlestick: { smooth: 100 } } }}>
831
997
  * <CandlestickSeries data={data} />
832
998
  * </ChartContainer>
833
999
  * ```
834
1000
  *
835
1001
  * `0` or `false` snaps the displayed value to the target on every tick
836
- * (no smoothing). A chart-level `animations.points: false` is a hard
837
- * disable that wins over this field.
1002
+ * (no smoothing). A chart-level `animations.series.candlestick: false` is
1003
+ * a hard disable that wins over this field.
838
1004
  */
839
1005
  smoothMs?: number | false;
840
1006
  }
@@ -857,41 +1023,58 @@ declare interface ChartEvents {
857
1023
  * subscribe to this instead of stacking multiple listeners.
858
1024
  */
859
1025
  overlayChange: () => void;
1026
+ /**
1027
+ * Fired once per main-layer frame *while* an axis tick is still in the
1028
+ * middle of its fade-in/out animation. DOM axis components (`<TimeAxis>`,
1029
+ * `<YAxis>`) listen to this to re-read the per-tick opacity from
1030
+ * `timeScale.tickTracker` / `yScale.tickTracker` so the DOM labels and
1031
+ * canvas grid lines fade in lockstep. Stops firing as soon as every
1032
+ * tracked tick has reached its target opacity.
1033
+ */
1034
+ tickFrame: () => void;
860
1035
  }
861
1036
 
862
1037
  /**
863
1038
  * Core chart controller. Manages series, viewport, scales, and rendering.
864
1039
  * Create one per chart container and call {@link destroy} on unmount.
865
1040
  */
866
- export declare class ChartInstance extends EventEmitter<ChartEvents> {
1041
+ export declare class ChartInstance extends EventEmitter<ChartEvents> implements PanZoomTarget {
867
1042
  #private;
868
1043
  /** Maps time values to horizontal pixel coordinates. */
869
- readonly timeScale: TimeScale;
1044
+ readonly timeScale: XScale;
870
1045
  /** Maps price/value to vertical pixel coordinates. */
871
1046
  readonly yScale: YScale;
872
1047
  get yAxisWidth(): number;
873
1048
  get xAxisHeight(): number;
874
1049
  constructor(container: HTMLElement, options?: ChartOptions);
875
- /** Add a candlestick (OHLC) series and return its unique ID. */
876
- addCandlestickSeries(options?: Partial<CandlestickSeriesOptions & {
1050
+ /**
1051
+ * Add a series of the given `type` and return its unique ID. `options` is
1052
+ * typed per `type` via the overloads. `layers` (line/bar) and `id` are
1053
+ * consumed here; everything else is forwarded to the renderer.
1054
+ */
1055
+ addSeries(type: 'candlestick', options?: Partial<CandlestickSeriesOptions & {
877
1056
  id?: string;
878
1057
  }>): string;
879
- /** Add a line series and return its unique ID. */
880
- addLineSeries(options?: Partial<LineSeriesOptions & {
1058
+ addSeries(type: 'line', options?: Partial<LineSeriesOptions & {
881
1059
  layers?: number;
882
1060
  id?: string;
883
1061
  }>): string;
884
- /** Add a bar series and return its unique ID. */
885
- addBarSeries(options?: Partial<BarSeriesOptions & {
1062
+ addSeries(type: 'bar', options?: Partial<BarSeriesOptions & {
886
1063
  layers?: number;
887
1064
  id?: string;
888
1065
  }>): string;
889
- /** Add a pie/donut series. Set `innerRadiusRatio > 0` for donut. */
890
- addPieSeries(options?: Partial<PieSeriesOptions & {
1066
+ addSeries(type: 'pie', options?: Partial<PieSeriesOptions & {
891
1067
  id?: string;
892
1068
  }>): string;
893
1069
  /** Remove a series by ID and clean up its resources. */
894
1070
  removeSeries(id: string): void;
1071
+ /**
1072
+ * Read-only snapshot of the chart's X / Y viewport animation. The same
1073
+ * shape (`xRange`, `yRange`, `animating`) every frame — call this inside
1074
+ * the current render pass rather than caching the reference, as the
1075
+ * underlying animator mutates between frames.
1076
+ */
1077
+ getAnimationState(): AnimationState;
895
1078
  /**
896
1079
  * Replace all data for a series.
897
1080
  *
@@ -906,6 +1089,20 @@ export declare class ChartInstance extends EventEmitter<ChartEvents> {
906
1089
  appendData(id: string, point: OHLCInput | TimePointInput, layerIndex?: number): void;
907
1090
  /** Update the last data point of a series in place (e.g. live candle update). */
908
1091
  updateData(id: string, point: OHLCInput | TimePointInput, layerIndex?: number): void;
1092
+ /**
1093
+ * Keep only the most recent `count` points of a series — drop the oldest
1094
+ * tail when the series exceeds the cap. Smooth Y-range chase (no snap):
1095
+ * unlike {@link setSeriesData}, this does NOT set the bulk-replace snap
1096
+ * flag, so streaming windows can roll without per-tick Y jitter.
1097
+ *
1098
+ * Idempotent: a no-op when the series is already at or below `count`.
1099
+ * Use after {@link appendData} in a rolling-window stream:
1100
+ * ```ts
1101
+ * chart.appendData('feed', point);
1102
+ * chart.keepLast('feed', 100);
1103
+ * ```
1104
+ */
1105
+ keepLast(id: string, count: number, layerIndex?: number): void;
909
1106
  /** Update visual options (color, width, etc.) for an existing series. */
910
1107
  updateSeriesOptions(id: string, options: Partial<CandlestickSeriesOptions> | Partial<LineSeriesOptions> | Partial<BarSeriesOptions> | Partial<PieSeriesOptions>): void;
911
1108
  /**
@@ -913,37 +1110,71 @@ export declare class ChartInstance extends EventEmitter<ChartEvents> {
913
1110
  * inside `fn` still flush the batch so counters don't leak across calls.
914
1111
  */
915
1112
  batch(fn: () => void): void;
916
- /** Show or hide a series. Hidden series are not rendered and excluded from Y-range. */
1113
+ /** Show or hide a series. The series cross-fades over
1114
+ * `animations.toggle`; the Y range re-fits on the same schedule
1115
+ * (one-shot duration override) so the fade and the axis adjustment
1116
+ * finish on the same frame. Hidden series are excluded from Y-range
1117
+ * computation immediately so the axis can start moving while the line
1118
+ * fades out in parallel.
1119
+ */
917
1120
  setSeriesVisible(seriesId: string, visible: boolean): void;
1121
+ /**
1122
+ * Whether streaming ticks slide the visible range to track the data tail.
1123
+ * Flipped off by a pan that pushes the tail off screen; re-engaged when
1124
+ * a follow-up pan brings the tail back into the destination window or
1125
+ * when {@link fitContent} / {@link setVisibleRange} commits a range
1126
+ * containing the tail.
1127
+ */
1128
+ getAutoScroll(): boolean;
918
1129
  isSeriesVisible(seriesId: string): boolean;
919
- /** Show or hide a specific layer within a multi-layer series. */
1130
+ /**
1131
+ * Show or hide a specific layer within a multi-layer series.
1132
+ *
1133
+ * Symmetric with {@link setSeriesVisible}: drives both the renderer's
1134
+ * per-layer alpha fade and the engine's Y re-fit through `toggleMs` so the
1135
+ * line fade and the axis adjustment finish on the same frame. Hidden layers
1136
+ * are excluded from Y-range computation immediately (via the renderer's
1137
+ * `getValueRange` reading `store.isVisible()`); the alpha fade keeps the
1138
+ * layer's geometry on screen until the engine's Y ease settles.
1139
+ */
920
1140
  setLayerVisible(seriesId: string, layerIndex: number, visible: boolean): void;
921
1141
  isLayerVisible(seriesId: string, layerIndex: number): boolean;
922
1142
  /** Auto-fit the viewport to show all data across every series. */
923
1143
  fitContent(): void;
924
- getVisibleRange(): VisibleRange;
1144
+ getVisibleRange(): XRange;
925
1145
  /**
926
1146
  * Return the full span of registered data, or `null` before any data has
927
- * arrived. `{ from: dataStart, to: dataEnd }` mirrors the viewport's own
1147
+ * arrived. `{ from: dataStart, to: dataEnd }` mirrors the chart's own
928
1148
  * tracking and is cheaper than recomputing from series stores.
929
1149
  */
930
- getDataRange(): VisibleRange | null;
1150
+ getDataRange(): XRange | null;
931
1151
  /**
932
- * Imperatively set the visible time range.
1152
+ * Imperatively set the visible time range. Three forms:
933
1153
  *
934
- * Two forms:
935
- * - `{ from, to }` — explicit millisecond range. Cancels any in-flight
936
- * animation and applies immediately. Auto-scroll stays on only if the
937
- * tail is inside the new range (mirrors pan semantics).
938
- * - `number N` — shorthand for "show the last N bars from the tail".
939
- * Resolved against the current data bounds and data interval; keeps
940
- * auto-scroll on so streaming ticks continue to track the tail.
941
- * No-op if data hasn't loaded yet.
1154
+ * - `number N` — show the last N bars from the data tail (anchor right).
1155
+ * Resolved against current data bounds and data interval; keeps
1156
+ * auto-scroll on. No-op if data hasn't loaded yet.
1157
+ * - `{ from, to }` — explicit time range. `from`/`to` accept either
1158
+ * epoch milliseconds or `Date`. Cancels any in-flight animation and
1159
+ * applies immediately. Auto-scroll stays on only if the tail is
1160
+ * inside the new range (mirrors pan semantics).
1161
+ * - `{ from, bars }` — anchor the visible window at `from` and extend
1162
+ * right by `bars` data intervals. Useful for warm-up windows where
1163
+ * seed points sit on the left and a stream fills the gap on the
1164
+ * right. `from` accepts a `Date` too.
942
1165
  *
943
1166
  * Typical use: on mount, zoom to the last N bars while keeping the full
944
1167
  * buffer available for pan-back history inspection.
945
- */
946
- setVisibleRange(range: VisibleRange | number): void;
1168
+ *
1169
+ * `opts.gesture` (explicit `{ from, to }` form only) eases X and Y on the
1170
+ * same fast, velocity-matched profile a user pan/zoom uses instead of the
1171
+ * default programmatic settle (snap X, sticky-Y ease). Use it for
1172
+ * multi-chart sync so a synced pane tracks the originating gesture in
1173
+ * lockstep rather than lagging behind on the long sticky contract.
1174
+ */
1175
+ setVisibleRange(spec: VisibleRangeSpec, opts?: {
1176
+ gesture?: boolean;
1177
+ }): void;
947
1178
  getYRange(): YRange;
948
1179
  getCrosshairPosition(): CrosshairPosition | null;
949
1180
  /**
@@ -999,11 +1230,6 @@ export declare class ChartInstance extends EventEmitter<ChartEvents> {
999
1230
  color: string;
1000
1231
  }[] | null;
1001
1232
  getSeriesIds(): string[];
1002
- /**
1003
- * Type of a registered series, or `null` for unknown ids. `'pie'` for
1004
- * `PieRenderer`; everything else is a time-series (`'time'`).
1005
- */
1006
- getSeriesType(seriesId: string): 'pie' | 'time' | null;
1007
1233
  /**
1008
1234
  * Filter `getSeriesIds()` by renderer type. `'pie'` returns pie series,
1009
1235
  * `'time'` returns line/bar/candlestick.
@@ -1082,25 +1308,6 @@ export declare class ChartInstance extends EventEmitter<ChartEvents> {
1082
1308
  * a wrapper re-applies padding reactively (e.g. in response to a Title /
1083
1309
  * InfoBar ResizeObserver).
1084
1310
  */
1085
- /**
1086
- * Replace the chart-level animation configuration at runtime. Updates the
1087
- * resolved durations and propagates them to every dependent subsystem:
1088
- *
1089
- * - viewport: reboundMs (next rebound), inputResponseMs (next pan/zoom).
1090
- * - per-frame: yAxisMs (next render).
1091
- * - existing series: only the **hard-disable** signal (0 / false) is pushed
1092
- * into renderers — that's the documented contract on
1093
- * {@link AnimationsConfig.points}, "chart-level `false` wins over per-
1094
- * series". Numeric chart-level changes update the default for *new*
1095
- * series but leave existing per-series overrides intact, which avoids
1096
- * silently clobbering custom values on every prop update from a React
1097
- * wrapper.
1098
- *
1099
- * In-flight animations are NOT cancelled — the new durations apply to the
1100
- * next animation that fires. To force-snap the current animation, call
1101
- * the relevant API explicitly (e.g. `setRange`) afterwards.
1102
- */
1103
- setAnimations(animations: ChartOptions['animations']): void;
1104
1311
  setPadding(padding: ChartOptions['padding']): void;
1105
1312
  /** Show or hide the background grid. Takes effect on the next render frame. */
1106
1313
  setGrid(grid: {
@@ -1118,9 +1325,13 @@ export declare class ChartInstance extends EventEmitter<ChartEvents> {
1118
1325
  setEdgeState(side: EdgeSide, state: EdgeState): void;
1119
1326
  /** Read the current host-declared state for a given edge. */
1120
1327
  getEdgeState(side: EdgeSide): EdgeState;
1121
- /** Notify chart that a YLabel is present (affects right padding). */
1122
- setYLabel(has: boolean): void;
1123
- private updateViewportPadding;
1328
+ /**
1329
+ * Notify chart that a YLabel overlay is mounted / unmounted. Currently a
1330
+ * no-op — placeholder for the right-padding reflow that will adjust the
1331
+ * chart area to make room for the badge.
1332
+ * TODO: implement reflow.
1333
+ */
1334
+ setYLabel(_has: boolean): void;
1124
1335
  /** Tear down the chart: cancel animations, remove listeners, and detach the canvas. */
1125
1336
  destroy(): void;
1126
1337
  /** The attached performance monitor, or `null` when instrumentation is disabled. */
@@ -1130,39 +1341,42 @@ export declare class ChartInstance extends EventEmitter<ChartEvents> {
1130
1341
  private onDataChanged;
1131
1342
  private updateDataInterval;
1132
1343
  /**
1133
- * Sample data inside `targetVisible` and return the unbounded [min, max] of
1134
- * the visible series, or `null` when nothing is in view. Bounds are NOT
1135
- * applied here — the caller composes them via {@link resolveBound}.
1344
+ * Shift the visible time range by `timeDelta` ms. Hard-clamped so at
1345
+ * least one data point stays on screen — no rubber-band, no overshoot.
1346
+ * A pan that moves the viewport off the live-tail position flips
1347
+ * autoscroll off. Fires `edgeReached` whenever the clamp trims the
1348
+ * gesture (i.e., the user pushed past the boundary), so consumers can
1349
+ * trigger history loads. Forwards the committed target to the engine
1350
+ * as a gesture for visual easing. Public so consumers can drive pan
1351
+ * programmatically.
1352
+ */
1353
+ pan(timeDelta: number, chartWidth?: number): void;
1354
+ /**
1355
+ * Zoom around a time anchor. `factor < 1` zooms in, `> 1` zooms out.
1356
+ * In historical mode the window anchors to `centerTime` (cursor-driven).
1357
+ * Zoom-out is hard-capped at the padded data span. Forwards the committed
1358
+ * target to the engine as a gesture for visual easing. Public so consumers
1359
+ * can drive zoom programmatically.
1136
1360
  *
1137
- * `targetVisible` is the X *destination* (logicalRange), not the animating
1138
- * current. Sampling against a moving X would make Y chase a definition of
1139
- * "in view" that shifts every frame; passing the destination explicitly
1140
- * keeps Y on a stable target so X and Y converge together.
1361
+ * Sticky-follow: while `#autoScroll` is on, the new window is repositioned
1362
+ * so its right edge sits at `dataEnd + paddingRight` (follow position).
1363
+ * Span (zoom level) from `computeZoom` is preserved; only the position
1364
+ * is locked to the tail. This avoids the next-tick `computeStreamingTarget`
1365
+ * offset clamp (which would otherwise slide X left to the follow position
1366
+ * and produce a visible jump). Cursor-anchored zoom is intentionally
1367
+ * sacrificed in follow-live mode — pan first to inspect history.
1141
1368
  */
1142
- private computeTargetYRange;
1143
- private updateYRange;
1144
- /** Resolve an {@link AxisBound} to a concrete numeric value. */
1145
- private resolveBound;
1369
+ zoomAt(centerTime: number, factor: number, chartWidth?: number): void;
1146
1370
  /**
1147
1371
  * Lightweight scale sync: updates timeScale/yScale from current viewport state
1148
1372
  * without advancing the Y smoothing animation. Called from the viewport 'change'
1149
- * handler so DOM axis components always read fresh coordinates on re-render.
1373
+ * handler, so DOM axis components always read fresh coordinates on re-render.
1150
1374
  */
1151
1375
  private syncScales;
1152
- private updateScales;
1153
1376
  /** Expensive: background, grid, all series. Only on data/viewport/resize change. */
1154
1377
  private renderMain;
1155
1378
  /** Cheap overlay: crosshair, nearest-point dots, pulse animation, edge indicator. */
1156
1379
  private renderOverlay;
1157
- private drawEdgeIndicators;
1158
- /**
1159
- * Pick the boundary time to anchor the edge indicator at. Prefer the
1160
- * cached value emitted by the most recent `edgeReached` — that's the
1161
- * *exact* point the user overshot. Fall back to the current data edge
1162
- * when no gesture has fired yet (host might invoke `setEdgeState`
1163
- * directly on mount to show a "no-data" marker from the start).
1164
- */
1165
- private resolveEdgeBoundary;
1166
1380
  }
1167
1381
 
1168
1382
  /** Layout metrics describing the chart area, Y axis, and time axis sizes. */
@@ -1172,6 +1386,7 @@ export declare interface ChartLayout {
1172
1386
  xAxisHeight: number;
1173
1387
  }
1174
1388
 
1389
+ /** Options passed when creating a new ChartInstance. */
1175
1390
  export declare interface ChartOptions {
1176
1391
  theme?: ChartTheme;
1177
1392
  axis?: AxisConfig;
@@ -1182,12 +1397,35 @@ export declare interface ChartOptions {
1182
1397
  padding?: {
1183
1398
  top?: number;
1184
1399
  bottom?: number;
1185
- right?: number | {
1186
- intervals: number;
1187
- };
1188
- left?: number | {
1189
- intervals: number;
1190
- };
1400
+ right?: HorizontalPadding;
1401
+ left?: HorizontalPadding;
1402
+ };
1403
+ /**
1404
+ * Viewport-level streaming behavior.
1405
+ */
1406
+ viewport?: {
1407
+ /**
1408
+ * Maximum number of data bars (candles/points) the viewport will fit
1409
+ * before it stops growing and switches to tail-scroll. While the data
1410
+ * span is below this threshold, streaming ticks expand the right edge
1411
+ * to absorb new points; once the span exceeds it, the visible window
1412
+ * holds at this width and slides forward as new data arrives.
1413
+ * Default: 200. Values below 2 are clamped.
1414
+ */
1415
+ maxVisibleBars?: number;
1416
+ /**
1417
+ * Initial visible range applied **before** the first paint after data
1418
+ * arrives. Same shape as `ChartInstance.setVisibleRange` (a bar count,
1419
+ * an explicit `{from, to}` window, or a `{from, bars}` warm-up pair).
1420
+ * Calling `setVisibleRange` after mount via `useEffect` runs post-paint
1421
+ * and visually re-zooms the chart on the next frame; this option folds
1422
+ * the same intent into the first render so the very first paint
1423
+ * already shows the requested window.
1424
+ *
1425
+ * One-shot — consumed by the first `onDataChanged` call that has data,
1426
+ * then cleared. Subsequent `setSeriesData` calls don't re-apply it.
1427
+ */
1428
+ initialRange?: VisibleRangeSpec;
1191
1429
  };
1192
1430
  /** Enable zoom, pan, and crosshair interactions. Defaults to true. */
1193
1431
  interactive?: boolean;
@@ -1196,17 +1434,16 @@ export declare interface ChartOptions {
1196
1434
  visible: boolean;
1197
1435
  };
1198
1436
  /**
1199
- * Animation control. Split into `points` (data-series animations) and
1200
- * `viewport` (pan/zoom rebound + Y-axis smoothing). See
1201
- * {@link AnimationsConfig} for the full shape and defaults.
1437
+ * Animation control. Grouped as `axis: { y, x, ticks }` (axis-side
1438
+ * behaviour), `toggle` (series visibility — alpha + Y refit), and
1439
+ * `series.{line,candlestick,bar,pie}` (per-series-type data tweens).
1440
+ * See {@link AnimationsConfig} for the full shape and defaults.
1202
1441
  *
1203
1442
  * Shorthands:
1204
1443
  * - `animations: true` (or omitted) uses built-in defaults.
1205
1444
  * - `animations: false` disables every animation category.
1206
- * - `animations: { points: false }` disables all data-series animations.
1207
- * - `animations: { viewport: false }` disables rebound + Y-axis smoothing.
1208
1445
  *
1209
- * Per-series options (`enterMs`, `smoothMs`, etc.) override chart-level
1446
+ * Per-series options (`entryMs`, `smoothMs`, etc.) override chart-level
1210
1447
  * defaults unless the category is explicitly `false` — then the chart-
1211
1448
  * level gate wins.
1212
1449
  */
@@ -1215,7 +1452,7 @@ export declare interface ChartOptions {
1215
1452
  * Invoked after the user releases a pan/zoom gesture that pulled the
1216
1453
  * viewport past a data edge by more than 10% of the visible range. Hosts
1217
1454
  * typically respond by prefetching more history and calling
1218
- * {@link ChartInstance.setEdgeState} to show a spinner or "no more data"
1455
+ * `ChartInstance.setEdgeState` to show a spinner or "no more data"
1219
1456
  * indicator at the corresponding edge.
1220
1457
  */
1221
1458
  onEdgeReached?: (info: EdgeReachedInfo) => void;
@@ -1447,15 +1684,6 @@ export declare interface CrosshairPosition {
1447
1684
  y: number;
1448
1685
  }
1449
1686
 
1450
- /**
1451
- * @deprecated Use a named preset instead — `catppuccin.theme` is the new
1452
- * default dark palette, and `dracula`, `nightOwl`, `oneDarkPro`, `gruvbox`,
1453
- * `monokaiPro`, `materialPalenight`, or `panda` cover the rest of the
1454
- * dark spectrum. `darkTheme` is kept as an alias for the previous default
1455
- * and will be removed in a future major release.
1456
- */
1457
- export declare const darkTheme: ChartTheme;
1458
-
1459
1687
  export declare function detectInterval(times: number[]): number;
1460
1688
 
1461
1689
  export declare const dracula: ThemePreset;
@@ -1528,6 +1756,11 @@ export declare const handwritten: ThemePreset;
1528
1756
 
1529
1757
  export declare const highContrast: ThemePreset;
1530
1758
 
1759
+ /** Horizontal padding expressed as a fixed pixel offset or a number of data intervals. */
1760
+ declare type HorizontalPadding = number | {
1761
+ intervals: number;
1762
+ };
1763
+
1531
1764
  /** Shape returned by {@link SeriesRenderer.getHoverInfo} / per-slice entries of {@link SeriesRenderer.getSliceInfo}. */
1532
1765
  export declare interface HoverInfo {
1533
1766
  label: string;
@@ -1589,18 +1822,6 @@ declare type LegendMode = 'toggle' | 'isolate' | 'solo';
1589
1822
 
1590
1823
  export declare const lightPink: ThemePreset;
1591
1824
 
1592
- /**
1593
- * @deprecated Use a named light preset instead — `quietLight`, `githubLight`,
1594
- * `solarizedLight`, `minimalLight`, `peachCream`, `sandDune`, `lightPink`,
1595
- * `lavenderMist`, `mintBreeze`, `rosePineDawn`, or `handwritten`. `lightTheme`
1596
- * is kept as an alias for the previous default and will be removed in a
1597
- * future major release.
1598
- */
1599
- export declare const lightTheme: ChartTheme;
1600
-
1601
- /** @deprecated Use {@link TimePoint} instead. */
1602
- export declare type LineData = TimePoint;
1603
-
1604
1825
  /**
1605
1826
  * Entrance animation styles for new line points.
1606
1827
  * - `'none'` — new segments appear instantly.
@@ -1638,14 +1859,14 @@ export declare interface LineSeriesOptions {
1638
1859
  * <LineSeries options={{ pulseMs: 1200 }} data={data} />
1639
1860
  *
1640
1861
  * // Chart-level default:
1641
- * <ChartContainer animations={{ points: { pulseMs: 1200 } }}>
1862
+ * <ChartContainer animations={{ series: { line: { pulse: 1200 } } }}>
1642
1863
  * <LineSeries data={data} />
1643
1864
  * </ChartContainer>
1644
1865
  * ```
1645
1866
  *
1646
1867
  * `false` or `0` turns the halo off entirely (drawing and animation loop).
1647
- * A chart-level `animations.points: false` is a hard disable that wins
1648
- * over this field.
1868
+ * A chart-level `animations.series.line: false` is a hard disable that
1869
+ * wins over this field.
1649
1870
  */
1650
1871
  pulseMs?: number | false;
1651
1872
  /** Stacking mode. Default: 'off'. */
@@ -1658,8 +1879,6 @@ export declare interface LineSeriesOptions {
1658
1879
  * @see entryMs — cross-linked duration for this animation.
1659
1880
  */
1660
1881
  entryAnimation?: LineEntryAnimation;
1661
- /** @deprecated Use {@link entryAnimation} instead. */
1662
- enterAnimation?: LineEntryAnimation;
1663
1882
  /**
1664
1883
  * Per-point entrance duration in milliseconds. Default: `250`.
1665
1884
  *
@@ -1667,24 +1886,19 @@ export declare interface LineSeriesOptions {
1667
1886
  * // Override for one series:
1668
1887
  * <LineSeries options={{ entryMs: 600 }} data={data} />
1669
1888
  *
1670
- * // Or set the default for every series at once:
1671
- * <ChartContainer animations={{ points: { enterMs: 600 } }}>
1889
+ * // Or set the default for every line series at once:
1890
+ * <ChartContainer animations={{ series: { line: { entry: 600 } } }}>
1672
1891
  * <LineSeries data={data} />
1673
1892
  * </ChartContainer>
1674
1893
  * ```
1675
1894
  *
1676
- * Note: chart-level uses `enterMs`, per-series uses `entryMs` — same
1677
- * animation, two names for historical reasons.
1678
- *
1679
1895
  * `false` or `0` disables the entrance (equivalent to
1680
- * `entryAnimation: 'none'`). A chart-level `animations.points: false` is a
1681
- * hard disable that wins over this field.
1896
+ * `entryAnimation: 'none'`). A chart-level `animations.series.line: false`
1897
+ * is a hard disable that wins over this field.
1682
1898
  *
1683
1899
  * @see LineSeriesOptions.entryAnimation
1684
1900
  */
1685
1901
  entryMs?: number | false;
1686
- /** @deprecated Use {@link entryMs} instead. */
1687
- enterMs?: number | false;
1688
1902
  /**
1689
1903
  * How long the displayed last value takes to catch up to the actual one
1690
1904
  * on every `updateLastPoint`. Default: `250` ms.
@@ -1694,13 +1908,13 @@ export declare interface LineSeriesOptions {
1694
1908
  * <LineSeries options={{ smoothMs: 100 }} data={data} />
1695
1909
  *
1696
1910
  * // Chart-level default:
1697
- * <ChartContainer animations={{ points: { smoothMs: 100 } }}>
1911
+ * <ChartContainer animations={{ series: { line: { smooth: 100 } } }}>
1698
1912
  * <LineSeries data={data} />
1699
1913
  * </ChartContainer>
1700
1914
  * ```
1701
1915
  *
1702
1916
  * `0` or `false` snaps the displayed value to the target on every tick
1703
- * (no smoothing). A chart-level `animations.points: false` is a hard
1917
+ * (no smoothing). A chart-level `animations.series.line: false` is a hard
1704
1918
  * disable that wins over this field.
1705
1919
  */
1706
1920
  smoothMs?: number | false;
@@ -1710,6 +1924,15 @@ declare type Listener = (...args: any[]) => void;
1710
1924
 
1711
1925
  export declare const materialPalenight: ThemePreset;
1712
1926
 
1927
+ /**
1928
+ * Time helpers for the animation config surface. The public config accepts
1929
+ * three shapes: a number (already milliseconds), a string with an explicit
1930
+ * unit (`"250ms"`, `"1s"`, `"2.5s"`), or `false` to disable. The resolver
1931
+ * parses each input once at chart construction; the hot render path then
1932
+ * only ever sees numbers.
1933
+ */
1934
+ declare type Milliseconds = number;
1935
+
1713
1936
  export declare const minimalLight: ThemePreset;
1714
1937
 
1715
1938
  export declare const mintBreeze: ThemePreset;
@@ -1827,6 +2050,25 @@ export declare const oneDarkPro: ThemePreset;
1827
2050
 
1828
2051
  export declare const panda: ThemePreset;
1829
2052
 
2053
+ /**
2054
+ * Narrow interface the interaction handlers expect from their host. Lets
2055
+ * `InteractionHandler` / `PanHandler` / `ZoomHandler` drive pan / zoom
2056
+ * without depending on the full ChartInstance surface.
2057
+ */
2058
+ declare interface PanZoomTarget {
2059
+ /**
2060
+ * Shift the visible time range by `timeDelta` ms. `chartWidth` is used
2061
+ * by pixel-padding resolution; passing the current canvas width yields
2062
+ * correct rubber-band clamps.
2063
+ */
2064
+ pan(timeDelta: number, chartWidth?: number): void;
2065
+ /**
2066
+ * Zoom around a time anchor. `factor < 1` zooms in, `> 1` zooms out.
2067
+ * `chartWidth` participates in soft-bound math the same way as in `pan`.
2068
+ */
2069
+ zoomAt(centerTime: number, factor: number, chartWidth?: number): void;
2070
+ }
2071
+
1830
2072
  export declare const peachCream: ThemePreset;
1831
2073
 
1832
2074
  /**
@@ -1909,8 +2151,6 @@ declare interface PerfStats {
1909
2151
  mainRendersPerSec: number;
1910
2152
  /** Same as {@link mainRendersPerSec} but for the overlay (crosshair + pulse) layer. */
1911
2153
  overlayRendersPerSec: number;
1912
- /** @deprecated Alias for {@link mainRendersPerSec}. Kept for older consumers. */
1913
- fps: number;
1914
2154
  mainFrameMs: FrameTimingSample;
1915
2155
  overlayFrameMs: FrameTimingSample;
1916
2156
  /** Total frames recorded per layer. Lets consumers distinguish "no data yet" from "drew once and ms is 0". */
@@ -1972,13 +2212,6 @@ declare interface PieLabelsOptions {
1972
2212
  * expressed as a multiplier of {@link fontSize}. Default: 1.8.
1973
2213
  */
1974
2214
  labelGap?: number;
1975
- /**
1976
- * @deprecated No effect in the radial per-slice layout. A label's X is
1977
- * pinned to its slice midangle, so forcing the "other" side would flip
1978
- * text direction without moving the label and push text across the pie.
1979
- * Kept in the option surface for backwards compatibility.
1980
- */
1981
- balanceSides?: boolean;
1982
2215
  }
1983
2216
 
1984
2217
  export declare const PieLegend: __VLS_WithTemplateSlots_4<typeof __VLS_component_4, __VLS_TemplateResult_4["slots"]>;
@@ -2096,6 +2329,30 @@ export declare function resolveAxisTextColor(theme: ChartTheme, axis?: 'x' | 'y'
2096
2329
  */
2097
2330
  export declare function resolveCandlestickBodyColor(body: string | [string, string]): string;
2098
2331
 
2332
+ /**
2333
+ * Per-call settle times supplied by the engine to {@link Transition.retarget}.
2334
+ * The engine owns all durations and pushes them per call; the curves carry
2335
+ * no baseline of their own.
2336
+ *
2337
+ * X transitions use only `expandMs` (single direction). Y transitions use
2338
+ * both `expandMs` (outward — new extreme enters window) and `contractMs`
2339
+ * (inward — extreme leaves; the sticky-Y mechanism).
2340
+ */
2341
+ declare interface RetargetOptions {
2342
+ /** Optional wall clock. Defaults to `performance.now()`. */
2343
+ now?: number;
2344
+ /**
2345
+ * Settle time (ms) for *outward* motion — bound reaching a new extreme.
2346
+ * Also used by X (single-direction) as the spring's settle time.
2347
+ */
2348
+ expandMs?: number;
2349
+ /**
2350
+ * Settle time (ms) for *inward* motion — bound contracting after an
2351
+ * extreme leaves the window. Y-only; X transitions ignore this field.
2352
+ */
2353
+ contractMs?: number;
2354
+ }
2355
+
2099
2356
  export declare const rosePineDawn: ThemePreset;
2100
2357
 
2101
2358
  export declare const sandDune: ThemePreset;
@@ -2195,7 +2452,39 @@ export declare interface ThemePreset {
2195
2452
  backgroundSize?: string;
2196
2453
  }
2197
2454
 
2198
- export declare const TimeAxis: DefineComponent<__VLS_Props_12, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_12> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
2455
+ /**
2456
+ * Per-axis tick-set holder with self-managed fade.
2457
+ *
2458
+ * Each tick value gets its own {@link Animator}: entering ticks ramp `0 → 1`,
2459
+ * exiting ticks ramp `1 → 0` and are removed once they settle at zero.
2460
+ * Callers drive the clock with {@link tick} once per frame, then read the
2461
+ * current opacity table via {@link snapshot}.
2462
+ *
2463
+ * Pre-arming (initial mount, dataset swap) the tracker uses duration `0` so
2464
+ * the very first nice-tick sets snap into place without an opening fade —
2465
+ * transient tick churn during layout settling should not look animated.
2466
+ */
2467
+ declare interface TickEntry {
2468
+ /** Tick value (time or price). */
2469
+ readonly value: number;
2470
+ /** Current opacity in [0, 1]. */
2471
+ readonly opacity: number;
2472
+ }
2473
+
2474
+ declare interface TickTrackerSnapshot {
2475
+ /**
2476
+ * Every tick the tracker still considers alive — current ones at their
2477
+ * resolved opacity (1.0 once any pending fade-in settles) and fading-out
2478
+ * ones above 0.
2479
+ */
2480
+ readonly entries: readonly TickEntry[];
2481
+ /** True while at least one entry hasn't reached its target opacity. */
2482
+ readonly isAnimating: boolean;
2483
+ }
2484
+
2485
+ export declare const TimeAxis: DefineComponent<__VLS_Props_12, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_12> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {
2486
+ containerRef: HTMLDivElement;
2487
+ }, HTMLDivElement>;
2199
2488
 
2200
2489
  /** A single time-value data point for line and bar series. Time is a timestamp in milliseconds. */
2201
2490
  export declare interface TimePoint {
@@ -2208,57 +2497,6 @@ export declare type TimePointInput = Omit<TimePoint, 'time'> & {
2208
2497
  time: TimeValue;
2209
2498
  };
2210
2499
 
2211
- declare class TimeScale {
2212
- private from;
2213
- private to;
2214
- private width;
2215
- private pixelRatio;
2216
- private dataInterval;
2217
- private labelCountHintValue;
2218
- private minSpacingValue;
2219
- private resolvedInterval;
2220
- private lastInterval;
2221
- /**
2222
- * "want" (desired interval post-floor) at the time lastInterval was snapped.
2223
- * Hysteresis band anchors to this so micro range drift back across a tier
2224
- * boundary doesn't flip the label density — mirrors YScale, see there for
2225
- * the full reasoning.
2226
- */
2227
- private lastWant;
2228
- /** Identifies the dataInterval bucket whose tier list drove lastInterval. */
2229
- private lastBucketKey;
2230
- private get labelCountHint();
2231
- private get minLabelSpacing();
2232
- update(range: VisibleRange, mediaWidth: number, pixelRatio: number, dataInterval?: number): void;
2233
- setLabelCount(n: number | null | undefined): void;
2234
- setMinSpacing(px: number | null | undefined): void;
2235
- private resetHysteresis;
2236
- timeToX(time: number): number;
2237
- timeToBitmapX(time: number): number;
2238
- xToTime(x: number): number;
2239
- pixelDeltaToTimeDelta(pixelDelta: number): number;
2240
- barWidthMedia(dataInterval: number): number;
2241
- barWidthBitmap(dataInterval: number): number;
2242
- /**
2243
- * Evenly spaced "nice" tick times. Resolution uses the cached
2244
- * `dataInterval` set by `update()`; callers that bypass `update()` can
2245
- * still pass it here for back-compat.
2246
- */
2247
- niceTickValues(dataInterval: number): {
2248
- ticks: number[];
2249
- tickInterval: number;
2250
- };
2251
- getRange(): VisibleRange;
2252
- getMediaWidth(): number;
2253
- /**
2254
- * Resolve the next tick interval. Walks `niceTimeIntervals(dataInterval)`
2255
- * looking for the smallest tier ≥ desired spacing; retains the previous
2256
- * tier inside a ratio band so micro pan/zoom doesn't flip label density.
2257
- */
2258
- private resolveInterval;
2259
- private countTicks;
2260
- }
2261
-
2262
2500
  /**
2263
2501
  * Accepted time input: a timestamp in **milliseconds** (like `Date.now()`) or a `Date` object.
2264
2502
  * `Date` values are converted to milliseconds internally via `Date.getTime()`.
@@ -2309,6 +2547,57 @@ export declare interface TooltipPositionArgs {
2309
2547
  offsetY?: number;
2310
2548
  }
2311
2549
 
2550
+ /**
2551
+ * Smoothing-curve contract. Implementations (`YRangeHermite`, `YRangeSpring`,
2552
+ * `RangeSnap` for Y; `VisibleRangeSpring`, `RangeSnap` for X) drive a value
2553
+ * of type `T` from one snapshot to the next while maintaining `current` /
2554
+ * `target` / velocity continuity.
2555
+ *
2556
+ * Parametric over `T` so X and Y share the same interface — Y uses
2557
+ * `Transition<YRange>` (default), X uses `Transition<VisibleRange>`.
2558
+ *
2559
+ * This is the single public customization point for the chart's curves.
2560
+ * Other animation math (entry tweens, pulse, axis tick fade) stays
2561
+ * engine-fixed.
2562
+ */
2563
+ declare interface Transition<T> {
2564
+ /** Current sampled position. Read by renderers on every frame. */
2565
+ readonly current: T;
2566
+ /** Active retarget destination. May equal `current` after settle. */
2567
+ readonly target: T;
2568
+ /** True while position has not yet converged to `target`. */
2569
+ readonly animating: boolean;
2570
+ /**
2571
+ * Begin a new transition toward `value`. Existing velocity is carried
2572
+ * over (no reset twitch). The engine supplies the active settle times
2573
+ * via `opts.expandMs` (and `opts.contractMs` for Y).
2574
+ */
2575
+ retarget(value: T, opts?: RetargetOptions): void;
2576
+ /** Land at `value` instantly. Velocity resets to zero. */
2577
+ snap(value: T, opts?: {
2578
+ now?: number;
2579
+ }): void;
2580
+ /** Advance to `now`. Returns `true` while still perceptibly moving. */
2581
+ tick(now: number): boolean;
2582
+ }
2583
+
2584
+ /**
2585
+ * Context handed to a {@link TransitionFactory} at chart construction.
2586
+ * Holds the initial value so the produced transition starts pinned to
2587
+ * the same value the chart will render on its first frame.
2588
+ */
2589
+ declare interface TransitionContext<T> {
2590
+ initial: T;
2591
+ }
2592
+
2593
+ /**
2594
+ * Factory function returning a fresh {@link Transition}. Pass one as
2595
+ * `animations.axis.y.curve` (or `animations.axis.x.curve`) to plug a custom
2596
+ * smoothing strategy. Built-in factories: {@link hermite} (Y default),
2597
+ * {@link spring} (X default, also valid for Y), {@link snap} (no animation).
2598
+ */
2599
+ declare type TransitionFactory<T> = (ctx: TransitionContext<T>) => Transition<T>;
2600
+
2312
2601
  /** Font family and base font size used across the chart. */
2313
2602
  export declare interface Typography {
2314
2603
  /** CSS `font-family` stack applied to all text rendered by the chart. */
@@ -2356,11 +2645,26 @@ export declare function useYRange(chart: ChartInstance): Ref<YRange>;
2356
2645
  /** Signature for a value-to-string formatter (YAxis, YLabel, Pie, Sparkline, NumberFlow). */
2357
2646
  export declare type ValueFormatter = (value: number) => string;
2358
2647
 
2359
- /** Time range (timestamps in milliseconds) of the currently visible portion of the chart. */
2360
- export declare interface VisibleRange {
2361
- from: number;
2362
- to: number;
2363
- }
2648
+ /** @deprecated Use {@link XRange} instead. Visible time range of the chart. */
2649
+ export declare type VisibleRange = XRange;
2650
+
2651
+ /**
2652
+ * Argument accepted by {@link Chart.setVisibleRange}. Three forms:
2653
+ *
2654
+ * - `number N` — show the last N bars from the data tail (anchor right).
2655
+ * - `{ from, to }` — explicit time range; `from`/`to` accept either epoch
2656
+ * milliseconds or `Date`, normalised to ms internally.
2657
+ * - `{ from, bars }` — anchor the visible window at `from` and extend
2658
+ * right by `bars` data intervals. Useful for "show N bars starting
2659
+ * here" patterns (warm-up windows for streaming charts, etc.).
2660
+ */
2661
+ declare type VisibleRangeSpec = number | {
2662
+ from: TimeValue;
2663
+ to: TimeValue;
2664
+ } | {
2665
+ from: TimeValue;
2666
+ bars: number;
2667
+ };
2364
2668
 
2365
2669
  /** Configuration for the X (time) axis. */
2366
2670
  export declare interface XAxisConfig {
@@ -2370,7 +2674,72 @@ export declare interface XAxisConfig {
2370
2674
  visible?: boolean;
2371
2675
  }
2372
2676
 
2373
- export declare const YAxis: DefineComponent<__VLS_Props_15, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_15> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
2677
+ /** Time range (timestamps in milliseconds) of the currently visible portion of the chart. */
2678
+ declare interface XRange {
2679
+ from: number;
2680
+ to: number;
2681
+ }
2682
+
2683
+ declare class XScale {
2684
+ /**
2685
+ * Shared fade state for time ticks. Grid lines (canvas) and DOM tick labels
2686
+ * read opacity from the same tracker, so a tick fading in/out looks
2687
+ * identical on both surfaces.
2688
+ */
2689
+ readonly tickTracker: AxisTickTracker;
2690
+ private from;
2691
+ private to;
2692
+ private width;
2693
+ private pixelRatio;
2694
+ private dataInterval;
2695
+ private labelCountHintValue;
2696
+ private minSpacingValue;
2697
+ private resolvedInterval;
2698
+ private lastInterval;
2699
+ /**
2700
+ * "want" (desired interval post-floor) at the time lastInterval was snapped.
2701
+ * Hysteresis band anchors to this so micro range drift back across a tier
2702
+ * boundary doesn't flip the label density — mirrors YScale, see there for
2703
+ * the full reasoning.
2704
+ */
2705
+ private lastWant;
2706
+ /** Identifies the dataInterval bucket whose tier list drove lastInterval. */
2707
+ private lastBucketKey;
2708
+ private get labelCountHint();
2709
+ private get minLabelSpacing();
2710
+ update(range: XRange, mediaWidth: number, pixelRatio: number, dataInterval?: number): void;
2711
+ setLabelCount(n: number | null | undefined): void;
2712
+ setMinSpacing(px: number | null | undefined): void;
2713
+ private resetHysteresis;
2714
+ timeToX(time: number): number;
2715
+ timeToBitmapX(time: number): number;
2716
+ xToTime(x: number): number;
2717
+ pixelDeltaToTimeDelta(pixelDelta: number): number;
2718
+ barWidthMedia(dataInterval: number): number;
2719
+ barWidthBitmap(dataInterval: number): number;
2720
+ /**
2721
+ * Evenly spaced "nice" tick times. Resolution uses the cached
2722
+ * `dataInterval` set by `update()`; callers that bypass `update()` can
2723
+ * still pass it here for back-compat.
2724
+ */
2725
+ niceTickValues(dataInterval: number): {
2726
+ ticks: number[];
2727
+ tickInterval: number;
2728
+ };
2729
+ getRange(): XRange;
2730
+ getMediaWidth(): number;
2731
+ /**
2732
+ * Resolve the next tick interval. Walks `niceTimeIntervals(dataInterval)`
2733
+ * looking for the smallest tier ≥ desired spacing; retains the previous
2734
+ * tier inside a ratio band so micro pan/zoom doesn't flip label density.
2735
+ */
2736
+ private resolveInterval;
2737
+ private countTicks;
2738
+ }
2739
+
2740
+ export declare const YAxis: DefineComponent<__VLS_Props_15, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_15> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {
2741
+ containerRef: HTMLDivElement;
2742
+ }, HTMLDivElement>;
2374
2743
 
2375
2744
  /** Configuration for the Y axis. */
2376
2745
  export declare interface YAxisConfig {
@@ -2389,7 +2758,10 @@ export declare const YLabel: __VLS_WithTemplateSlots_8<typeof __VLS_component_8,
2389
2758
  /** Direction of the current value vs. previous close. Drives the badge color in the default UI. */
2390
2759
  declare type YLabelDirection = 'up' | 'down' | 'neutral';
2391
2760
 
2392
- /** Min/max value range for the Y axis. */
2761
+ /** Value range covered by the chart's Y axis at a given frame. Animated as a
2762
+ * single struct so the upper and lower bounds always move in lockstep — no
2763
+ * half-tween states where the visible domain is wider on one side than the
2764
+ * other for a frame. */
2393
2765
  export declare interface YRange {
2394
2766
  min: number;
2395
2767
  max: number;
@@ -2400,6 +2772,8 @@ export declare interface YRange {
2400
2772
  * Also provides tick generation and value formatting for the Y axis.
2401
2773
  */
2402
2774
  declare class YScale {
2775
+ /** Shared fade state for Y ticks; see {@link TimeScale.tickTracker}. */
2776
+ readonly tickTracker: AxisTickTracker;
2403
2777
  private min;
2404
2778
  private max;
2405
2779
  private height;