MAIDR Documentation - v4.4.0
    Preparing search index...

    Class NetworkTrace

    Trace implementation for network and node-link diagrams.

    The same graph cursor a FlowTrace carries, with the constraints relaxed: the edges are undirected and there are no stages, because a force layout has no columns and nothing to lay them out along.

    Layout position is emergent and carries no meaning, so it is not in the schema at all. Where a force-directed node lands is a fact about the solver's random seed, and announcing "upper left" as though it were data would be inventing a finding. The type has no x or y to be tempted by; highlighting goes through selectors, as everywhere else.

    What replaces position is the structure that is actually there. A node's degree is primary information on this chart -- the hub is the finding -- so it is announced on every move, and the nodes of a component are ordered by it, which puts the hubs where a reader arrives first.

    A reader must never be stuck in one component. Following edges reaches only the component you are in, and a graph with several would leave the rest unreachable and unannounced. So the arrows do not follow edges:

    • left and right walk the nodes of this component, most connected first;
    • up and down move to another component entirely.

    Between them they reach every node of the chart, which is the guarantee that matters. Following an edge -- the graph traversal itself -- is the rotor, which is also where it belongs on an undirected graph: a node's neighbours have equal status, so there is no "the" edge for an arrow to take, unlike a sankey where the widest ribbon is the one an eye follows.

    Hierarchy (View Summary)

    Implements

    Index

    Constructors

    Properties

    observers: Observer<TraceState>[]
    isWarning: boolean
    isComputingStateAt: boolean

    True while AbstractTrace.getStateAt computes state at a temporarily moved cursor. Enforces (structurally, not just by documentation) that state getters never notify observers.

    id: string
    type: TraceType
    title: string
    name: string | undefined

    What this layer is, when the producer named it. See MaidrLayer.name.

    xAxis: string
    yAxis: string
    z: string
    navigationService: NavigationService
    layer: MaidrLayer
    supportsExtrema: false

    No go-to-extrema dialog. The arrows already reach every node, and the most connected are named in the description; see extremaContract.

    movable: MovableGraph
    highlightValues: SVGElement[][] | null

    Accessors

    • get isInitialEntry(): boolean

      Returns boolean

    • set isInitialEntry(value: boolean): void

      Parameters

      • value: boolean

      Returns void

    • get row(): number

      Returns number

    • set row(value: number): void

      Parameters

      • value: number

      Returns void

    • get col(): number

      Returns number

    • set col(value: number): void

      Parameters

      • value: number

      Returns void

    • get isEmptyAtCursor(): boolean

      Whether 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 cursorLineTrace 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.

      Returns boolean

      True when there is nothing at (row, col) to describe

    • get state(): TraceState

      Gets the current state of the trace including audio, braille, text, and highlight information.

      Returns TraceState

      The current TraceState

    • get outOfBoundsState(): TraceEmptyState

      The 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.

      Returns TraceEmptyState

      The empty trace state, positioned for out-of-bounds audio panning.

    • get hasMultiPoints(): boolean

      Returns boolean

    • get traceType(): TraceType

      The 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.

      Returns TraceType

    • get values(): number[][]

      Returns number[][]

    • get highlightedPointIndices(): readonly number[]

      The line the highlight currently covers, as an index into this layer's data array.

      This is highlight answered in a renderer-neutral currency. A network drawn on a canvas has no SVG elements for selectors to reach, and an adapter that rebuilt the component walk to find the node itself would drift from findComponents silently -- so the trace names the line by the position it occupies in the link array the adapter supplied, and the adapter inverts that against its own extraction walk.

      Derived from lineOf, the same expression mapToSvgElements indexes its elements with, so the canvas highlight and the SVG highlight cannot name different lines.

      Deliberately not gated on SVG availability: a canvas chart has no elements by definition, and that is the case this exists to serve.

      Returns readonly number[]

      One index into layer.data, or nothing when the cursor is on no node or on an isolated one.

    Methods

    • Gets safe row and column indices to prevent accessing undefined values

      Returns { row: number; col: number }

      Object with safe row and column indices

    • Base implementation of navigation in HIGHER and LOWER modes of ROTOR, default is no-op Needs to be implemented in Line, Bar, Heatmap, Candlestick

      Parameters

      • _direction: "left" | "right" | "up" | "down"
      • _type: "lower" | "higher"

      Returns boolean

    • Parameters

      • a: number

        Utility function to compare point values for rotor functionality

      • b: number
      • type: "lower" | "higher"

      Returns boolean

      boolean value

    • Moves up in rotor mode, optionally filtering by lower or higher values.

      Parameters

      • Optional_mode: "lower" | "higher"

        Optional mode for filtering (lower or higher)

      Returns boolean

      Error always - subclasses must override this method

    • Moves down in rotor mode, optionally filtering by lower or higher values.

      Parameters

      • Optional_mode: "lower" | "higher"

        Optional mode for filtering (lower or higher)

      Returns boolean

      Error always - subclasses must override this method

    • Moves left in rotor mode, optionally filtering by lower or higher values.

      Parameters

      • Optional_mode: "lower" | "higher"

        Optional mode for filtering (lower or higher)

      Returns boolean

      Error always - subclasses must override this method

    • Moves right in rotor mode, optionally filtering by lower or higher values.

      Parameters

      • Optional_mode: "lower" | "higher"

        Optional mode for filtering (lower or higher)

      Returns boolean

      Error always - subclasses must override this method

    • 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 boolean

    • 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 string

    • Cleans up trace resources including values and highlighted SVG elements.

      Only removes elements MAIDR created (hidden clones, synthetic markers); traces that highlight the chart's original live elements in place (e.g. heatmap cells, line dots) merely drop their references so the visible chart geometry survives focusout and live-data rebuilds.

      Returns void

    • Get all highlight SVG elements for this trace Used by HighlightService for high contrast mode

      Returns SVGElement[]

      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.

      Returns SVGElement[]

      Array of all original SVG elements, or empty array if none

    • Computes 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.

      Parameters

      • row: number

        The row of the position to compute state for

      • col: number

        The column of the position to compute state for

      Returns TraceState

      The trace state at the requested position

    • Returns 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.

      Returns string

    • Builds 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.

      Returns { x?: string; y?: string; z?: string }

    • 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 boolean

    • 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.

      Returns boolean

    • 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.

      Parameters

      • _enabled: boolean

        True when entering intersection mode, false when leaving.

      Returns void

    • 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.

      Parameters

      • x: number

        Screen-space x position of the pointer/finger

      • y: number

        Screen-space y position of the pointer/finger

      Returns PointerGuidanceState | null

      Guidance state relative to nearest point, or null when unavailable

    • Moves 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:

      • Box / ViolinBox no-op the move while still surfacing guidance.
      • Scatter switches into column navigation mode before delegating.

      Parameters

      Returns void

    • Checks if the specified coordinates are within bounds of the element.

      Parameters

      • x: number

        The x-coordinate

      • y: number

        The y-coordinate

      • element: NearestPoint

        Object containing the SVG element and its position

        • element: SVGElement
        • row: number
        • col: number
        • centerX: number
        • centerY: number

      Returns boolean

      True if the point is in bounds, false otherwise

    • Offers a walk along the current node's links.

      The arrows deliberately do not follow edges -- that would strand every component but the first -- so this is where the graph traversal lives. It is also where it belongs on an undirected graph: a node's neighbours have equal status, so there is no single edge for an arrow to take.

      Withheld on a chart where nothing is linked to anything.

      Returns readonly RotorFilterUnit[]

      The link unit alongside whatever else is offered

    • 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.

      Parameters

      • key: string
      • direction: "left" | "right"

      Returns boolean

      True if the cursor moved, false otherwise