# LinearMultiSampleVariantDisplay

Auto-generated @jbrowse/mobx-state-tree API for the current JBrowse release —
see [pluggable elements](https://jbrowse.org/jb2-staging/docs/developer_guide/) for concepts. Provided by the
`variants` plugin.
[View source](https://github.com/GMOD/jbrowse-components/blob/main/plugins/variants/src/LinearMultiSampleVariantDisplay/model.ts).

Multi-sample variant display drawing one genotype row per sample, with a
per-cell feature widget on click.

The configuration slots for this model are documented on its
[config schema page](../../config/linearmultisamplevariantdisplay).

Members a composed model contributes are listed here too, so these tables are
the whole surface.

## Properties

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="property-type">**type**</span><br><code>type: types.literal('LinearMultiSampleVariantDisplay')</code> |  | LinearMultiSampleVariantDisplay |
| <span id="property-configuration">**configuration**</span><br><code>configuration: ConfigurationReference(configSchema)</code> |  | LinearMultiSampleVariantDisplay |
| <span id="property-jexlfilterssetting">**jexlFiltersSetting**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>jexlFiltersSetting: types.stripDefault( types.maybe(types.array…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>jexlFiltersSetting: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.maybe(types.array(types.string)),&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;undefined,&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | <span data-pagefind-ignore>Runtime "Filter by..." override, already `jexl:`-prefixed. When set (even to an empty list) it replaces the `jexlFilters` config slot; when undefined the config default applies. See `JexlFilterModel`.<br><br>The name is load-bearing: this used to be called `jexlFilters`, the same name as the inherited config slot, so `self.jexlFilters` read the property and the slot was live in no reader at all — a config declaring filters on one of these tracks did nothing and said nothing. `preProcessSnapshot` below carries the old name over.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#property-jexlfilterssetting) |
| <span id="property-id">**id**</span><br><code>id: ElementId</code> |  | [BaseDisplay](../basedisplay#property-id) |
| <span id="property-layout">**layout**</span><br><code>layout: types.stripDefault(types.frozen&lt;S[]&gt;(), [])</code> |  | [TreeSidebarMixin](../treesidebarmixin#property-layout) |
| <span id="property-clustertree">**clusterTree**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>clusterTree: types.stripDefault(types.maybe(types.string), unde…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>clusterTree: types.stripDefault(types.maybe(types.string), undefined)</code></pre></dialog></span> |  | [TreeSidebarMixin](../treesidebarmixin#property-clustertree) |
| <span id="property-clusterprovenance">**clusterProvenance**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>clusterProvenance: types.stripDefault( types.maybe(types.frozen…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>clusterProvenance: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.maybe(types.frozen&lt;ClusterProvenance&gt;()),&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;undefined,&#10;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | <span data-pagefind-ignore>What `clusterTree` was computed from — the locus and the settings. Set only for a tree this app computed; a supplied phylogeny (maf's `.nh`) leaves it undefined. Persisted with the tree so it survives a session snapshot, which is the case that most needs it: a shared link otherwise hands over a dendrogram with no way to learn its locus.</span> | [TreeSidebarMixin](../treesidebarmixin#property-clusterprovenance) |
| <span id="property-treeareawidth">**treeAreaWidth**</span><br><code>treeAreaWidth: types.stripDefault(types.number, 80)</code> |  | [TreeSidebarMixin](../treesidebarmixin#property-treeareawidth) |
| <span id="property-subtreefilter">**subtreeFilter**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>subtreeFilter: types.stripDefault( types.maybe(types.array(type…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>subtreeFilter: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.maybe(types.array(types.string)),&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;undefined,&#10;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> |  | [TreeSidebarMixin](../treesidebarmixin#property-subtreefilter) |
| <span id="property-runclustering">**runClustering**</span><br><code>runClustering: types.maybe(types.boolean)</code> | <span data-pagefind-ignore>Transient declarative launch spec, the same idea as `LinearGenomeView`'s `init`: a session or config sets this true and the real clustering RPC runs once automatically, with no dialog, as soon as the display reports itself ready. `setupRunClusteringAutorun` clears it afterwards, so a saved session never re-triggers.<br><br>Lives here rather than on each display because it is the trigger for a run whose *output* — `clusterTree`, `clusterProvenance`, `layout` — is this mixin's state. Three displays declared it identically, each with its own wrapper module that existed to code-split the clustering code and, along the way, hand-wrote the same six-member duck type of the display. Splitting inside the `run` callback does the same job and loads on a run rather than on every attach. What each run actually *is* stays per display, in that callback.</span> | [TreeSidebarMixin](../treesidebarmixin#property-runclustering) |
| <span id="property-clusterregion">**clusterRegion**</span><br><code>clusterRegion: types.maybe(types.string)</code> | <span data-pagefind-ignore>Where that run reads from, as a locstring (whitespace-separated for several). Clustering is region-scoped, so running it over the visible window feeds the estimator whatever happens to be on screen; naming the locus instead lets a session cluster on the signal and then show it against its context — otherwise a zoom the user has to perform in the right order. Cleared with `runClustering`, since it is that flag's argument and a locus left standing describes a run that is not coming.</span> | [TreeSidebarMixin](../treesidebarmixin#property-clusterregion) |
| <span id="property-sortrowsby">**sortRowsBy**</span><br><code>sortRowsBy: types.maybe(types.frozen&lt;RowSortSpec&gt;())</code> | <span data-pagefind-ignore>Transient declarative launch spec, the same idea as `runClustering`: set `{refName, pos}` to order the rows once by the value each carries at that genomic column — the session-expressible form of the right-click "Sort rows by ... here". `setupRowSortAutorun` applies it once the region containing it has loaded and then clears it, so the resulting `layout` persists but a saved session never re-sorts.<br><br>Where clustering orders rows by the whole region in view and `layout` states an order outright, only this one says "rank them here", which is what lets a figure open a cohort ranked at a candidate locus with the surrounding context still on screen. What the value at the column *is* stays per display, in its `sortRows` callback.</span> | [TreeSidebarMixin](../treesidebarmixin#property-sortrowsby) |

## Volatiles

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="volatile-dismissedlegendsections">**dismissedLegendSections**</span><br><code>dismissedLegendSections: [] as string[]</code> | <span data-pagefind-ignore>Ids of legend sections the user has individually closed (e.g. 'genotypes' / 'group'); reset when the whole legend is re-shown. Stays volatile where `showLegend` did not: this is which sections a reader collapsed in one sitting, not how the track is configured.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#volatile-dismissedlegendsections) |
| <span id="volatile-contextmenufeature">**contextMenuFeature**</span><br><code>contextMenuFeature: undefined as Feature &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#volatile-contextmenufeature) |
| <span id="volatile-sourcesvolatile">**sourcesVolatile**</span><br><code>sourcesVolatile: undefined as Source[] &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#volatile-sourcesvolatile) |
| <span id="volatile-hoveredgenotype">**hoveredGenotype**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>hoveredGenotype: undefined as &#124; (Record&lt;string, unknown&gt; &amp; { ge…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>hoveredGenotype: undefined as&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124; (Record&lt;string, unknown&gt; &amp; { genotype: string; name: string })&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124; undefined</code></pre></dialog></span> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#volatile-hoveredgenotype) |
| <span id="volatile-celldata">**cellData**</span><br><code>cellData: undefined as CellDataResult &#124; undefined</code> | <span data-pagefind-ignore>Single source of truth for fetched per-display data. hasPhased, sampleInfo, and featuresVolatile are derived from this via getters — fetchNeeded only needs to call setCellData(result).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#volatile-celldata) |
| <span id="volatile-error">**error**</span><br><code>error: undefined as unknown</code> |  | [BaseDisplay](../basedisplay#volatile-error) |
| <span id="volatile-statusmessage">**statusMessage**</span><br><code>statusMessage: undefined as string &#124; undefined</code> |  | [BaseDisplay](../basedisplay#volatile-statusmessage) |
| <span id="volatile-statusprogress">**statusProgress**</span><br><code>statusProgress: undefined as number &#124; undefined</code> | <span data-pagefind-ignore>determinate progress fraction [0,1] for the current status, or undefined when the in-flight phase is indeterminate. Set alongside `statusMessage` by `setStatusMessage`; a display that never shows a bar simply leaves it undefined.</span> | [BaseDisplay](../basedisplay#volatile-statusprogress) |
| <span id="volatile-scrolltop">**scrollTop**</span><br><code>scrollTop: 0</code> |  | [TrackHeightMixin](../trackheightmixin#volatile-scrolltop) |
| <span id="volatile-loadedregions">**loadedRegions**</span><br><code>loadedRegions: regionDataMap&lt;LoadedRegion&gt;('loadedRegions')</code> | <span data-pagefind-ignore>regions whose data has been fetched and committed, keyed by displayedRegionIndex; populated only after the fetch work callback returns</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#volatile-loadedregions) |
| <span id="volatile-forceloadtrack">**forceLoadTrack**</span><br><code>forceLoadTrack: false</code> | <span data-pagefind-ignore>The force-load button's track-wide approval. Volatile so it never reaches a saved session; the `forceLoad` config slot is the durable form.</span> | [RegionTooLargeMixin](../regiontoolargemixin#volatile-forceloadtrack) |
| <span id="volatile-byteestimate">**byteEstimate**</span><br><code>byteEstimate: undefined as ByteEstimate &#124; undefined</code> | <span data-pagefind-ignore>The last byte measurement: bytes, the span they were taken at, and whether zooming has been shown not to shrink them. Survives `clearAllRpcData`; dropped on chromosome navigation and on a tier swap.</span> | [RegionTooLargeMixin](../regiontoolargemixin#volatile-byteestimate) |
| <span id="volatile-gatemeasuredviewportkey">**gateMeasuredViewportKey**</span><br><code>gateMeasuredViewportKey: undefined as string &#124; undefined</code> | <span data-pagefind-ignore>The viewport key the gate last asked the adapter about, on either axis. Separate from `byteEstimate` because a density refusal measures no bytes.</span> | [RegionTooLargeMixin](../regiontoolargemixin#volatile-gatemeasuredviewportkey) |
| <span id="volatile-canvasdrawn">**canvasDrawn**</span><br><code>canvasDrawn: false</code> | <span data-pagefind-ignore>flips true on first paint; read by test selectors to detect render</span> | [RenderLifecycleMixin](../renderlifecyclemixin#volatile-canvasdrawn) |
| <span id="volatile-currentrenderingbackend">**currentRenderingBackend**</span><br><code>currentRenderingBackend: undefined</code> | <span data-pagefind-ignore>current backend reference, updated on context-loss recovery. Typed `unknown` (not generic `B`) on purpose: this mixin is composed by every display via a non-generic factory, so the per-display backend type `B` isn't known here — it's supplied at `attachRenderingBackend<B>` and narrowed with `as B` inside the autoruns. Don't "fix" the cast.</span> | [RenderLifecycleMixin](../renderlifecyclemixin#volatile-currentrenderingbackend) |
| <span id="volatile-rendertick">**renderTick**</span><br><code>renderTick: 0</code> | <span data-pagefind-ignore>counter the render autorun observes; bumped to force a re-render</span> | [RenderLifecycleMixin](../renderlifecyclemixin#volatile-rendertick) |
| <span id="volatile-autorunsinstalled">**autorunsInstalled**</span><br><code>autorunsInstalled: false</code> | <span data-pagefind-ignore>guards attachRenderingBackend so the autorun pair spawns once per instance</span> | [RenderLifecycleMixin](../renderlifecyclemixin#volatile-autorunsinstalled) |
| <span id="volatile-rendererror">**renderError**</span><br><code>renderError: undefined</code> | <span data-pagefind-ignore>the render-backend (GPU/Canvas2D init or context-loss) error, or undefined. Single source of truth for the render-error terminal state: `useRenderingBackend` writes it from the canvas-init mechanism so the model — not React-local hook state — owns every terminal state. Read by `displayPhase` (whose `renderError` term outranks `loading`, suppressing the scrim) and by `DisplayChrome` (shows the retry overlay).</span> | [RenderLifecycleMixin](../renderlifecyclemixin#volatile-rendererror) |
| <span id="volatile-activestoptoken">**activeStopToken**</span><br><code>activeStopToken: undefined as StopToken &#124; undefined</code> | <span data-pagefind-ignore>stop token of the in-flight fetch, or undefined when idle</span> | [FetchMixin](../fetchmixin#volatile-activestoptoken) |
| <span id="volatile-fetchgeneration">**fetchGeneration**</span><br><code>fetchGeneration: 0</code> | <span data-pagefind-ignore>bumps at every fetch end; autoruns read it to re-evaluate, and it doubles as the staleness epoch inside runFetch</span> | [FetchMixin](../fetchmixin#volatile-fetchgeneration) |
| <span id="volatile-reloadcounter">**reloadCounter**</span><br><code>reloadCounter: 0</code> | <span data-pagefind-ignore>Bumped by `reload()` and read unconditionally by the fetch autoruns, so a user retry re-runs the body even where nothing else moved — after an error every other fetch input is unchanged. It is also the half that survives a `reload()` override that forgets to invalidate, which is the dead Retry button `makeRetryContractCheck` reports. Declared here because this is the one mixin both LGV fetch foundations compose, the same argument that put `fetchInert` below; the comparative family carries its own on `SyntenyFetchStateMixin` (ADR-054).</span> | [FetchMixin](../fetchmixin#volatile-reloadcounter) |
| <span id="volatile-statuswindow">**statusWindow**</span><br><code>statusWindow: createStatusWindow(writeStatus(self))</code> | <span data-pagefind-ignore>This display's status field, and the only thing that writes it: one throttle window, one slot per concurrent operation, so N parallel per-region fetches thin to one stream between them rather than N and a second operation cannot end the first one's label (ADR-081). Lent whole to `createStopTokenRotation` by a display that also runs a bare-autorun fetch — see `StatusReporter`.</span> | [FetchMixin](../fetchmixin#volatile-statuswindow) |
| <span id="volatile-fetchcanceled">**fetchCanceled**</span><br><code>fetchCanceled: false</code> | <span data-pagefind-ignore>true after the user explicitly cancels a load (the loading overlay's cancel button → `cancelFetchByUser`). A durable, blocking state — unlike `cancelFetch`, it does not retrigger the fetch autoruns — so the load stays stopped until the user retries (`reload`) or the viewport changes. Any new fetch clears it (`runFetch` resets it at the start).</span> | [FetchMixin](../fetchmixin#volatile-fetchcanceled) |
| <span id="volatile-fetchrotation">**fetchRotation**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>fetchRotation: createStopTokenRotation(self, { statusWindow: se…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>fetchRotation: createStopTokenRotation(self, {&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;statusWindow: self.statusWindow,&#10;&#160;&#160;&#160;&#160;&#160;&#160;})</code></pre></dialog></span> | <span data-pagefind-ignore>**The latest-wins machine this mixin is a wrapper around**, and not a second one: `createStopTokenRotation` owns token rotation, the `isCurrent` guard, the status slot and the supersede-versus-end rule (ADR-080, ADR-081), for every fetch in the codebase that has one. `runFetch` adds the observable bookkeeping a display needs on top — `isLoading`, `error`, `fetchGeneration`, `fetchCanceled` — and nothing else.<br><br>It was two implementations of that machine until 2026-08-20, which is how they came to disagree about whether a completed fetch releases its token. A display's *primary* fetch is this wrapper; a second concurrent fetch on the same node holds a rotation of its own, which is why the primitive is the thing that exists and this is the thing built on it (ADR-054 §1).<br><br>It is lent this display's `statusWindow`, so the fetch takes a slot on the one field rather than opening a second window over it — the whole point of `StatusReporter`.</span> | [FetchMixin](../fetchmixin#volatile-fetchrotation) |
| <span id="volatile-hoveredtreenode">**hoveredTreeNode**</span><br><code>hoveredTreeNode: undefined as HoveredTreeNode &#124; undefined</code> |  | [TreeSidebarMixin](../treesidebarmixin#volatile-hoveredtreenode) |
| <span id="volatile-treecanvas">**treeCanvas**</span><br><code>treeCanvas: null as HTMLCanvasElement &#124; null</code> |  | [TreeSidebarMixin](../treesidebarmixin#volatile-treecanvas) |
| <span id="volatile-mouseovercanvas">**mouseoverCanvas**</span><br><code>mouseoverCanvas: null as HTMLCanvasElement &#124; null</code> |  | [TreeSidebarMixin](../treesidebarmixin#volatile-mouseovercanvas) |

## Getters

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="getter-showvariantlane">**showVariantLane**</span><br><code>boolean</code> |  | LinearMultiSampleVariantDisplay |
| <span id="getter-variantlaneheight">**variantLaneHeight**</span><br><code>number</code> |  | LinearMultiSampleVariantDisplay |
| <span id="getter-variantlanelabels">**variantLaneLabels**</span><br><code>"auto" &#124; "description" &#124; "name" &#124; "nameAndDescription" &#124; "none"</code> |  | LinearMultiSampleVariantDisplay |
| <span id="getter-showinsertionglyphs">**showInsertionGlyphs**</span><br><code>boolean</code> | Whether an insertion is drawn wider than the reference span it consumes — a marker sized by the inserted bp — or at the 2px floor like a SNP.<br><br>A getter and not three `getConf` calls, because it is the answer *three* separate pieces of geometry need and they must give the same one: the marker overlay, the cells' hover highlight, and their click target. All three read it through `variantCellSpanPx`, which is where the invariant is written down.<br><br>It used to be four — the variant lane's marks were the fourth. They are plugin-canvas boxes now, and a box there is its reference span, so the band does not widen an insertion at all; the length lives in the rows' markers alone. | LinearMultiSampleVariantDisplay |
| <span id="getter-visibleregions">**visibleRegions**</span><br><code>VisibleRegion[]</code> |  | LinearMultiSampleVariantDisplay |
| <span id="getter-renderstate">**renderState**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>{ canvasWidth: number; canvasHeight: number; rowHeight: number;…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>{ canvasWidth: number; canvasHeight: number; rowHeight: number; scrollTop: number; }</code></pre></dialog></span> |  | LinearMultiSampleVariantDisplay |
| <span id="getter-prefersoffset">**prefersOffset**</span><br><code>boolean</code> |  | LinearMultiSampleVariantDisplay |
| <span id="getter-perregioncellmap">**perRegionCellMap**</span><br><code>Map&lt;number, Placed&lt;VariantCellData&gt;&gt;</code> | The one walk of `perRegionCellData`, and the point where a fetched cell becomes a *placed* cell. Every regular-mode consumer reads this map, so "does the glyph overlay see the same regions, and the same rows, as the canvas" has a single answer — the placed payload structurally satisfies `VariantUploadData` (GPU/Canvas upload) and `VariantInsertionGlyphData` (overlay), and carries `featureIndexData` for the hit-test index plus `cellWorkerRowIndices` for its lookup.<br><br>This is the display's "derived region map" in the sense of ARCHITECTURE.md's re-upload-without-refetch pattern: the arrays are freshly allocated per region and never mutated in place, so a row reorder changes each entry's identity, `createRegionUploadSync` sees the change and re-uploads, and no RPC is involved. Rows are the only thing derived here — the worker's numbering is arbitrary and must not reach a painter.<br><br>A computed returning a plain Map, for the same reason the multi-row display's is: the overlay draws inside an effect, where nothing it reads is tracked, so the read has to happen here for a refetch to repaint. Rebuilding is cheap (typical view shows 1-3 regions); MobX caches the computed so only cellData or a reorder invalidates it. | LinearMultiSampleVariantDisplay |
| <span id="getter-insertionglyphregions">**insertionGlyphRegions**</span><br><code>Map&lt;number, Placed&lt;VariantCellData&gt;&gt; &#124; undefined</code> | Per-region cell data for the insertion-glyph overlay, or undefined when the slot is off. | LinearMultiSampleVariantDisplay |
| <span id="getter-variantlaneregions">**variantLaneRegions**</span><br><code>Map&lt;number, Placed&lt;VariantCellData&gt;&gt; &#124; undefined</code> | Per-region data for the variant lane, or undefined when the band is off. The same `perRegionCellMap` the canvas and the glyph overlay read, so the lane cannot see a different region set — or a different row placement — than the cells under it. The lane itself only touches the per-*feature* arrays in there. | LinearMultiSampleVariantDisplay |
| <span id="getter-insertionlegendcolor">**insertionLegendColor**</span><br><code>string &#124; undefined</code> | Overrides the base's `undefined`: this display draws the markers, so it is the one that puts them in the legend. `getPaletteHost(self).palette` rather than a React theme, because this is a model getter — and it is the same `palette.insertion` the on-screen overlay paints with (via `usePalette`), so the swatch cannot drift from the glyph there. The SVG export paints with the *export* theme's palette instead, and passes it to `legendSections` so the swatch follows it too.<br><br>The condition is `markersForBlock` — the painter's own test, on the painter's own blocks — because both cheaper approximations are wrong on real figures. "The window holds an insertion" puts a swatch on a callset of short indels, which can never draw a marker at any zoom. "The window holds a *long* insertion" puts one on any view zoomed out far enough that even a long bar falls under the 2px cell floor; that was three of the fourteen committed figures carrying this display, each gaining exactly one 576px swatch and no glyph.<br><br>So the entry does come and go with zoom, unlike `hasSecondaryAlt` / `hasNoCall`. That is the honest behavior for a glyph whose visibility is itself a function of zoom, and it is why this reads the view: the components that call `legendSections` are the same ones that already read `renderState`. | LinearMultiSampleVariantDisplay |
| <span id="getter-featureindices">**featureIndices**</span><br><code>Map&lt;number, Flatbush&gt;</code> | Per-region spatial index over feature intervals, for the hit-test. One entry per variant, not per cell — see computeVariantCells. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanedisplayconfig">**laneDisplayConfig**</span><br><code>DisplayConfig</code> | The plugin-canvas display config the lane's band is laid out with. See `laneDisplayConfig` — a literal, because a band has no config schema. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanefontsize">**laneFontSize**</span><br><code>number</code> | The label size the lane's marks are lettered at — plugin-canvas's, for the lane's display mode, so the width its packer reserved is the width the text draws at. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanerenderdatamap">**laneRenderDataMap**</span><br><code>ReadonlyMap&lt;number, LayoutRegionData&gt;</code> | The lane's marks as plugin-canvas render data, one entry per visible region — the payload that display's own RPC produces, built here from records this display already parsed. Empty when the band is off, which is what stops every getter below it from doing any work.<br><br>See `buildLaneRenderData` for why this is main-thread and costs no second fetch. A MobX computed, so it is rebuilt when the payload or the label mode changes and not per frame — and the entries' identity changing is what lets the packer below re-pack. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanelayoutinputs">**laneLayoutInputs**</span><br><code>Omit&lt;LayoutInputs, "showDescriptions" &#124; "showLabels"&gt;</code> | What the lane's packer reads, minus the label reservation each fit rung varies. One source, so the rungs cannot drift on zoom or orientation.<br><br>`coarseBpPerPx`, the 500ms-debounced one, for the reason `LinearBasicDisplay` uses it: row packing must not recompute on every frame of a smooth zoom. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanedecimatedinputs">**laneDecimatedInputs**</span><br><code>LabelRoomFactorFreeInputs</code> | Inputs for the `decimated` rung, whose whitespace factor is solved against the band height. Descriptions are already gone by that rung. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanefitstage">**laneFitStage**</span><br><code>FitStage</code> | The rung the lane keeps and the scale that fills the band with it — plugin-canvas's fit ladder, run against `laneHeight` instead of a track height. Names and descriptions if they fit; else descriptions dropped; else names kept only where they have room; else bodies alone, squeezed and scrolled-off if even that overflows.<br><br>This is the whole of "compact": the band never grows, so what adapts is how much of each record the band spends its pixels on — which is the question `LinearVariantDisplay` in fit mode already answers. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanelaidoutdatamap">**laneLaidOutDataMap**</span><br><code>ReadonlyMap&lt;number, FeatureDataResult&gt;</code> | What the lane's painter, its labels and its hit test all read: the resolved stack, scaled only when the fit grew or squeezed it. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanecontentheight">**laneContentHeight**</span><br><code>number</code> | The band's own drawn height — the kept rung's stack, scaled. Less than `laneHeight` on a sparse window (the surplus is bottom whitespace, so a relayout packs back against the top rather than jumping to a re-centred offset) and equal to it whenever the fit had to work. | LinearMultiSampleVariantDisplay |
| <span id="getter-lanerenderedlabels">**laneRenderedLabels**</span><br><code>{ showLabels: boolean; showDescriptions: boolean; }</code> | Which label kinds the lane actually paints. The mode asked for them; the rung that survived decides — a box must never reserve width for a description the band had no room to draw. | LinearMultiSampleVariantDisplay |
| <span id="getter-laneflatbushindexes">**laneFlatbushIndexes**</span><br><code>Map&lt;number, FlatbushRegionIndexes&gt;</code> | Per-region hit index over the lane's laid-out marks — plugin-canvas's, built off the same stack it painted, so the box under the cursor is the box the pick returns. Its label overhang is part of the hit box there, which is why this reads the RENDERED label flags and not the mode's. | LinearMultiSampleVariantDisplay |
| <span id="getter-view">**view**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>ModelInstanceTypeProps&lt;_OverrideProps&lt;_OverrideProps&lt;…&gt;, { ...;…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>ModelInstanceTypeProps&lt;_OverrideProps&lt;_OverrideProps&lt;…&gt;, { ...; }&gt;&gt; &amp; ... 25 more ... &amp; IStateTreeNode&lt;...&gt;</code></pre></dialog></span> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-view) |
| <span id="getter-featuresvolatile">**featuresVolatile**</span><br><code>Feature[] &#124; undefined</code> | <span data-pagefind-ignore>SimpleFeature instances derived from the simplifiedFeatures list in the most recent cellData payload. Cached by MobX while cellData is unchanged. Named `featuresVolatile` for backwards-compat with consumers that originally read it as a volatile field.<br><br>These carry ONLY positional fields (id/start/end/refName/name) — not ALT or genotypes. Don't re-derive feature-level facts from them (`.get('ALT')` etc. returns undefined); summary facts are computed in the worker and exposed as scalars (hasPhased/hasSecondaryAlt/ hasUnphased), and per-feature genotype info lives in the cell-data featureGenotypeMap/featureData.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-featuresvolatile) |
| <span id="getter-hasphased">**hasPhased**</span><br><code>boolean</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasphased) |
| <span id="getter-hasphasedorhaploid">**hasPhasedOrHaploid**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any called genotype is phased or haploid, which is what gates the "Phased" rendering mode. Wider than `hasPhased` on purpose: the painter's rule is `isPhasedOrHaploid` (no `/`), because a pangenome callset is haploid per assembly path and `vg deconstruct` writes bare `0`/`1`/`23` — a file with no `\|` anywhere that phased mode renders correctly. Gating the menu on `hasPhased` left that rendering reachable only from the config slot.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasphasedorhaploid) |
| <span id="getter-hassecondaryalt">**hasSecondaryAlt**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any visible site is multiallelic (drives the "Other alt allele" legend entry). Computed in the worker since the simplified features sent to the client don't carry ALT.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hassecondaryalt) |
| <span id="getter-hasunphased">**hasUnphased**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any genotype call is unphased (drives the "Unphased" legend entry in phased mode).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasunphased) |
| <span id="getter-hasnocall">**hasNoCall**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any genotype is a no-call (drives the "No call" legend entry in phased mode; allele-count mode always shows it).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasnocall) |
| <span id="getter-hasconsequence">**hasConsequence**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any visible variant carries a SnpEff/VEP annotation, gating the "Color by...→Consequence impact" menu option.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasconsequence) |
| <span id="getter-hassvtype">**hasSvType**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any visible variant is a structural variant, gating the "Color by...→SV type" menu option.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hassvtype) |
| <span id="getter-hasphaseset">**hasPhaseSet**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether any visible variant declares a phase set (PS in FORMAT), gating the "Color by...→Phase set" menu option.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasphaseset) |
| <span id="getter-svtypecolors">**svTypeColors**</span><br><code>Record&lt;string, string&gt; &#124; undefined</code> | <span data-pagefind-ignore>The color assigned to each present SV type, built in the worker so the legend swatches match the painted cells (drives the "SV type" legend section).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-svtypecolors) |
| <span id="getter-sampleinfo">**sampleInfo**</span><br><code>Record&lt;string, SampleInfo&gt; &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-sampleinfo) |
| <span id="getter-renderingmode">**renderingMode**</span><br><code>string</code> | <span data-pagefind-ignore>Returns the rendering mode config slot value</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-renderingmode) |
| <span id="getter-linezoneheight">**lineZoneHeight**</span><br><code>number</code> | <span data-pagefind-ignore>Height of the connector-line zone above the rows; 0 for a display that draws variants at their genomic positions and needs no connectors. On the config rather than a bespoke property for the same reason `height` is (see TrackHeightMixin): a drag-resize outlives the display instance, so unticking and reticking the track keeps the zone the user set. LD declares the same slot and the same clamped `setConf` setter.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-linezoneheight) |
| <span id="getter-showrowseparators">**showRowSeparators**</span><br><code>boolean</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-showrowseparators) |
| <span id="getter-showtooltips">**showTooltips**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether a hover draws the tooltip table. Only the tooltip: the crosshairs, the hovered-cell highlight and `hoveredFeature` (the cross-display hover channel) all keep working with it off, which is the point — the reader who turns it off wants the rows uncovered, not the pointer silenced.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-showtooltips) |
| <span id="getter-colorby">**colorBy**</span><br><code>string</code> | <span data-pagefind-ignore>The effective sample-grouping attribute (config default or runtime override). Drives the sidebar row coloring and the legend's group section; '' means no grouping.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-colorby) |
| <span id="getter-groupby">**groupBy**</span><br><code>string</code> | <span data-pagefind-ignore>Sample-metadata attribute the rows are grouped (reordered) by; '' leaves the existing order alone.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-groupby) |
| <span id="getter-featurecolor">**featureColor**</span><br><code>string</code> | <span data-pagefind-ignore>Optional per-variant cell color (jexl string or CSS color) applied to alt-carrying cells; '' means default genotype coloring. Reads the raw config value directly (not `getConf`, which evaluates a `jexl:...` string immediately with no `feature` bound) — this crosses the RPC boundary as-is and is evaluated once per feature in the worker (see `makeFeatureColor` in `executeVariantCellData.ts`).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-featurecolor) |
| <span id="getter-featurewidgettype">**featureWidgetType**</span><br><code>{ type: string; id: string; }</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-featurewidgettype) |
| <span id="getter-roworderiscustom">**rowOrderIsCustom**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overrides the mixin's `layout.length > 0`: here a configured `colorBy` / `groupBy` seeds `layout` on first load, so a non-empty layout is the ordinary state of a track nobody has rearranged, and `clearLayout` puts that same arrangement straight back. "Reset row order" is offered only once the layout has moved away from what the config alone would produce.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-roworderiscustom) |
| <span id="getter-minorallelefrequencyfilter">**minorAlleleFrequencyFilter**</span><br><code>number</code> | <span data-pagefind-ignore>Returns the minor allele frequency filter config slot value</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-minorallelefrequencyfilter) |
| <span id="getter-maxmissingnessfilter">**maxMissingnessFilter**</span><br><code>number</code> | <span data-pagefind-ignore>Max fraction of no-call genotypes a variant may have before it's hidden; 1 keeps every variant</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-maxmissingnessfilter) |
| <span id="getter-filters">**filters**</span><br><code>SerializableFilterChain &#124; undefined</code> | <span data-pagefind-ignore>The jexl filter expressions (from the Edit filters dialog) as a SerializableFilterChain, ready to pass as the RPC `filters` arg. MultiSampleVariantGet{CellData,GenotypeMatrix,ClusterGenotypeMatrix} all extend RpcMethodTypeWithFiltersAndRenameRegions, which serializes this to string[] and rebuilds it in the worker with pluginManager.jexl.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-filters) |
| <span id="getter-referencedrawingmode">**referenceDrawingMode**</span><br><code>string</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-referencedrawingmode) |
| <span id="getter-colorbyattributes">**colorByAttributes**</span><br><code>string[]</code> | <span data-pagefind-ignore>Distinct sample-metadata attributes (from samplesTsv) the user can color rows by — every key the sources carry except internal plumbing.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-colorbyattributes) |
| <span id="getter-sourceswithoutlayout">**sourcesWithoutLayout**</span><br><code>ProcessedSource[] &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-sourceswithoutlayout) |
| <span id="getter-sourcesbase">**sourcesBase**</span><br><code>ProcessedSource[] &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-sourcesbase) |
| <span id="getter-sources">**sources**</span><br><code>ProcessedSource[]</code> | <span data-pagefind-ignore>The display rows: `sourcesBase` expanded for phased rendering when sampleInfo is available. Sources already carrying HP (from clustering) pass through unchanged.<br><br>**Resolved — an array, never `undefined`**, which is the shared spelling across the row displays (canvas's multi-row painting and multi-wiggle already answered this way). `sourcesVolatile` and `sourcesBase` keep their `undefined`, because there it is genuinely load-bearing: `sampleFilter` and `fetchNeeded` both read `sourcesBase`, and its `undefined` → list transition is what wakes the fetch autorun (ARCHITECTURE.md §"The global-fetch trigger list must be read unconditionally"). Nothing reads *this* getter for that — every consumer immediately collapsed the absent case with `?.length`, `?? []` or `?? 0`, so the option was about eighteen defensive reads and no decision.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-sources) |
| <span id="getter-editablesources">**editableSources**</span><br><code>ProcessedSource[]</code> | <span data-pagefind-ignore>Layout-merged, phased-expanded view for the Edit Color/Arrangement dialog. Does NOT apply the subtree filter — submitting the dialog persists every row it was shown back to `layout`, so a filtered list would submit the focused clade as the whole order and leave every other sample appended after it. Same reason the other row displays' `editableSources` sit upstream of `filterRowsBySubtree`.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-editablesources) |
| <span id="getter-clusteringready">**clusteringReady**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the fetched inputs clustering needs are present yet. Phased clustering clusters haplotypes, which needs per-sample ploidy from `sampleInfo`; that arrives with `cellData`, later than the header-only `sourcesVolatile`. Gating the auto-cluster run on this (not just `sourcesVolatile`) stops it racing ahead and building a sample-level tree whose leaves ("HG001") never match the expanded haplotype rows ("HG001 HP0").</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-clusteringready) |
| <span id="getter-hasclusterablerows">**hasClusterableRows**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether there is anything to cluster: clustering reorders rows, so it needs at least two rows to put in an order. Undefined is not "none" — it is the sample list not having landed yet — but both mean "not now", which is why one boolean answers for both and the menu's help text asks `sourcesWithoutLayout` itself which of the two it is.<br><br>The unfiltered, haplotype-expanded list, because that is the row set the tree comes back describing.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hasclusterablerows) |
| <span id="getter-autoclusterready">**autoClusterReady**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the declarative `runClustering: true` path may fire: the inputs have landed AND there are rows worth ordering. Both halves are named booleans rather than one expression at the autorun, so each can be read — and tested — on its own.<br><br>The dialog gates on `clusteringReady` alone and needs no second half: the menu row that opens it carries `hasClusterableRows`, so it cannot be opened on a cohort too small to cluster in the first place.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-autoclusterready) |
| <span id="getter-samplefilter">**sampleFilter**</span><br><code>string[] &#124; undefined</code> | <span data-pagefind-ignore>Which samples the worker should emit rows for, as a **set** — sorted and deduped, so only a membership change can move it. Row order is not a fetch input here; ARCHITECTURE.md §"Row order is not a fetch input", has the why and how the three row displays each do it.<br><br>Two local rules:<br><br>- `undefined` means the sources haven't loaded, and is deliberately not reused for "all of them". `fetchNeeded` declines until `sourcesBase` exists and this key changing is the only thing that wakes it, so collapsing the two would leave it unchanged when sources landed and wedge the display with nothing drawn. - Deduped because after a phased clustering run `sourcesBase` is haplotype-level, listing a sample once per haplotype. The worker takes samples and expands them itself, so a key that moved with ploidy would refetch on a rendering-mode round trip that changed no sample.<br><br>Reads `sourcesBase`, never `sources`, for the loop reason below.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-samplefilter) |
| <span id="getter-sourcemap">**sourceMap**</span><br><code>Map&lt;string, ProcessedSource&gt;</code> | <span data-pagefind-ignore>Row name -> source, for the hover tooltip. A Map for the same reason `getSources`' is: row names come from the file, and on a plain object a sample called `constructor` resolves to something inherited rather than to a miss.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-sourcemap) |
| <span id="getter-genotypesampleindex">**genotypeSampleIndex**</span><br><code>Map&lt;string, number&gt; &#124; undefined</code> | <span data-pagefind-ignore>sampleName -> column index into each feature's interned `genotypeCodes`. Rebuilt only when cellData changes. Used by the tooltips to decode a hovered cell's genotype (see genotypeCodec.ts).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-genotypesampleindex) |
| <span id="getter-rowremap">**rowRemap**</span><br><code>Uint32Array&lt;ArrayBufferLike&gt; &#124; undefined</code> | <span data-pagefind-ignore>Worker row -> screen row, the client half of taking row order out of the RPC (see `sampleFilter`). The cells arrive numbered against the worker's own `rowNames` list; this is what turns that into the row the user is looking at, and rebuilding it is all a reorder costs.<br><br>A worker row the display isn't drawing maps to `HIDDEN_ROW` rather than being dropped: at that index every painter's own Y-cull puts the cell far below the canvas, so the sentinel needs no special case on either backend, in the glyph overlay, or in the SVG export. (It stays rare — the *set* is still a fetch input, so normally every row shipped is a row drawn.)<br><br>Undefined until data lands. Consumers that draw cells must treat that as "nothing to draw yet" rather than falling back to identity: the worker's order is arbitrary, so identity would paint rows under the wrong sample names.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-rowremap) |
| <span id="getter-topbands">**topBands**</span><br><code>VariantTopBands</code> | <span data-pagefind-ignore>The bands stacked above the rows — the variant lane and the connector-line zone — resolved once. Both the layout below and the painters read this, never their own sum: see `variantTopBands.ts`.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-topbands) |
| <span id="getter-rowstopoffset">**rowsTopOffset**</span><br><code>number</code> | <span data-pagefind-ignore>Px reserved above the rows, and so where the rows begin. This is the name `TreeSidebar`'s model contract reads (it positions the sidebar against the rows, not against any one band), and what every component offsetting itself past the bands takes.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-rowstopoffset) |
| <span id="getter-availableheight">**availableHeight**</span><br><code>number</code> | <span data-pagefind-ignore>Available height for rows (total height minus whatever the bands above them take). Floored at 0: `lineZoneHeight` (matrix only, user-draggable up to 1000 independently of `height`) can exceed a shrunk display height on its own, and the variant lane adds to it. Every consumer treats this as a real pixel dimension (canvas height, CSS `height`, scroll viewport height), so it must never go negative.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-availableheight) |
| <span id="getter-nrow">**nrow**</span><br><code>number</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-nrow) |
| <span id="getter-autorowheight">**autoRowHeight**</span><br><code>number</code> | <span data-pagefind-ignore>What fit-to-display-height divides between the rows, and the reason `RowHeightMixin`'s non-positive floor is reachable at all here: `availableHeight` floors at 0, so a `lineZoneHeight` that swallows the whole display makes this exactly 0.<br><br>A **fixed** height goes the other way and is used as-is however many samples there are — the rows area is a scroll viewport, so rows that don't fit cost scroll extent rather than a resize.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-autorowheight) |
| <span id="getter-hierarchy">**hierarchy**</span><br><code>ClusterHierarchyNode &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hierarchy) |
| <span id="getter-rowunmap">**rowUnmap**</span><br><code>Int32Array&lt;ArrayBufferLike&gt; &#124; undefined</code> | <span data-pagefind-ignore>Screen row -> worker row, the inverse of `rowRemap`; `-1` for a screen row this window's data has no cells for (a sample the layout draws but whose genotypes never appear in the fetched variants).<br><br>The hit test needs this direction, and needs it separately, because the cell arrays stay in the worker's numbering: they are sorted by `(featureIndex, rowIndex)` and `findCellIndex` binary-searches that order, which remapping the array in place would destroy. Converting the one row the cursor is over is O(1) and keeps the search O(log n).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-rowunmap) |
| <span id="getter-spatialindex">**spatialIndex**</span><br><code>TreeSpatialIndex &#124; undefined</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-spatialindex) |
| <span id="getter-hoveredfeature">**hoveredFeature**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(Record&lt;string, unknown&gt; &amp; { genotype: string; name: string; })…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(Record&lt;string, unknown&gt; &amp; { genotype: string; name: string; }) &#124; undefined</code></pre></dialog></span> | <span data-pagefind-ignore>Fills `BaseDisplay`'s cross-display hover hook with the genotype cell under the pointer, so the view's `session.hovered` channel sees this display like every other one.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hoveredfeature) |
| <span id="getter-hoveredtooltipsource">**hoveredTooltipSource**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(Record&lt;string, unknown&gt; &amp; { genotype: string; name: string; })…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(Record&lt;string, unknown&gt; &amp; { genotype: string; name: string; }) &#124; undefined</code></pre></dialog></span> | <span data-pagefind-ignore>The hovered thing as the tooltip table reads it: the record's fields, with the hovered sample row's metadata attributes merged underneath them so a cohort colored by a `samplesTsv` column reports that column too.<br><br>A hover naming no row falls through to the record's fields alone, and that is the variant lane's whole tooltip: its marks are records, so `buildVariantLaneHit` leaves `name` empty precisely so there is no source to find here. A *cell* hover always finds one — both hit tests take the name off `sources`, which is what `sourceMap` is built from.<br><br>`showTooltips` is gated here rather than in the component, so the one getter feeding the tooltip is the one place that answers "is there a tooltip" — the hit test, `hoveredFeature` and the hovered-cell highlight go on reading `hoveredGenotype` and are unaffected.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-hoveredtooltipsource) |
| <span id="getter-totalheight">**totalHeight**</span><br><code>number</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-totalheight) |
| <span id="getter-scrollableheight">**scrollableHeight**</span><br><code>number</code> | <span data-pagefind-ignore>Max valid `scrollTop`: how far the rows can scroll before the bottom row reaches the viewport floor. Zero when the rows fit — which auto-fit mode always does, since `effectiveRowHeight` derives from `availableHeight`. `scrollableHeight > 0` is therefore also the "does this display scroll" answer; both displays scroll virtually (fixed canvas + VerticalScrollbar overlay), so there is no native overflow container to gate separately.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-scrollableheight) |
| <span id="getter-gateenabled">**gateEnabled**</span><br><code>boolean</code> | <span data-pagefind-ignore>Opt into RegionTooLargeMixin's byte gate: `fetchNeeded` passes `resolvedByteLimit()` to `MultiSampleVariantGetCellData`, whose first await on the adapter is the index estimate — so an over-budget viewport is refused before a single genotype is downloaded.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-gateenabled) |
| <span id="getter-regionfetchkey">**regionFetchKey**</span><br><code>string</code> | <span data-pagefind-ignore>Matrix mode draws columns by feature index across the full width, so the set of features belongs to the visible region at the *current* zoom — zooming in/out changes which features show even when the viewport stays spatially inside loaded data, so cached cells at a different bpPerPx are stale (wiggle uses the same strict-zoom rule, adr-008). Regular mode draws each variant at its genomic position, so spatial coverage alone suffices and the empty key holds every region a fetch has loaded.<br><br>A getter, not an action: as an action MobX untracks the `bpPerPx` read and `FetchVisibleRegions` keeps a stale answer (`isCacheValidTracking.test.ts`).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-regionfetchkey) |
| <span id="getter-awaitingprerequisite">**awaitingPrerequisite**</span><br><code>boolean</code> | <span data-pagefind-ignore>Retry here is two-stage: the sources autorun reads the same `reloadCounter` bump `reload()` makes for the region fetch, and `fetchNeeded` below declines until `sourcesBase` lands. So the retry contract is judged on the run that follows, not on the declining one — see `FetchMixin.awaitingPrerequisite`.<br><br>Strictly narrower than the declines it explains, which is what makes it a deferral rather than an opt-out: `FetchVisibleRegions` also declines when every visible block is already covered, and that one is judged as soon as `sourcesBase` is in hand. Not `fetchNeeded`'s own empty-region return — the autorun only calls it with a non-empty `needed`, which means the view has visible regions, so that branch is unreachable from there.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#getter-awaitingprerequisite) |
| <span id="getter-parenttrack">**parentTrack**</span><br><code>AbstractTrackModel</code> |  | [BaseDisplay](../basedisplay#getter-parenttrack) |
| <span id="getter-renderingcomponent">**RenderingComponent**</span><br><code>FC&lt;…&gt;</code> |  | [BaseDisplay](../basedisplay#getter-renderingcomponent) |
| <span id="getter-displayblurb">**DisplayBlurb**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>FC&lt;{ model: ModelInstanceTypeProps&lt;{ id: IOptionalIType&lt;ISimple…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>FC&lt;{ model: ModelInstanceTypeProps&lt;{ id: IOptionalIType&lt;ISimpleType&lt;string&gt;, [undefined]&gt;; type: ISimpleType&lt;string&gt;; }&gt; &amp; { ...; } &amp; { ...; } &amp; IStateTreeNode&lt;...&gt;; }&gt; &#124; null</code></pre></dialog></span> |  | [BaseDisplay](../basedisplay#getter-displayblurb) |
| <span id="getter-adapterconfig">**adapterConfig**</span><br><code>Record&lt;string, unknown&gt;</code> |  | [BaseDisplay](../basedisplay#getter-adapterconfig) |
| <span id="getter-isminimized">**isMinimized**</span><br><code>boolean</code> | <span data-pagefind-ignore>Returns true if the parent track is minimized. Used to skip expensive operations like autoruns when track is not visible.</span> | [BaseDisplay](../basedisplay#getter-isminimized) |
| <span id="getter-featurenoun">**featureNoun**</span><br><code>string</code> | <span data-pagefind-ignore>Overridable hook (default `'feature'`): the SINGULAR word for one of the things this display draws, as a menu row or a chip says it — "Hide this read", "Showing 3 variants".<br><br>Declared here for the same reason as `hoveredFeature` above: it is read across the display boundary, by chrome that has no idea which display it is drawing for (`SoloSelectionChip`, alignments' group-label overlay), and a name only the base declares is a name every such consumer can rely on. Two displays declared it independently and one of those declarations WAS this default.<br><br>**A control keeps the generic word; content takes this one.** "Variant height" reads as a different setting from "Feature height" when it is the same one, so the shared menus stay on "feature" however the display answers here, and the noun varies where it names what the user is looking at — "Showing 3 variants", "Hide this read". A display drawing something the generic word already fits is right to leave this alone.<br><br>Distinct from the per-hit noun a context menu takes off the clicked item's own `type` ("mRNA", "gene"); that names one annotation, this names what the track holds. The hit noun falls back to this.</span> | [BaseDisplay](../basedisplay#getter-featurenoun) |
| <span id="getter-height">**height**</span><br><code>number</code> |  | [TrackHeightMixin](../trackheightmixin#getter-height) |
| <span id="getter-resizing">**resizing**</span><br><code>boolean</code> | <span data-pagefind-ignore>True for the duration of a height drag on this track, whichever handle is running it. A display whose row geometry is a function of the track height restretches every row per animation frame, and can use this to sit an expensive per-frame layer out of the drag (MAF's dense per-base letter overlay is a Canvas2D pass that scales with rows x columns).<br><br>The flag itself is the track's (`BaseTrackModel`), so the view brackets a drag without needing the active display to have opted into this mixin. Reading it here is what makes `self.resizing` available to a display that did.</span> | [TrackHeightMixin](../trackheightmixin#getter-resizing) |
| <span id="getter-host">**host**</span><br><code>RegionHost</code> | <span data-pagefind-ignore>The containing LinearGenomeView, typed once for every display in this family — see `containingHost` for the cast it owns and why both foundations still declare the name.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-host) |
| <span id="getter-canvaswidthpx">**canvasWidthPx**</span><br><code>number</code> | <span data-pagefind-ignore>The CSS width of this display's on-screen canvas, in px — and the `canvasWidth` its `renderState` must carry, since the two have to agree or the bp→px mapping is scaled against a box it doesn't fill.<br><br>`trackWidthPx`, **not** `view.width`: `TrackRenderingContainer` insets the rendering component by the 2px track outline under `contain: strict`, so a `view.width`-wide canvas overhangs its own container and the browser clips the overhang away. It renders almost identically, which is why MAF drifted onto `view.width` uncaught.<br><br>A getter rather than a note on each display, because the choice was being made by copying a neighbour out of four plausible view getters — `width` (the viewport), this one, and `totalWidthPx` / `totalWidthPxWithoutBorders` (the *content* width, which the global family's heatmaps legitimately want: a different question, not a different answer). `no-restricted-syntax` bans the underlying read everywhere but this line, since a second spelling agrees until it doesn't.<br><br>SVG export is the one exception: the export shell has no outline, so `renderSvg` overrides `canvasWidth` with the shell's own width (see `LgvSvgBodyProps`).</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-canvaswidthpx) |
| <span id="getter-canrender">**canRender**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overrides `RenderLifecycleMixin`'s default-true hook with the LGV precondition both foundations share — see `foundationCanRender`.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-canrender) |
| <span id="getter-viewportwithinloadeddata">**viewportWithinLoadedData**</span><br><code>boolean</code> | <span data-pagefind-ignore>true when every visible block lies within an already-fetched region — i.e. the viewport shows data we actually loaded, not the stale fringe left after a zoom-out/pan. Drives the loading overlay through the pre-refetch debounce.<br><br>**Spatial only, and it stays that way.** Whether the data held for a block is still what a fetch would bring back is `isCacheValid`, which `dataCurrent` conjoins for the export gate. The scrim reads this getter alone: a phase that went `loading` on a moved `regionFetchKey` would raise the overlay into every zoom.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-viewportwithinloadeddata) |
| <span id="getter-viewportempty">**viewportEmpty**</span><br><code>boolean</code> | <span data-pagefind-ignore>No content block is on screen, so this display has nothing to fetch and nothing to paint — see `viewportEmpty.ts` for the one viewport that reaches it, how narrow that is, and why the state still has to be terminal rather than a permanent scrim. Both foundations declare it over that one expression, the same way they each declare `host` and `paintInert`.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-viewportempty) |
| <span id="getter-layoutready">**layoutReady**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overridable hook (default false): whether a searchable feature layout currently exists. Any display defining a feature-lookup method (`searchFeatureByID`, `getFeatureById`) must override it, so callers can tell "laid out, but off-display" from "no layout exists yet" — a distinction only the display can make. See packages/display-kit/CLAUDE.md §"Four readiness axes".</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-layoutready) |
| <span id="getter-datasuperseded">**dataSuperseded**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overridable hook (default false): the held data is loaded and covers the viewport, but a fetch input has moved past it, so the data is about to be cleared and refetched. A display says so here rather than overriding `dataCurrent`, for the reason `FetchMixin.fetchInert` is a hook: an override has to restate the freshness terms and then misses the next one added.<br><br>On screen this window is invisible (the clear lands a tick later and the loading scrim covers it), which is exactly why it needs saying: `awaitSvgReady` samples freshness once, and an export that samples it inside this window renders the data that is about to be discarded — or, once the clear lands mid-render, nothing at all. GWAS's LD auto-index is the case: adopting the top hit as the index SNP is an `rpcProps` change, so the very load that produced the top hit is what it invalidates.<br><br>**The input need not have settled yet.** Alignments counts the debounce window ahead of its per-base bin, where the bin the data was fetched under has not moved and the clear is inevitable rather than committed. That is the half of the window an export lands in, since a reader zooms and then reaches for the menu. What may NOT go in is a change that could still be taken back: this fails hung, not stale.<br><br>So state the live-vs-settled half as a **value** compare and leave key strings alone. The settled half — the stamp a fetch committed under against the key a fetch now would use — is the foundation's already, through the `isCacheValid` term in `dataCurrent`, and an override restating it buys nothing: a second derivation of the key's vocabulary reads `"16\|fine"` against a live `"16"` the day the key grows an axis, latches this true, and every export of the display then waits out `awaitSvgReady`'s backstop instead of failing.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-datasuperseded) |
| <span id="getter-renderblocks">**renderBlocks**</span><br><code>RenderBlock[]</code> | <span data-pagefind-ignore>Shared cached view for every LGV-based GPU display. A single displayedRegion may produce multiple render blocks (shared GPU buffer, different scissor clips on screen). Plugins that want to suppress rendering in certain states (e.g. no domain yet) can override this getter to return [] — the autorun lifecycle will then issue an empty-blocks render that clears the canvas.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-renderblocks) |
| <span id="getter-datacurrent">**dataCurrent**</span><br><code>boolean</code> | <span data-pagefind-ignore>This family's answer to the shared freshness question every display foundation must answer (`dataCurrent`): the held data corresponds to what is on screen right now. Four terms — spatial coverage of every visible block, `loadedRegions.size` to rule out the vacuously-true empty viewport, `isCacheValid` per block, and the display's own `dataSuperseded`. Regions stream in one at a time, so this (not "the first datum arrived") is what keeps a multi-region/whole-genome export complete.<br><br>**`isCacheValid` belongs here and not in the scrim.** Coverage answers "is the data here", never "is it what a fetch now would bring back", so a zoom that moves `regionFetchKey` leaves every held region covered and stale at once — and an export sampling `svgReady` across that window painted bins the worker computed for the previous zoom. `displayPhase` still reads `viewportWithinLoadedData` alone: folding staleness into the phase raises the loading scrim into every zoom, which is the trade REJECTED_IDEAS.md "Folding content staleness into `displayPhase`" turned down and this does not take.<br><br>The term cannot latch, and the reason is structural rather than a case list: a block reaches `fetchNeeded` unless `planRegionFetch` finds it ungated, covered AND cache-valid, and it reads that last term tracked. The `&&` short-circuits ahead of it drop its observables only where the block is fetched anyway, so the key move that closes this gate is the same read, in the same dependency set, that wakes the refetch reopening it.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-datacurrent) |
| <span id="getter-loadedassembly">**loadedAssembly**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(ModelInstanceTypeProps&lt;…&gt; &amp; { error: unknown; loadingP: Promis…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(ModelInstanceTypeProps&lt;…&gt; &amp; { error: unknown; loadingP: Promise&lt;…&gt; &#124; undefined; ... 10 more ...; refNameMismatches: Map&lt;…&gt;; } &amp; ... 13 more ... &amp; IStateTreeNode&lt;...&gt;) &#124; undefined</code></pre></dialog></span> | <span data-pagefind-ignore>The assembly the data in hand came from, once it can answer about refNames — `undefined` before that.<br><br>Off the first LOADED region rather than the view's displayed ones, which is the distinction that makes it belong here: a display holding fetched data is asking about the assembly THAT data is on, and the view's regions can already have moved on.<br><br>The `initialized` gate is why this returns the assembly rather than its name. `getCanonicalRefName2` and `refNameToIndex` answer WRONGLY rather than throwing before the aliases land — identity, and a miss — so a caller that skips the gate gets a plausible answer and no signal. Handing back `undefined` until it can answer is what makes the caller write its fallback.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-loadedassembly) |
| <span id="getter-svgready">**svgReady**</span><br><code>boolean</code> | <span data-pagefind-ignore>true once an off-screen (SVG) export can safely read this display's data. Policy single-sourced in `computeSvgReady`; this family supplies only the freshness half, which `foundationSvgReady` reads as `dataCurrent` or the vacuous currency of `viewportEmpty`. Off-screen renderers gate on it via `awaitSvgReady(model)` instead of inlining the condition.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-svgready) |
| <span id="getter-paintinert">**paintInert**</span><br><code>boolean</code> | <span data-pagefind-ignore>Fills `RenderLifecycleMixin`'s `paintInert` hook — see there for why a failed fetch has to read as finished to the consumers outside the display, and `foundationPaintInert` for the second such state and why both fetch families answer it through one function. Overridable, as the hook is: a display with a third inert state of its own says so here.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-paintinert) |
| <span id="getter-displayphase">**displayPhase**</span><br><code>DisplayPhase</code> | <span data-pagefind-ignore>The display's mutually-exclusive visual state, mapped in `foundationDisplayPhase` — every foundation calls it and supplies only its staleness argument, so a term added to `computeLoadingTerm` reaches all three without being wired three times.<br><br>This family's argument is spatial: `loading` also covers stale data (viewport past loaded) still on screen through the pre-refetch debounce. A thunk, so a suppressed or already-loading display doesn't subscribe to viewport churn.<br><br>A subclass customizes this through `fetchInert` (FetchMixin), never by overriding the getter — see that hook.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#getter-displayphase) |
| <span id="getter-densitygateenabled">**densityGateEnabled**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the density axis applies. `CanvasFeatureGateMixin` contributes `true` beside its measurement; byte-only displays leave it.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-densitygateenabled) |
| <span id="getter-bytegateadapterconfig">**byteGateAdapterConfig**</span><br><code>Record&lt;string, unknown&gt;</code> | <span data-pagefind-ignore>The adapter config the gate measures — the one at `byteGateAdapterPath`. Overridable for a display whose adapter config is synthesized rather than read off the track.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-bytegateadapterconfig) |
| <span id="getter-configuredfetchsizelimit">**configuredFetchSizeLimit**</span><br><code>number</code> | <span data-pagefind-ignore>The display's `fetchSizeLimit` slot, from `regionTooLargeConfigSchemaFields`.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-configuredfetchsizelimit) |
| <span id="getter-densitytoolarge">**densityTooLarge**</span><br><code>boolean</code> | <span data-pagefind-ignore>The density axis's verdict; canvas overrides it.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-densitytoolarge) |
| <span id="getter-bytegateadapterpath">**byteGateAdapterPath**</span><br><code>string[]</code> | <span data-pagefind-ignore>Where on the track config the measured adapter sits. A tiered display overrides this one hook (MAF: `['adapter', 'summaryAdapter']` while `showSummary`), and both the measurement and the budget follow it.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-bytegateadapterpath) |
| <span id="getter-adapterfetchsizelimit">**adapterFetchSizeLimit**</span><br><code>number &#124; undefined</code> | <span data-pagefind-ignore>The measured adapter's own `fetchSizeLimit` slot, read off the live track config rather than the `adapterConfig` snapshot, which omits slots at their default.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-adapterfetchsizelimit) |
| <span id="getter-configforceload">**configForceLoad**</span><br><code>boolean</code> | <span data-pagefind-ignore>The declarative `forceLoad` slot.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-configforceload) |
| <span id="getter-gateviewport">**gateViewport**</span><br><code>GateViewport &#124; undefined</code> | <span data-pagefind-ignore>What a measurement taken now would be about: the span on screen and a key for the stretch of genome it covers. Undefined until the view is measured, and the mixin's only read of the view. Captured before the fetch's round trip, never at commit.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-gateviewport) |
| <span id="getter-bytegateadapterkey">**byteGateAdapterKey**</span><br><code>string</code> | <span data-pagefind-ignore>Which tier the estimate is about, as a comparable string.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-bytegateadapterkey) |
| <span id="getter-aboveforceloadfloor">**aboveForceLoadFloor**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the span on screen is at or above `AUTO_FORCE_LOAD_BP`, the one comparison against that constant. False on an unmeasured view.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-aboveforceloadfloor) |
| <span id="getter-gateexempt">**gateExempt**</span><br><code>boolean</code> | <span data-pagefind-ignore>Nothing may gate on either axis: the `forceLoad` slot or the button.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-gateexempt) |
| <span id="getter-estimatedfetchbytes">**estimatedFetchBytes**</span><br><code>number &#124; undefined</code> | <span data-pagefind-ignore>The stored estimate's bytes; undefined when nothing has been measured.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-estimatedfetchbytes) |
| <span id="getter-gatemeasurementstale">**gateMeasurementStale**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the last measurement is about a viewport the user has since left. True before any measurement.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-gatemeasurementstale) |
| <span id="getter-gatebytelimit">**gateByteLimit**</span><br><code>number</code> | <span data-pagefind-ignore>The byte budget: the adapter's limit, else the display's, doubled below `AUTO_FORCE_LOAD_BP`. Read only through `resolvedByteLimit()`.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-gatebytelimit) |
| <span id="getter-gateactive">**gateActive**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the gate may act right now, on any axis: opted in, not exempt, view measured. The view is read last, so an ungated display never touches it.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-gateactive) |
| <span id="getter-densitygateactive">**densityGateActive**</span><br><code>boolean</code> | <span data-pagefind-ignore>`gateActive` plus the density axis's own terms: the axis is on, and the span is above the floor.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-densitygateactive) |
| <span id="getter-toolargestatus">**tooLargeStatus**</span><br><code>RegionTooLargeStatus</code> | <span data-pagefind-ignore>The verdict and its banner text, from the stored estimate against `resolvedByteLimit()` and the density axis when it may act.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-toolargestatus) |
| <span id="getter-regiontoolarge">**regionTooLarge**</span><br><code>boolean</code> |  | [RegionTooLargeMixin](../regiontoolargemixin#getter-regiontoolarge) |
| <span id="getter-regiontoolargereason">**regionTooLargeReason**</span><br><code>string</code> | <span data-pagefind-ignore>Banner text for the axis that tripped; empty when not too large.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-regiontoolargereason) |
| <span id="getter-zoomcanreleasegate">**zoomCanReleaseGate**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether "zoom in to see features" is honest advice. Density always releases on zoom; bytes only if the last zoom-in moved the estimate.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-zoomcanreleasegate) |
| <span id="getter-gateskipsmeasuredviewport">**gateSkipsMeasuredViewport**</span><br><code>boolean</code> | <span data-pagefind-ignore>The skip both fetch skeletons apply: the banner is up and its measurement already describes the viewport on screen.</span> | [RegionTooLargeMixin](../regiontoolargemixin#getter-gateskipsmeasuredviewport) |
| <span id="getter-renderscanvas">**rendersCanvas**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overridable hook (default true): whether this display paints a canvas in its **current** configuration, as opposed to a deliberate static placeholder (LD with the triangle off, sequence past base resolution — both render a message where the `<canvas>` would go, so `canvasRef` is never called and `canvasDrawn` can never flip).<br><br>Lives here, beside `canvasDrawn`, because every consumer of "has this display painted" needs the pair — and until 2026-08 each family declared its own copy (per-region hard-coded `true`, global carried the hook for LD), so a display could express the state only to whichever family it happened to compose. See `painted` below for the reader that was missed.</span> | [RenderLifecycleMixin](../renderlifecyclemixin#getter-renderscanvas) |
| <span id="getter-painted">**painted**</span><br><code>boolean</code> | <span data-pagefind-ignore>**The first-paint answer every consumer outside the display should read**, `canvasDrawn` being only the raw flag: a display that is deliberately not painting a canvas has finished, and saying otherwise is a lie that never resolves.<br><br>The two `rendersCanvas: false` states each had three of their four consumers wired by hand — the loading scrim (`rendersCanvas` / `fetchInert`) and the SVG export (`fetchInert`) — while the fourth, `data-display-drawn`, went on publishing `"false"` forever off the raw flag. That attribute is what `PENDING_DISPLAYS` (`@jbrowse/browser-test-utils`) selects on, so a zoomed-out reference sequence track made every `waitForDisplaysDone` on the page burn its full timeout — silently, since that wait swallows its own. Same shape as `fetchInert` on the comparative side: the reader you forget is the one outside the display, so the display has to publish one name for it.<br><br>`paintInert` is the third term and the same argument once more, for the state where a display *would* paint a canvas and never gets to — a fetch that failed before first paint. See that hook.</span> | [RenderLifecycleMixin](../renderlifecyclemixin#getter-painted) |
| <span id="getter-isloading">**isLoading**</span><br><code>boolean</code> | <span data-pagefind-ignore>true while a fetch is active</span> | [FetchMixin](../fetchmixin#getter-isloading) |
| <span id="getter-isloadingorcanceled">**isLoadingOrCanceled**</span><br><code>boolean</code> | <span data-pagefind-ignore>`isLoading` widened to cover a user-canceled load. **This, not `isLoading`, is what a `displayPhase` loading term wants.** `cancelFetchByUser` clears the stop token synchronously, so `isLoading` goes false the instant the user clicks Cancel — and the loading overlay that unmounts on it is carrying the Retry button, which is the only way back: the state is deliberately durable, so no autorun restarts the fetch on its own. A bare `isLoading` therefore reads as `ready` over a display that is stopped, empty and offering nothing.<br><br>Arc read `isLoading` directly and had exactly that hole. It is a getter here so no family has to remember the second term.</span> | [FetchMixin](../fetchmixin#getter-isloadingorcanceled) |
| <span id="getter-fetchinert">**fetchInert**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overridable hook (default false): the states where this display deliberately never fetches, so it holds no data and none is coming. Sequence sets it past base resolution ("Zoom in to see sequence"); LD sets it with the triangle toggled off.<br><br>**One hook, three readers**, and that is the whole point — a display that grows such a state has one thing to say rather than three, and the reader it would have forgotten is always the one outside itself:<br><br>- the loading scrim (`computeLoadingTerm`), which otherwise parks over the placeholder, permanently once a cancel has been clicked; - the SVG export (`computeSvgReady`'s `extraTerminal`), whose `awaitSvgReady` is an unbounded `when`, so one such display hangs the whole view's export; - the dev-only retry check (`makeRetryContractCheck`), which would otherwise report a dead Retry on a display correctly declining to load anything.<br><br>It was three hooks — `loadingSuppressed`, `svgReadyExtraTerminal` on each of the two foundations, and `fetchInert` on the comparative family, which had already collapsed them. Both LGV displays that override it returned one expression for all three, and one of the three was hard-coded `false` on the global family for a while, which is how LD came to be able to express only half its own state. Same name and same meaning as `SyntenyFetchStateMixin.fetchInert` now, so the retry check reads one field across all three fetch families. ADR-082.<br><br>A hook rather than a `displayPhase` override, because overriding the getter means restating the whole loading condition — which is how sequence came to hold a verbatim copy of the other terms, one `git blame` away from silently missing the next one added.<br><br>It lives **here** because this is the one mixin all three display foundations compose. Same argument, one level down, that put `rendersCanvas` on `RenderLifecycleMixin` beside `canvasDrawn`.</span> | [FetchMixin](../fetchmixin#getter-fetchinert) |
| <span id="getter-rpcpropscachekey">**rpcPropsCacheKey**</span><br><code>string</code> | <span data-pagefind-ignore>The RPC cache key both fetch foundations invalidate on: this display's `rpcProps()` payload serialized to a string. `serializeRpcProps` owns the why, including the silently-dead-axis corollary.<br><br>Here, beside the two hooks above, for the same reason they are: it describes the display, and every foundation composes this mixin. The per-region family watches it from `SettingsInvalidate` and the global one from its fetch autorun's trigger list — one getter and one name, so the two cannot come to invalidate on different axes. The global side built its own local `computed` over the same function until 2026-08, which was the same value under a second spelling.</span> | [FetchMixin](../fetchmixin#getter-rpcpropscachekey) |
| <span id="getter-showlegend">**showLegend**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the legend is drawn. Resolved through the promotable-slot tiers (`resolveConf`): an explicit track value customizes it either way, otherwise it follows the session-wide default for this display type, falling back to the slot's `promotedBase`.</span> | [LegendMixin](../legendmixin#getter-showlegend) |
| <span id="getter-showlegenddisplaytypedefault">**showLegendDisplayTypeDefault**</span><br><code>Pin</code> | <span data-pagefind-ignore>The "make the current legend visibility the default for all tracks" control. Symmetric, so it promotes whichever value the track currently shows. `showLegendCheckboxItem` takes this as its `pin`.</span> | [LegendMixin](../legendmixin#getter-showlegenddisplaytypedefault) |
| <span id="getter-rowheight">**rowHeight**</span><br><code>number</code> | <span data-pagefind-ignore>Raw per-row height setting: `0` is fit-to-display-height, any positive value is a fixed px height. The resolved value is `effectiveRowHeight` — consumers read that, never this. On the config rather than the display snapshot for the same reason `height` is: the config node outlives the display instance, so a fixed height survives unticking and reticking the track.</span> | [RowHeightMixin](../rowheightmixin#getter-rowheight) |
| <span id="getter-effectiverowheight">**effectiveRowHeight**</span><br><code>number</code> | <span data-pagefind-ignore>Resolved per-row height. `rowHeight === 0` divides the display's own `autoRowHeight` across the rows; any positive value is the fixed px height, used as-is however many rows there are.<br><br>Sub-pixel is legitimate and deliberately not floored here — a cohort with more rows than the track has pixels has a genuinely fractional row height, and flooring it makes the content taller than the height it was asked to fit inside. `resolveRowHeight` floors only a **non-positive** result, which consumers divide by.</span> | [RowHeightMixin](../rowheightmixin#getter-effectiverowheight) |
| <span id="getter-showtree">**showTree**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether the dendrogram sidebar is drawn.</span> | [TreeSidebarMixin](../treesidebarmixin#getter-showtree) |
| <span id="getter-showbranchlength">**showBranchLength**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether tree nodes are positioned by branch length (dendrogram) or evenly by topology (cladogram).</span> | [TreeSidebarMixin](../treesidebarmixin#getter-showbranchlength) |
| <span id="getter-showrowlabels">**showRowLabels**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether each row's name is drawn over the left of the plot.</span> | [TreeSidebarMixin](../treesidebarmixin#getter-showrowlabels) |
| <span id="getter-parsedtree">**parsedTree**</span><br><code>HierarchyNode&lt;NewickNode&gt; &#124; undefined</code> |  | [TreeSidebarMixin](../treesidebarmixin#getter-parsedtree) |
| <span id="getter-root">**root**</span><br><code>HierarchyNode&lt;NewickNode&gt; &#124; undefined</code> |  | [TreeSidebarMixin](../treesidebarmixin#getter-root) |
| <span id="getter-treehasbranchlengths">**treeHasBranchLengths**</span><br><code>boolean</code> |  | [TreeSidebarMixin](../treesidebarmixin#getter-treehasbranchlengths) |

## Methods

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="method-rpcprops">**rpcProps**</span><br><code>() =&gt; {…}</code> |  | LinearMultiSampleVariantDisplay |
| <span id="method-trackmenuitems">**trackMenuItems**</span><br><code>() =&gt; MenuItem[]</code> |  | LinearMultiSampleVariantDisplay |
| <span id="method-showsubmenuitems">**showSubmenuItems**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>() =&gt; (MenuDivider &#124; MenuSubHeader &#124; NormalMenuItem &#124; CheckboxM…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>() =&gt; (MenuDivider &#124; MenuSubHeader &#124; NormalMenuItem &#124; CheckboxMenuItem &#124; RadioMenuItem &#124; SubMenuItem &#124; CustomMenuItem &#124; { ...; })[]</code></pre></dialog></span> |  | LinearMultiSampleVariantDisplay |
| <span id="method-lanefeatureinfo">**laneFeatureInfo**</span><br><code>(featureId: string) =&gt; VariantFeatureInfo &#124; undefined</code> | The record behind a lane mark, by feature id. plugin-canvas's hit test answers with an id (its payload carries no VCF fields), and the tooltip and the click both want the record — so this is the one place that crosses back, over `featureGenotypeMap`, the same map the genotype cells' hit test reads. | LinearMultiSampleVariantDisplay |
| <span id="method-lanelayoutat">**laneLayoutAt**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(showLabels: boolean, showDescriptions: boolean) =&gt; Map&lt;number,…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(showLabels: boolean, showDescriptions: boolean) =&gt; Map&lt;number, FeatureDataResult&gt;</code></pre></dialog></span> | One fit candidate: the lane's stack packed with the given label reservation. plugin-canvas's packer, so overlapping SVs stack instead of overdrawing, a label is placed by the layout that reserved room for it, and paint order is the order the hit test resolves by.<br><br>Non-incremental, unlike that display's four memos: those exist so a GPU upload diff stays small across a pan over a stack of hundreds of thousands of features. A band holds thousands and repaints whole. | LinearMultiSampleVariantDisplay |
| <span id="method-rendersvg">**renderSvg**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(opts?: ExportSvgDisplayOptions &#124; undefined) =&gt; Promise&lt;ReactEl…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(opts?: ExportSvgDisplayOptions &#124; undefined) =&gt; Promise&lt;ReactElement&lt;unknown, string &#124; JSXElementConstructor&lt;any&gt;&gt; &#124; Iterable&lt;...&gt; &#124; AwaitedReactNode&gt;</code></pre></dialog></span> |  | LinearMultiSampleVariantDisplay |
| <span id="method-configuredfilters">**configuredFilters**</span><br><code>() =&gt; string[]</code> | <span data-pagefind-ignore>What the `jexlFilters` config slot alone declares, `jexl:`-prefixed. In its own block ahead of every reader so they reach it through `self`, the arrangement `LinearBasicDisplay` uses for the same pair.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#method-configuredfilters) |
| <span id="method-activefilters">**activeFilters**</span><br><code>() =&gt; string[]</code> | <span data-pagefind-ignore>The filters actually applied, `jexl:`-prefixed: the runtime override when set, otherwise the config tier. In its own block after `configuredFilters` so it reaches it through `self`, the arrangement `LinearBasicDisplay` uses for the same pair.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#method-activefilters) |
| <span id="method-contextmenuitems">**contextMenuItems**</span><br><code>() =&gt; MenuItem[]</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#method-contextmenuitems) |
| <span id="method-getportablesettings">**getPortableSettings**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(newDisplayId?: string &#124; undefined) =&gt; { jexlFiltersSetting: (I…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(newDisplayId?: string &#124; undefined) =&gt; { jexlFiltersSetting: (IMSTArray&lt;…&gt; &amp; IStateTreeNode&lt;…&gt;) &#124; undefined; ... 4 more ...; layout: Source[] &amp; IStateTreeNode&lt;...&gt;; }</code></pre></dialog></span> | <span data-pagefind-ignore>Called by BaseTrackModel.replaceDisplay when switching between the regular and matrix variant displays. The config-slot settings (colorBy, renderingMode, etc.) now live on each display's own config-schema node rather than a display-instance override map, so porting them means writing directly into the *target* display's config (via setSlot) rather than spreading them into the new display's instance snapshot — hence the `newDisplayId` param. Only genuine display-instance state (not config-backed) is returned for the instance-snapshot spread.<br><br>`clusterProvenance` and `subtreeFilter` travel with `clusterTree` and `layout`: the tree without its provenance loses the "Clustered on <locus>" row and the drift chip, and the layout without the filter un-focuses a clade the reader had narrowed to.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#method-getportablesettings) |
| <span id="method-legendsections">**legendSections**</span><br><code>(insertionColor?: string &#124; undefined) =&gt; LegendSection[]</code> | <span data-pagefind-ignore>Legend split into independently-closable sections: the genotype/cell coloring and (when colorBy is set) the sample-grouping coloring shown on the sidebar row labels. Dismissed sections are filtered out.<br><br>`insertionColor` repaints the marker swatch without touching *whether* one is shown — that stays `insertionLegendColor`'s answer, which is the painter's own test on the painter's own blocks. Only the SVG export passes it, and it has to: the export draws its glyphs with the palette of the theme the user picked in the export dialog rather than the live session's (the rule plugin-maf's export follows too), so a session that themes `palette.insertion` would otherwise key an export in one color and draw it in another.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#method-legendsections) |
| <span id="method-renderingprops">**renderingProps**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>() =&gt; { displayModel: ModelInstanceTypeProps&lt;{ id: IOptionalITy…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>() =&gt; { displayModel: ModelInstanceTypeProps&lt;{ id: IOptionalIType&lt;…&gt;; type: ISimpleType&lt;string&gt;; }&gt; &amp; { ...; } &amp; { ...; } &amp; { ...; } &amp; IStateTreeNode&lt;...&gt;; }</code></pre></dialog></span> | <span data-pagefind-ignore>props passed to the renderer's React "Rendering" component. these are client-side only and never sent to the worker. includes displayModel and callbacks</span> | [BaseDisplay](../basedisplay#method-renderingprops) |
| <span id="method-regionhasdata">**regionHasData**</span><br><code>(_displayedRegionIndex: number) =&gt; boolean</code> | <span data-pagefind-ignore>Overridable hook (default true): whether the display can actually draw what this region is marked loaded over. Two different displays want it for two different reasons, and both are real:<br><br>- **The reader-side check of the write-side rule.** `loadedRegions` is written where the payload is stored (`RegionFetchContext`), so an entry with nothing behind it means that rule was broken somewhere. Answering off the data map costs a lookup and decides which way the break fails: a refetch, or a viewport that reads as covered against data nobody has and never asks again. Both canvas displays. - **Which of several held payloads answers.** MAF caches a summary tier and a detail tier side by side under one `displayedRegionIndex`, so crossing the threshold inside an already-loaded region changes which map has to answer — something the coverage bounds cannot see at all.<br><br>Separate from `regionFetchKey` on purpose: for MAF a key would refetch the summary on every zoom back out, since both tiers are still held. And the mixin cannot see a display's data map, so a key that changed when data arrived would be the `rpcProps()` loop in different clothes.<br><br>**The fail-open default is load-bearing, not an omission.** A byte-gate refusal never marks a region loaded (the commit sits beside the store and skips refused results), so "marked loaded with nothing behind it" is unreachable from the gate — the one path that stamps without storing is sequence's legitimately-empty-region answer, and a store-derived default there would refetch forever: stamp, store nothing, read uncovered, fetch again. `true` is what lets "this fetch completed and there is genuinely nothing here" be a terminal state.<br><br>A view, not an action, for the reason `regionFetchKey` is a getter.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#method-regionhasdata) |
| <span id="method-iscachevalid">**isCacheValid**</span><br><code>(displayedRegionIndex: number) =&gt; boolean</code> | <span data-pagefind-ignore>Whether the data held for a region still answers the current view. Not a hook a display fills: a display states its rule as `regionFetchKey` (what a fetch now would produce) and `regionHasData` (did the last one store anything), and this compares the key against the one the region was fetched under. A subclass that changes what it fetches spells the change in the key, and one that forgets gets a redundant fetch rather than a cached answer for a zoom the data was never fetched at.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#method-iscachevalid) |
| <span id="method-resolvedbytelimit">**resolvedByteLimit**</span><br><code>() =&gt; number &#124; undefined</code> | <span data-pagefind-ignore>The budget the worker enforces and the banner compares against — the one spelling of that pair. Undefined when the gate may not act.</span> | [RegionTooLargeMixin](../regiontoolargemixin#method-resolvedbytelimit) |
| <span id="method-gatefetchstate">**gateFetchState**</span><br><code>() =&gt; GateFetchState</code> | <span data-pagefind-ignore>The gate as it stands for a fetch about to be issued. Calling it is the capture, which is why it is a method.</span> | [RegionTooLargeMixin](../regiontoolargemixin#method-gatefetchstate) |
| <span id="method-willcleartree">**willClearTree**</span><br><code>(next: S[]) =&gt; boolean</code> |  | [TreeSidebarMixin](../treesidebarmixin#method-willcleartree) |

## Actions

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="action-setshowvariantlane">**setShowVariantLane**</span><br><code>(arg: boolean) =&gt; void</code> | Switch the variant lane on or off. The rows resize with it — `availableHeight` subtracts the band — which is the point: the lane takes its space from the plot rather than growing the track. | LinearMultiSampleVariantDisplay |
| <span id="action-setvariantlaneheight">**setVariantLaneHeight**</span><br><code>(arg: number) =&gt; void</code> | Resize the variant lane, clamped. Clamped in the setter rather than at read time for the same reason `setLineZoneHeight` is: a drag can deliver any number, and a band dragged shut has to stay grabbable. | LinearMultiSampleVariantDisplay |
| <span id="action-setvariantlanelabels">**setVariantLaneLabels**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(arg: "auto" &#124; "description" &#124; "name" &#124; "nameAndDescription" &#124;…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(arg: "auto" &#124; "description" &#124; "name" &#124; "nameAndDescription" &#124; "none") =&gt; void</code></pre></dialog></span> |  | LinearMultiSampleVariantDisplay |
| <span id="action-startrenderingbackend">**startRenderingBackend**</span><br><code>(backend: VariantRenderingBackend) =&gt; void</code> |  | LinearMultiSampleVariantDisplay |
| <span id="action-setcelldata">**setCellData**</span><br><code>(data: CellDataResult &#124; undefined) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setcelldata) |
| <span id="action-setcontextmenufeature">**setContextMenuFeature**</span><br><code>(feature?: Feature &#124; undefined) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setcontextmenufeature) |
| <span id="action-fetchmetadatadescriptions">**fetchMetadataDescriptions**</span><br><code>() =&gt; Promise&lt;unknown&gt;</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-fetchmetadatadescriptions) |
| <span id="action-setjexlfilters">**setJexlFilters**</span><br><code>(f?: string[] &#124; undefined) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setjexlfilters) |
| <span id="action-setshowlegend">**setShowLegend**</span><br><code>(s: boolean) =&gt; void</code> | <span data-pagefind-ignore>The one override of `LegendMixin`'s setter: this display keeps a per-section dismissed list, and re-showing the whole legend restores the sections closed inside it. The slot write stays the mixin's.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setshowlegend) |
| <span id="action-dismisslegendsection">**dismissLegendSection**</span><br><code>(id: string) =&gt; void</code> | <span data-pagefind-ignore>Close a single legend section (leaving the others visible).</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-dismisslegendsection) |
| <span id="action-selectfeature">**selectFeature**</span><br><code>(feature: Feature) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-selectfeature) |
| <span id="action-sethoveredgenotype">**setHoveredGenotype**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(arg?: (Record&lt;string, unknown&gt; &amp; { genotype: string; name: str…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(arg?: (Record&lt;string, unknown&gt; &amp; { genotype: string; name: string; }) &#124; undefined) =&gt; void</code></pre></dialog></span> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-sethoveredgenotype) |
| <span id="action-setsources">**setSources**</span><br><code>(sources: Source[]) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setsources) |
| <span id="action-setcolorby">**setColorBy**</span><br><code>(colorBy: string) =&gt; void</code> | <span data-pagefind-ignore>Recolor sample rows by a metadata attribute (e.g. 'population'), or pass '' to clear the coloring. Persists the arrangement as the layout and records the choice in the `colorBy` config slot so it survives a data refetch and serializes into the session. Re-applies `groupBy` in the same pass so recoloring doesn't drop an existing grouping, and recolors the rows in place (see `applyArrangement`) so it doesn't drop an existing order either.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setcolorby) |
| <span id="action-setgroupby">**setGroupBy**</span><br><code>(groupBy: string) =&gt; void</code> | <span data-pagefind-ignore>Reorder sample rows so each value of a metadata attribute (e.g. 'population') is contiguous, or pass '' to clear the grouping. Persists the arrangement as the layout and records the choice in the `groupBy` config slot so it survives a data refetch and serializes into the session. Re-applies `colorBy` in the same pass so grouping doesn't drop an existing palette.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setgroupby) |
| <span id="action-setmaffilter">**setMafFilter**</span><br><code>(arg: number) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setmaffilter) |
| <span id="action-setmaxmissingnessfilter">**setMaxMissingnessFilter**</span><br><code>(arg: number) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setmaxmissingnessfilter) |
| <span id="action-setphasedmode">**setPhasedMode**</span><br><code>(arg: string) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setphasedmode) |
| <span id="action-setfittoheight">**setFitToHeight**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Enable fit-to-display-height mode: `rowHeight = 0` makes `effectiveRowHeight` divide `availableHeight` across the rows.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setfittoheight) |
| <span id="action-resizeheight">**resizeHeight**</span><br><code>(distance: number) =&gt; number</code> | <span data-pagefind-ignore>Drag-resize the track. In fit-to-display-height mode the new height flows straight into `autoRowHeight`, so the rows stretch with the drag. With a fixed `rowHeight` the rows keep the size the user chose and the drag reveals more of them — scaling that value by the same ratio instead would keep content and viewport locked together, so dragging a track taller could not show one extra sample.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-resizeheight) |
| <span id="action-setreferencedrawingmode">**setReferenceDrawingMode**</span><br><code>(arg: string) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setreferencedrawingmode) |
| <span id="action-setshowrowseparators">**setShowRowSeparators**</span><br><code>(arg: boolean) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setshowrowseparators) |
| <span id="action-setshowtooltips">**setShowTooltips**</span><br><code>(arg: boolean) =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setshowtooltips) |
| <span id="action-setfeaturecolor">**setFeatureColor**</span><br><code>(arg: string) =&gt; void</code> | <span data-pagefind-ignore>Set the per-variant cell color override (jexl string or CSS color), or '' to restore default genotype coloring. A fetch input — recomputes cells in the worker.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-setfeaturecolor) |
| <span id="action-clearlayout">**clearLayout**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Restore the configured default arrangement. The mixin's `clearLayout` empties the layout and drops the tree plus the subtree filter that named its leaves; with no layout left, `applyArrangement` re-derives from adapter order — the same thing it does on first load, so a reset and a fresh load can't come out different.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-clearlayout) |
| <span id="action-sortbygenotype">**sortByGenotype**</span><br><code>(featureId: string) =&gt; void</code> | <span data-pagefind-ignore>Order the rows by their genotype at one variant, breaking ties by how far each row agrees with its neighbours to either side of it. The flanking tiebreak is what makes the local haplotype structure legible: rows sharing the anchor allele sit together, and their shared block frays outward at the recombination breakpoints that end it.<br><br>Sorts the rows that are already on screen, so the palette color, label and labelColor ride along and nothing has to be merged back. Sorting adapter metadata instead discarded all three: **Color by… → Population** then **Sort by genotype** reordered correctly and blanked every sidebar swatch, with the menu still showing Population ticked. Nothing re-seeds the palette afterwards — `setSources` short-circuits on `deepEqual`, and `applyArrangement` is reachable only from `setColorBy` / `setGroupBy` / `clearLayout` / `setPhasedMode`.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-sortbygenotype) |
| <span id="action-sortrowsbygenotypeat">**sortRowsByGenotypeAt**</span><br><code>(refName: string, pos: number) =&gt; void</code> | <span data-pagefind-ignore>`sortByGenotype` at a genomic column rather than a record: the declarative `sortRowsBy` entry point, for a session that wants a cohort to open sorted at a locus. The variant is the loaded record covering the column; a column no record covers leaves the rows alone, the rule every "sort rows here" shares (`rowSortColumn.ts`).<br><br>`refName` arrives canonical — the autorun normalizes it — while a record's refName is whatever the file spelled, so the comparison canonicalizes the record's side.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-sortrowsbygenotypeat) |
| <span id="action-focusgroup">**focusGroup**</span><br><code>(label: string) =&gt; void</code> | <span data-pagefind-ignore>Narrow the rows to one `colorBy` group — what clicking that group's swatch in the legend does. `label` is the legend's own spelling, so the unlabeled group comes in as it is listed there.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-focusgroup) |
| <span id="action-cleardisplayspecificdata">**clearDisplaySpecificData**</span><br><code>() =&gt; void</code> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-cleardisplayspecificdata) |
| <span id="action-fetchneeded">**fetchNeeded**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(_needed: { region: Region; displayedRegionIndex: number; }[])…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(_needed: { region: Region; displayedRegionIndex: number; }[]) =&gt; Promise&lt;void&gt;</code></pre></dialog></span> |  | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-fetchneeded) |
| <span id="action-clearhoveredfeature">**clearHoveredFeature**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Fills `BaseDisplay`'s hover-clear hook, which the fetch foundation's reaction calls on every viewport change.<br><br>The matrix is a sticky canvas, so a pan, a zoom or an internal wheel-scroll fires no mousemove and no mouseleave, and `hoveredGenotype` goes on naming a cell that has moved out from under the pointer — the tooltip then reports another sample's genotype at the cursor. `useVariantCanvasInteraction` only covers the cases where the *pointer* moves.</span> | [MultiSampleVariantBaseModel](../multisamplevariantbasemodel#action-clearhoveredfeature) |
| <span id="action-setstatusmessage">**setStatusMessage**</span><br><code>(status?: RpcStatus &#124; undefined) =&gt; void</code> |  | [BaseDisplay](../basedisplay#action-setstatusmessage) |
| <span id="action-seterror">**setError**</span><br><code>(error?: unknown) =&gt; void</code> |  | [BaseDisplay](../basedisplay#action-seterror) |
| <span id="action-reload">**reload**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>base display reload does nothing, see specialized displays for details</span> | [BaseDisplay](../basedisplay#action-reload) |
| <span id="action-setscrolltop">**setScrollTop**</span><br><code>(scrollTop: number) =&gt; void</code> | <span data-pagefind-ignore>Clamped into `[0, scrollableHeight]`, so no caller has to remember the bound. Unbounded for a display that leaves `scrollableHeight` at its `Infinity` default.</span> | [TrackHeightMixin](../trackheightmixin#action-setscrolltop) |
| <span id="action-setheight">**setHeight**</span><br><code>(displayHeight: number) =&gt; number</code> |  | [TrackHeightMixin](../trackheightmixin#action-setheight) |
| <span id="action-expandtocontentheight">**expandToContentHeight**</span><br><code>() =&gt; number</code> | <span data-pagefind-ignore>Grow the track by exactly the content it is currently hiding, so a display scrolled over a taller stack ends up showing all of it. The track's resize handle runs this on a double click.<br><br>`scrollableHeight` is the whole measurement — it is already every scrolling display's answer to "how much is off the bottom", so no display has to supply a second one. A display that doesn't scroll internally leaves it at `Infinity` and gets a no-op, as does one already showing everything (0).<br><br>Routed through `resizeHeight` rather than `setHeight` so grow mode's override still gets to leave grow first; going straight to the slot would let the reactive height re-derive `grownHeight` and the double click would appear to do nothing.</span> | [TrackHeightMixin](../trackheightmixin#action-expandtocontentheight) |
| <span id="action-setloadedregion">**setLoadedRegion**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(displayedRegionIndex: number, region: Region, fetchKey?: strin…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(displayedRegionIndex: number, region: Region, fetchKey?: string) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>The raw write behind `ctx.commitRegion`, and **not what a fetch should call**: a display naming its own span is the bug this family spent a release on, and going through the context is what makes that inexpressible — see RegionFetchContext. Direct callers are tests staging an already-loaded display.<br><br>An action so callers after an async boundary stay in MST strict mode. Stamps the region with the fetch key its data came back under. `fetchRegions` passes the key it captured before issuing the RPC; the default reads it *now*, which is right for a caller holding the region already and wrong for anything resuming after an await, where the viewport may have moved under the fetch.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#action-setloadedregion) |
| <span id="action-droploadedregion">**dropLoadedRegion**</span><br><code>(displayedRegionIndex: number) =&gt; void</code> | <span data-pagefind-ignore>Forget one region — for a display pruning what has scrolled off screen.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#action-droploadedregion) |
| <span id="action-clearallrpcdata">**clearAllRpcData**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>full reset: cancels fetch, clears error, loadedRegions, display-specific data, and the canvas-drawn flag. The too-large gate is derived (a pure function of the cached estimate × viewport), so it needs no explicit clear here — the fetch autorun re-measures at the new viewport and the verdict follows.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#action-clearallrpcdata) |
| <span id="action-fetchregions">**fetchRegions**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(needed: IndexedRegion[], work: (ctx: RegionFetchContext) =&gt; Pr…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(needed: IndexedRegion[], work: (ctx: RegionFetchContext) =&gt; Promise&lt;void&gt;) =&gt; Promise&lt;void&gt;</code></pre></dialog></span> | <span data-pagefind-ignore>Run a per-region fetch. The work callback calls `ctx.commitRegion` as it stores each region's payload, which is what marks it loaded — see RegionFetchContext for why this function no longer does that itself. Its only callers are the three helpers in `fetchEachRegion.ts`, which make that call for every display in the family; a display reaching past them owns both `ctx.isStale()` guards and the commit by hand, and none does.<br><br>The fetch key is captured here, at issue, and carried into every commit — never re-read after the await. `ctx.isStale()` trips on a newer fetch or a cancel, not on a viewport that moved under a fetch that is still current, so a key read at commit time would stamp this data with a zoom it was not fetched at.</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#action-fetchregions) |
| <span id="action-afterattach">**afterAttach**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>installs the fetch-lifecycle autoruns (DisplayedRegionsChange, FetchVisibleRegions, SettingsInvalidate, ClearBlockingStateOnViewportChange)</span> | [MultiRegionDisplayMixin](../multiregiondisplaymixin#action-afterattach) |
| <span id="action-setbyteestimate">**setByteEstimate**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(measurement: { bytes: number; viewport: GateViewport; }) =&gt; vo…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(measurement: { bytes: number; viewport: GateViewport; }) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>The bytes half of a measurement alone, for a test staging a display. Production commits through `commitFetchBytes`.</span> | [RegionTooLargeMixin](../regiontoolargemixin#action-setbyteestimate) |
| <span id="action-clearbyteestimate">**clearByteEstimate**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Drops the estimate and the viewport stamp. `forceLoadTrack` survives: it is a track-wide approval.</span> | [RegionTooLargeMixin](../regiontoolargemixin#action-clearbyteestimate) |
| <span id="action-setforceloadtrack">**setForceLoadTrack**</span><br><code>(flag: boolean) =&gt; void</code> |  | [RegionTooLargeMixin](../regiontoolargemixin#action-setforceloadtrack) |
| <span id="action-commitfetchbytes">**commitFetchBytes**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(perRegionBytes: (number &#124; undefined)[], issued: GateFetchState…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(perRegionBytes: (number &#124; undefined)[], issued: GateFetchState) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>The byte axis of a finished fetch, called by the fetch runners with the `gateFetchState()` they captured at issue. Commits the per-region max; an empty batch, or an ungated display, commits nothing.</span> | [RegionTooLargeMixin](../regiontoolargemixin#action-commitfetchbytes) |
| <span id="action-forceload">**forceLoad**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>The banner's button: exempt the track on both axes and refetch.</span> | [RegionTooLargeMixin](../regiontoolargemixin#action-forceload) |
| <span id="action-markcanvasdrawn">**markCanvasDrawn**</span><br><code>() =&gt; void</code> |  | [RenderLifecycleMixin](../renderlifecyclemixin#action-markcanvasdrawn) |
| <span id="action-resetcanvasdrawn">**resetCanvasDrawn**</span><br><code>() =&gt; void</code> |  | [RenderLifecycleMixin](../renderlifecyclemixin#action-resetcanvasdrawn) |
| <span id="action-stoprenderingbackend">**stopRenderingBackend**</span><br><code>() =&gt; void</code> |  | [RenderLifecycleMixin](../renderlifecyclemixin#action-stoprenderingbackend) |
| <span id="action-rendernow">**renderNow**</span><br><code>() =&gt; void</code> |  | [RenderLifecycleMixin](../renderlifecyclemixin#action-rendernow) |
| <span id="action-setrendererror">**setRenderError**</span><br><code>(error: unknown) =&gt; void</code> | <span data-pagefind-ignore>set/clear the render-backend error. Called by `useRenderingBackend`: with the error when the canvas factory rejects (or context-loss re-init fails), and with `undefined` on successful (re)init and on retry.</span> | [RenderLifecycleMixin](../renderlifecyclemixin#action-setrendererror) |
| <span id="action-attachrenderingbackend">**attachRenderingBackend**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>&lt;B&gt;(backend: B, setup: () =&gt; RenderingBackendCallbacks&lt;B&gt;) =&gt; v…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>&lt;B&gt;(backend: B, setup: () =&gt; RenderingBackendCallbacks&lt;B&gt;) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>attach a GPU/Canvas2D backend and install the upload + render autorun pair. Idempotent: re-calling swaps the backend and does not run `setup` again, so the callbacks and everything they close over are the first call's.</span> | [RenderLifecycleMixin](../renderlifecyclemixin#action-attachrenderingbackend) |
| <span id="action-stopactivefetch">**stopActiveFetch**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Abort the in-flight fetch (if any) and retire its slot. The shared preamble of both cancel paths; the difference between them is only what they do to `fetchCanceled` / `fetchGeneration` afterward.</span> | [FetchMixin](../fetchmixin#action-stopactivefetch) |
| <span id="action-openstatusstream">**openStatusStream**</span><br><code>(isCurrent: () =&gt; boolean) =&gt; StatusStream</code> | <span data-pagefind-ignore>Open one operation's slot on the display's status field: an RPC `statusCallback` throttled through the display-wide window and guarded so a callback that fires after the node is torn down (RPCs resolve their status stream asynchronously) is a safe no-op, plus the `clear` that retires the slot when the operation ends.<br><br>**Every operation on the display opens one**, and the two come back together because an operation that never retires goes on voting for a phase that is over. The viewport fetch (`runFetch`), the clustering run and a lent `createStopTokenRotation` are three of them on one field; before ADR-081 each blanked the field outright and the last one to finish decided what the other two were still saying.<br><br>`isCurrent` is required and has no "node is alive" default, because alive is not the interesting question: a *superseded* fetch is on a live node, and its late status repainting the overlay of the fetch that replaced it is the failure this guards. `runFetch` passes `!isStale()`, which is what every display gets for free through `ctx.statusCallback`; a caller outside a fetch (the clustering autorun) passes its own run's flag. Defaulting to `isAlive` made the loose answer the easy one and five displays took it.<br><br>Declared this early only so `runFetch` can put one on every `FetchContext`.</span> | [FetchMixin](../fetchmixin#action-openstatusstream) |
| <span id="action-cancelfetch">**cancelFetch**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>cancel any in-flight fetch and bump fetchGeneration (always bumps, so callers can retrigger fetch autoruns even when nothing was in flight). This is the *internal* reset `clearAllRpcData` runs — it clears any user-cancel flag so the retrigger actually re-fetches.</span> | [FetchMixin](../fetchmixin#action-cancelfetch) |
| <span id="action-cancelfetchbyuser">**cancelFetchByUser**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>User-initiated cancel from the loading overlay. Stops the in-flight fetch and lands in a durable `fetchCanceled` state. Unlike `cancelFetch`, it does NOT bump fetchGeneration — so the fetch autoruns don't immediately restart the load. The user retries via `reload` (the overlay's retry button), or it clears on the next viewport change.</span> | [FetchMixin](../fetchmixin#action-cancelfetchbyuser) |
| <span id="action-beforedestroy">**beforeDestroy**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Release an in-flight fetch's stop token on teardown. Without this, a display destroyed mid-fetch (track/view closed while loading) never signals the worker to abort the now-useless work, and its in-flight HTTP reads keep downloading. MST auto-chains lifecycle hooks, so a composing display can still define its own beforeDestroy.</span> | [FetchMixin](../fetchmixin#action-beforedestroy) |
| <span id="action-endfetch">**endFetch**</span><br><code>(current: boolean, stopToken: StopToken) =&gt; void</code> | <span data-pagefind-ignore>The `finally` half of `runFetch`'s bookkeeping, an action of its own because `runFetchOnce`'s `finally` resumes on a microtask the flow does not own — a direct volatile write there is outside the action context, which is the one thing hoisting the sequence into a shared function costs. The stale branch is a superseded fetch: whoever superseded it — a newer `begin`, or `cancel` — already released this token.</span> | [FetchMixin](../fetchmixin#action-endfetch) |
| <span id="action-runfetch">**runFetch**</span><br><code>(work: (ctx: FetchContext) =&gt; Promise&lt;void&gt;) =&gt; Promise&lt;void&gt;</code> | <span data-pagefind-ignore>Run a cancel-safe fetch (cancels any prior). The work callback gets a FetchContext with a stopToken to forward to the RPC and an isStale() check to short-circuit commits once the user has moved on.<br><br>**The MST-flow wrapper over the shared `runFetchOnce` sequence**, and only the wrapper: the begin/clear/run/commit/error/end order, and the rules that keep a superseded run from writing back, are the same function every other fetch in the tree runs. What this adds is the observable bookkeeping a display needs — `isLoading` through `activeStopToken`, `fetchGeneration`, the user-cancel clear — and the flow itself, which is an action, so `work`'s synchronous prefix runs untracked wherever a fetch autorun calls this.</span> | [FetchMixin](../fetchmixin#action-runfetch) |
| <span id="action-setrowheight">**setRowHeight**</span><br><code>(n: number) =&gt; void</code> | <span data-pagefind-ignore>Pin a px row height. `0` is the fit sentinel, but enter fit mode through `setFitToHeight` instead — displays whose `height` getter is content-derived have to re-seed the slot on the way in, and that is what the action is for.</span> | [RowHeightMixin](../rowheightmixin#action-setrowheight) |
| <span id="action-setshowtree">**setShowTree**</span><br><code>(arg: boolean) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setshowtree) |
| <span id="action-setshowbranchlength">**setShowBranchLength**</span><br><code>(arg: boolean) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setshowbranchlength) |
| <span id="action-setshowrowlabels">**setShowRowLabels**</span><br><code>(arg: boolean) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setshowrowlabels) |
| <span id="action-setlayout">**setLayout**</span><br><code>(layout: S[]) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setlayout) |
| <span id="action-setclustertree">**setClusterTree**</span><br><code>(tree?: string &#124; undefined) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setclustertree) |
| <span id="action-setlayoutandclustertree">**setLayoutAndClusterTree**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(layout: S[], tree?: string &#124; undefined, provenance?: ClusterPr…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(layout: S[], tree?: string &#124; undefined, provenance?: ClusterProvenance &#124; undefined) =&gt; void</code></pre></dialog></span> |  | [TreeSidebarMixin](../treesidebarmixin#action-setlayoutandclustertree) |
| <span id="action-settreeareawidth">**setTreeAreaWidth**</span><br><code>(width: number) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-settreeareawidth) |
| <span id="action-setsubtreefilter">**setSubtreeFilter**</span><br><code>(names?: string[] &#124; undefined) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setsubtreefilter) |
| <span id="action-setrunclustering">**setRunClustering**</span><br><code>(arg?: boolean &#124; undefined) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setrunclustering) |
| <span id="action-setclusterregion">**setClusterRegion**</span><br><code>(arg?: string &#124; undefined) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setclusterregion) |
| <span id="action-setsortrowsby">**setSortRowsBy**</span><br><code>(arg?: RowSortSpec &#124; undefined) =&gt; void</code> | <span data-pagefind-ignore>Trigger (or clear) a one-shot declarative row sort; consumed and reset by `setupRowSortAutorun`. A display's right-click item calls its own sort directly (instant, the data is already loaded); this is the session-level entry point.</span> | [TreeSidebarMixin](../treesidebarmixin#action-setsortrowsby) |
| <span id="action-sethoveredtreenode">**setHoveredTreeNode**</span><br><code>(node?: HoveredTreeNode &#124; undefined) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-sethoveredtreenode) |
| <span id="action-settreecanvasref">**setTreeCanvasRef**</span><br><code>(ref: HTMLCanvasElement &#124; null) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-settreecanvasref) |
| <span id="action-setmouseovercanvasref">**setMouseoverCanvasRef**</span><br><code>(ref: HTMLCanvasElement &#124; null) =&gt; void</code> |  | [TreeSidebarMixin](../treesidebarmixin#action-setmouseovercanvasref) |

