loom-browser 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/loom.esm.js CHANGED
@@ -3551,14 +3551,14 @@ class BinaryParser {
3551
3551
  // ─── Internal helpers ─────────────────────────────────────────────────────────
3552
3552
  // Cache BigWig instances by URL to reuse parsed headers and trees.
3553
3553
  // Auth-aware readers share the cache key (URL) — the fetchImpl is bound at creation.
3554
- const readerCache$4 = new Map();
3554
+ const readerCache$5 = new Map();
3555
3555
  function getGmodReader(url, fetchImpl) {
3556
3556
  const resolvedUrl = normalizeGoogleURL(url);
3557
- let reader = readerCache$4.get(resolvedUrl);
3557
+ let reader = readerCache$5.get(resolvedUrl);
3558
3558
  if (!reader) {
3559
3559
  const fileOpts = fetchImpl ? { fetch: fetchImpl } : undefined;
3560
3560
  reader = new BigWig({ filehandle: new RemoteFile(resolvedUrl, fileOpts) });
3561
- readerCache$4.set(resolvedUrl, reader);
3561
+ readerCache$5.set(resolvedUrl, reader);
3562
3562
  }
3563
3563
  return reader;
3564
3564
  }
@@ -3679,7 +3679,7 @@ async function fetchBigWigFeatures(url, locus, options = {}) {
3679
3679
  // Evict the cached reader so the next fetch gets a fresh one.
3680
3680
  // @gmod/bbi caches the header promise; an aborted parse poisons it permanently.
3681
3681
  if (err instanceof Error && (err.name === 'AbortError' || ((_b = err.message) === null || _b === void 0 ? void 0 : _b.includes('aborted')))) {
3682
- readerCache$4.delete(url);
3682
+ readerCache$5.delete(url);
3683
3683
  }
3684
3684
  throw err;
3685
3685
  }
@@ -3695,7 +3695,7 @@ async function fetchBigWigWGFeatures(url, chromNames, bpPerPixel, options = {})
3695
3695
  }
3696
3696
  /** Clear the BigWig reader cache (useful for testing or memory management). */
3697
3697
  function clearBigWigCache() {
3698
- readerCache$4.clear();
3698
+ readerCache$5.clear();
3699
3699
  }
3700
3700
 
3701
3701
  /**
@@ -5040,12 +5040,12 @@ class GtxFetchCoordinator {
5040
5040
  * Layer 1 (Data + Layout): no DOM, no canvas.
5041
5041
  */
5042
5042
  // Cache readers by URL to reuse parsed headers, dictionaries, and indexes
5043
- const readerCache$3 = new Map();
5044
- function getReader$3(url, fetchImpl) {
5045
- let reader = readerCache$3.get(url);
5043
+ const readerCache$4 = new Map();
5044
+ function getReader$4(url, fetchImpl) {
5045
+ let reader = readerCache$4.get(url);
5046
5046
  if (!reader) {
5047
5047
  reader = new GtxReader(url, fetchImpl);
5048
- readerCache$3.set(url, reader);
5048
+ readerCache$4.set(url, reader);
5049
5049
  }
5050
5050
  return reader;
5051
5051
  }
@@ -5054,7 +5054,7 @@ function getReader$3(url, fetchImpl) {
5054
5054
  */
5055
5055
  async function fetchGtxFeatures(url, experimentId, locus, options = {}) {
5056
5056
  var _a;
5057
- const reader = getReader$3(url, options.fetchImpl);
5057
+ const reader = getReader$4(url, options.fetchImpl);
5058
5058
  await reader.init(options.signal);
5059
5059
  const expIdx = reader.resolveExperimentIndex(experimentId);
5060
5060
  if (expIdx === undefined) {
@@ -5068,7 +5068,7 @@ async function fetchGtxFeatures(url, experimentId, locus, options = {}) {
5068
5068
  * Returns features with per-chromosome coordinates (caller transforms to genome-wide).
5069
5069
  */
5070
5070
  async function fetchGtxWGFeatures(url, experimentId, chromNames, bpPerPixel, options = {}) {
5071
- const reader = getReader$3(url, options.fetchImpl);
5071
+ const reader = getReader$4(url, options.fetchImpl);
5072
5072
  await reader.init(options.signal);
5073
5073
  const expIdx = reader.resolveExperimentIndex(experimentId);
5074
5074
  if (expIdx === undefined) {
@@ -5097,7 +5097,7 @@ async function fetchGtxWGFeatures(url, experimentId, chromNames, bpPerPixel, opt
5097
5097
  */
5098
5098
  async function fetchGtxMultiFeatures(url, experimentIds, locus, options = {}) {
5099
5099
  var _a;
5100
- const reader = getReader$3(url, options.fetchImpl);
5100
+ const reader = getReader$4(url, options.fetchImpl);
5101
5101
  await reader.init(options.signal);
5102
5102
  const idToIdx = new Map();
5103
5103
  const indexes = [];
@@ -5119,10 +5119,10 @@ async function fetchGtxMultiFeatures(url, experimentIds, locus, options = {}) {
5119
5119
  }
5120
5120
  /** Clear the GTX reader cache (useful for testing or memory management). */
5121
5121
  function clearGtxCache() {
5122
- for (const reader of readerCache$3.values()) {
5122
+ for (const reader of readerCache$4.values()) {
5123
5123
  reader.dispose();
5124
5124
  }
5125
- readerCache$3.clear();
5125
+ readerCache$4.clear();
5126
5126
  clearCoordinators();
5127
5127
  }
5128
5128
 
@@ -5144,12 +5144,12 @@ function clearGtxCache() {
5144
5144
  * Layer 1 (Data + Layout): no DOM, no canvas.
5145
5145
  */
5146
5146
  // Cache readers by URL (shared with gtx/index.ts reader cache)
5147
- const readerCache$2 = new Map();
5148
- function getReader$2(url, fetchImpl) {
5149
- let reader = readerCache$2.get(url);
5147
+ const readerCache$3 = new Map();
5148
+ function getReader$3(url, fetchImpl) {
5149
+ let reader = readerCache$3.get(url);
5150
5150
  if (!reader) {
5151
5151
  reader = new GtxReader(url, fetchImpl);
5152
- readerCache$2.set(url, reader);
5152
+ readerCache$3.set(url, reader);
5153
5153
  }
5154
5154
  return reader;
5155
5155
  }
@@ -5159,7 +5159,7 @@ class GtxDataSource {
5159
5159
  this.experimentId = experimentId;
5160
5160
  this._windowFunction = windowFunction;
5161
5161
  this.fetchImpl = fetchImpl;
5162
- this.reader = getReader$2(url, fetchImpl);
5162
+ this.reader = getReader$3(url, fetchImpl);
5163
5163
  }
5164
5164
  get windowFunction() { return this._windowFunction; }
5165
5165
  /** Update the window function for future fetches. */
@@ -15393,6 +15393,12 @@ function isBinaryFormat(format) {
15393
15393
  }
15394
15394
  /** BigWig/BigBed format set — these use BWSource in igv.js. */
15395
15395
  const bbFormats = new Set(['bigwig', 'bw', 'bigbed', 'bb', 'biginteract', 'biggenepred', 'bignarrowpeak']);
15396
+ /** BigBed-specific formats (annotation data, not quantitative). */
15397
+ const bigBedFormats = new Set(['bigbed', 'bb', 'biginteract', 'biggenepred', 'bignarrowpeak']);
15398
+ /** Check if a format string represents a BigBed (annotation) format vs BigWig (quantitative). */
15399
+ function isBigBedFormat(format) {
15400
+ return bigBedFormats.has(format.toLowerCase());
15401
+ }
15396
15402
  /**
15397
15403
  * Check if a URL is likely tabix-indexed.
15398
15404
  *
@@ -22075,15 +22081,15 @@ class TwoBitFile {
22075
22081
  */
22076
22082
  // ─── Internal helpers ─────────────────────────────────────────────────────────
22077
22083
  // Cache TwoBitFile instances by URL to reuse parsed headers and indices.
22078
- const readerCache$1 = new Map();
22084
+ const readerCache$2 = new Map();
22079
22085
  // Parallel filehandle cache for direct batched reads (bypasses @gmod/twobit).
22080
22086
  const filehandleCache = new Map();
22081
- function getReader$1(url, fetchImpl) {
22082
- let reader = readerCache$1.get(url);
22087
+ function getReader$2(url, fetchImpl) {
22088
+ let reader = readerCache$2.get(url);
22083
22089
  if (!reader) {
22084
22090
  const filehandle = getFilehandle(url, fetchImpl);
22085
22091
  reader = new TwoBitFile({ filehandle });
22086
- readerCache$1.set(url, reader);
22092
+ readerCache$2.set(url, reader);
22087
22093
  }
22088
22094
  return reader;
22089
22095
  }
@@ -22147,7 +22153,7 @@ function mergeOffsetsToRanges(sortedOffsets) {
22147
22153
  * instead of 100K+.
22148
22154
  */
22149
22155
  async function fetchChromSizesBatched(url, fetchImpl) {
22150
- const reader = getReader$1(url, fetchImpl);
22156
+ const reader = getReader$2(url, fetchImpl);
22151
22157
  const fh = getFilehandle(url, fetchImpl);
22152
22158
  // Step 1: get the index (name → file offset). Cached after first call.
22153
22159
  const index = await reader.getIndex();
@@ -22215,14 +22221,14 @@ async function fetchChromSizesBatched(url, fetchImpl) {
22215
22221
  function createTwoBitSequenceProvider(url, fetchImpl) {
22216
22222
  return async (locus) => {
22217
22223
  var _a;
22218
- const reader = getReader$1(url, fetchImpl);
22224
+ const reader = getReader$2(url, fetchImpl);
22219
22225
  try {
22220
22226
  const sequence = await reader.getSequence(locus.chr, locus.start, locus.end);
22221
22227
  return sequence !== null && sequence !== void 0 ? sequence : '';
22222
22228
  }
22223
22229
  catch (err) {
22224
22230
  if (err instanceof Error && (err.name === 'AbortError' || ((_a = err.message) === null || _a === void 0 ? void 0 : _a.includes('aborted')))) {
22225
- readerCache$1.delete(url);
22231
+ readerCache$2.delete(url);
22226
22232
  filehandleCache.delete(url);
22227
22233
  }
22228
22234
  throw err;
@@ -22250,12 +22256,12 @@ async function fetchTwoBitChromSizes(url, fetchImpl) {
22250
22256
  * individual sequence records.
22251
22257
  */
22252
22258
  async function fetchTwoBitSequenceNames(url, fetchImpl) {
22253
- const reader = getReader$1(url, fetchImpl);
22259
+ const reader = getReader$2(url, fetchImpl);
22254
22260
  return reader.getSequenceNames();
22255
22261
  }
22256
22262
  /** Clear the TwoBit reader cache (useful for testing or memory management). */
22257
22263
  function clearTwoBitCache() {
22258
- readerCache$1.clear();
22264
+ readerCache$2.clear();
22259
22265
  filehandleCache.clear();
22260
22266
  }
22261
22267
 
@@ -22459,10 +22465,10 @@ class FetchableSmallFasta {
22459
22465
  */
22460
22466
  // ─── Internal helpers ─────────────────────────────────────────────────────────
22461
22467
  // Cache reader instances by URL to reuse parsed indices.
22462
- const readerCache = new Map();
22463
- function getReader(fastaURL, indexURL, compressedIndexURL, fetchImpl) {
22468
+ const readerCache$1 = new Map();
22469
+ function getReader$1(fastaURL, indexURL, compressedIndexURL, fetchImpl) {
22464
22470
  const cacheKey = fastaURL;
22465
- let reader = readerCache.get(cacheKey);
22471
+ let reader = readerCache$1.get(cacheKey);
22466
22472
  if (!reader) {
22467
22473
  const fileOpts = fetchImpl ? { fetch: fetchImpl } : undefined;
22468
22474
  if (compressedIndexURL) {
@@ -22478,7 +22484,7 @@ function getReader(fastaURL, indexURL, compressedIndexURL, fetchImpl) {
22478
22484
  fai: new RemoteFile(indexURL, fileOpts),
22479
22485
  });
22480
22486
  }
22481
- readerCache.set(cacheKey, reader);
22487
+ readerCache$1.set(cacheKey, reader);
22482
22488
  }
22483
22489
  return reader;
22484
22490
  }
@@ -22498,14 +22504,14 @@ function createFastaSequenceProvider(fastaURL, indexURL, compressedIndexURL, fet
22498
22504
  const faiURL = indexURL !== null && indexURL !== void 0 ? indexURL : fastaURL + '.fai';
22499
22505
  return async (locus, signal) => {
22500
22506
  var _a;
22501
- const reader = getReader(fastaURL, faiURL, compressedIndexURL, fetchImpl);
22507
+ const reader = getReader$1(fastaURL, faiURL, compressedIndexURL, fetchImpl);
22502
22508
  try {
22503
22509
  const sequence = await reader.getSequence(locus.chr, locus.start, locus.end, { signal });
22504
22510
  return sequence !== null && sequence !== void 0 ? sequence : '';
22505
22511
  }
22506
22512
  catch (err) {
22507
22513
  if (err instanceof Error && (err.name === 'AbortError' || ((_a = err.message) === null || _a === void 0 ? void 0 : _a.includes('aborted')))) {
22508
- readerCache.delete(fastaURL);
22514
+ readerCache$1.delete(fastaURL);
22509
22515
  }
22510
22516
  throw err;
22511
22517
  }
@@ -22519,7 +22525,7 @@ function createFastaSequenceProvider(fastaURL, indexURL, compressedIndexURL, fet
22519
22525
  */
22520
22526
  async function fetchFastaChromSizes(fastaURL, indexURL, fetchImpl) {
22521
22527
  const faiURL = indexURL !== null && indexURL !== void 0 ? indexURL : fastaURL + '.fai';
22522
- const reader = getReader(fastaURL, faiURL, undefined, fetchImpl);
22528
+ const reader = getReader$1(fastaURL, faiURL, undefined, fetchImpl);
22523
22529
  return reader.getSequenceSizes();
22524
22530
  }
22525
22531
  /**
@@ -22527,12 +22533,12 @@ async function fetchFastaChromSizes(fastaURL, indexURL, fetchImpl) {
22527
22533
  */
22528
22534
  async function fetchFastaSequenceNames(fastaURL, indexURL, fetchImpl) {
22529
22535
  const faiURL = indexURL !== null && indexURL !== void 0 ? indexURL : fastaURL + '.fai';
22530
- const reader = getReader(fastaURL, faiURL, undefined, fetchImpl);
22536
+ const reader = getReader$1(fastaURL, faiURL, undefined, fetchImpl);
22531
22537
  return reader.getSequenceNames();
22532
22538
  }
22533
22539
  /** Clear the FASTA reader cache (useful for testing or memory management). */
22534
22540
  function clearFastaCache() {
22535
- readerCache.clear();
22541
+ readerCache$1.clear();
22536
22542
  }
22537
22543
 
22538
22544
  /**
@@ -23056,7 +23062,7 @@ function indexGenomes(genomes, table) {
23056
23062
  * Layer 1 (Data): no DOM, no canvas.
23057
23063
  */
23058
23064
  /** Known data source config types. */
23059
- const KNOWN_DS_TYPES = new Set(['bigwig', 'gtx', 'ucsc', 'text', 'memory']);
23065
+ const KNOWN_DS_TYPES = new Set(['bigwig', 'bigbed', 'gtx', 'ucsc', 'text', 'memory']);
23060
23066
  /** Check whether a data source config type is one of the known concrete types. */
23061
23067
  function isKnownDataSourceType(type) {
23062
23068
  return KNOWN_DS_TYPES.has(type);
@@ -23090,7 +23096,16 @@ function resolveDataSourceConfig(config) {
23090
23096
  auth.headers = config.headers;
23091
23097
  if (config.withCredentials)
23092
23098
  auth.withCredentials = config.withCredentials;
23093
- // BigWig / BigBed binary formats
23099
+ // BigBed binary formats (annotation data)
23100
+ if (format && isBigBedFormat(format)) {
23101
+ log.warn(`Unknown data source type "${type}", inferred "bigbed" from URL: ${url}`);
23102
+ return {
23103
+ type: 'bigbed',
23104
+ url,
23105
+ ...auth,
23106
+ };
23107
+ }
23108
+ // BigWig / other binary formats (quantitative data)
23094
23109
  if (format && (format === 'bigwig' || format === 'bw' || isBinaryFormat(format))) {
23095
23110
  log.warn(`Unknown data source type "${type}", inferred "bigwig" from URL: ${url}`);
23096
23111
  return {
@@ -23528,6 +23543,106 @@ class SequenceTrackCanvas extends BaseTrackCanvas {
23528
23543
  }
23529
23544
  }
23530
23545
 
23546
+ /**
23547
+ * BigBed data source — fetches BED features from BigBed binary files.
23548
+ *
23549
+ * Uses @gmod/bbi's BigBed class for binary parsing and range queries.
23550
+ * Returns BedFeature[] suitable for annotation track rendering.
23551
+ *
23552
+ * Mirrors igv.js BWSource behavior for bigbed format:
23553
+ * - Features are decoded from BED rest fields via decodeBed()
23554
+ * - No zoom-level summarization (unlike BigWig)
23555
+ * - Feature density estimation from header dataCount
23556
+ *
23557
+ * Layer 1 (Data + Layout): no DOM.
23558
+ */
23559
+ // Cache BigBed instances by URL to reuse parsed headers and index trees.
23560
+ const readerCache = new Map();
23561
+ function getReader(url, fetchImpl) {
23562
+ const resolvedUrl = normalizeGoogleURL(url);
23563
+ let reader = readerCache.get(resolvedUrl);
23564
+ if (!reader) {
23565
+ const fileOpts = fetchImpl ? { fetch: fetchImpl } : undefined;
23566
+ reader = new BigBed({ filehandle: new RemoteFile(resolvedUrl, fileOpts) });
23567
+ readerCache.set(resolvedUrl, reader);
23568
+ }
23569
+ return reader;
23570
+ }
23571
+ class BigBedDataSource {
23572
+ constructor(url, fetchImpl) {
23573
+ this.url = url;
23574
+ this.fetchImpl = fetchImpl;
23575
+ this.bb = getReader(url, fetchImpl);
23576
+ }
23577
+ /** Set a chromosome name resolver for alias resolution (e.g., "1" → "chr1"). */
23578
+ setChromNameResolver(resolver) {
23579
+ this._resolveChromName = resolver;
23580
+ }
23581
+ async fetch(locus, _bpPerPixel, signal) {
23582
+ var _a;
23583
+ const chr = this._resolveChromName
23584
+ ? this._resolveChromName(locus.chr)
23585
+ : locus.chr;
23586
+ try {
23587
+ const rawFeatures = await this.bb.getFeatures(chr, locus.start, locus.end, { signal });
23588
+ const result = [];
23589
+ for (const f of rawFeatures) {
23590
+ const parsed = parseBigBedFeature(chr, f.start, f.end, f.rest);
23591
+ if (parsed)
23592
+ result.push(parsed);
23593
+ }
23594
+ return result;
23595
+ }
23596
+ catch (err) {
23597
+ // Evict poisoned reader on abort (same pattern as BigWig)
23598
+ if (err instanceof Error && (err.name === 'AbortError' || ((_a = err.message) === null || _a === void 0 ? void 0 : _a.includes('aborted')))) {
23599
+ readerCache.delete(normalizeGoogleURL(this.url));
23600
+ }
23601
+ throw err;
23602
+ }
23603
+ }
23604
+ /**
23605
+ * Search for a feature by name via BigBed extra index.
23606
+ * Returns matching features, or empty array if not found or not indexed.
23607
+ */
23608
+ async search(name) {
23609
+ const header = await this.bb.getHeader();
23610
+ const results = await this.bb.searchExtraIndex(name);
23611
+ if (results.length === 0)
23612
+ return [];
23613
+ const refsByNumber = header.refsByNumber;
23614
+ const features = [];
23615
+ for (const r of results) {
23616
+ const chromId = r.chromId;
23617
+ if (chromId == null || !(refsByNumber === null || refsByNumber === void 0 ? void 0 : refsByNumber[chromId]))
23618
+ continue;
23619
+ const chr = refsByNumber[chromId].name;
23620
+ const parsed = parseBigBedFeature(chr, r.start, r.end, r.rest);
23621
+ if (parsed)
23622
+ features.push(parsed);
23623
+ }
23624
+ return features;
23625
+ }
23626
+ dispose() {
23627
+ readerCache.delete(normalizeGoogleURL(this.url));
23628
+ }
23629
+ }
23630
+ /**
23631
+ * Parse a BigBed feature's rest field into a BedFeature.
23632
+ * Reconstructs BED tokens from chr/start/end + tab-delimited rest, then uses decodeBed().
23633
+ */
23634
+ function parseBigBedFeature(chr, start, end, rest) {
23635
+ const tokens = [chr, String(start), String(end)];
23636
+ if (rest) {
23637
+ tokens.push(...rest.split('\t'));
23638
+ }
23639
+ return decodeBed(tokens);
23640
+ }
23641
+ /** Clear the BigBed reader cache (useful for testing or memory management). */
23642
+ function clearBigBedCache() {
23643
+ readerCache.clear();
23644
+ }
23645
+
23531
23646
  /**
23532
23647
  * DataSource backed by an in-memory feature array.
23533
23648
  *
@@ -26672,6 +26787,8 @@ function createDataSource(config) {
26672
26787
  switch (config.type) {
26673
26788
  case 'bigwig':
26674
26789
  return new BigWigDataSource(config.url, config.windowFunction);
26790
+ case 'bigbed':
26791
+ return new BigBedDataSource(config.url);
26675
26792
  case 'gtx':
26676
26793
  return new GtxDataSource(config.url, config.experimentId, config.windowFunction);
26677
26794
  case 'ucsc':
@@ -26953,6 +27070,11 @@ registerTypeAlias('broadpeak', 'annotation');
26953
27070
  registerTypeAlias('genepred', 'annotation');
26954
27071
  registerTypeAlias('genepredext', 'annotation');
26955
27072
  registerTypeAlias('refflat', 'annotation');
27073
+ // BigBed format → annotation track type aliases
27074
+ registerTypeAlias('bigbed', 'annotation');
27075
+ registerTypeAlias('bedtype', 'annotation');
27076
+ registerTypeAlias('biggenepred', 'annotation');
27077
+ registerTypeAlias('bignarrowpeak', 'annotation');
26956
27078
  // Merged/overlay aliases
26957
27079
  registerTypeAlias('overlay', 'merged');
26958
27080
  // Interaction format aliases
@@ -27043,6 +27165,10 @@ const IGV_TRACK_TYPE_MAP = {
27043
27165
  'gtf': 'annotation',
27044
27166
  'narrowpeak': 'annotation',
27045
27167
  'broadpeak': 'annotation',
27168
+ 'bigbed': 'annotation',
27169
+ 'biggenepred': 'annotation',
27170
+ 'bignarrowpeak': 'annotation',
27171
+ 'biginteract': 'interact',
27046
27172
  'sequence': 'sequence',
27047
27173
  'interact': 'interact',
27048
27174
  'bedpe': 'interact',
@@ -27160,23 +27286,35 @@ function convertIgvWigTrack(igvTrack) {
27160
27286
  return result;
27161
27287
  }
27162
27288
  function convertIgvAnnotationTrack(igvTrack) {
27289
+ var _a, _b;
27163
27290
  const result = { type: 'annotation' };
27164
27291
  if (igvTrack.name)
27165
27292
  result.name = igvTrack.name;
27166
27293
  if (igvTrack.order != null)
27167
27294
  result.order = igvTrack.order;
27168
- // Data source — gene tracks in igv.js can come from URLs (text files) or UCSC
27295
+ // Data source — gene tracks in igv.js can come from BigBed, text files, or UCSC
27169
27296
  if (igvTrack.url) {
27170
- const ds = {
27171
- type: 'text',
27172
- url: igvTrack.url,
27173
- ...extractAuthFromIgv(igvTrack),
27174
- };
27175
- if (igvTrack.indexURL)
27176
- ds.indexURL = igvTrack.indexURL;
27177
- if (igvTrack.format)
27178
- ds.format = igvTrack.format;
27179
- result.dataSource = ds;
27297
+ const format = (_b = (_a = igvTrack.format) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
27298
+ if (isBigBedFormat(format) || /\.bb$/i.test(igvTrack.url) || /\.bigbed$/i.test(igvTrack.url)) {
27299
+ const ds = {
27300
+ type: 'bigbed',
27301
+ url: igvTrack.url,
27302
+ ...extractAuthFromIgv(igvTrack),
27303
+ };
27304
+ result.dataSource = ds;
27305
+ }
27306
+ else {
27307
+ const ds = {
27308
+ type: 'text',
27309
+ url: igvTrack.url,
27310
+ ...extractAuthFromIgv(igvTrack),
27311
+ };
27312
+ if (igvTrack.indexURL)
27313
+ ds.indexURL = igvTrack.indexURL;
27314
+ if (igvTrack.format)
27315
+ ds.format = igvTrack.format;
27316
+ result.dataSource = ds;
27317
+ }
27180
27318
  }
27181
27319
  // Config overrides
27182
27320
  const config = {};
@@ -27272,13 +27410,23 @@ function convertToIgvWigTrack(track) {
27272
27410
  return igv;
27273
27411
  }
27274
27412
  function convertToIgvAnnotationTrack(track) {
27275
- var _a;
27413
+ var _a, _b;
27276
27414
  const igv = { type: 'annotation' };
27277
27415
  if (track.name)
27278
27416
  igv.name = track.name;
27279
27417
  if (track.order != null)
27280
27418
  igv.order = track.order;
27281
27419
  if (((_a = track.dataSource) === null || _a === void 0 ? void 0 : _a.type) === 'text') {
27420
+ igv.url = track.dataSource.url;
27421
+ if (track.dataSource.format)
27422
+ igv.format = track.dataSource.format;
27423
+ if (track.dataSource.indexURL)
27424
+ igv.indexURL = track.dataSource.indexURL;
27425
+ Object.assign(igv, extractAuthForIgv(track.dataSource));
27426
+ }
27427
+ else if (((_b = track.dataSource) === null || _b === void 0 ? void 0 : _b.type) === 'bigbed') {
27428
+ igv.url = track.dataSource.url;
27429
+ igv.format = 'bigbed';
27282
27430
  Object.assign(igv, extractAuthForIgv(track.dataSource));
27283
27431
  }
27284
27432
  if (track.config) {
@@ -28827,6 +28975,9 @@ function wireDataSource(ds, ctx) {
28827
28975
  if (ds instanceof BigWigDataSource || ds instanceof GtxDataSource) {
28828
28976
  ds.setChromNameResolver(alias => ctx.genome.getChromosomeName(alias));
28829
28977
  }
28978
+ else if (ds instanceof BigBedDataSource) {
28979
+ ds.setChromNameResolver(alias => ctx.genome.getChromosomeName(alias));
28980
+ }
28830
28981
  else if (ds instanceof TextFeatureSource) {
28831
28982
  ds.setChromNameResolver(alias => ctx.genome.getChromosomeName(alias));
28832
28983
  if (ctx.cumulativeOffsets) {
@@ -29014,6 +29165,30 @@ function createBedTrack(ctx, url, options) {
29014
29165
  searchableFields: options === null || options === void 0 ? void 0 : options.searchableFields,
29015
29166
  };
29016
29167
  }
29168
+ function createBigBedTrack(ctx, url, options) {
29169
+ var _a;
29170
+ const { canvas } = ctx.canvasProvider.createCanvas(0, 0);
29171
+ const track = new AnnotationTrackCanvas(canvas, {
29172
+ locus: ctx.locus,
29173
+ features: [],
29174
+ config: options === null || options === void 0 ? void 0 : options.config,
29175
+ theme: ctx.theme,
29176
+ canvasProvider: ctx.canvasProvider,
29177
+ name: options === null || options === void 0 ? void 0 : options.name,
29178
+ });
29179
+ const dataSourceConfig = { type: 'bigbed', url, ...options === null || options === void 0 ? void 0 : options.auth };
29180
+ const fetchImpl = resolveTrackFetchImpl(ctx, options);
29181
+ const { dataSource } = getOrCreateDataSource(dataSourceConfig, () => new BigBedDataSource(url, fetchImpl), ctx);
29182
+ return {
29183
+ track,
29184
+ dataSource,
29185
+ dataSourceConfig,
29186
+ maxTrackHeight: options === null || options === void 0 ? void 0 : options.maxTrackHeight,
29187
+ metadata: options === null || options === void 0 ? void 0 : options.metadata,
29188
+ searchable: (_a = options === null || options === void 0 ? void 0 : options.searchable) !== null && _a !== void 0 ? _a : true,
29189
+ searchableFields: options === null || options === void 0 ? void 0 : options.searchableFields,
29190
+ };
29191
+ }
29017
29192
  function createInteractionTrack(ctx, url, options) {
29018
29193
  var _a;
29019
29194
  const { canvas } = ctx.canvasProvider.createCanvas(0, 0);
@@ -29363,10 +29538,10 @@ class HeadlessGenomeBrowser {
29363
29538
  }
29364
29539
  // ─── Track lifecycle ─────────────────────────────────────────────────────
29365
29540
  /** Add a track with an optional data source for automatic data management. */
29366
- addTrack(track, dataSource, dataSourceConfig, maxTrackHeight, order) {
29541
+ addTrack(track, dataSource, dataSourceConfig, maxTrackHeight, order, id) {
29367
29542
  var _a;
29368
29543
  this._snapshotForUndo('track-add');
29369
- const id = generateTrackId(track.type);
29544
+ id !== null && id !== void 0 ? id : (id = generateTrackId(track.type));
29370
29545
  const mt = {
29371
29546
  id,
29372
29547
  track,
@@ -30245,11 +30420,9 @@ class HeadlessGenomeBrowser {
30245
30420
  if (!this.dataSourceWorkerProvider && dataSource) {
30246
30421
  wireDataSource(dataSource, ctx);
30247
30422
  }
30248
- this.addTrack(created.track, dataSource !== null && dataSource !== void 0 ? dataSource : undefined, (_a = created.dataSourceConfig) !== null && _a !== void 0 ? _a : undefined, undefined, (_b = created.order) !== null && _b !== void 0 ? _b : undefined);
30423
+ this.addTrack(created.track, dataSource !== null && dataSource !== void 0 ? dataSource : undefined, (_a = created.dataSourceConfig) !== null && _a !== void 0 ? _a : undefined, undefined, (_b = created.order) !== null && _b !== void 0 ? _b : undefined, trackConfig.id);
30249
30424
  // Restore bookkeeping fields for round-trip serialization
30250
30425
  const mt = this.findMT(created.track);
30251
- if (trackConfig.id)
30252
- mt.id = trackConfig.id;
30253
30426
  if (created.name)
30254
30427
  mt.name = created.name;
30255
30428
  if (trackConfig.metadata)
@@ -30335,10 +30508,8 @@ class HeadlessGenomeBrowser {
30335
30508
  wireDataSource(dataSource, ctx);
30336
30509
  }
30337
30510
  }
30338
- this.addTrack(created.track, dataSource !== null && dataSource !== void 0 ? dataSource : undefined, dataSourceConfig !== null && dataSourceConfig !== void 0 ? dataSourceConfig : undefined, undefined, (_a = created.order) !== null && _a !== void 0 ? _a : undefined);
30511
+ this.addTrack(created.track, dataSource !== null && dataSource !== void 0 ? dataSource : undefined, dataSourceConfig !== null && dataSourceConfig !== void 0 ? dataSourceConfig : undefined, undefined, (_a = created.order) !== null && _a !== void 0 ? _a : undefined, trackConfig.id);
30339
30512
  const mt = this.findMT(created.track);
30340
- if (trackConfig.id)
30341
- mt.id = trackConfig.id;
30342
30513
  if (created.name)
30343
30514
  mt.name = created.name;
30344
30515
  if (trackConfig.metadata)
@@ -30397,6 +30568,10 @@ class HeadlessGenomeBrowser {
30397
30568
  addBedTrack(url, options) {
30398
30569
  return this.registerFactory(createBedTrack(this.factoryContext(), url, options));
30399
30570
  }
30571
+ /** Add a BigBed annotation track from a URL. */
30572
+ addBigBedTrack(url, options) {
30573
+ return this.registerFactory(createBigBedTrack(this.factoryContext(), url, options));
30574
+ }
30400
30575
  /** Add an interaction (arc/BEDPE) track from a URL. */
30401
30576
  addInteractionTrack(url, options) {
30402
30577
  return this.registerFactory(createInteractionTrack(this.factoryContext(), url, options));
@@ -35876,8 +36051,12 @@ function createFeatureSource(config) {
35876
36051
  const windowFunction = (_d = config.windowFunction) !== null && _d !== void 0 ? _d : 'mean';
35877
36052
  dataSource = new GtxDataSource(config.url, (_e = config.experimentId) !== null && _e !== void 0 ? _e : '', windowFunction);
35878
36053
  }
36054
+ else if (isBigBedFormat(format)) {
36055
+ // BigBed → BigBedDataSource (annotation features)
36056
+ dataSource = new BigBedDataSource(config.url);
36057
+ }
35879
36058
  else if (isBinaryFormat(format)) {
35880
- // BigWig/BigBed → BigWigDataSource
36059
+ // BigWig → BigWigDataSource (quantitative features)
35881
36060
  const windowFunction = (_f = config.windowFunction) !== null && _f !== void 0 ? _f : 'mean';
35882
36061
  dataSource = new BigWigDataSource(config.url, windowFunction);
35883
36062
  }
@@ -35895,4 +36074,4 @@ function createFeatureSource(config) {
35895
36074
  return { dataSource, trackType, format };
35896
36075
  }
35897
36076
 
35898
- export { AnnotationTrackCanvas, AuthProviderChain, BaseCompositeTrack, BaseTrackCanvas, BigBedAnnotationSource, BigWigDataSource, BigWigReader, BrowserEvent, C2S, CSS_VAR_NAMES, ChromAliasBB, ChromAliasDefaults, ChromAliasFile, CommandDispatcher, CommandError, CredentialStore, DEFAULT_BPP_SEQUENCE_THRESHOLD, DEFAULT_SEARCHABLE_FIELDS, DOMCanvasProvider, DefaultContextMenuProvider, DefaultPopupProvider, EventEmitter, FeatureCache, FeatureNameIndex, GeneDataSource, GenomeBrowser, GoogleAuthManager, GoogleAuthProvider, GtxDataSource, GtxReader, HeadlessGenomeBrowser, IdeogramTrackCanvas, InteractionTrackCanvas, IntervalTree, LoomBrowserShell, LoomChromosomeSelect, LoomContextMenu, LoomExportControls, LoomInputDialog, LoomLocusInput, LoomNavbar, LoomPopup, LoomWindowSize, LoomZoomControls, MainThreadProvider, MemoryDataSource, MergedDataSource, MergedFeatureCollection, MergedTrackCanvas, NodeWorkerProvider, PeakOverlayTrackCanvas, READY_STATE_OPEN, ROISet, ROI_DEFAULT_COLOR, ROI_USER_DEFINED_COLOR, RemoteConnection, RulerTrackCanvas, SESSION_VERSION, SequenceDataSource, SequenceTrackCanvas, StateProjection, TabixReader, TextFeatureSource, TrackFeatureLRU, UndoManager, WebWorkerPool, WebWorkerProvider, WigGroupDataSource, WigGroupFeatureCollection, WigGroupTrackCanvas, WigTrackCanvas, WorkerDataSource, addCaseAliases, addGoogleApiKey, aggregateWigFeatures, assembleGFFTranscripts, autoThemeCSS, bufferLocus, buildFetchFromCredentials, cacheCoversViewport, clampLocus, classicThemeCSS, classicThemeValues, clearBigWigCache, clearFastaCache, clearGenomeRegistry, clearGtxCache, clearTwoBitCache, commonContextMenuItems, complementBase, complementSequence, computeCumulativeOffsets, computeWigDataRange, createAuthenticatedFetch, createBrowser, createCachedSequence, createDefaultContextMenuProvider, createDefaultPopupProvider, createFastaSequenceProvider, createFeatureSource, createGenome, createGenomeSync, createReferenceFrame, createShell, createTrackFromConfig, createTrackFromSession, createTwoBitSequenceProvider, createWorkerAuthFetch, darkRenderTheme, darkThemeValues, dataSourceCacheKey, decodeBed, decodeBedGraph, decodeBedpe, decodeBroadPeak, decodeGFF3, decodeGFFAttribute, decodeGTF, decodeGappedPeak, decodeGenePred, decodeGenePredExt, decodeInteract, decodeNarrowPeak, decodeRefGeneJson, decodeRefflat, defaultCanvasProvider, defaultNucleotideColors, defaultRenderTheme, drawLetterGlyph, encodeGCSObject, fetchBigWigFeatures, fetchBigWigWGFeatures, fetchCytobands, fetchFastaChromSizes, fetchFastaSequenceNames, fetchGeneFeatures, fetchGtxFeatures, fetchGtxMultiFeatures, fetchGtxWGFeatures, fetchSequence, fetchTwoBitChromSizes, fetchTwoBitSequenceNames, findUTRs, fixBedPE, formatBpLength, formatLocus, fromIgvSession, generateCSSVariableBlock, generateFrameId, generateROIId, genomeToChromCoord, getChromLength, getCodingEnd, getCodingLength, getCodingStart, getDecoder, getDriveDownloadURL, getGoogleDriveFileID, getKnownGenome, getKnownGenomes, getLogLevel, getThemeCSS, getTrackCreator, hg38ChromSizes, hg38Genome, inferFormatFromPath, inferIndexURL, inferTrackType, initializeGenomeRegistry, isBinaryFormat, isCoding, isExon, isGoogleDriveURL, isGoogleStorageSigned, isGoogleStorageURL, isGoogleURL, isHiccups, isIntron, isKnownDataSourceType, isLikelyIndexed, isMainChromosome, isTranscript, isTranscriptPart, isUTR, isValidHGVS, isWholeGenomeView, isZoomAware, knownFileExtensions, knownTrackTypes, lineWigConfig, mainChromosomeNames, mainThreadProvider, matchesSelector, mergeThemeFromCSS, modernRenderTheme, modernThemeCSS, modernThemeValues, normalizeWigGroupRawArrays, numericDataMenuItems, packFeatures, parseBucketName, parseChromSizes, parseColorString, parseCytobandLine, parseCytobands, parseFeatures, parseGFFAttributes, parseHeader, parseLocus, parseSearchResults, parseStrand, peakPopupData, positionString, prettyPrintNumber, recalcBpPerPixel, registerTrackCreator, registerTypeAlias, renderAnnotationTrack, renderDOMBrowserSVG, renderDynSeqFeature, renderIdeogram, renderInteractionTrack, renderPeakOverlay, renderQuantitativeAxis, renderROIOverlays, renderRulerTrack, renderSequenceTrack, renderTrackNameLabel, renderViewportIndicator, renderWholeGenomeRuler, renderWigTrack, resolveAnnotationConfig, resolveDataSourceConfig, resolveGenomeConfig, resolveIdeogramConfig, resolveInteractionConfig, resolvePeakOverlayConfig, resolveRulerConfig, resolveSequenceConfig, resolveTheme, resolveThemeFromCSSVariables, resolveToken, resolveWigConfig, resolveWigGroupConfig, reverseComplementSequence, roiContextMenuItems, searchHGVS, searchWebService, selectTracks, setLogLevel, summarizeWigData, svgToPNG, toIgvSession, toTrackSelector, translateGoogleCloudURL, translateSequence, translationDict, triggerDownload, warmWigConfig, wildcardMatch, wildcardToRegExp };
36077
+ export { AnnotationTrackCanvas, AuthProviderChain, BaseCompositeTrack, BaseTrackCanvas, BigBedAnnotationSource, BigBedDataSource, BigWigDataSource, BigWigReader, BrowserEvent, C2S, CSS_VAR_NAMES, ChromAliasBB, ChromAliasDefaults, ChromAliasFile, CommandDispatcher, CommandError, CredentialStore, DEFAULT_BPP_SEQUENCE_THRESHOLD, DEFAULT_SEARCHABLE_FIELDS, DOMCanvasProvider, DefaultContextMenuProvider, DefaultPopupProvider, EventEmitter, FeatureCache, FeatureNameIndex, GeneDataSource, GenomeBrowser, GoogleAuthManager, GoogleAuthProvider, GtxDataSource, GtxReader, HeadlessGenomeBrowser, IdeogramTrackCanvas, InteractionTrackCanvas, IntervalTree, LoomBrowserShell, LoomChromosomeSelect, LoomContextMenu, LoomExportControls, LoomInputDialog, LoomLocusInput, LoomNavbar, LoomPopup, LoomWindowSize, LoomZoomControls, MainThreadProvider, MemoryDataSource, MergedDataSource, MergedFeatureCollection, MergedTrackCanvas, NodeWorkerProvider, PeakOverlayTrackCanvas, READY_STATE_OPEN, ROISet, ROI_DEFAULT_COLOR, ROI_USER_DEFINED_COLOR, RemoteConnection, RulerTrackCanvas, SESSION_VERSION, SequenceDataSource, SequenceTrackCanvas, StateProjection, TabixReader, TextFeatureSource, TrackFeatureLRU, UndoManager, WebWorkerPool, WebWorkerProvider, WigGroupDataSource, WigGroupFeatureCollection, WigGroupTrackCanvas, WigTrackCanvas, WorkerDataSource, addCaseAliases, addGoogleApiKey, aggregateWigFeatures, assembleGFFTranscripts, autoThemeCSS, bufferLocus, buildFetchFromCredentials, cacheCoversViewport, clampLocus, classicThemeCSS, classicThemeValues, clearBigWigCache, clearFastaCache, clearGenomeRegistry, clearGtxCache, clearTwoBitCache, commonContextMenuItems, complementBase, complementSequence, computeCumulativeOffsets, computeWigDataRange, createAuthenticatedFetch, createBrowser, createCachedSequence, createDefaultContextMenuProvider, createDefaultPopupProvider, createFastaSequenceProvider, createFeatureSource, createGenome, createGenomeSync, createReferenceFrame, createShell, createTrackFromConfig, createTrackFromSession, createTwoBitSequenceProvider, createWorkerAuthFetch, darkRenderTheme, darkThemeValues, dataSourceCacheKey, decodeBed, decodeBedGraph, decodeBedpe, decodeBroadPeak, decodeGFF3, decodeGFFAttribute, decodeGTF, decodeGappedPeak, decodeGenePred, decodeGenePredExt, decodeInteract, decodeNarrowPeak, decodeRefGeneJson, decodeRefflat, defaultCanvasProvider, defaultNucleotideColors, defaultRenderTheme, drawLetterGlyph, encodeGCSObject, fetchBigWigFeatures, fetchBigWigWGFeatures, fetchCytobands, fetchFastaChromSizes, fetchFastaSequenceNames, fetchGeneFeatures, fetchGtxFeatures, fetchGtxMultiFeatures, fetchGtxWGFeatures, fetchSequence, fetchTwoBitChromSizes, fetchTwoBitSequenceNames, findUTRs, fixBedPE, formatBpLength, formatLocus, fromIgvSession, generateCSSVariableBlock, generateFrameId, generateROIId, genomeToChromCoord, getChromLength, getCodingEnd, getCodingLength, getCodingStart, getDecoder, getDriveDownloadURL, getGoogleDriveFileID, getKnownGenome, getKnownGenomes, getLogLevel, getThemeCSS, getTrackCreator, hg38ChromSizes, hg38Genome, inferFormatFromPath, inferIndexURL, inferTrackType, initializeGenomeRegistry, isBinaryFormat, isCoding, isExon, isGoogleDriveURL, isGoogleStorageSigned, isGoogleStorageURL, isGoogleURL, isHiccups, isIntron, isKnownDataSourceType, isLikelyIndexed, isMainChromosome, isTranscript, isTranscriptPart, isUTR, isValidHGVS, isWholeGenomeView, isZoomAware, knownFileExtensions, knownTrackTypes, lineWigConfig, mainChromosomeNames, mainThreadProvider, matchesSelector, mergeThemeFromCSS, modernRenderTheme, modernThemeCSS, modernThemeValues, normalizeWigGroupRawArrays, numericDataMenuItems, packFeatures, parseBucketName, parseChromSizes, parseColorString, parseCytobandLine, parseCytobands, parseFeatures, parseGFFAttributes, parseHeader, parseLocus, parseSearchResults, parseStrand, peakPopupData, positionString, prettyPrintNumber, recalcBpPerPixel, registerTrackCreator, registerTypeAlias, renderAnnotationTrack, renderDOMBrowserSVG, renderDynSeqFeature, renderIdeogram, renderInteractionTrack, renderPeakOverlay, renderQuantitativeAxis, renderROIOverlays, renderRulerTrack, renderSequenceTrack, renderTrackNameLabel, renderViewportIndicator, renderWholeGenomeRuler, renderWigTrack, resolveAnnotationConfig, resolveDataSourceConfig, resolveGenomeConfig, resolveIdeogramConfig, resolveInteractionConfig, resolvePeakOverlayConfig, resolveRulerConfig, resolveSequenceConfig, resolveTheme, resolveThemeFromCSSVariables, resolveToken, resolveWigConfig, resolveWigGroupConfig, reverseComplementSequence, roiContextMenuItems, searchHGVS, searchWebService, selectTracks, setLogLevel, summarizeWigData, svgToPNG, toIgvSession, toTrackSelector, translateGoogleCloudURL, translateSequence, translationDict, triggerDownload, warmWigConfig, wildcardMatch, wildcardToRegExp };