# LinearSyntenyView

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
`linear-comparative-view` plugin.
[View source](https://github.com/GMOD/jbrowse-components/blob/main/plugins/linear-comparative-view/src/LinearSyntenyView/model.ts).

## Example usage

Hand-authored under `defaultSession.views`. `init.views` declares the two member
assemblies (stacked as linear views) and `tracks` the synteny feature track
connecting them with a ribbon:

```js
{
  type: 'LinearSyntenyView',
  init: {
    views: [{ assembly: 'hg38' }, { assembly: 'mm10' }],
    tracks: ['hg38_vs_mm10.paf'],
    drawCurves: true,
  },
}
```

`init` also takes the launch commands (`levelHeights`, `autoDiagonalize`,
`sameScale`, `collapseEmptyRows`) and ANY property below — `colorBy`, `alpha`,
`minAlignmentLength`, `drawLocationMarkers`, … . There is no list to join:
`applyInitSettings` matches an init key against this model's own properties, and
`LinearSyntenyViewInit` is derived from its snapshot type.

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('LinearSyntenyView')</code> |  | LinearSyntenyView |
| <span id="property-cigarmode">**cigarMode**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>cigarMode: types.stripDefault( types.enumeration(['off', 'match…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>cigarMode: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.enumeration(['off', 'matches', 'full'] as const),&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'full',&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | How per-base insertions and deletions inside each alignment are shown: 'full' paints indel wedges, 'matches' leaves them see-through, 'off' draws blocks only. | LinearSyntenyView |
| <span id="property-drawcurves">**drawCurves**</span><br><code>drawCurves: types.stripDefault(types.boolean, false)</code> | Render ribbons as bezier curves rather than straight chords. Reads much better at whole-genome scale, where straight crossings stack into noise. | LinearSyntenyView |
| <span id="property-drawlocationmarkers">**drawLocationMarkers**</span><br><code>drawLocationMarkers: types.stripDefault(types.boolean, false)</code> | Continue the query view's scalebar grid down through the ribbons: a tick at each round query coordinate, joined to the coordinate the alignment pairs it with. | LinearSyntenyView |
| <span id="property-showoffscreenmates">**showOffscreenMates**</span><br><code>showOffscreenMates: types.stripDefault(types.boolean, true)</code> | Mark, on the query axis, the alignments whose mate is on a contig the facing row is not displaying — real synteny a ribbon has nowhere to land, which the view otherwise draws nothing for. | LinearSyntenyView |
| <span id="property-bidirectionalfetch">**bidirectionalFetch**</span><br><code>bidirectionalFetch: types.stripDefault(types.boolean, false)</code> | Ask each level's adapter for the alignments anchored on its LOWER row as well as its upper one.<br><br>A synteny band queries its query axis — the upper row of the pair — so an alignment anchored on a lower-row contig whose other end is somewhere the upper row is not showing is never requested, and nothing downstream can recover it. Which genome a user stacked on top therefore decided what the view was able to report.<br><br>A FETCH INPUT, unlike `showOffscreenMates` above, and off by default because it is a second query per level. | LinearSyntenyView |
| <span id="property-overdrawpx">**overdrawPx**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>overdrawPx: types.stripDefault(types.number, DEFAULT_OVERDRAW_P…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>overdrawPx: types.stripDefault(types.number, DEFAULT_OVERDRAW_PX)</code></pre></dialog></span> | pixels beyond the visible viewport edge that synteny lines are still drawn. Effective up to the pan buffer (`syntenyPanBufferPx`: 2000px, or half the viewport when that is wider) — the worker emits CIGAR detail and location markers only that far, so a larger value draws ribbons whose detail stops partway along them. | LinearSyntenyView |
| <span id="property-alpha">**alpha**</span><br><code>alpha: types.stripDefault(types.number, DEFAULT_ALPHA)</code> | Per-feature opacity in [0,1]. The default is tuned for dense unfiltered hairballs; a whole-genome view with minAlignmentLength set can use a higher value (~0.4) for stronger color. | LinearSyntenyView |
| <span id="property-minalignmentlength">**minAlignmentLength**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>minAlignmentLength: types.stripDefault( types.number, DEFAULT_M…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>minAlignmentLength: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.number,&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DEFAULT_MIN_ALIGNMENT_LENGTH,&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | Hide alignment blocks shorter than this many bp. Enforced per-feature by its own span in buildSyntenyGeometry, then culled in the shader (isCulled) and pick engine. Cuts whole-genome hairball noise. | LinearSyntenyView |
| <span id="property-lodmode">**lodMode**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>lodMode: types.stripDefault( types.enumeration('LodMode', ['aut…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>lodMode: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.enumeration('LodMode', ['auto', 'fine', 'coarse']),&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'auto',&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | Level-of-detail tier selection for PIF adapters. 'auto' uses the adapter's bpPerPx threshold; 'fine' forces the per-row CIGAR tier (t/q); 'coarse' forces the no-CIGAR tier (T/Q) when present. | LinearSyntenyView |
| <span id="property-opacitybyidentity">**opacityByIdentity**</span><br><code>opacityByIdentity: types.stripDefault(types.boolean, false)</code> | Fade alignment blocks by per-feature identity (lower identity = more transparent). Orthogonal to colorBy — surfaces identity-dropoff zones without consuming the color channel. | LinearSyntenyView |
| <span id="property-fadethinalignmentsmode">**fadeThinAlignmentsMode**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>fadeThinAlignmentsMode: types.stripDefault( types.enumeration('…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>fadeThinAlignmentsMode: types.stripDefault(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;types.enumeration('FadeThinMode', ['auto', 'on', 'off']),&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'auto',&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | Whether to fade a sub-pixel-thin ribbon's opacity by its on-screen width (see WIDTH_FADE_FLOOR in syntenyTypes.slang), so an unfiltered whole-genome view doesn't read as a hard full-opacity hairball. 'auto' enables the fade once a display is dominated by sub-pixel ribbons (see `autoFadeWidthPx`); a genuinely sparse comparison (only a handful of ribbons) keeps full alpha so the fade doesn't wash it out. 'on'/'off' pin it. Resolved view-wide by the `fadeThinAlignments` getter, so all levels fade together. | LinearSyntenyView |
| <span id="property-init">**init**</span><br><code>init: types.frozen&lt;LinearSyntenyViewCommands &#124; undefined&gt;()</code> | used for initializing the view from a session snapshot. tracks is 2D — outer index is the level (the gap between views[i] and views[i+1]), so a 3-way view has two entries. example: ```json { views: [ { loc: "chr1:1-100", assembly: "hg38", tracks: ["genes"] }, { loc: "chr1:1-100", assembly: "mm39" }, { loc: "chr1:1-100", assembly: "rn7" } ], tracks: [["hg38_vs_mm39_synteny"], ["mm39_vs_rn7_synteny"]] } ``` | LinearSyntenyView |
| <span id="property-id">**id**</span><br><code>id: ElementId</code> |  | [LinearComparativeView](../linearcomparativeview#property-id) |
| <span id="property-trackselectortype">**trackSelectorType**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>trackSelectorType: types.stripDefault(types.string, 'hierarchic…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>trackSelectorType: types.stripDefault(types.string, 'hierarchical')</code></pre></dialog></span> | <span data-pagefind-ignore>vestigial: the hierarchical selector is the only one that exists, so this value is ignored. Retained because saved sessions and configs persist it.</span> | [LinearComparativeView](../linearcomparativeview#property-trackselectortype) |
| <span id="property-linkviews">**linkViews**</span><br><code>linkViews: types.stripDefault(types.boolean, false)</code> | <span data-pagefind-ignore>sync scroll and zoom across the genome rows, so panning one pans them all</span> | [LinearComparativeView](../linearcomparativeview#property-linkviews) |
| <span id="property-followsynteny">**followSynteny**</span><br><code>followSynteny: types.stripDefault(types.boolean, false)</code> | <span data-pagefind-ignore>Move the non-anchor genome rows to whatever region aligns to the anchor row, re-resolved through the synteny data each time the anchor settles. The synteny-aware alternative to `linkViews`, which locks the rows in PIXELS and so drifts apart as soon as an indel accumulates — the two are mutually exclusive (see setRowSyncMode).</span> | [LinearComparativeView](../linearcomparativeview#property-followsynteny) |
| <span id="property-samescale">**sameScale**</span><br><code>sameScale: types.stripDefault(types.boolean, false)</code> | <span data-pagefind-ignore>Hold every genome row on one bp/px — the coarsest row's fit — so the rows compare by drawn length instead of all filling their pane. A mode rather than a one-shot zoom because it is the rows' zoom-out LIMIT it moves (`sharedFit`), and a limit has to still be there on the next wheel tick.</span> | [LinearComparativeView](../linearcomparativeview#property-samescale) |
| <span id="property-followanchorindex">**followAnchorIndex**</span><br><code>followAnchorIndex: types.stripDefault(types.number, 0)</code> | <span data-pagefind-ignore>Which genome row drives the others while `followSynteny` is on. Every other row is placed by mapping this one's window outward one level at a time. Clamped to the views array by reconcileLevels.</span> | [LinearComparativeView](../linearcomparativeview#property-followanchorindex) |
| <span id="property-followmatchorientation">**followMatchOrientation**</span><br><code>followMatchOrientation: types.stripDefault(types.boolean, false)</code> | <span data-pagefind-ignore>While following, flip a row whose placing alignment runs the other way from the anchor's, so the two pan in the same direction. Off by default: the crossing ribbons are the picture of an inversion, and a row turning round under the reader is the loudest thing one can do.</span> | [LinearComparativeView](../linearcomparativeview#property-followmatchorientation) |
| <span id="property-levels">**levels**</span><br><code>levels: types.array(LinearSyntenyLevel)</code> | <span data-pagefind-ignore>One synteny band per adjacent pair of `views`. Each holds its own track list, which is why the track-selector and add-track widgets address them through `trackContainerFor` — a level is not a view and cannot be the target of their `view` reference.</span> | [LinearComparativeView](../linearcomparativeview#property-levels) |
| <span id="property-views">**views**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>views: types.array( pluginManager.getViewType('LinearGenomeView…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>views: types.array(&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;pluginManager.getViewType('LinearGenomeView')&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;.stateModel as LinearGenomeViewStateModel,&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)</code></pre></dialog></span> | <span data-pagefind-ignore>N genome rows, with N-1 synteny `levels` between adjacent pairs. The views/levels invariant is maintained by reconcileLevels().</span> | [LinearComparativeView](../linearcomparativeview#property-views) |
| <span id="property-displayname">**displayName**</span><br><code>displayName: types.maybe(types.string)</code> | <span data-pagefind-ignore>displayName is displayed in the header of the view, or assembly names being used if none is specified</span> | [BaseViewModel](../baseviewmodel#property-displayname) |
| <span id="property-minimized">**minimized**</span><br><code>minimized: types.stripDefault(types.boolean, false)</code> | <span data-pagefind-ignore>collapse the view to its header bar, keeping it in the session rather than closing it</span> | [BaseViewModel](../baseviewmodel#property-minimized) |
| <span id="property-colorby">**colorBy**</span><br><code>colorBy: types.stripDefault(types.string, 'default')</code> | <span data-pagefind-ignore>The color-by mode the whole view renders with, unless a track overrides it in `trackColorBy`.</span> | [TrackColorsMixin](../trackcolorsmixin#property-colorby) |
| <span id="property-trackcolorby">**trackColorBy**</span><br><code>trackColorBy: types.map(types.string)</code> | <span data-pagefind-ignore>trackId -> color-by mode for that track alone. Absent means the track follows the view-wide `colorBy`.</span> | [TrackColorsMixin](../trackcolorsmixin#property-trackcolorby) |
| <span id="property-trackcolors">**trackColors**</span><br><code>trackColors: types.map(types.string)</code> | <span data-pagefind-ignore>trackId -> explicit color under `colorBy: 'track'`. Absent means the track takes an automatic slot from the palette.</span> | [TrackColorsMixin](../trackcolorsmixin#property-trackcolors) |
| <span id="property-showcolorlegend">**showColorLegend**</span><br><code>showColorLegend: types.stripDefault(types.boolean, false)</code> | <span data-pagefind-ignore>Show the floating color-by legend. Dismissible via the legend's close button; re-enable from the color-by (palette) menu.</span> | [TrackColorsMixin](../trackcolorsmixin#property-showcolorlegend) |

## Volatiles

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="volatile-importformsyntenytrackselections">**importFormSyntenyTrackSelections**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>importFormSyntenyTrackSelections: observable.array&lt;ImportFormSy…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>importFormSyntenyTrackSelections:&#10;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;observable.array&lt;ImportFormSyntenyTrack&gt;()</code></pre></dialog></span> |  | LinearSyntenyView |
| <span id="volatile-fadethinlatch">**fadeThinLatch**</span><br><code>fadeThinLatch: false</code> | Whether the 'auto' thin-fade is latched on. State rather than a derived value because the decision has hysteresis, and hysteresis is a memory — see `fadeThinAlignments`. | LinearSyntenyView |
| <span id="volatile-width">**width**</span><br><code>width: undefined as number &#124; undefined</code> |  | [LinearComparativeView](../linearcomparativeview#volatile-width) |
| <span id="volatile-volatileerror">**volatileError**</span><br><code>volatileError: undefined as unknown</code> | <span data-pagefind-ignore>View-level failure (e.g. an `init` block that couldn't be applied). Volatile on purpose: a reload re-runs the init autorun from a clean slate, so a transient failure stays recoverable.</span> | [LinearComparativeView](../linearcomparativeview#volatile-volatileerror) |
| <span id="volatile-followunaligned">**followUnaligned**</span><br><code>followUnaligned: false</code> | <span data-pagefind-ignore>The follow found no alignment over the anchor row's window on its last pass, so the other rows are holding position. What the header's follow button reports; without it the rows simply stop tracking, which is the same picture as a broken follow. Volatile because it describes the current window, not the session.</span> | [LinearComparativeView](../linearcomparativeview#volatile-followunaligned) |
| <span id="volatile-followapproximate">**followApproximate**</span><br><code>followApproximate: false</code> | <span data-pagefind-ignore>The follow placed a row by mapping the anchor window proportionally rather than by walking a CIGAR, so its position is close but not base-exact — a window wider than one alignment, or a tier carrying no CIGAR. What the header's follow tooltip reports; nothing else in the view distinguishes the two.</span> | [LinearComparativeView](../linearcomparativeview#volatile-followapproximate) |
| <span id="volatile-followpartial">**followPartial**</span><br><code>followPartial: undefined as FollowPartialReport &#124; undefined</code> | <span data-pagefind-ignore>The follow had a multi-contig answer and refused it: placing a row on two regions that are not neighbours in its layout puts every contig between them on screen too, and past a point that is nearly all of what the reader is looking at. The rows are on one of the anchor's regions instead, and this names it and the ones whose answers are therefore off screen — enough for the header to say which region to scroll onto to see those instead. Read only by the header's follow tooltip.</span> | [LinearComparativeView](../linearcomparativeview#volatile-followpartial) |
| <span id="volatile-bodymounted">**bodyMounted**</span><br><code>bodyMounted: true</code> | <span data-pagefind-ignore>Whether the container has this view's body in the DOM.<br><br>`ViewContainer` mounts a view's body only while an IntersectionObserver says it is on screen, to hold the app under the WebGL2 context ceiling (`reference/GPU_CONTEXT_BUDGET.md`). A view below the fold therefore has no canvas, so nothing ever calls `markCanvasDrawn` and the pre-first-paint term of `displayPhase` pins every display in it at `loading` with nothing left to resolve it — which parks `[data-app-phase="ready"]` for the whole app on a view the user cannot see.<br><br>Defaults true so the containers that always mount a body — embedded views, workspace panels, and any test rendering a display directly — are unaffected and need not set it.<br><br>The raw flag, written by this view's own container. A display asks `effectiveBodyMounted` instead, because a nested view has no container of its own.</span> | [BaseViewModel](../baseviewmodel#volatile-bodymounted) |
| <span id="volatile-awaitingautodiagonalize">**awaitingAutoDiagonalize**</span><br><code>awaitingAutoDiagonalize: false</code> | <span data-pagefind-ignore>True while the init autorun is waiting on the diagonalize RPC. Gates the canvas off — otherwise the user watches an undiagonalized hairball flash before the reorder kicks in.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#volatile-awaitingautodiagonalize) |
| <span id="volatile-pendingautodiagonalize">**pendingAutoDiagonalize**</span><br><code>pendingAutoDiagonalize: false</code> | <span data-pagefind-ignore>A reorder this init asked for that has not succeeded yet. Raised before any render can paint, and lowered only once the pass RESOLVES — a skipped or thrown reorder leaves it up, so the view's `settled` gate never reports done on an undiagonalized view and the capture fails loudly (times out) instead of committing a hairball.<br><br>One flag rather than a requested/complete pair: the two only ever moved together, and every state a pair can drift into either wedges the gate shut or opens it on the wrong pass.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#volatile-pendingautodiagonalize) |
| <span id="volatile-diagonalizestatus">**diagonalizeStatus**</span><br><code>diagonalizeStatus: createStatusChannel()</code> | <span data-pagefind-ignore>Live status from the auto-diagonalize RPC (download %, parse, algorithm phase) shown on the reordering spinner; blank outside that wait.<br><br>A `StatusChannel` rather than a status field plus a setter: there is one operation to narrate here, and the channel is that pair with the message/fraction split already done, so the spinner reads `{ message, fraction }` instead of calling `statusMessageText` / `statusFraction` at every render site.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#volatile-diagonalizestatus) |
| <span id="volatile-diagonalizestoptoken">**diagonalizeStopToken**</span><br><code>diagonalizeStopToken: undefined as StopToken &#124; undefined</code> | <span data-pagefind-ignore>Stop token for the in-flight auto-diagonalize, so the spinner's Cancel can abort it; undefined when none is running.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#volatile-diagonalizestoptoken) |
| <span id="volatile-seenattributeranges">**seenAttributeRanges**</span><br><code>seenAttributeRanges: {} as Record&lt;string, AttributeRange&gt;</code> | <span data-pagefind-ignore>The widest span each numeric channel has been seen to cover, over every fetch this view has taken — what keeps an `attribute:<column>` ramp from re-scaling under a pan. Widened by `observeAttributeRanges`, dropped by `resetAttributeRanges`, read through `attributeRanges`, which is where the reasoning is.</span> | [TrackColorsMixin](../trackcolorsmixin#volatile-seenattributeranges) |

## Getters

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="getter-hassomethingtoshow">**hasSomethingToShow**</span><br><code>boolean</code> |  | LinearSyntenyView |
| <span id="getter-initpending">**initPending**</span><br><code>boolean</code> | An `init` blob that has not been applied yet — `installInitAutorun` clears it as the last thing an apply pass does. The view is assembling itself: the rows can already exist, and be initialized, while the synteny tracks are still several awaits away, which is why the levels' `settled` gate reads this.<br><br>Same predicate as dotplot's, and read the same way — by `settled`, not by `showLoading`. LGV's `awaitingInitNavigation` is the narrower "init set and nothing on screen at all", which it does fold into `showLoading`; it used to share this name. | LinearSyntenyView |
| <span id="getter-showassemblynameinsubviewscalebar">**showAssemblyNameInSubviewScalebar**</span><br><code>boolean</code> | Opt each sub-view's scalebar into prefixing its refName labels with the assembly name (e.g. "hg38:chr1"), so stacked genome rows of different assemblies stay distinguishable. Read duck-typed by the child LinearGenomeView (scalebarDisplayPrefix) to avoid an upward plugin dependency. | LinearSyntenyView |
| <span id="getter-drawcigar">**drawCIGAR**</span><br><code>boolean</code> |  | LinearSyntenyView |
| <span id="getter-drawcigarmatchesonly">**drawCIGARMatchesOnly**</span><br><code>boolean</code> |  | LinearSyntenyView |
| <span id="getter-haslodcapableadapter">**hasLodCapableAdapter**</span><br><code>boolean</code> | True if any track on any level has an adapter with tiered storage. Used to gate the "Level of detail" row — PAFAdapter, BlastTabularAdapter and friends have nothing to switch between. | LinearSyntenyView |
| <span id="getter-hascigardata">**hasCigarData**</span><br><code>boolean</code> | True if any synteny display could show CIGAR detail — used to gate the CIGAR settings row, which a CIGAR-less PAF has nothing to put in. Optimistic while no display has finished a fetch yet, so the row is there from the first render rather than popping in once data lands (the common case: most synteny files carry CIGARs). A view with no synteny tracks at all has nothing to gate, so it reports false. | LinearSyntenyView |
| <span id="getter-offscreenmatemode">**offscreenMateMode**</span><br><code>"both" &#124; "off" &#124; "query"</code> | Which of the three steps the two properties are in. `both` implies marking, so a hand-written snapshot that fetches the lower row without drawing it reads as the mode it behaves like — the fetch is happening, and the marks are the half of it that shows. | LinearSyntenyView |
| <span id="getter-offscreenmatetally">**offscreenMateTally**</span><br><code>{ refName: string; count: number; }[]</code> | The contigs this view has alignments to and cannot draw, largest first. A locus can be syntenic to a contig you did not stack, and a view showing no ribbon for it looks exactly like one where it is syntenic to nothing; the marks along the axis are what says so, and a mark's tooltip is where this contig's own number appears.<br><br>Summed across levels rather than reported per level, because the answer a reader wants is about the view: a contig missing from two levels is one contig to go add. The case for the whole feature, with the numbers, is agent-docs/ideas/offscreen-synteny-mates.md. | LinearSyntenyView |
| <span id="getter-presentcigarkinds">**presentCigarKinds**</span><br><code>number</code> | Union across every loaded synteny display of which CIGAR indel ops are actually drawn on screen. The floating legend lists an indel chip only when a visible-width op of that kind is painted somewhere in the view. | LinearSyntenyView |
| <span id="getter-fadethinalignments">**fadeThinAlignments**</span><br><code>boolean</code> | Resolved fade-thin flag that every display's renderParams reads. In 'auto' mode the fade turns on once ANY loaded synteny display is dominated by sub-pixel ribbons (a thin hairball that benefits from decluttering); a sparse view keeps its few ribbons at full alpha. 'on'/'off' pin it.<br><br>LATCHED, with a deadband (`fadesThinAt`): a fade that is off engages at 1px and one that is on holds until the ribbons come back above 1.25px. The signal underneath is a mean over the features the current fetch window holds, and that window rolls over once per `syntenyPanBufferPx` of panning, stepping the mean with the slice it swapped; on a single threshold a view sitting near it flipped every ribbon in the stack between full alpha and WIDTH_FADE_FLOOR while the reader was merely scrolling. `installAutoFadeLatch` moves the latch, and an un-moved latch reads as the plain un-hysteretic answer, so a first frame or an SVG export taken before it runs is not a different picture.<br><br>Deliberately view-wide rather than per display: stacked levels are read as one picture, so levels resolving the fade independently would paint the same ribbon density differently from row to row. | LinearSyntenyView |
| <span id="getter-autofadewidthpx">**autoFadeWidthPx**</span><br><code>number</code> | The width 'auto' compares against its thresholds: the narrowest capped mean block width any loaded display reports, or `Infinity` when none of them has enough blocks to judge by. Each display measures its own ribbons (`cappedMeanAlignmentPx`) and this takes the thinnest, so the densest level in a stack carries the view-wide decision.<br><br>Skips a display holding fewer than `FADE_AUTO_MIN_FEATURES` blocks, and one still at 0 (no fetch landed yet), so neither can fade the view on its own. | LinearSyntenyView |
| <span id="getter-anchorassemblyname">**anchorAssemblyName**</span><br><code>string &#124; undefined</code> | The "anchor" assembly for colorBy:'reference': the assembly bordering the most synteny levels. In a stacked ref-vs-A / ref-vs-B layout each interior assembly touches two levels and the ends touch one, so the max-adjacency assembly is the shared reference. Ties resolve to the topmost. Every level then colors by this assembly's chromosome names, so a region keeps its color as it's traced across levels. | LinearSyntenyView |
| <span id="getter-colorabletrackconfigs">**colorableTrackConfigs**</span><br><code>() =&gt; { trackId: string; name: string; }[]</code> | Every synteny track across every level, in order, paired with whatever color the user pinned on it. View-wide rather than per level: the floating legend is one box for the whole stack, so two levels handing out the same color would make that one legend lie. | LinearSyntenyView |
| <span id="getter-showloading">**showLoading**</span><br><code>boolean</code> | Whether to show a loading indicator instead of the import form or view | LinearSyntenyView |
| <span id="getter-loadingassembly">**loadingAssembly**</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> | The assembly whose load the spinner is waiting on. `init` names them before the rows are built, so it is the source until then. | LinearSyntenyView |
| <span id="getter-loadingmessage">**loadingMessage**</span><br><code>string &#124; undefined</code> | Label for the generic loading spinner, naming the assembly file being downloaded when the assembly load is what the wait is. The auto-diagonalize wait is a separate render branch (DiagonalizeLoadingScreen), so this only covers the plain "view not ready" case. | LinearSyntenyView |
| <span id="getter-loadingprogress">**loadingProgress**</span><br><code>number &#124; undefined</code> | Determinate fraction for the spinner's bar, when the assembly load reports one | LinearSyntenyView |
| <span id="getter-loadingsource">**loadingSource**</span><br><code>string &#124; undefined</code> | The URL the assembly load is currently fetching, when the phase named one. Only the stalled-load notice reads it — see `ViewLoadingScreen`. | LinearSyntenyView |
| <span id="getter-showimportform">**showImportForm**</span><br><code>boolean</code> | Whether to show the import form. A failed `init` counts: `init` is kept so a reload can retry it, but in this session there is nothing to show and no second attempt coming, so the form (with the error banner) is the only way forward — matching LGV/dotplot/circular, which also fall back to the form on error rather than spinning. | LinearSyntenyView |
| <span id="getter-status">**status**</span><br><code>ViewStatus</code> | The view's lifecycle as one value — ready, error, loading or noRegions — for a host that draws its own chrome and has to render all four. Same shape and same precedence as the linear view's, through `computeViewStatus`.<br><br>A host gating on `initialized` alone gets the trap this closes: it waits on every row, so a failure in either assembly leaves it false for good, and the empty box that follows says nothing about which of the two happened. | LinearSyntenyView |
| <span id="getter-scrollzoom">**scrollZoom**</span><br><code>boolean</code> | <span data-pagefind-ignore>scroll-to-zoom is a global, personal preference resolved from the session; toggling it in any view applies everywhere</span> | [LinearComparativeView](../linearcomparativeview#getter-scrollzoom) |
| <span id="getter-initialized">**initialized**</span><br><code>boolean</code> |  | [LinearComparativeView](../linearcomparativeview#getter-initialized) |
| <span id="getter-error">**error**</span><br><code>unknown</code> |  | [LinearComparativeView](../linearcomparativeview#getter-error) |
| <span id="getter-assemblynames">**assemblyNames**</span><br><code>string[]</code> |  | [LinearComparativeView](../linearcomparativeview#getter-assemblynames) |
| <span id="getter-sharedfit">**sharedFit**</span><br><code>SharedFit</code> | <span data-pagefind-ignore>The zoom-out limit every row shares while `sameScale` is on, and whether it can be answered at all. Each row PULLS this back through its own `maxBpPerPx` (`sharedScaleContainerOf` finds this view by the presence of this getter), so nothing here is copied onto the rows and nothing can go stale between a resize and the next layout. The dotplot's `lockAspectRatio` derives the same quantity the same way.<br><br>The rule, and why the unanswered state is not a zero, are in `sharedFit.ts`.</span> | [LinearComparativeView](../linearcomparativeview#getter-sharedfit) |
| <span id="getter-allsyntenydisplays">**allSyntenyDisplays**</span><br><code>any[]</code> | <span data-pagefind-ignore>Every synteny display across every level, flattened. One memoized getter for the view-wide aggregates that would otherwise each re-flatten the levels.</span> | [LinearComparativeView](../linearcomparativeview#getter-allsyntenydisplays) |
| <span id="getter-followpairs">**followPairs**</span><br><code>{…}[]</code> | <span data-pagefind-ignore>Each synteny level resolved into the pair of rows a follow would move it between: which row stays, which row moves, which axis the anchor window is read off, and the assembly naming the level's lane of an all-vs-all track. Levels whose rows are not both initialized are dropped, since there is nothing to place yet.<br><br>A getter rather than a loop in each caller because the follow reads it from TWO autoruns — the exact one and the per-frame one — which had each resolved the direction, looked the two rows up and repeated the initialized guard. Those are the same question, and the answer changes only when the rows or the anchor do.<br><br>ORDERED OUTWARD FROM THE ANCHOR rather than by level index, which is what makes a stack of three or more settle in one pass: a level's staying row is either the anchor or a row some nearer level places, so visiting them nearest-first means every level reads an input the same pass has already written. In level order that only holds when the anchor is the top row.</span> | [LinearComparativeView](../linearcomparativeview#getter-followpairs) |
| <span id="getter-syntenywarnings">**syntenyWarnings**</span><br><code>ComparativeWarning[]</code> | <span data-pagefind-ignore>Data-quality warnings raised by every synteny display, e.g. a reversed assembly row order. What the header's warning button counts.</span> | [LinearComparativeView](../linearcomparativeview#getter-syntenywarnings) |
| <span id="getter-trackwarnings">**trackWarnings**</span><br><code>TrackWarning[]</code> | <span data-pagefind-ignore>The same warnings grouped under the track that raised each, which is what the dialog reports. A stacked view's levels raise `swappedAssembliesWarning` verbatim, and so does every overlaid track that hits it, so the flat list above was N identical rows with nothing to tell the user which file to go fix. Shared with the dotplot's table so the two reports say the same thing.</span> | [LinearComparativeView](../linearcomparativeview#getter-trackwarnings) |
| <span id="getter-trackcontainers">**trackContainers**</span><br><code>TrackContainer[]</code> | <span data-pagefind-ignore>The same track lists, for a reader with no id to ask with. This view has no `tracks` of its own, so anything walking a session for displays — `AppReadyMarker`, the capture harness's busy probe — sees an empty view and reports a still-fetching synteny stack as idle unless it asks here too.</span> | [LinearComparativeView](../linearcomparativeview#getter-trackcontainers) |
| <span id="getter-effectivebodymounted">**effectiveBodyMounted**</span><br><code>boolean</code> | <span data-pagefind-ignore>Whether this view's body is in the DOM, counting the views it is nested inside — which is the question a display's phase actually asks.<br><br>`bodyMounted` alone answers it only for a view a container renders directly. A view nested in another view (a synteny row, a breakpoint panel) has no container writing its flag, so it reads `true` forever while its whole subtree is out of the DOM, and every display in it waits for a first paint that nothing will make — the hang this flag exists to prevent, one level down.<br><br>An ancestor that does not carry the flag at all leaves the answer alone rather than excusing the paint: only an explicit `false` unmounts, so a duck-typed stand-in that forgot it keeps waiting, which is the failure that shows up as a slow test rather than as a picture of an empty view.</span> | [BaseViewModel](../baseviewmodel#getter-effectivebodymounted) |
| <span id="getter-colorableattributes">**colorableAttributes**</span><br><code>string[]</code> | <span data-pagefind-ignore>Distinct numeric columns across the overlaid tracks, in first-seen order — two tracks declaring `dn` offer one `dn` mode, not two.</span> | [TrackColorsMixin](../trackcolorsmixin#getter-colorableattributes) |
| <span id="getter-attributeranges">**attributeRanges**</span><br><code>Record&lt;string, AttributeRange&gt;</code> | <span data-pagefind-ignore>The span each numeric channel covers: unioned over the loaded displays, and over every fetch this view has already taken (`seenAttributeRanges`). An `attribute:<column>` mode has no declared domain, so this is what its ramp scales to, what the legend labels it with, and — since it is the one domain — what the two cannot disagree about.<br><br>MONOTONIC, which is the point. A fetch's payload reports the span of the slice it holds, and that slice is the snapped window: painting straight off it re-maps every feature onto the ramp each time a pan rolls the window over, so a ribbon in the middle of the ramp turns into one at the bottom while the reader is scrolling and its value has not changed. A domain that only ever widens still says what the reader is looking at — the legend prints the actual numbers — and settles instead of oscillating.<br><br>Monotonic UNTIL A MODE IS PICKED, which is the way back: one window holding an outlier would otherwise compress the ramp for the rest of the session, and the union above is over the LOADED spans, so `resetAttributeRanges` rescales to what is on screen there and then.<br><br>View-wide rather than per display because the floating legend is one box for the whole view: two displays scaling the same ramp from different spans would make that one legend lie about one of them.</span> | [TrackColorsMixin](../trackcolorsmixin#getter-attributeranges) |
| <span id="getter-colorabletracks">**colorableTracks**</span><br><code>ColorableTrack[]</code> | <span data-pagefind-ignore>`colorableTrackConfigs` paired with whatever color the user pinned. This is the single definition of "the tracks that get colors" — the palette, the legend and the palette menu all read it, so they cannot disagree about which tracks are in play.</span> | [TrackColorsMixin](../trackcolorsmixin#getter-colorabletracks) |
| <span id="getter-trackcolorassignments">**trackColorAssignments**</span><br><code>Map&lt;string, string&gt;</code> | <span data-pagefind-ignore>trackId -> the color it draws in under `colorBy: 'track'`. Assigned across the whole view rather than per display, so an automatic slot can't duplicate a color pinned on a sibling.</span> | [TrackColorsMixin](../trackcolorsmixin#getter-trackcolorassignments) |
| <span id="getter-uniformcolorby">**uniformColorBy**</span><br><code>SyntenyColorBy &#124; undefined</code> | <span data-pagefind-ignore>The mode to report as "the view's mode" — undefined when tracks disagree, so the menu shows nothing checked and the legend says so instead of picking one track's answer for everyone.</span> | [TrackColorsMixin](../trackcolorsmixin#getter-uniformcolorby) |
| <span id="getter-colorlegendchips">**colorLegendChips**</span><br><code>ColorChip[]</code> | <span data-pagefind-ignore>Legend rows naming the overlaid tracks — non-empty only when they are colored by track, or by different modes.</span> | [TrackColorsMixin](../trackcolorsmixin#getter-colorlegendchips) |

## Methods

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="method-colorableattributenames">**colorableAttributeNames**</span><br><code>() =&gt; string[]</code> | The numeric columns the overlaid tracks declare, so the palette menu can offer one mode per measurement without any of them being a named mode. `attributeColumns` is the ortholog-table adapter's slot; a track whose adapter has no such slot contributes nothing. | LinearSyntenyView |
| <span id="method-loadedattributeranges">**loadedAttributeRanges**</span><br><code>() =&gt; Record&lt;string, AttributeRange&gt;[]</code> | Each loaded display's observed attribute spans, which the mixin unions into the domain the legend labels its ramp with. | LinearSyntenyView |
| <span id="method-headermenuitems">**headerMenuItems**</span><br><code>() =&gt; MenuItem[]</code> | The header hamburger, which is NOT a subset of `menuItems()` — the two share only Export SVG. This one is the synteny surface; the app menubar's is the generic view one.<br><br>SIX ROWS WHATEVER THE STACK HOLDS — seven on screen, where `ViewOptionsMenuButton` appends the "Show..." row carrying the search box prefs, whose state is React's rather than the model's. The menu answers what the view IS — where the rows point, which genomes it stacks, what leaves it — and nothing about how the ribbons are drawn: every render setting is in the header's settings menu, and `SyntenySettingsMenu` states that division from the other side.<br><br>A group in THIS menu names a CHOICE ("Link views") or what varies with row count ("Rows"), never a topic: the "Navigation" group that used to hold the zoom commands was named after what the whole menu is about, and charged a popup for it. LGV's menu had one too, and it went the same way. | LinearSyntenyView |
| <span id="method-menuitems">**menuItems**</span><br><code>() =&gt; MenuItem[]</code> |  | LinearSyntenyView |
| <span id="method-isviewcompact">**isViewCompact**</span><br><code>(idx: number) =&gt; boolean</code> |  | [LinearComparativeView](../linearcomparativeview#method-isviewcompact) |
| <span id="method-trackcontainerfor">**trackContainerFor**</span><br><code>(id: string) =&gt; TrackContainer &#124; undefined</code> | <span data-pagefind-ignore>The level that owns a given track list. This view holds one track list per synteny band rather than one of its own, so the track-selector and add-track widgets target a level through here instead of referencing this view directly. By id, not index: reconcileLevels pops levels when a genome row is removed, and an index would silently retarget a different pair.</span> | [LinearComparativeView](../linearcomparativeview#method-trackcontainerfor) |
| <span id="method-showmenuitems">**showMenuItems**</span><br><code>() =&gt; MenuItem[]</code> | <span data-pagefind-ignore>items for the "Show..." submenu in the header. overridden by subclasses to add view-specific toggle options</span> | [LinearComparativeView](../linearcomparativeview#method-showmenuitems) |
| <span id="method-rubberbandmenuitems">**rubberBandMenuItems**</span><br><code>() =&gt; { label: string; onClick: () =&gt; void; }[]</code> |  | [LinearComparativeView](../linearcomparativeview#method-rubberbandmenuitems) |
| <span id="method-colorabletrackconfigs">**colorableTrackConfigs**</span><br><code>() =&gt; { trackId: string; name: string; }[]</code> | <span data-pagefind-ignore>The tracks that can take a palette slot, in paint order. Overridden by the composing view; a method rather than a getter because that is the form MST overrides cleanly.</span> | [TrackColorsMixin](../trackcolorsmixin#method-colorabletrackconfigs) |
| <span id="method-resolvecolorby">**resolveColorBy**</span><br><code>(trackId: string) =&gt; SyntenyColorBy</code> | <span data-pagefind-ignore>The mode one track renders with: its own override, else the view-wide mode.</span> | [TrackColorsMixin](../trackcolorsmixin#method-resolvecolorby) |
| <span id="method-trackcolorfor">**trackColorFor**</span><br><code>(trackId: string) =&gt; string</code> |  | [TrackColorsMixin](../trackcolorsmixin#method-trackcolorfor) |

## Actions

<!-- prettier-ignore -->
| Member | Description | Defined by |
| --- | --- | --- |
| <span id="action-clearimportformsyntenytracks">**clearImportFormSyntenyTracks**</span><br><code>() =&gt; void</code> | Drop every pending pair-selection. The import form rewrites the whole list through this whenever its assembly rows change (a selection is about a pair of assemblies, not a row index — see `remapSelectionsToPairs`), and again once they have been applied. | LinearSyntenyView |
| <span id="action-setimportformsyntenytrack">**setImportFormSyntenyTrack**</span><br><code>(arg: number, val: ImportFormSyntenyTrack) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setdrawcurves">**setDrawCurves**</span><br><code>(arg: boolean) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setcigarmode">**setCigarMode**</span><br><code>(arg: "full" &#124; "matches" &#124; "off") =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setdrawlocationmarkers">**setDrawLocationMarkers**</span><br><code>(arg: boolean) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setshowoffscreenmates">**setShowOffscreenMates**</span><br><code>(arg: boolean) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setbidirectionalfetch">**setBidirectionalFetch**</span><br><code>(arg: boolean) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setoffscreenmatemode">**setOffscreenMateMode**</span><br><code>(mode: "both" &#124; "off" &#124; "query") =&gt; void</code> | The two properties above as the one question a reader is actually answering — how much of what this view cannot draw to go and find.<br><br>They stay two properties because they are two KINDS: marking is a repaint of what the worker already counted, and the second query is a fetch input. One control over both is what keeps the free half from costing a round trip, and it closes the combination nothing wanted — fetching the lower row and then not drawing what came back. | LinearSyntenyView |
| <span id="action-setoverdrawpx">**setOverdrawPx**</span><br><code>(arg: number) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setalpha">**setAlpha**</span><br><code>(arg: number) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setminalignmentlength">**setMinAlignmentLength**</span><br><code>(arg: number) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setlodmode">**setLodMode**</span><br><code>(arg: LodMode) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setopacitybyidentity">**setOpacityByIdentity**</span><br><code>(arg: boolean) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setfadethinalignmentsmode">**setFadeThinAlignmentsMode**</span><br><code>(arg: FadeThinMode) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-setfadethinlatch">**setFadeThinLatch**</span><br><code>(arg: boolean) =&gt; void</code> | Move the latched 'auto' thin-fade decision — `installAutoFadeLatch` is the only caller. | LinearSyntenyView |
| <span id="action-showallregions">**showAllRegions**</span><br><code>() =&gt; void</code> | Every row back to its own whole assembly, fit to its own width — and so also the way off `sameScale`, whose raised ceiling would otherwise make "show all regions" mean the shared scale on every row. The fit-to-width half of `showAllRegionsAcrossRows`, under the name the rest of the app reaches it by. | LinearSyntenyView |
| <span id="action-setinit">**setInit**</span><br><code>(init?: LinearSyntenyViewCommands &#124; undefined) =&gt; void</code> |  | LinearSyntenyView |
| <span id="action-clearview">**clearView**</span><br><code>() =&gt; void</code> | Also drops `init`, which `hasSomethingToShow` keys off while views is empty — leaving it set would bounce "return to import form" straight back to the loading spinner. | LinearSyntenyView |
| <span id="action-exportsvg">**exportSvg**</span><br><code>(opts: ExportSvgOptions) =&gt; Promise&lt;void&gt;</code> |  | LinearSyntenyView |
| <span id="action-setfollowunaligned">**setFollowUnaligned**</span><br><code>(arg: boolean) =&gt; void</code> | <span data-pagefind-ignore>Written by the follow's autorun and read only by the header, which is what keeps it from being a dependency of the very pass that writes it.<br><br>In THIS block, ahead of afterAttach, rather than with the other follow actions below: a later block's actions are not on the `self` an earlier one sees, so anything afterAttach calls has to be declared before it — the same reason `reconcileLevels` is here.</span> | [LinearComparativeView](../linearcomparativeview#action-setfollowunaligned) |
| <span id="action-setfollowapproximate">**setFollowApproximate**</span><br><code>(arg: boolean) =&gt; void</code> | <span data-pagefind-ignore>Same terms as setFollowUnaligned above: written by the autorun, read only by the header.</span> | [LinearComparativeView](../linearcomparativeview#action-setfollowapproximate) |
| <span id="action-setfollowpartial">**setFollowPartial**</span><br><code>(arg: FollowPartialReport &#124; undefined) =&gt; void</code> | <span data-pagefind-ignore>Same terms again: written by the autorun, read only by the header.</span> | [LinearComparativeView](../linearcomparativeview#action-setfollowpartial) |
| <span id="action-reconcilelevels">**reconcileLevels**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Reconcile the levels array to the views array: exactly one synteny level per gap between adjacent views (N views -> N-1 levels). Grows or shrinks from the end, preserving existing levels and their tracks. The single source of truth for the views/levels invariant.</span> | [LinearComparativeView](../linearcomparativeview#action-reconcilelevels) |
| <span id="action-setwidth">**setWidth**</span><br><code>(newWidth: number) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-setwidth) |
| <span id="action-seterror">**setError**</span><br><code>(e: unknown) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-seterror) |
| <span id="action-setviews">**setViews**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(views: ModelCreationType&lt;ExtractCFromProps&lt;_OverrideProps&lt;_Ove…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(views: ModelCreationType&lt;ExtractCFromProps&lt;_OverrideProps&lt;_OverrideProps&lt;…&gt;, { ...; }&gt;&gt;&gt;[]) =&gt; void</code></pre></dialog></span> |  | [LinearComparativeView](../linearcomparativeview#action-setviews) |
| <span id="action-addview">**addView**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(view: ModelCreationType&lt;ExtractCFromProps&lt;_OverrideProps&lt;_Over…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(view: ModelCreationType&lt;ExtractCFromProps&lt;_OverrideProps&lt;_OverrideProps&lt;…&gt;, { ...; }&gt;&gt;&gt;) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>Push a new genome row. The new trailing level starts with no synteny tracks.</span> | [LinearComparativeView](../linearcomparativeview#action-addview) |
| <span id="action-removelastrow">**removeLastRow**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Drop the bottom genome row and its synteny level. Only terminal removal is supported: a level's `level` index addresses views[level]/[level+1], so removing a middle row would require reindexing every level below it. Growth and shrinkage both happen at the end of the chain.</span> | [LinearComparativeView](../linearcomparativeview#action-removelastrow) |
| <span id="action-setlinkviews">**setLinkViews**</span><br><code>(arg: boolean) =&gt; void</code> | <span data-pagefind-ignore>Kept for the plugin ABI; `setRowSyncMode` is what the UI calls. It still has to drop the follow, since the exclusion below is a property of the two flags rather than of the action that happens to set them.</span> | [LinearComparativeView](../linearcomparativeview#action-setlinkviews) |
| <span id="action-setrowsyncmode">**setRowSyncMode**</span><br><code>(mode: "follow" &#124; "independent" &#124; "link") =&gt; void</code> | <span data-pagefind-ignore>The one way the UI changes how the rows track each other, so the two flags can't both be on. They fight if they are: `linkViews` replays the anchor's own scroll/zoom onto every row, which is precisely the pixel lock the follow then has to undo on the next settle, and the moving row visibly jumps twice.</span> | [LinearComparativeView](../linearcomparativeview#action-setrowsyncmode) |
| <span id="action-setfollowanchorindex">**setFollowAnchorIndex**</span><br><code>(idx: number) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-setfollowanchorindex) |
| <span id="action-setfollowmatchorientation">**setFollowMatchOrientation**</span><br><code>(arg: boolean) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-setfollowmatchorientation) |
| <span id="action-setscrollzoom">**setScrollZoom**</span><br><code>(arg: boolean) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-setscrollzoom) |
| <span id="action-activatetrackselector">**activateTrackSelector**</span><br><code>(level: number) =&gt; Widget</code> |  | [LinearComparativeView](../linearcomparativeview#action-activatetrackselector) |
| <span id="action-toggletrack">**toggleTrack**</span><br><code>(trackId: string, level?: any) =&gt; any</code> |  | [LinearComparativeView](../linearcomparativeview#action-toggletrack) |
| <span id="action-showtrack">**showTrack**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>(trackId: string, level?: any, initialSnapshot?: object, displa…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>(trackId: string, level?: any, initialSnapshot?: object, displayInitialSnapshot?: DisplayInitialSnapshot, inlineConf?: Record&lt;string, unknown&gt; &#124; undefined) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>No-op for a level that doesn't exist, matching hideTrack/toggleTrack. reconcileLevels already materializes exactly one level per adjacent view pair, so a missing level means the caller named a gap that has no views (e.g. an `init.tracks` with more levels than `init.views` has gaps); creating one here would append a level whose views[level+1] is absent, which renders nothing and silently breaks the views/levels invariant.</span> | [LinearComparativeView](../linearcomparativeview#action-showtrack) |
| <span id="action-hidetrack">**hideTrack**</span><br><code>(trackId: string, level?: any) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-hidetrack) |
| <span id="action-squareview">**squareView**</span><br><code>() =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-squareview) |
| <span id="action-showallregionsacrossrows">**showAllRegionsAcrossRows**</span><br><code>(sameScale: boolean) =&gt; void</code> | <span data-pagefind-ignore>Every row onto its whole assembly, and the one choice about it: leave them all on ONE bp/px — the coarsest row's fit, so the largest genome fills its pane and every other row is drawn shorter in proportion to its size — or hand each row its own fit, so each fills its own pane.<br><br>That difference is the point of offering the choice: rows fit individually to width all end up the same length, which silently stretches a small genome to look like a large one and misaligns every ribbon between them by the ratio. Distinct from squareView, which averages the rows' current scales (the average fits nobody, and each row's own zoom clamp pulls the small ones back to fit-to-width anyway).<br><br>ONE ACTION FOR BOTH, because the menu offers them as one radio and a reader reads them as one sentence with one word changed. Written as two bodies they drifted: the same-scale half took its scale off whatever region subset a row happened to be displaying while the other half reset the rows first, so the pair was not a pair — switching between them did not land back where it started.<br><br>`sameScale` LATCHES rather than firing once, because the shared scale is coarser than a small row's own fit: without the raised ceiling the first wheel tick or `setDisplayedRegions` clamps that row straight back to fit-to-width and the comparison is gone.</span> | [LinearComparativeView](../linearcomparativeview#action-showallregionsacrossrows) |
| <span id="action-setsamescale">**setSameScale**</span><br><code>(sameScale: boolean) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-setsamescale) |
| <span id="action-applysharedscale">**applySharedScale**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Latch the mode and zoom every row onto the scale it implies, without touching any row's regions or its centre — `init` names a `loc` per row, and both a region reset and a re-centre would throw that away. `zoomTo` anchors at the centre, which is the difference.</span> | [LinearComparativeView](../linearcomparativeview#action-applysharedscale) |
| <span id="action-togglecompactview">**toggleCompactView**</span><br><code>(idx: number) =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-togglecompactview) |
| <span id="action-compactallviews">**compactAllViews**</span><br><code>() =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-compactallviews) |
| <span id="action-expandallviews">**expandAllViews**</span><br><code>() =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-expandallviews) |
| <span id="action-autoscalelevelheights">**autoScaleLevelHeights**</span><br><code>() =&gt; void</code> |  | [LinearComparativeView](../linearcomparativeview#action-autoscalelevelheights) |
| <span id="action-appendrow">**appendRow**</span><br><span class="cell-more"><button type="button" class="cell-more-trigger"><code>({ assembly, loc, syntenyTrackId, }: { assembly: string; loc?:…</code></button><dialog class="cell-dialog"><form method="dialog"><button class="cell-dialog-close" aria-label="Close">✕</button></form><pre><code>({ assembly, loc, syntenyTrackId, }: { assembly: string; loc?: string &#124; undefined; syntenyTrackId?: string &#124; undefined; }) =&gt; void</code></pre></dialog></span> | <span data-pagefind-ignore>Append an assembly to the bottom of the stack and optionally show a synteny track on the new level connecting it to the previous bottom row. A synteny dataset is an edge between two adjacent assemblies, so rows are only ever added at the chain's end.<br><br>The new row is created with a LinearGenomeView `init` — its own afterAttach autorun loads the assembly regions and navigates (whole genome, or `loc` when given), so we don't reimplement that imperatively here.</span> | [LinearComparativeView](../linearcomparativeview#action-appendrow) |
| <span id="action-setdisplayname">**setDisplayName**</span><br><code>(name: string) =&gt; void</code> |  | [BaseViewModel](../baseviewmodel#action-setdisplayname) |
| <span id="action-setbodymounted">**setBodyMounted**</span><br><code>(flag: boolean) =&gt; void</code> | <span data-pagefind-ignore>See `bodyMounted`. Written by the view's container, which is the only thing that knows whether it rendered the body.</span> | [BaseViewModel](../baseviewmodel#action-setbodymounted) |
| <span id="action-setminimized">**setMinimized**</span><br><code>(flag: boolean) =&gt; void</code> |  | [BaseViewModel](../baseviewmodel#action-setminimized) |
| <span id="action-setawaitingautodiagonalize">**setAwaitingAutoDiagonalize**</span><br><code>(arg: boolean) =&gt; void</code> |  | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#action-setawaitingautodiagonalize) |
| <span id="action-beginautodiagonalize">**beginAutoDiagonalize**</span><br><code>(requested: boolean) =&gt; void</code> | <span data-pagefind-ignore>Declare the gate at the top of one init apply pass: a reorder is pending iff THIS init asked for one. Assigning rather than raising is what hands the gate over cleanly — a superseded init that asked for a reorder and then skipped it would otherwise leave the flag up with nothing coming, wedging `settled` forever.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#action-beginautodiagonalize) |
| <span id="action-finishautodiagonalize">**finishAutoDiagonalize**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>The init-time reorder resolved, so the view on screen is the diagonalized one — open the gate.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#action-finishautodiagonalize) |
| <span id="action-setdiagonalizestoptoken">**setDiagonalizeStopToken**</span><br><code>(arg?: StopToken &#124; undefined) =&gt; void</code> |  | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#action-setdiagonalizestoptoken) |
| <span id="action-cancelautodiagonalize">**cancelAutoDiagonalize**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Abort an in-flight auto-diagonalize; `withDiagonalizeProgress`'s finally clears the wait flag, revealing the (undiagonalized) view.<br><br>Lowers the gate too. The abort reaches the caller as a throw, which skips its `finishAutoDiagonalize()` — right for a reorder that failed on its own (`settled` stays false and a capture times out loudly rather than committing a hairball), wrong for one the user stopped: cancelling IS the user settling for this view, and a gate nothing will lower again leaves `settled` false forever.</span> | [DiagonalizeProgressMixin](../diagonalizeprogressmixin#action-cancelautodiagonalize) |
| <span id="action-observeattributeranges">**observeAttributeRanges**</span><br><code>(ranges: Record&lt;string, AttributeRange&gt;) =&gt; void</code> | <span data-pagefind-ignore>Fold one fetch's observed attribute spans into the domain this view paints and labels its ramps with. Called by each display as its fetch lands, because the accumulation has to outlive the payload it came from: the previous window's span is gone from `loadedAttributeRanges` the moment the next one commits.</span> | [TrackColorsMixin](../trackcolorsmixin#action-observeattributeranges) |
| <span id="action-resetattributeranges">**resetAttributeRanges**</span><br><code>() =&gt; void</code> | <span data-pagefind-ignore>Forget the accumulated domain, leaving `attributeRanges` reporting what the LOADED fetches cover and nothing else.<br><br>The way back from a monotonic domain, and the only one: a single window holding an outlier widens the ramp for the rest of the session, and `attributeRanges` unions the loaded spans over this, so a reset rescales to what is on screen without waiting for a refetch. Picking a mode is what calls it — the gesture a reader makes when the ramp is telling them nothing is to choose it again.</span> | [TrackColorsMixin](../trackcolorsmixin#action-resetattributeranges) |
| <span id="action-setcolorby">**setColorBy**</span><br><code>(value: SyntenyColorBy) =&gt; void</code> | <span data-pagefind-ignore>Set the view-wide mode. Clears every per-track override, so picking a mode from the top level of the palette menu really does mean "all tracks" — and rescales the ramp, which is the only way back from a domain one outlying window widened.</span> | [TrackColorsMixin](../trackcolorsmixin#action-setcolorby) |
| <span id="action-settrackcolorby">**setTrackColorBy**</span><br><code>(trackId: string, value: SyntenyColorBy &#124; undefined) =&gt; void</code> | <span data-pagefind-ignore>Point one track at its own mode, or back at the view-wide one.</span> | [TrackColorsMixin](../trackcolorsmixin#action-settrackcolorby) |
| <span id="action-settrackcolor">**setTrackColor**</span><br><code>(trackId: string, value: string &#124; undefined) =&gt; void</code> | <span data-pagefind-ignore>Pin one track's color under `colorBy: 'track'`, or release it back to an automatic palette slot.</span> | [TrackColorsMixin](../trackcolorsmixin#action-settrackcolor) |
| <span id="action-cleartrackcolorsettings">**clearTrackColorSettings**</span><br><code>() =&gt; void</code> |  | [TrackColorsMixin](../trackcolorsmixin#action-cleartrackcolorsettings) |
| <span id="action-setshowcolorlegend">**setShowColorLegend**</span><br><code>(value: boolean) =&gt; void</code> |  | [TrackColorsMixin](../trackcolorsmixin#action-setshowcolorlegend) |

