# BaseTrackModel

Auto-generated from the @jbrowse/mobx-state-tree model in the source — see the [developer guide](https://jbrowse.org/jb2/docs/developer_guide/) for concepts. Built into JBrowse core. [View source](https://github.com/GMOD/jbrowse-components/blob/main/packages/core/src/pluggableElementTypes/models/BaseTrackModel.ts).

Holds the UI state of a track that is *shown* in a view, with a reference to
its track configuration and the displays drawing it. Only shown tracks have
this model, and several shown tracks can use the same configuration.

## Properties

| Member | Description |
| --- | --- |
| **id**<br><code>id: ElementId</code> |  |
| **type**<br><code>type: types.literal(trackType)</code> |  |
| **configuration**<br><code>configuration: ConfigurationReference(baseTrackConfig)</code> |  |
| **minimized**<br><code>minimized: types.stripDefault(types.boolean, false)</code> |  |
| **pinned**<br><code>pinned: types.stripDefault(types.boolean, false)</code> |  |
| **displays**<br><code>displays: types.array( pm.pluggableMstType('display', 'stateModel') as unknown as IType&lt; unknown, unknown, DisplayModel &gt;, )</code> | The runtime plugin union (`pluggableMstType`) is typed only as `IAnyType`, erasing the element to `any`. Assert the concrete `DisplayModel` instance every registered display satisfies so reads (`activeDisplay`, `trackMenuItems`) are checked; create/snapshot stay `unknown` since the union's snapshot shape is genuinely dynamic (`replaceDisplay` writes a partial snapshot). |

## Volatiles

| Member | Description |
| --- | --- |
| **resizing**<br><code>boolean</code> | Whether a height-resize gesture is in progress on this track. Set by whichever handle owns the drag — the view's track resize handle, or a handle a display draws inside itself — and read by displays that sit an expensive per-frame layer out of the gesture.<br><br>On the track rather than the display because the gesture belongs to the container running it, not to whatever display happens to be active: the view can bracket a drag without knowing which display it landed on, and two handles on one track share one flag rather than racing to clear each other's. |

## Getters

| Member | Description |
| --- | --- |
| **trackId**<br><code>string</code> |  |
| **rpcSessionId**<br><code>string</code> | determines which webworker to send the track to, currently based on trackId |
| **name**<br><code>string</code> |  |
| **textSearchAdapter**<br><code>any</code> | this track's own name-search index, from the `textSearching` sub-config. `undefined` when the track has none.<br><br>The path, not a bare `'textSearchAdapter'`: the slot is `textSearching.textSearchAdapter` (`baseTrackConfig.ts`), and a bare read of a name no schema declares returns `undefined` and reports nothing at any layer, so this getter answered `undefined` for every track ever configured with one. `TextSearchManager` reads the same slot by hand-walking `conf.textSearching.textSearchAdapter`, which is why nothing noticed. |
| **adapterConfig**<br><code>Record&lt;string, unknown&gt;</code> |  |
| **activeDisplay**<br><code>DisplayModel &amp; IStateTreeNode&lt;IType&lt;unknown, unknown, DisplayModel&gt;&gt;</code> | a shown track always has at least one display |
| **compatibleDisplays**<br><code>AnyConfigurationModel[]</code> | the configured displays the CONTAINING VIEW can draw and the track's adapter feeds, which is the set `replaceDisplay` will accept<br><br>`configuration.displays` is not that set: baseTrackConfig injects one entry per display type registered for the track TYPE, across every view type, so a VariantTrack carries a ChordVariantDisplay a linear view cannot draw. The track menu's own "Display types" submenu has always filtered them; this exposes the same list to code, because the alternative is every caller re-deriving it from the plugin manager. |
| **refNameMismatch**<br><code>RefNameMismatch &#124; undefined</code> | Set when this track's file and one of its assemblies share no reference name at all — the `1/2/3` file loaded against a `chr1/chr2/chr3` assembly, which otherwise draws an empty track and says nothing.<br><br>The verdict is reached in `loadRefNameMap`, which is the only place both name sets are in scope, and recorded on the *assembly* because nothing in the assembly manager can reach a track (the session is a sibling subtree, so `getSession` from there finds only the root). The lookup inverts that: the record is keyed by adapter cache key, which is exactly what `rpcSessionId` already is, so a track finds its own with no plumbing in between.<br><br>The names come from `getConfAssemblyNamesOrNone`, not from a raw `assemblyNames` slot read: this model is shared by every track type, and `ReferenceSequenceTrack`'s schema does not declare that slot — it names its assembly by being the `sequence` of one. A raw read there returns `undefined` with no diagnostic at any layer, so the getter was inert for that one track type while looking like it worked. The `OrNone` half is what keeps this total: it runs on every render of every track label, and an unanswerable question must not become a thrown getter.<br><br>Diagnostic only. It gates nothing, and a track carrying one still loads, still fetches and still draws whatever it can. |
| **adapterType**<br><code>AdapterType&lt;any&gt;</code> |  |
| **exportsDataViaAdapter**<br><code>boolean</code> | Whether this track's adapter writes an export format itself, rather than the save dialog rebuilding one out of rendered features. A claim about the adapter type, not about a given format — the fetch still falls back when the adapter declines the one that was asked for. |
| **exportByteLimit**<br><code>number</code> | The size in bytes above which "Save track data" asks for confirmation before fetching. Uses the adapter's `fetchSizeLimit` where it declares one, so a save asks at the same size at which the track's display refuses to render; otherwise a default. The default is generous because exceeding it only prompts for confirmation, and the user explicitly requested the data. |
| **saveTrackDataMenuItem**<br><code>MenuItem</code> | the "Save track data" menu entry. Kept separate from trackMenuItems so consumers (e.g. the LGV track-label menu) can place it alongside the session's Settings/Copy/Delete track actions without fishing it back out of the general list |

## Methods

| Member | Description |
| --- | --- |
| **saveTrackFileFormatOptions**<br><code>() =&gt; Record&lt;string, FileTypeExporter&gt;</code> |  |
| **trackMenuItems**<br><code>() =&gt; MenuItem[]</code> |  |

## Actions

| Member | Description |
| --- | --- |
| **persistConfigurationNow**<br><code>() =&gt; void</code> | Write the config to the session now rather than after the 400 ms wait, for an edit that has to be undoable the moment it lands. |
| **setPinned**<br><code>(flag: boolean) =&gt; void</code> |  |
| **setMinimized**<br><code>(flag: boolean) =&gt; void</code> |  |
| **setResizing**<br><code>(flag: boolean) =&gt; void</code> |  |
| **applyDisplaySettings**<br><code>(settings: Record&lt;string, unknown&gt;, options?: { allowSetters?: boolean &#124; undefined; } &#124; undefined) =&gt; { applied: string[]; unapplied: UnappliedSetting[]; failed: { key: string; error: string; }[]; }</code> | `applyDisplaySettings` on the display being drawn (`activeDisplay`, which a shown track always has — this is not meaningful on a bare config node) — the track-level entry for "restyle this track in place" (a session spec's inline keys, an agent's settings bag). Only that one display: settings vocabularies are per display type, so broadcasting one bag across a track's other displays would mis-route keys; address a non-active display directly if that is what you mean. See BaseDisplayModel for the routing and the `allowSetters` opt-in. |
| **replaceDisplay**<br><code>(oldDisplayId: string, newDisplayId: string, initialSnapshot?: any) =&gt; void</code> |  |
| **afterAttach**<br><code>() =&gt; void</code> | Persist any config-schema mutation (quick track-menu edits calling `setSlot` directly, or the full Settings dialog) back to the session, debounced, mirroring ConfigurationEditorWidget's own save. Both savers intentionally coexist — this one covers direct setSlot edits on a shown track, the widget covers an unshown track edited from the selector (no BaseTrackModel). When both fire they compute an identical delta, deduped in updateTrackConfiguration; don't drop one to "simplify". `reaction` (not `autorun`) on purpose: `self.configuration` is defined immediately on attach, unlike ConfigurationEditorWidget's `target` (which starts undefined), so an autorun's guaranteed first run would otherwise schedule a spurious flush for every track ever shown, even completely untouched ones — `reaction` only fires on an actual change.<br><br>`equals: compareStructural` is load-bearing, not an optimization: `self.configuration` is a re-resolving reference, and an undo or a session restore swaps the resolved node for a new working copy. Referential comparison would treat every such swap as a fresh change and re-fire the save, an unbounded debounced loop. Structural comparison settles once the content stops changing. |
| **launchDisplay**<br><code>(displayId: string) =&gt; Promise&lt;void&gt;</code> | The awaitable sibling of `replaceDisplay`: loads the target display's state model, then swaps to it carrying whatever settings the outgoing display can hand over.<br><br>`replaceDisplay` stays a plain sync action and ASSERTS the model is loaded, and every display state model in this tree is a dynamic import until something shows one — so a caller that has not already shown the target needs this. Named like `launchTrack`, which is the same problem one level up. |

