@pond-ts/charts API Reference
    Preparing search index...

    Interface ChartContainerProps

    interface ChartContainerProps {
        calendar?: TradingCalendarLike;
        children?: ReactNode;
        creating?: AnnotationKind | null;
        crosshairSnap?: boolean;
        cursor?: CursorMode;
        cursorSequence?: Sequence | BoundedSequence;
        cursorTime?: boolean;
        discontinuities?: DiscontinuityProvider;
        editAnnotations?: boolean;
        hovered?: SelectInfo | null;
        minDuration?: number;
        onCreate?: (spec: CreateSpec) => void;
        onEditAnnotation?: (id: string) => void;
        onHover?: (hit: SelectInfo | null) => void;
        onHoverAnnotation?: (id: string | null) => void;
        onRegionSelect?: (range: readonly [number, number]) => void;
        onSelect?: (hit: SelectInfo | null) => void;
        onSelectAnnotation?: (id: string | null) => void;
        onTimeRangeChange?: (range: [number, number]) => void;
        onTrackerChanged?: (info: TrackerInfo | null) => void;
        panZoom?: boolean;
        range?: TimeRange | readonly [number, number];
        regionSelectModifier?: "shift";
        rowGap?: number;
        selected?: SelectInfo | null;
        showAxis?: boolean;
        snap?: boolean;
        spacing?: "proportional" | "uniform";
        theme?: ChartTheme;
        timeFormat?: AxisFormat;
        trackerPosition?: number | null;
        width: number;
    }
    Index

    Properties

    calendar?: TradingCalendarLike

    The high-level sugar for discontinuities: a trading calendar the container derives the provider from itself (calendar.discontinuities({ spacing })), so you don't wire the low-level prop. A @pond-ts/financial TradingCalendar satisfies the structural TradingCalendarLike shape (charts never imports that package). Combine with spacing. For the full option matrix (a bar period, a scoped range) use the low-level discontinuities prop instead. Only affects a time axis.

    The provider is memoized on (calendar, spacing), so pass a stable calendar reference (build it once, not inline in JSX).

    children?: ReactNode
    creating?: AnnotationKind | null

    The armed annotation creation tool (the consumer's toolbar sets it), or null/omitted for idle. When set, the plot captures a create gesture — a preview tracks the pointer, and on release onCreate fires. The consumer then adds the mark, disarms (back to null), and selects it (spring-loaded); keep it set to place several. Requires editAnnotations.

    crosshairSnap?: boolean

    cursor="crosshair" reticle y snapping. Default true — the crosshair centres on the nearest data point (the horizontal line snaps to that sample's value). false — the horizontal line + centre follow the pointer y freely, the value read as yScale.invert(pointerY). Either way the vertical line snaps its x to the data grid (so the time readout is clean), and both draw a full-height dashed vertical + full-width dashed horizontal line.

    cursor?: CursorMode

    In-chart cursor presentation — the default for all rows (a row may override via <ChartRow cursor>). Default 'line' — the synced vertical line, with values surfaced outside the chart via onTrackerChanged. 'point' / 'inline' / 'flag' add per-series marks; 'none' hides it. 'region' shades the bucket under the pointer (needs cursorSequence). See CursorMode.

    cursorSequence?: Sequence | BoundedSequence

    The bucketing for cursor="region" — the interval highlighted under the pointer. A pond Sequence (duration or calendar-aware — Sequence.every('1d'), Sequence.calendar('month')) is realized over the current view; a BoundedSequence (e.g. a TradingCalendar's sessionSequence() / barSequence()) is used as-is, so the band can track whole sessions. Either way the band maps through xScale, so on a trading-time axis the closed part of the bucket collapses. Ignored unless cursor="region".

    Time axis only. A bucket is a time interval, so the region cursor is gated to a time x-axis — on a value axis (a horizontal histogram, a value-keyed chart) it's a no-op (highlighting a value band on a horizontal histogram would be a different, y-oriented cursor).

    Pass a stable reference. The buckets are memoized on this value + the view range; a Sequence/BoundedSequence rebuilt inline every render re-realizes the buckets on each pointer move (harmless for a coarse day/session sequence, wasteful for a fine one over a wide view) — hoist it or useMemo it.

    cursorTime?: boolean

    Show the cursor's time atop the in-chart readout (when a row's cursor draws one). Default false. Formatted by timeFormat to match the time axis.

    discontinuities?: DiscontinuityProvider

    A trading-calendar discontinuity provider — closed-market time (weekends, holidays, overnight, lunch breaks) collapsed. Supply it to turn the shared x axis into a trading-time axis: gaps disappear and time stays proportional within each session. A @pond-ts/financial TradingCalendar.discontinuities() satisfies this structurally (charts never imports that package). The low-level primitive: pass calendar.discontinuities() (or a { spacing, period } variant) directly. Only affects a time axis (ignored on a value axis). Takes precedence over calendar if both are given.

    Pass a stable reference. The scale (and container frame) rebuild when this prop's identity changes, so memoize it — const disc = useMemo(() => calendar.discontinuities(), [calendar]) — rather than calling .discontinuities() inline in JSX, which would rebuild every render.

    editAnnotations?: boolean

    Enter annotation-edit mode: suppresses the data cursor and makes editable annotations (those given an onChange) interactive — hovering one reveals its handles + highlights it, and dragging edits it. Default false. Pairs with each annotation's onChange (where the edit goes); this is the mode that turns the affordances on and gets the cursor out of the way.

    hovered?: SelectInfo | null

    Controlled hover-highlight — the transiently lit mark (echo the onHover arg back), or null. Omitted ⇒ uncontrolled (the pointer over a selectable layer manages it internally). The hover analog of selected: pass it to pin a lit mark from outside the chart (e.g. hovering a legend / list row lights the matching BarChart bar). Only layers with a hover-highlight (currently BarChart) render it; keyed by the same SelectInfo identity as selection.

    minDuration?: number

    Zoom-in floor — the minimum visible duration in ms. Default 1.

    onCreate?: (spec: CreateSpec) => void

    Fired when a create gesture completes (on release). See CreateSpec.

    onEditAnnotation?: (id: string) => void

    Fired when a mark is double-clicked — the request to edit just that one (set its editing prop in response). Single click selects (inspect); double click edits. Works in any mode.

    onHover?: (hit: SelectInfo | null) => void

    Fires when the pointer enters a selectable layer's mark (the hit mark) or leaves every mark (null) — the hover analog of onSelect. Notification only (works controlled or uncontrolled), and deduped: it fires on a mark transition, not on every pointer move. Wire it to mirror hover out-of-band (e.g. a list row ↔ the bar), pairing with hovered to sync both ways. (The annotation counterpart is onHoverAnnotation.)

    Dedup key: by the mark's key + label only (not value/color). So on a live chart where a bar's value changes while the cursor stays on it, this won't re-fire — read the current value from your series, not the last onHover payload. (Matches the internal hover-highlight, which repaints on key transitions.)

    onHoverAnnotation?: (id: string | null) => void

    Fired when the pointer enters an annotation (its id) or leaves it (null). Mirror it to a controlled hovered prop on each mark to sync hover both ways (e.g. a legend row ↔ the mark). Fires in any mode.

    onRegionSelect?: (range: readonly [number, number]) => void

    Makes the region cursor draggable: drag across the plot and the band extends bucket by bucket (snapping to cursorSequence points); on release this fires once with the selected [lo, hi] span, and the cursor reverts to the single-bucket highlight (it does not keep the range). Typical use — zoom the view to the returned span (the container doesn't zoom itself; that's the consumer's call), or map it onto a data subscription's range params.

    The span is a neutral numeric pair in axis units — epoch ms on a time axis, the axis value (strike, distance, …) on a value axis — mirroring the polymorphic range input. A time consumer that wants a TimeRange builds one from the pair.

    With no cursorSequence the region cursor is the degenerate case — it renders as a line on hover and the drag is freeform (raw [lo, hi], no bucket snapping); the same callback fires on release. Bucket snapping needs a cursorSequence, which is time-axis only (a time interval over a value domain is meaningless), so a value axis is always freeform. No-op unless cursor="region" on a time or value x-axis (a category axis is excluded — an ordinal-slot select is a different gesture).

    onSelect?: (hit: SelectInfo | null) => void

    Fires when a selectable layer's mark is clicked, with the hit mark, or null when a click misses every mark (or hits a layer with no id — display-only, so it reads as empty space). Notification only — works in both controlled and uncontrolled mode. If this or selected is set but no layer has an id, a dev-warning notes that nothing is selectable.

    onSelectAnnotation?: (id: string | null) => void

    Fired when an annotation is clicked (its id), the plot is clicked empty (null), or a region is double-clicked (the shortcut into edit). The consumer holds the selected id and sets each mark's selected={id === sel}.

    onTimeRangeChange?: (range: [number, number]) => void

    Controlled view range — fires on pan/zoom with the new [start, end]. Wire it back to range for a controlled chart; omit for uncontrolled (the container holds the view internally). Uncontrolled + panZoom seeds the internal view from range whenever it isn't actively holding one — so toggling panZoom on, or a controlled→uncontrolled switch, starts from the current range, not the mount-time one. Once uncontrolled, later range changes are ignored so they can't fight the user's pan. To drive the range externally — or to follow a live sliding window — use controlled mode (this callback).

    onTrackerChanged?: (info: TrackerInfo | null) => void

    Fires on pointer move with the hovered time + every series' value there (so you can render a readout outside the chart), and null on leave.

    panZoom?: boolean

    Enable pan/zoom: drag the plot to pan the time range, wheel to zoom around the cursor. Default off — so it doesn't capture drag/scroll unless asked.

    range?: TimeRange | readonly [number, number]

    The shared x domain [begin, end] — a tuple, or a TimeRange (series.timeRange()). Units follow the data: epoch-ms for a time axis, the value units (distance, …) for a value axis. Omit to auto-fit to the rows' extents. The axis kind is never taken from here — it's inferred from the data — so a tuple stays a time domain on a time chart.

    regionSelectModifier?: "shift"

    Which modifier a region-drag needs — set 'shift' when you also enable panZoom and want plain drag to pan, shift-drag to select. It's only enforced while panZoom is on (with pan off there's no gesture conflict, so shift is optional — either drag selects). Omitted ⇒ a region-drag preempts pan (drag always selects; document that precedence for users). Wheel-zoom is unaffected in every case.

    rowGap?: number

    Vertical space between rows in CSS pixels (not under the axis). Default 0.

    selected?: SelectInfo | null

    Controlled selection — the selected mark (echo the onSelect arg back), or null. Omitted ⇒ uncontrolled (a click on a selectable layer manages it internally; pass null to force nothing selected). A layer is selectable only when it carries an id (the stable series identity) — BarChart / ScatterChart highlight the mark matching the selection's id (the series) and its key (the sample), so two series sharing a timestamp don't both light up, and the selection survives a data update (it keys on the stable id, not the sample key). A layer with no id renders + reads out but can't be selected.

    showAxis?: boolean

    Auto-render the shared x axis under the rows. Default true. Set false for a bare plot (a sparkline), or when you place your own <XAxis> child (e.g. with a label, custom ticks, or on side="top"). Named showAxis (not axis) to avoid clashing with a layer's axis prop, which picks which <YAxis> it scales against — a different axis entirely.

    snap?: boolean

    Snap mode (the toolbar's "Snap"). Default true. When on, a dragged mark snaps to other marks' guidelines (their x-positions, within a few px) so spans align; off = free placement. (Snapping to the nearest data sample is not implemented — guideline alignment only.)

    spacing?: "proportional" | "uniform"

    The trading axis metric, when a calendar is supplied (trading-calendar RFC Q7). 'proportional' (default) keeps time proportional within and across sessions — a half-day is half as wide. 'uniform' gives every session equal width (the TradingView ordinal look). Ignored without calendar (a low-level discontinuities provider already carries its own metric).

    theme?: ChartTheme

    Visual theme for all rows; defaults to defaultTheme.

    timeFormat?: AxisFormat

    Time-axis value formatting — a d3 time specifier string (e.g. '%H:%M') or a (epochMs) => string function (AxisFormat); applies to both the time axis labels and the cursor-time readout. Omitted ⇒ d3's multi-scale time format (12 PM, 12:10, …).

    trackerPosition?: number | null

    Controlled tracker position (epoch ms) — pins the synced crosshair across rows. Omit for uncontrolled (the chart tracks the pointer itself); pass null to force it hidden. See onTrackerChanged.

    width: number

    Total width in CSS pixels (plot + axis gutters).