interface CandleGapBridgeStyle {
color?: string;
opacity?: number;
strokeWidth?: number;
strokeCap?: "butt" | "round" | "square";
}
interface CandleGapBandStyle {
fillColor?: string;
fillOpacity?: number;
borderColor?: string;
borderOpacity?: number;
borderWidth?: number;
intervals?: [number, number];
}
interface CandleGapLabelStyle {
color?: string;
position?: "left" | "right";
}
interface CandleGapStyle {
bridge?: false | CandleGapBridgeStyle;
band?: false | CandleGapBandStyle;
label?: false | CandleGapLabelStyle;
}
interface CandleGapsConfig {
gaps: CandleGap[];
styles?: Partial<Record<CandleGapKind, CandleGapStyle>>;
}
type ChartGapBridgeStyle = CandleGapBridgeStyle;
type ChartGapBandStyle = CandleGapBandStyle;
type ChartGapLabelStyle = CandleGapLabelStyle;
type ChartGapStyle = CandleGapStyle;
type ChartGapsConfig = CandleGapsConfig;
interface LineConfig {
width?: number; // stroke width in px; default 2
color?: string | SharedValue<string>; // line color override; defaults to palette
// accent. A SharedValue animates the stroke and the built-in
// selection dot on the UI thread; a custom selection dot,
// segment base, area-dot tint, and threshold rest color then
// use the palette line color
colors?: string[];// per-point gradient stops (left → right); wins over color
curve?: "monotone" | "linear"; // point interpolation; default "monotone"
// (smooth cubic). "linear" = straight segments / hard-edged.
simplify?: number; // screen-space path tolerance in px; default 0 (off).
// Removes only intermediate drawn points within the tolerance;
// source data, axis fitting, markers, and scrubbing stay exact.
join?: "round" | "miter" | "bevel"; // corner join; default "round".
// "miter" = sharp/angular peaks, "bevel" = flattened.
cap?: "round" | "butt" | "square"; // start/end cap; default "round".
// pair "butt" + join "miter" for a fully hard-edged line.
}
interface GradientConfig {
topOpacity?: number; // accent-derived top fill opacity
bottomOpacity?: number; // accent-derived bottom fill opacity
colors?: string[] | SharedValue<string[]>; // explicit gradient stops (top →
// bottom), ≥ 2 entries; overrides topOpacity/
// bottomOpacity when provided. A SharedValue animates
// the stops on the UI thread; keep ≥ 2 entries in it
positions?: number[]; // optional stop positions (0..1, ascending), same
// length as colors; ignored if the lengths differ
// (with animated colors, applied as given)
}
interface AreaDotsConfig { // dot-lattice fill of the area beneath the line
spacing?: number; // lattice pitch (px) between dots, both axes; default 12
size?: number; // dot diameter (px); default 1.6
color?: string; // dot color; omit to derive a faint tint from the line color
opacity?: number; // overall field opacity (0..1); default 1
}
interface ThresholdConfig {
// The split value (Y-axis units). A SharedValue<number> for a single live
// benchmark, OR a LiveChartPoint[] for a time-varying threshold the split,
// band + marker follow point-for-point (clamps to its first/last value outside
// its range → flat-extends to the live edge). See the Threshold split guide.
// Provide value OR series (series wins).
value?: SharedValue<number> | LiveChartPoint[];
// LIVE time-varying threshold: like the LiveChartPoint[] form but a
// SharedValue — .set()/.modify() tracks on the UI thread, no re-render
// (a VWAP updated every tick). Points sorted by time, like `data`.
series?: SharedValue<LiveChartPoint[]>;
aboveColor?: string; // stroke at/above value; default palette up-green
belowColor?: string; // stroke below value; default palette down-red
fill?: boolean | ThresholdFillConfig; // line↔threshold P/L band; default off
includeInRange?: boolean; // fold the threshold into the Y-range fit (like reference lines); default false
extendToStart?: boolean; // series: extend first value flat to the window start; default true
extendToNow?: boolean; // series: extend flat past the last point to "now"; default true
line?: boolean | ThresholdLineConfig; // marker line at value; default off
}
// Object form of `fill`: band opacity (0..1) on the above/below colors; default 0.16.
interface ThresholdFillConfig { opacity?: number }
interface ThresholdLineConfig {
label?: string; // label text, e.g. "Break-even"
labelPosition?: "left" | "right"; // "left" = inside plot (clear of y-axis); default "left"
labelAnchor?: "first" | "last"; // series: visible left-edge or live/right-edge value; default "last"
color?: string; // line + label color; default palette refLine/refLabel
labelColor?: string; // label text color; falls back to color, then palette refLabel
intervals?: [number, number]; // dash pattern; default [4, 4]
strokeWidth?: number; // default 1
showValue?: boolean; // append the formatted value to the label; default false
}
interface ThresholdBadgeRenderProps {
line: ThresholdLineConfig; // resolved marker-line config
value: SharedValue<number>; // live threshold value
valueStr: SharedValue<string>; // formatted with the chart's formatValue
y: SharedValue<number>; // live canvas Y (NaN when geometry is unavailable)
visible: SharedValue<boolean>; // whether the badge is inside the plot
}
interface BadgeConfig {
variant?: "default" | "minimal";
tail?: boolean; // pointed tail toward the dot; false = pill sits flush
// at the gutter edge (no tail space reserved); default true
background?: string;
position?: "right" | "left";
// Value in the right-gutter pill: centered, or lined up with a right-anchored
// Y-axis label column (yAxis.labelRightMargin) — kept within the pill's padX
// (next to the tail, a narrow pill gives up the left padding, then the
// right), moves with the column's width. Default "center".
textAlign?: "center" | "yAxisColumn";
// Shape / style — all Skia-native, drawn in the batched canvas pass (no perf cost):
radius?: number; // corner radius (px); default capsule (pillHeight/2), clamped to that max
borderColor?: string; // pill border color; default none
borderWidth?: number; // border stroke width (px), only drawn with borderColor; default 1
textColor?: string; // label text color override; default variant/theme rule
fontSize?: number; // badge font size (px); falls back to the chart `font`
fontFamily?: string; // badge font family; falls back to the chart `font`
fontWeight?: FontWeight; // badge font weight; falls back to the chart `font`
offsetX?: number; // nudge the whole badge horizontally (px); default 0
offsetY?: number; // nudge the whole badge vertically (px); default 0
followViewEdge?: boolean; // while time-scrolled, track the price at the visible
// window's right edge (badge value/color + value line + dot);
// default false
}
interface PulseConfig {
interval?: number; duration?: number; maxRadius?: number;
opacity?: number; strokeWidth?: number;
}
interface ValueLineConfig { strokeWidth?: number; intervals?: [number, number]; color?: string }
// Shared styling for a straight line (the connector, valueLine, …). Omit `intervals` for solid.
interface LineStyleConfig { color?: string; strokeWidth?: number; intervals?: [number, number] }
interface ScrubConfig {
markers?: boolean | ScrubMarkerConfig; // opt-in timestamp matching; default false
tooltip?: boolean; // existing master tooltip switch; false also suppresses seriesTooltip
// LiveChartSeries only: opt-in Morfi-style time + per-series value pills.
// false/omitted preserves the existing guide-only default.
seriesTooltip?: boolean | PerSeriesTooltipConfig;
dimTarget?: "future" | "otherCandles"; // default "future"; otherCandles hides the scrub line/dot in candle mode, falls back to future in line mode
dimOpacity?: number; // opacity of the selected dim target; clamped to [0, 1]; default 0.3
dimFadeMs?: number; // otherCandles fade-in/out duration; default 60; 0 = instant
crosshairLineColor?: string; crosshairDimColor?: string; // crosshairDimColor = legacy colored mask
crosshairStrokeWidth?: number; // line width in px; default 1
crosshairOvershoot?: number; // extend past top/bottom in px; preserves a custom top-tooltip stop; negatives clamp to 0; default 0
crosshairFade?: boolean; // fade near the live edge; default true
crosshairFadeDistance?: number; // visible line/dot/tooltip fade distance in px; negatives clamp to 0; default 4
crosshairLineCap?: "butt" | "round" | "square"; // omit to preserve the existing Skia default
crosshairDash?: number[] | boolean; // dash the crosshair line; true = [4,4], or explicit [on, off, …] px
tooltipBackground?: string; tooltipColor?: string; tooltipBorderColor?: string;
tooltipBorderRadius?: number; // pill corner radius; default 5
tooltipPlacement?: "side" | "top" | "bottom" | "point"; // default "side" (offset/flip); top/bottom center over the line; point floats above the scrub dot
tooltipMargin?: number; // gap (px) to the pinned plot edge (top for side/top, bottom for bottom); default 8
tooltipShowValue?: boolean; tooltipShowTime?: boolean; // default both true; drop a row (e.g. date-only)
panGestureDelay?: number; // press-and-hold ms before scrubbing activates; default 0
clampToPlot?: boolean; // plain scrub: ignore starts beyond the plot's X bounds and clamp active drags; default false
hideOverlaysOnScrub?: boolean; // fade markers + reference lines out while scrubbing; default false
snapToCandles?: boolean; // candle mode: snap the crosshair to candle centers (tick-to-tick); gaps between candles + line mode keep the raw X; default false
}
interface PerSeriesTooltipConfig {
alwaysShow?: boolean; // pin value pills to visible endpoints while idle; default false
bucketSeconds?: number; // omit to infer from the first visible series
formatSeriesValue?: (value: number, seriesId: string) => string; // UI-thread worklet
formatTimeRange?: (from: number, to: number) => string; // UI-thread worklet
maxLabelChars?: number; // ellipsis truncation; default 14
guideColor?: string;
guideWidth?: number; // default 1
guideDashPattern?: boolean | number[]; // default [3,3]; false = solid
timePillBackground?: string; timePillColor?: string; timePillBorderColor?: string;
timePillRadius?: number; timePillPaddingX?: number; timePillPaddingY?: number;
seriesPillBackground?: string;
seriesPillLabelColor?: string;
seriesPillValueColor?: string;
seriesPillBorderColor?: string;
seriesPillRadius?: number;
seriesPillPaddingX?: number; seriesPillPaddingY?: number;
seriesPillDotSize?: number; seriesPillDotGap?: number;
seriesPillLabelValueGap?: number;
intersectionDotSize?: number;
}
// Order-ticket mode (scrubAction). Opt-in — default off.
interface ScrubActionConfig {
icon?: string; // action-badge glyph; default "+"
background?: string; // action-badge background; default the accent / badge color
iconColor?: string; // icon + price-text color; default the badge text color
lineColor?: string; // horizontal level-line color; default palette.crosshairLine
text?: boolean; // show the price readout; default true. false → icon-only pill
timeBadge?: boolean; // date/time pill where the line meets the x-axis; default false
snap?: number; // round the reported price to this increment (e.g. 0.01, 0.5)
dismissOnTapOutside?: boolean; // empty-plot tap dismisses vs. re-places; default false
dismissOnAction?: boolean; // dismiss the reticle once the badge fires onScrubAction; default false
}
interface SelectionDotRingConfig {
color?: string; // ring color, defaults to the dot color
width?: number; // ring thickness past the dot, default 2
}
// The scrub-intersection dot (selectionDot). Default ON for LiveChart,
// OFF for LiveChartSeries (the crosshair + opt-in per-series tooltip dots mark it).
interface SelectionDotConfig {
size?: number; // dot radius, default 4
color?: string; // dot color, defaults to the line / leading-series color
ring?: boolean | SelectionDotRingConfig; // outer halo, default on
component?: ComponentType<SelectionDotProps>; // custom Skia dot; ignores size/color/ring
}
interface GridStyleConfig { color?: string; strokeWidth?: number; intervals?: number[]; opacity?: number }
interface YAxisScaleGestureConfig {
minScale?: number; // positive finite; default 0.25
maxScale?: number; // positive finite, at least minScale; default 10
dragDistance?: number; // points per exponential step; default 160
doubleTapReset?: boolean; // animate to clamped 1 over 240ms; default true
}
interface YAxisConfig {
// Chart formatValue(value, tickStep?) receives this grid's source-unit step.
// Fixed count supplies the evenly spaced step; dynamic ticks supply the fine
// interval. Badges/tooltips/layout samples omit it; one-arg formatters work.
// Built-in vertical price-axis drag; writes yRangeScale or internal state.
// Down zooms out, up zooms in. Default false. See the Y-range scaling guide.
scaleGesture?: boolean | YAxisScaleGestureConfig;
// Label side; reserve left label width with insets.left. Default "right".
side?: "left" | "right";
minGap?: number; // min px gap between grid lines; default 36
// Multiplier used to choose dynamic nice intervals without changing plotted
// values. Pair with formatValue using the same multiplier. Must be positive
// and finite; invalid values use 1. Unrepresentable scaled ranges fall back
// to source-unit intervals. Ignored with count. Default 1.
intervalScale?: number;
// Show a fixed number of evenly-spaced prices (top = high, bottom = low)
// instead of the dynamic nice-interval grid. Values track the live range each
// frame. `minGap` still floors the spacing; clamped to at most 15. Default 0.
count?: number;
// Place labels in a shared left-aligned column whose right edge sits this
// many px from the canvas edge. Omit for the centered-gutter placement.
// Line the live badge's value up with it via badge.textAlign "yAxisColumn".
labelRightMargin?: number;
// Gap between the shared label column and each grid/plain-reference-line end.
// Only applies with labelRightMargin. Default 0.
gridEndGap?: number;
// Float the price axis over a full-width plot instead of reserving a right
// gutter — the line/candles run to the edge and the labels float on top.
// Pairs with `timeScroll` (see the Time-scroll guide). Default false. @experimental
float?: boolean;
}
interface XAxisConfig {
// Minimum pixel gap between time labels. Updates immediately, even while paused.
minGap?: number; // default 60
// Vertical grid lines at the time labels, behind the series, each fading with
// its label. true = the gridStyle look; a GridStyleConfig overrides only the
// fields it sets (the rest fall back to gridStyle). Default false.
// Strokes stay within the plot width while departing labels fade into gutters.
gridLines?: boolean | GridStyleConfig;
}
// Fades both axes while LiveChart is idle. @experimental
interface AxisAutoHideConfig {
fadeInMs?: number; // interaction-start fade duration; default 60
fadeOutMs?: number; // fade back to idle; default 250
idleOpacity?: number; // axes' resting opacity (0 = hidden); default 0
hideAfterMs?: number; // idle delay before fade-out; default 3000
}
// Volume bars below the candles (candle mode only). Bars normalize to the largest
// visible volume; the candle plot shrinks by `maxHeight` to make room. @see CandlePoint.volume
interface VolumeConfig {
upColor?: string; // bars for up (close ≥ open) candles; default palette.candleUp
downColor?: string; // bars for down candles; default palette.candleDown
maxHeight?: number; // reserved band height (px) = the tallest bar; default 48
radius?: number; // bar-top corner radius (px); default 2
opacity?: number; // opacity of the whole band (0..1); default 0.6
}
// Horizontal time-scrolling (pan back through history). @experimental
interface TimeScrollConfig {
gesture?: "holdToScrub" | "axisDrag"; // activation; default "holdToScrub"
scrubHoldMs?: number; // holdToScrub: press-hold (ms) before scrub engages; default 500
hideLiveOnScrollBack?: boolean; // hide live badge + dot + value line while scrolled back (they mark the off-screen live price); default true. Ignored with badge.followViewEdge
overscroll?: number; // fraction of the window (0–1) pan/zoom may travel past the data bounds into blank space (TradingView-style); default 0 (hard stops at the oldest data / live edge)
fling?: boolean; // keep release momentum after a fast drag; false stops exactly where the finger lifts. Default true.
}
// Tunes the return-to-live glide (the `returnToLive` prop). @experimental
interface ReturnToLiveConfig {
duration?: number; // glide duration (ms) back to live; default 450 (0 = instant snap)
}
// Tune/disable the built-in transition animations — the object form of `transitions`.
interface TransitionConfig {
reveal?: number; // grow-in when data appears, on timeframe change, or candle→line; default 600 (0 = snap)
mode?: number; // candle↔line crossfade (single-series LiveChart only); default 300 (0 = snap)
candleLerpSpeed?: number; // candle-width ease speed (0–1, like smoothing); candle mode; default 0.08 (1 = instant resize)
}
// Styling for the breathing loading shell — the object form of `loading`.
interface LoadingConfig {
color?: string; // squiggle + skeleton color; default theme gridLine
strokeWidth?: number; // squiggle stroke width; default the chart line strokeWidth
amplitude?: number; // base breathing-wave height (px); default 14
speed?: number; // breathing-wave speed multiplier; default 1 (0 freezes)
axisLabels?: boolean; // draw the skeleton Y-axis placeholders; default true (false = squiggle only)
freezeAfterMs?: number; // freeze the squiggle after this many ms per showing; default none (≤ 0 = frozen at once)
}
// Pinch-to-zoom the visible time window (two-finger, focal-anchored). @experimental
interface ZoomConfig {
minTimeWindow?: number; // tightest window in seconds (max zoom-in); default timeWindow / 8
maxTimeWindow?: number; // explicit widest window; default full data/anchored history span, at least timeWindow
}
// App-owned UI-thread viewport. LiveChart only (line/candle). @experimental
interface ChartViewportControl {
end: SharedValue<number | null>; // right-edge unix seconds; null = follow live
window: SharedValue<number | null>; // positive, finite width in seconds; null = timeWindow
range?: SharedValue<Pick<ChartScale, "min" | "max"> | null>; // exact price bounds while end is non-null; invalid/null/omitted = auto-fit
}
// The viewport prop accepts false | ViewportConfig; false/omitted uses private state.
// Both shared values are required, so there is no true shorthand.
interface ViewportConfig extends ChartViewportControl {
windowSmoothing?: boolean; // default true; false copies non-null widths immediately
}
// Gestures write this pair; resetZoom() nulls both. Non-null values survive
// timeWindow/timeScroll/overscroll-setting changes. Future end values are honored;
// an end before the first retained point falls back to live unless range is valid.
// range requires finite min/max and difference, with min < max; it applies immediately,
// overriding auto-fit, range easing, nonNegative, maxValue, minRange, and yRangeScale.
// Gestures/resetZoom never write range; end=null makes it inactive.
// windowSmoothing affects only non-null widths, not value, automatic Y-range, or reset easing.
// Visible window reported by onVisibleRangeChange (unix seconds). @experimental
interface VisibleRange {
startSec: number; // left-edge time of the visible window
endSec: number; // right-edge time of the visible window
following: boolean; // true when at the live edge (not scrolled back / paused)
}
// Edge label (topLabel / bottomLabel). Default off — both opt-in.
interface AxisLabelConfig {
format?: (v: number) => string; // built-in value formatter; defaults to formatValue
color?: string; // text color; defaults to palette.gridLabel (muted)
// "left"/"right" pin to that edge (default "right"). "extrema" floats the label
// on the actual high (topLabel) / low (bottomLabel) data point. "extrema-edge"
// keeps the label on the top/bottom edge (x-aligned) with a dot + connector.
position?: "left" | "right" | "extrema" | "extrema-edge";
fontSize?: number; // built-in value text size (px); default 11
fontWeight?: FontWeight; // built-in value text weight; default platform default
fontFamily?: string; // built-in value text font family
dotColor?: string; // extrema modes — dot color; defaults to color
dotSize?: number; // extrema modes — dot diameter (px); default 7
dot?: boolean; // extrema modes — draw the marker dot; default true
// "extrema-edge" connector (dot → edge label). true = dashed default, false =
// none, or a LineStyleConfig. Default on (dashed) in "extrema-edge" mode.
connector?: boolean | LineStyleConfig;
render?: () => React.ReactElement | null; // custom element; overrides everything above
}
interface ChartInsets { top?: number; right?: number; bottom?: number; left?: number }
interface LeftEdgeFadeConfig { width?: number; startColor?: string; endColor?: string }
interface DotGlowConfig {
color?: string; // default: resolved dot fill color
radius?: number; // glow source-circle radius, default 7
blur?: number; // Skia blur radius, default 5
opacity?: number; // 0–1, default 0.18
}
interface DotRingConfig {
color?: string; // default: theme `badgeOuterBg`
width?: number; // default 2.5
}
// Shared live-dot styling (LiveChart `dot`; LiveChartSeries `dot` extends it)
interface DotConfig {
radius?: number; // color-filled dot radius, default 3.5
ring?: boolean | DotRingConfig; // crisp outer backing ring, default true
glow?: boolean | DotGlowConfig; // soft static glow, default false
show?: boolean; // @deprecated — prefer dot={false}; default true
color?: string; // dot fill, defaults to the line color
trackWhileParked?: boolean; // while scrolled back / overscrolled, the dot tracks the true live point — keeps pulsing, stays visible, hides once the point leaves the window; ignored with badge.followViewEdge (LiveChart only). Default false
}
interface MultiSeriesDotConfig extends DotConfig {
pulse?: boolean | PulseConfig;
valueLine?: boolean | ValueLineConfig;
valueLabel?: boolean;
}
interface LegendConfig {
visible?: boolean;
compact?: boolean;
position?: "top" | "bottom";
style?: LegendStyle;
}
interface FontConfig {
fontFamily?: string; // default "Menlo"
fontSize?: number; // default 11
fontWeight?: FontWeight;
typeface?: DataSourceParam; // require(...) / path / Uint8Array
fontManager?: SkFontMgr | null;
}