Creates a new diverging bar trace.
The MAIDR layer carrying the two sides
Protected ReadonlyobserversProtectedisProtectedisTrue while AbstractTrace.getStateAt computes state at a temporarily moved cursor. Enforces (structurally, not just by documentation) that state getters never notify observers.
Protected ReadonlyidProtected ReadonlytypeProtected ReadonlytitleProtected ReadonlynameWhat this layer is, when the producer named it. See MaidrLayer.name.
Protected ReadonlyxProtected ReadonlyyProtected ReadonlyzProtected ReadonlynavigationProtected ReadonlylayerProtected ReadonlymovableProtected ReadonlypointsProtected ReadonlybarProtected ReadonlyhighlightProtected ReadonlyorientationProtected ReadonlyminProtected ReadonlymaxProtected ReadonlysupportsAbstract property that subclasses must implement to indicate extrema support
ProtectedisWhether the cursor has no point to report.
Read from dimension rather than from any one trace's data,
because that is the one shape every trace already answers in. It is also
evaluated at the cursor — LineTrace returns the current series'
length as cols — so this covers a ragged layer, where one series has
points and another has none, and not only a layer that is empty
throughout.
True when there is nothing at (row, col) to describe
ProtectedoutThe state pushed to observers when navigation leaves the data.
Declared as TraceEmptyState rather than the whole TraceState union
because that is what every implementation actually returns — the accessor
exists so AbstractPlot.notifyOutOfBounds has an empty state to
push. Narrowing it here is what lets the braille and highlight callers
hand the value straight on: those states accept the empty trace shape but
not a populated one, so a wider declaration would force each of them to
cast, and a cast is exactly what stops the compiler from noticing if an
override ever starts returning a populated state.
The empty trace state, positioned for out-of-bounds audio panning.
ProtectedautoplayProtectedhasThe trace's chart type. Lightweight alternative to reading
state.traceType, which eagerly computes the full audio/braille/text/
highlight state just to expose this one string.
ProtectedbrailleProtecteddimensionProtectedvaluesProtectedgroupsA diverging chart's sides are drawn in the order they are declared.
SegmentedTrace defaults to reverse because a stacked bar's producers
draw its segments bottom-up. A diverging chart is not stacked -- the two
sides sit either side of a baseline rather than on top of one another --
so there is no stacking order to inherit, and a producer emits the left
bar then the right one, which is the order the data declares them in.
The first example authored for this type got it wrong by following that natural order, which is the evidence: an author who has to know about the stacked bar's convention to draw a pyramid will not know about it. The failure is silent and visual-only -- audio, text and braille never go through the element mapping, so every announcement stays correct while the highlight sits on the opposite bar.
domMapping.groupDirection still overrides this in either direction.
True unless the layer asks for the reverse
ProtectedaudioProtectedtextGets the description state for the segmented bar trace. Overrides bar description to include fill category information.
The description state containing chart metadata and data table
Gets the current state of the trace including audio, braille, text, and highlight information.
The current TraceState
ProtectedhighlightProtectedgetGets safe row and column indices to prevent accessing undefined values
Object with safe row and column indices
Registers an observer to receive state updates.
The observer to add
Removes an observer from receiving state updates.
The observer to remove
Notifies all registered observers with the current state.
Notifies observers that an out-of-bounds condition occurred.
Base implementation of navigation in HIGHER and LOWER modes of ROTOR, default is no-op Needs to be implemented in Line, Bar, Heatmap, Candlestick
Utility function to compare point values for rotor functionality
boolean value
Returns true if this trace supports compare (lower/higher value) navigation. Override to false for trace types that don't use compare modes (e.g., scatter, which is all we currently have).
Returns the display name for the default data navigation mode. Override to provide a trace-specific name (e.g., "ROW AND COLUMN NAVIGATION" for scatter).
Returns the rotor's compare-mode labels and boundary-message nouns. Override to rename the two compare units for a trace-specific semantic (e.g., the candlestick delta layer uses "above line" / "below line").
Get all highlight SVG elements for this trace Used by HighlightService for high contrast mode
Array of all SVG elements, or empty array if none
Get all original (visible) SVG elements for this trace. These are the actual rendered elements, not the hidden clones used for highlighting. Used by HighlightService for high contrast mode color changes.
Array of all original SVG elements, or empty array if none
ProtectedgetComputes the trace state at an arbitrary position without moving the user's cursor or notifying observers. Used by monitor mode to sonify and announce a newly appended point while the user stays put.
The state getters read this.row/this.col internally, so the cursor
is moved temporarily and always restored in a finally block — this
method is the single owner of that pattern.
Re-entrancy hazard: this is only safe because the entire call chain is synchronous (no await points), so timers (e.g. autoplay ticks) cannot interleave before the finally-restore, and state getters never notify observers. If a getter ever becomes async or triggers notifications, callers could observe the temporary cursor.
The row of the position to compute state for
The column of the position to compute state for
The trace state at the requested position
Resets the trace to initial entry state
ProtectedgetReturns a human-readable label for this trace's chart type (e.g., 'Bar Chart', 'Scatter Plot') for display in the description modal. Falls back to the raw layer type if no mapping is registered.
ProtectedgetBuilds the axes object for the description state, including z only when the layer explicitly provides a z-axis label. Subclasses should call this instead of constructing the axes object inline so charts without a real z dimension don't surface the placeholder default.
ProtectedfinalizeCommon post-navigation cleanup that should be called by subclasses after they update their internal state
Returns true if this trace supports intersection navigation mode. Opt-in per trace type: override to return true (possibly conditionally, e.g. based on data shape) for trace types that expose point intersections between series. Intersection navigation is a trace-level capability — it has no meaning at the figure or subplot level, which is why it lives on AbstractTrace rather than AbstractPlot.
Returns true if this trace supports point-by-point navigation mode. Opt-in per trace type: override to return true for traces that expose individual data points navigable in reading order (left/right) and column-major order (up/down). Currently only ScatterTrace.
Move to the next point intersection (right arrow in intersection rotor mode). Default is a no-op returning false; subclasses that advertise supportsIntersectionMode must override to provide real behavior.
Move to the previous point intersection (left arrow in intersection rotor mode). Default is a no-op returning false; subclasses that advertise supportsIntersectionMode must override to provide real behavior.
Notifies the trace that the rotor is entering or leaving INTERSECTION_MODE. Default is a no-op; line-style traces don't need to track mode state because their state output is unchanged by the rotor mode. Traces whose audio/text output differs in intersection mode (e.g. ScatterTrace, which normally plays the whole x-column as a chord and must instead focus a single point) override this to flip an internal flag.
True when entering intersection mode, false when leaving.
Trace-specific rotor filter units appended to the rotor cycle after the built-in data/compare/grid/intersection modes. Each unit restricts navigation to points matching a predicate (e.g. only bullish candles). Default: none. Override to opt in (e.g. Candlestick exposes bullish/bearish/neutral units). The returned list is treated as read-only by the rotor service.
Moves within an active rotor filter unit along the filtered axis.
Called by RotorNavigationService when the current rotor mode is
one of this trace's getRotorFilterUnits. Filter units navigate a
single axis, so only left/right are dispatched here — the service
announces up/down as unavailable without calling the model (matching
intersection mode). Implementations should move to the nearest point
matching the unit identified by key and notify observers, returning
true; when no such point exists they should call notifyRotorBounds
and return false.
Default is a no-op that reports bounds, so a trace advertising a filter unit but forgetting to implement movement fails safe (announces "no point found") rather than moving unexpectedly.
The RotorFilterUnit.key of the active unit
The direction to search
True if the cursor moved, false otherwise
Checks if this plot supports extrema navigation.
True if extrema navigation is supported
Base implementation for getting current X value Subclasses can override if they have different data structures
Moves to a specific X value in the trace.
The X value to navigate to
True if the move was successful, false otherwise
Gets the unique identifier for this trace.
The trace ID
Moves the active point to the pointer location and returns directional guidance toward the nearest data geometry in a single call.
Combining both operations avoids running findNearestPoint twice per
pointermove event — important on dense plots where the scan is the
hot path.
Screen-space x position of the pointer/finger
Screen-space y position of the pointer/finger
Guidance state relative to nearest point, or null when unavailable
ProtectedmoveMoves the trace to the nearest point when the pointer is within its bounds and the trace is not already focused on that point.
onCurve is intentionally non-optional: the caller has already paid
the cost of isPointInBounds to assemble guidance state, and
forcing subclasses to accept the value makes the contract explicit so a
future override cannot silently recompute (or worse, ignore) it.
Subclasses override this to customise hover-driven navigation:
Checks if the specified coordinates are within bounds of the element.
The x-coordinate
The y-coordinate
Object containing the SVG element and its position
True if the point is in bounds, false otherwise
Cleans up bar plot resources including points and min/max arrays.
ProtectedrangeThe chart's min and max description stats.
A chart of nothing but gaps has no range at all, and safeMin/safeMax
answer an empty set with positive and negative Infinity. Report that the
way every other modality reports an absent value rather than announcing an
infinity.
Shared so SegmentedTrace, which replaces the whole stats block rather
than extending it, cannot drift back to announcing an infinity.
The min and max stats, in that order
Finds the bar element under the specified coordinates.
Unlike line/scatter/box traces (which return the nearest center regardless of cursor position), bar charts hit-test against each bar's bounding box and return null when the cursor is between bars. As a consequence, pointer guidance beeps fire only when the pointer is inside a bar — there is no directional guidance toward the closest bar from outside. This is intentional: bars are area marks (not points), and "nearest bar" from an arbitrary position is rarely the user's intent.
The x-coordinate
The y-coordinate
Object containing the element and its position, or null if not found
ProtectedcompareShared rotor compare-search across the bars in the current row. Steps through barValues from the current column in the given direction, moving to the first bar whose value satisfies the comparison.
The direction to search (left or right)
The comparison type (lower or higher)
True if a matching bar was found, false otherwise
Get extrema targets for the current segmented bar plot trace Returns min and max values within the current group the user is navigating
Array of extrema targets for navigation
Navigate to a specific extrema target
The extrema target to navigate to
ProtectedupdateUpdate the visual position of the current point This method should be called when navigation changes
ProtectedmapOptionalselector: string | string[] | (string | null)[][]
Trace implementation for population pyramids and diverging bar charts.
Two series drawn back to back across a shared category axis, one growing left and one growing right -- a population pyramid by age band, or a Likert scale split around a neutral midpoint. The category navigation is the segmented bar's, so what is new is entirely in how a signed value is read.
The sign is a direction, not a magnitude. A producer emits the values as the chart draws them, so the left-hand series is negative. Pitched that way, the biggest bar on the left becomes the lowest note on the chart: a cohort of two million men sounds smaller than a cohort of ten thousand women, and the pyramid is heard as a chart that sags on one side. The pitch takes the magnitude and the announcement names the side, which is how a sighted reader takes it in -- length from the bar, side from which way it points.
The balance is the finding. A pyramid is drawn back to back so the two sides can be compared at a glance, and that comparison is a subtraction a listener cannot do by ear across every band. Because the values arrive signed, the summary row the segmented bar already builds -- the sum down a category -- is that comparison:
(-left) + rightis what one side has over the other. It is renamed rather than recomputed, since "Sum is -40,000" invites a reader to hear a total that came out negative.