# SharedLDModel

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/LDDisplay/shared.ts).

Shared state model for LD displays

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-configuration">**configuration**</span><br><code>configuration: ConfigurationReference(configSchema)</code> |  | SharedLDModel |
| <span id="property-jexlfilterssetting">**jexlFiltersSetting**</span><br><code>jexlFiltersSetting: types.maybe(types.array(types.string))</code> | Runtime "General JEXL filters..." override, already `jexl:`-prefixed. When set (even to an empty list) it replaces the `jexlFilters` config slot; when undefined the config default applies. The two-tier contract every display with this row implements — see `JexlFilterModel`. | SharedLDModel |
| <span id="property-id">**id**</span><br><code>id: ElementId</code> |  | [BaseDisplay](../basedisplay#property-id) |
| <span id="property-type">**type**</span><br><code>type: types.string</code> |  | [BaseDisplay](../basedisplay#property-type) |

## Volatiles

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="volatile-rpcdata">**rpcData**</span><br><code>rpcData: null as LDDataResult &#124; null</code> |  | SharedLDModel |
| <span id="volatile-focalsnplocus">**focalSnpLocus**</span><br><code>focalSnpLocus: undefined as string &#124; undefined</code> | Locus (`refName:start`) of the focal SNP whose LD row+column is emphasized, or undefined. Keyed by locus rather than array index so the selection survives a re-fetch that reorders SNPs. | SharedLDModel |
| <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-loadedfetchsignature">**loadedFetchSignature**</span><br><code>loadedFetchSignature: undefined as string &#124; undefined</code> | <span data-pagefind-ignore>`fetchSignature` as it stood when the held data was committed — the loaded half of this family's freshness compare. Written only by `commitFetchResult` and cleared only by `reload`, so a display cannot stamp data it did not fetch or forget to invalidate on retry; the data itself stays display-owned (arc keeps stale arcs on screen under the loading overlay, HiC keeps the stale matrix).</span> | [GlobalFetchMixin](../globalfetchmixin#volatile-loadedfetchsignature) |
| <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) |

## Getters

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <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> |  | SharedLDModel |
| <span id="getter-prefersoffset">**prefersOffset**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-minorallelefrequencyfilter">**minorAlleleFrequencyFilter**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-lengthcutofffilter">**lengthCutoffFilter**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-linezoneheight">**lineZoneHeight**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-ldmetric">**ldMetric**</span><br><code>"dprime" &#124; "r2"</code> |  | SharedLDModel |
| <span id="getter-showldtriangle">**showLDTriangle**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-squashtoheight">**squashToHeight**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-hwefilterthreshold">**hweFilterThreshold**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-callratefilter">**callRateFilter**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-maxvariantseparation">**maxVariantSeparation**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-showverticalguides">**showVerticalGuides**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-showlabels">**showLabels**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-tickheight">**tickHeight**</span><br><code>number</code> |  | SharedLDModel |
| <span id="getter-usegenomicpositions">**useGenomicPositions**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-signedld">**signedLD**</span><br><code>boolean</code> |  | SharedLDModel |
| <span id="getter-configuredldmethod">**configuredLDMethod**</span><br><code>"auto" &#124; "composite" &#124; "phased"</code> | Which estimator the `ldMethod` config slot ASKS for. Named apart from `ldMethod` below, which is what the RPC actually ran — they differ whenever the request cannot be honoured ('phased' on unphased data) and whenever 'auto' resolves. | SharedLDModel |
| <span id="getter-snps">**snps**</span><br><code>LDSnp[]</code> | The loaded matrix's SNPs, in the order they are drawn along the column axis (the worker puts them in screen order — see `RenderLDDataRPC/reversedRegions.ts`). Empty until data arrives. | SharedLDModel |
| <span id="getter-cellwidth">**cellWidth**</span><br><code>number</code> | Fetch-time width of one column in the un-rotated frame (`uniformW`). Read through `columnX`, which rescales it to the live viewport. | SharedLDModel |
| <span id="getter-filterstats">**filterStats**</span><br><code>FilterStats &#124; undefined</code> |  | SharedLDModel |
| <span id="getter-viewsignature">**viewSignature**</span><br><code>string &#124; undefined</code> | LD's half of `GlobalFetchMixin`'s freshness compare: the dynamic-block set. LD's SNP set is viewport-defined (the index-mode triangle spans the visible blocks), so a pan refetches — but worker output is genomic, so the stale triangle draws at its own position under the live transform while the refetch runs. The settings axis — what keeps `svgReady` from capturing a matrix computed under the filters the user just changed — rides in through the `rpcPropsCacheKey` half the mixin appends. | SharedLDModel |
| <span id="getter-renderscanvas">**rendersCanvas**</span><br><code>boolean</code> | Override of the `GlobalFetchMixin` hook that gates the initial pre-first-paint loading scrim (`rendersCanvas && !canvasDrawn`). With the triangle toggled off, `LDDisplayComponent` renders an EmptyState ("Enable LD triangle…") instead of a canvas, so `canvasDrawn` never flips. Returning false here keeps the scrim from sitting permanently over that placeholder. This is the *only* override of the hook — do not remove it as dead-looking single-use code: without it the LD track shows a stuck loading spinner whenever the triangle is disabled. If the EmptyState is ever moved outside `DisplayChrome`, revisit together. | SharedLDModel |
| <span id="getter-fetchinert">**fetchInert**</span><br><code>boolean</code> | With the triangle off the display shows an EmptyState and its `prepare` declines forever, so nothing is loading and nothing ever will. Both readers need that: the scrim would otherwise park over the placeholder — permanently, once a cancel has been clicked, since `fetchCanceled` is durable — and `awaitSvgReady` is an unbounded `when`, so one such track hangs the whole view's SVG export.<br><br>Deliberately not spelled `!self.rendersCanvas`: "paints no canvas" and "will never fetch" are independent axes that merely coincide here, and arc is the display that has the second without the first. | SharedLDModel |
| <span id="getter-isprecomputedld">**isPrecomputedLD**</span><br><code>boolean</code> | True when this display reads LD out of a file (PLINK, ldmat) rather than computing it from a VCF's genotypes — which decides the fetch path, whether the filter menus mean anything, and whether the byte gate has a `getFeatures` to measure with. | SharedLDModel |
| <span id="getter-effectiveldmetric">**effectiveLdMetric**</span><br><code>LDMetric</code> | Metric the loaded data actually represents. A pre-computed file with no D' column downgrades a 'dprime' request to 'r2', so the legend and the metric radios read this rather than the raw requested `ldMetric`. | SharedLDModel |
| <span id="getter-effectivesignedld">**effectiveSignedLD**</span><br><code>boolean</code> | Whether the loaded values actually carry a sign. Reads the packed matrix rather than the slot for the same reason as `effectiveLdMetric`: a pre-computed file states magnitudes and cannot honor the request, so a track configured `signedLD: true` against one would otherwise get a legend reading -1..1 and a tooltip calling r² "R" over 0..1 values. The cells already follow the data (the ramp is built from `rpcData`). | SharedLDModel |
| <span id="getter-effectiveusegenomicpositions">**effectiveUseGenomicPositions**</span><br><code>boolean</code> | Whether the loaded matrix was actually laid out at genomic positions. The worker falls back to uniform cells when the viewport holds more than one region (SNPs from the later ones would collapse onto the first's coordinates), so the raw slot can say yes while what is on screen is index-laid-out. Every consumer that branches on the layout — the hit test, the zone height, the connectors-vs-labels choice — reads this, not the slot, or it describes a matrix that isn't there. Same requested-vs-loaded split as `effectiveLdMetric`; `rpcProps` still sends the slot, which is the request. | SharedLDModel |
| <span id="getter-dprimeavailable">**dprimeAvailable**</span><br><code>boolean</code> | Whether the D' metric can be shown — false only for a pre-computed file lacking a DP column, which disables the D' option. | SharedLDModel |
| <span id="getter-ldmethod">**ldMethod**</span><br><code>LDMethod &#124; undefined</code> | How the loaded LD values were derived: 'phased' (exact haplotypic), 'composite' (Weir estimate from unphased genotypes), or 'precomputed' (read from a PLINK/ldmat file). Undefined until data loads. This is what RAN, which is not always what `configuredLDMethod` asked for. | SharedLDModel |
| <span id="getter-loadedldwindow">**loadedLDWindow**</span><br><code>number &#124; undefined</code> | The pair-separation window the LOADED matrix was computed at, in variants, or undefined when it covers the whole triangle. Read off the result rather than off `maxVariantSeparation`, for the same reason `ldMethod` is: the slot is a request, and `resolveBand` clamps it to `n - 1`, at which point there is no window to report.<br><br>The status bar names it because nothing else on screen can. A pair past the window is not drawn, and an in-band pair at r² = 0 is painted at the ramp's white end at full alpha — so against a light theme's background "not measured" and "no linkage" are the same pixel, and long-range LD, which is the interesting case, reads as absent rather than as unasked. | SharedLDModel |
| <span id="getter-focalsnpindex">**focalSnpIndex**</span><br><code>number</code> | Array index of the focal SNP in the current `snps`, or -1 if none is selected or the locus is no longer present after a re-fetch. | SharedLDModel |
| <span id="getter-gateenabled">**gateEnabled**</span><br><code>boolean</code> | Opt into RegionTooLargeMixin's derived byte gate (byte axis only, no density axis). On for every adapter, including the pre-computed ones (PlinkLD*), which serve no features at all: `RenderLDData` measures the genotype adapter it is about to read and skips those entirely, so they report no bytes — "unmeasurable", the same answer a BigWig gives — and an unmeasurable estimate keeps the byte axis out of the verdict without anything here having to know which adapter it has.<br><br>This is the last display-side answer to an adapter-side question to go — the same shape as the `alwaysRender` estimate flag that preceded it — so the opt-in has no "except when the adapter would explode" caveat anywhere in the tree. It used to cost one pre-flight round trip per pre-computed fetch, returning undefined by construction; folded into the fetch, it costs nothing at all. | SharedLDModel |
| <span id="getter-effectivelinezoneheight">**effectiveLineZoneHeight**</span><br><code>number</code> | Pixel height of the SVG zone above the canvas (variant labels + lines). The hit-test subtracts this from mouseY before reversing the render transform. | SharedLDModel |
| <span id="getter-ldcanvasheight">**ldCanvasHeight**</span><br><code>number</code> | Effective height for the LD canvas (total height minus the zone the variant lines occupy above the matrix). | SharedLDModel |
| <span id="getter-canvaswidth">**canvasWidth**</span><br><code>number</code> | The box the triangle is drawn in. One pair for all three of the canvas element's CSS size, the backing store the rendering backends resize to, and the SVG export's paint layer — they have to be the same number or the drawn matrix is stretched against the box it sits in, and they were previously derived independently on either side of that boundary. `totalWidthPxWithoutBorders` is the rounded content width, so this is the drawn width even when the genome doesn't fill the viewport. | SharedLDModel |
| <span id="getter-canvasheight">**canvasHeight**</span><br><code>number</code> | Height of that box: the triangle's natural apex height (half its width), or the display's own height when squashed to fit. | SharedLDModel |
| <span id="getter-yscalar">**yScalar**</span><br><code>number</code> | Per-frame yScalar squash factor. When squashToHeight is on, squashes the natural (canvasWidth/2) triangle into ldCanvasHeight. Lives on the main thread so resize doesn't trigger a worker re-fetch. | SharedLDModel |
| <span id="getter-renderstate">**renderState**</span><br><code>LDRenderState</code> | Per-frame render state for the GPU backend. Read by the upload/render autorun — every change to any tracked observable (view.bpPerPx, view.offsetPx, model.squashToHeight, rpcData contents, …) re-fires it. | SharedLDModel |
| <span id="getter-viewtransform">**viewTransform**</span><br><code>{ viewScale: number; viewOffsetX: number; }</code> | The per-frame map from the payload's pre-rotation data space (origin-relative bp / √2) to canvas px, shared by the render state, the hit test, the overlays and the SVG export so none of them can disagree. Pure live-view arithmetic; the one payload-derived term, `originBp`, folds the payload's own axis anchor back in — in double precision — so a stale triangle draws at its genomic position while a refetch runs. | SharedLDModel |
| <span id="getter-connectorlinecoords">**connectorLineCoords**</span><br><code>ConnectorCoord[]</code> | The connector lines tying each matrix column to its SNP's genomic position, in viewport pixels, plus the label the hover tooltip and `VariantLabels` show. Only meaningful in index mode (genomic-positions mode already draws columns at their genomic x). | SharedLDModel |
| <span id="getter-triangletransform">**triangleTransform**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>{ yScalar: number; yOffsetPx: number; viewScale: number; viewOf…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>{ yScalar: number; yOffsetPx: number; viewScale: number; viewOffsetX: number; }</code></pre></dialog></span> | The whole triangle map as the shared `TriangleTransform`: the view scale/offset, the fit-to-height squash, and the connector zone LD reserves above the matrix. One value, so `cellToScreen` and `screenToCell` below cannot disagree about a term — a dropped `yScalar` in a hand-spelled inverse survived the coarse round-trip test here once. | SharedLDModel |
| <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-hoveredfeature">**hoveredFeature**</span><br><code>unknown</code> | <span data-pagefind-ignore>Overridable hook (default `undefined`): what the pointer is currently over, for readers **outside** the display. `LinearGenomeViewContainer` publishes it to `session.hovered`, the view-wide "what is the user pointing at" channel a plugin can subscribe to.<br><br>Declared here because a cross-display consumer can only read a name the base declares — the same reason `SyntenyFetchStateMixin.fetchInert` is a hook rather than a getter each display invents. The container used to read `featureUnderMouse`, which only the wiggle, alignments and Manhattan families spelled that way — canvas said `hoveredFeature`, variants `hoveredGenotype` — so the channel carried a hover from a third of the display types and nothing said which. It also asked only `displays[0]` of each track.<br><br>`unknown` because the payload genuinely differs — a read, a wiggle bin, a SNP, a genotype cell — and `session.hovered` is typed to match ("can be anything; code that wants to deal with this should examine it"). Narrow it in the override.</span> | [BaseDisplay](../basedisplay#getter-hoveredfeature) |
| <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-featurewidgettype">**featureWidgetType**</span><br><code>{ type: string; id: string; }</code> | <span data-pagefind-ignore>Overridable hook: which widget `openFeatureWidget` opens for one of this display's features. The default is the generic one, which is what a display drawing plain features wants and what the canvas base spelled out by hand.<br><br>An override is a display whose features have a vocabulary of their own — a read, a variant, a synteny block — and the `id` is deliberately part of it: two displays naming one id share the drawer panel, which is the behaviour when the two are showing the same kind of thing.</span> | [BaseDisplay](../basedisplay#getter-featurewidgettype) |
| <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-scrollableheight">**scrollableHeight**</span><br><code>number</code> | <span data-pagefind-ignore>Overridable hook: how far this display's content can scroll past its viewport, in px. `Infinity` (the default) means "this display doesn't scroll internally" — `setScrollTop` then never clamps and the re-clamp autorun below is inert, so a non-scrolling display pays nothing and, crucially, never evaluates a getter that would read view geometry.<br><br>A display that scrolls a canvas overrides this with `max(0, contentHeight - viewportHeight)`, and gets the clamped setter plus the shrink autorun for free. It is the single "does it scroll, and by how much" answer: the wheel handler (`useVirtualScrollWheel`) and `VerticalScrollbar` read the same getter.</span> | [TrackHeightMixin](../trackheightmixin#getter-scrollableheight) |
| <span id="getter-host">**host**</span><br><code>RegionHost</code> | <span data-pagefind-ignore>The hosting view as the `RegionHost` contract — see `containingHost` for the cast it owns, why the name is `host` and not `view`, and why both foundations still declare the name over one body.</span> | [GlobalFetchMixin](../globalfetchmixin#getter-host) |
| <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> | [GlobalFetchMixin](../globalfetchmixin#getter-viewportempty) |
| <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> | [GlobalFetchMixin](../globalfetchmixin#getter-canrender) |
| <span id="getter-fetchsignature">**fetchSignature**</span><br><code>string &#124; undefined</code> | <span data-pagefind-ignore>Signature of the fetch the current view and settings call for — the display's `viewSignature` plus the serialized `rpcProps()` axis. What `runGlobalFetch` gates on, captures at issue, and stamps at commit.</span> | [GlobalFetchMixin](../globalfetchmixin#getter-fetchsignature) |
| <span id="getter-datacurrent">**dataCurrent**</span><br><code>boolean</code> | <span data-pagefind-ignore>The shared freshness answer, now derived rather than a hook: data has been committed (`loadedFetchSignature` is only ever written beside it) and it was fetched for the current view and settings. A pan inside the loaded blocks stays current; a block entering, a tier step, a settings change or a `reload()` moves one side of the compare and refetches.</span> | [GlobalFetchMixin](../globalfetchmixin#getter-datacurrent) |
| <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> | [GlobalFetchMixin](../globalfetchmixin#getter-paintinert) |
| <span id="getter-svgready">**svgReady**</span><br><code>boolean</code> | <span data-pagefind-ignore>Policy single-sourced in `computeSvgReady`; this family supplies only the freshness half, which `foundationSvgReady` reads as `dataCurrent` or the vacuous currency of `viewportEmpty`. Note it requires the dataset to actually be current, NOT merely "not currently fetching": the fetch trigger is a debounced `afterAttach` autorun, so at export time `isLoading` can still be false with no data yet — a `displayPhase !== 'loading'` test would then capture an empty render. Never gates on `canvasDrawn`, which an off-screen export never sets. Off-screen renderers gate on it via `awaitSvgReady(model)`.</span> | [GlobalFetchMixin](../globalfetchmixin#getter-svgready) |
| <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 of them without being wired twice.<br><br>This family's argument is the constant `true`, deliberately: a global display keeps the last frame up through a refetch (worker output is genomic, so the stale frame draws correctly under the live view transform), so a pan or zoom shows no scrim beyond the `isLoading` window. The pre-first-paint scrim it *does* want — the gap between mount and `isLoading` going true, which on HiC is the `CoreGetInfo` round trip its first fetch waits on — is `computeLoadingTerm`'s shared `rendersCanvas && !canvasDrawn` term, not anything this family spells out.<br><br>A display with no rendering backend narrows this to the backend-free `DisplayStatusPhase` with `foundationDisplayStatusPhase`, which is what arc does: it cannot reach `renderError`, and the narrower type is what lets `DisplayStatusChrome` take it with neither a cast nor a dead branch.</span> | [GlobalFetchMixin](../globalfetchmixin#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-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-awaitingprerequisite">**awaitingPrerequisite**</span><br><code>boolean</code> | <span data-pagefind-ignore>Overridable hook (default false), read only by the dev-only retry check (`makeRetryContractCheck`): "this run declined because a prerequisite fetch in another autorun has not landed, and its arrival wakes this one again". It **defers** the retry verdict to that later run rather than waiving it, so a display cannot spend its retry on a decline it called preliminary.<br><br>Two displays say it, one per fetch foundation, which is why it lives beside `fetchInert` rather than on either: HiC's contacts fetch declines until `CoreGetInfo` lands, and `MultiSampleVariantBaseModel`'s `fetchNeeded` declines until `sourcesBase` does. Both have a `reload()` that wakes the prerequisite's autorun as well as their own.<br><br>**It has to be strictly narrower than the gate it explains.** One that restates the gate's negation makes every decline a deferred one, so no run is ever judged and the display has silently opted out — an exemption by another name. HiC is in that shape deliberately, because its gate and its prerequisite are one condition; what covers its retry instead is `LinearHicDisplay/infoFetchFailure.test.ts`.<br><br>Not for a display deliberately not fetching at all — that is `fetchInert` above, which the loading scrim and the export read too.</span> | [FetchMixin](../fetchmixin#getter-awaitingprerequisite) |
| <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) |

## Methods

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="method-configuredfilters">**configuredFilters**</span><br><code>() =&gt; string[]</code> | What the `jexlFilters` config slot alone declares, `jexl:`-prefixed. Prefixing on read is what makes a config-declared filter work at all — the slot stores them unprefixed (deferred evaluation) and `stringToJexlExpression` throws on anything else, so before this an admin following the slot's own documented convention got a worker exception. | SharedLDModel |
| <span id="method-activefilters">**activeFilters**</span><br><code>() =&gt; string[]</code> | 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. | SharedLDModel |
| <span id="method-rpcprops">**rpcProps**</span><br><code>() =&gt; LDRpcProps</code> |  | SharedLDModel |
| <span id="method-columnx">**columnX**</span><br><code>(column: number) =&gt; number</code> | Viewport x of a position on the matrix's column axis, in fractional column indices: 0 is the triangle's left corner, `i + 0.5` the apex of column i, `i + 1` the boundary between columns i and i+1. The index-mode connector lines anchor through this.<br><br>It rides the same forward transform the shader does — `cellWidth` (uniformW) is the payload's cell span in bp and `viewTransform` maps it to the live viewport, exactly like `hitTest` inverts it. Deriving the column pitch from the *current* block width instead applies the zoom twice, sliding everything anchored here off the triangle for the whole debounce+RPC window after a zoom. | SharedLDModel |
| <span id="method-locusviewportx">**locusViewportX**</span><br><code>(refName: string, coord: number) =&gt; number &#124; undefined</code> | Viewport x of one locus, through the same `genomicViewportX` the connector lines use. The crosshair ticks and the view's vertical guides go through this rather than measuring off `contentBlocks[0]`: that block's own left edge is only x=0 while the content reaches the viewport edge, and a SNP in any *later* block isn't measured against its own region at all. Undefined when the locus has no on-screen x, which the caller drops rather than pinning to 0. | SharedLDModel |
| <span id="method-celltoscreen">**cellToScreen**</span><br><code>(x: number, y: number) =&gt; { x: number; y: number; }</code> | Forward transform of the LD matrix (`triangleDataToScreen`), paired with `hitTest` below (its exact inverse): pre-rotation cell coordinates to canvas-relative pixels. The overlays that decorate individual cells — the hover crosshair, the focal-SNP band — place themselves through this, so they land on the cells the shader drew and move with the same rescale during the debounce+RPC window. | SharedLDModel |
| <span id="method-screentocell">**screenToCell**</span><br><code>(mouseX: number, mouseY: number) =&gt; { x: number; y: number; }</code> | The exact inverse of `cellToScreen` (`triangleScreenToData`), split out of `hitTest` so the pair is checkable as an **identity** rather than only through the cell it lands in — `overlayCoords.test.ts` asserts coordinates, which is what catches a dropped term. | SharedLDModel |
| <span id="method-hittest">**hitTest**</span><br><code>(mouseX: number, mouseY: number) =&gt; LDFlatbushItem &#124; undefined</code> | Takes mouse coords (canvas-relative) and returns the LD cell under the cursor, or undefined: `screenToCell` above, then the boundary walk. Mirrors plugins/hic's `hitTest` so both contact maps keep the forward and inverse transforms paired on the model. | SharedLDModel |
| <span id="method-svglegendwidth">**svgLegendWidth**</span><br><code>() =&gt; number</code> | How much room the SVG export's container reserves to the right of the plot for this display's legend (it maxes this across tracks), via the shared helper — see `gradientSvgLegendWidth` for why it reserves on the setting alone. | SharedLDModel |
| <span id="method-trackmenuitems">**trackMenuItems**</span><br><code>() =&gt; MenuItem[]</code> |  | SharedLDModel |
| <span id="method-rendersvg">**renderSvg**</span><br><code>(opts: ExportSvgDisplayOptions) =&gt; Promise&lt;ReactNode&gt;</code> |  | SharedLDModel |
| <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-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) |

## Actions

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="action-setrpcdata">**setRpcData**</span><br><code>(data: LDDataResult) =&gt; void</code> | `runGlobalFetch` stamps the signature this was fetched for (`GlobalFetchMixin.commitFetchResult`) in the same transaction. | SharedLDModel |
| <span id="action-setfocalsnp">**setFocalSnp**</span><br><code>(snp: LDSnp &#124; undefined) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setlinezoneheight">**setLineZoneHeight**</span><br><code>(n: number) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setmaffilter">**setMafFilter**</span><br><code>(arg: number) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setldmetric">**setLDMetric**</span><br><code>(metric: LDMetric) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setshowldtriangle">**setShowLDTriangle**</span><br><code>(show: boolean) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setsquashtoheight">**setSquashToHeight**</span><br><code>(value: boolean) =&gt; void</code> |  | SharedLDModel |
| <span id="action-sethwefilter">**setHweFilter**</span><br><code>(threshold: number) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setcallratefilter">**setCallRateFilter**</span><br><code>(threshold: number) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setshowverticalguides">**setShowVerticalGuides**</span><br><code>(show: boolean) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setshowlabels">**setShowLabels**</span><br><code>(show: boolean) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setusegenomicpositions">**setUseGenomicPositions**</span><br><code>(value: boolean) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setsignedld">**setSignedLD**</span><br><code>(value: boolean) =&gt; void</code> |  | SharedLDModel |
| <span id="action-setjexlfilters">**setJexlFilters**</span><br><code>(filters?: string[] &#124; undefined) =&gt; void</code> |  | SharedLDModel |
| <span id="action-startrenderingbackend">**startRenderingBackend**</span><br><code>(backend: LDRenderingBackend) =&gt; void</code> | Starts the upload/render autorun. No upload-diffing helper here on purpose: matrix and color ramp both derive from the one `rpcData` object, so the upload autorun's whole dependency set is that field and it can't re-fire without both genuinely being stale. (HiC needs `createGlobalUploadSync` because its palette is a config slot with an input independent of the RPC result.) | SharedLDModel |
| <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-clearhoveredfeature">**clearHoveredFeature**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Overridable hook (default no-op): drop whatever `hoveredFeature` reports. The writing twin of that getter, and what `installClearHoverOnViewportChange` calls.<br><br>A display that STORES its hover owes an override; one that derives it from the live pointer (MAF, Hi-C, LD) owes nothing, and the default costs it nothing. Declared here so the clear can be installed for every display rather than remembered per display — forgetting it is the failure ARCHITECTURE.md's stored-hover section is about, and it used to be six closures at six call sites, which is six chances to omit one.</span> | [BaseDisplay](../basedisplay#action-clearhoveredfeature) |
| <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-resizeheight">**resizeHeight**</span><br><code>(distance: number) =&gt; number</code> |  | [TrackHeightMixin](../trackheightmixin#action-resizeheight) |
| <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-commitfetchresult">**commitFetchResult**</span><br><code>(commit: () =&gt; void, signature: string) =&gt; void</code> | <span data-pagefind-ignore>The commit half of `runGlobalFetch`: run the display's own store in the same transaction as the signature stamp, so no observer can see fresh data under a stale signature or the reverse. Being the only writer of `loadedFetchSignature` is what makes `dataCurrent` derivable — a display cannot commit without stamping.</span> | [GlobalFetchMixin](../globalfetchmixin#action-commitfetchresult) |
| <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-setshowlegend">**setShowLegend**</span><br><code>(arg: boolean) =&gt; void</code> |  | [LegendMixin](../legendmixin#action-setshowlegend) |

