loom-browser 0.0.3 → 0.0.4

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.
Files changed (38) hide show
  1. package/README.md +28 -3
  2. package/dist/loom-react.esm.js +13290 -0
  3. package/dist/loom-react.esm.min.js +2 -0
  4. package/dist/loom-react.esm.min.js.map +1 -0
  5. package/dist/loom.esm.js +166 -147
  6. package/dist/loom.esm.min.js +1 -1
  7. package/dist/loom.esm.min.js.map +1 -1
  8. package/dist/loom.js +165 -148
  9. package/dist/loom.min.js +1 -1
  10. package/dist/loom.min.js.map +1 -1
  11. package/dist/tsconfig.src.tsbuildinfo +1 -0
  12. package/dist/types/headlessGenomeBrowser.d.ts +8 -1
  13. package/dist/types/index.d.ts +0 -1
  14. package/dist/types/react/GenomeBrowserContext.d.ts +6 -0
  15. package/dist/types/react/LoomBrowser.d.ts +86 -0
  16. package/dist/types/react/hooks/index.d.ts +3 -0
  17. package/dist/types/react/hooks/useBrowserEvent.d.ts +7 -0
  18. package/dist/types/react/hooks/useGenomeBrowser.d.ts +7 -0
  19. package/dist/types/react/hooks/useLocus.d.ts +11 -0
  20. package/dist/types/react/hooks/useTrackManager.d.ts +11 -0
  21. package/dist/types/react/index.d.ts +7 -0
  22. package/dist/types/react/tracks/BedTrack.d.ts +14 -0
  23. package/dist/types/react/tracks/GeneTrack.d.ts +14 -0
  24. package/dist/types/react/tracks/GtxTrack.d.ts +13 -0
  25. package/dist/types/react/tracks/InteractionTrack.d.ts +12 -0
  26. package/dist/types/react/tracks/RulerTrack.d.ts +6 -0
  27. package/dist/types/react/tracks/SequenceTrack.d.ts +6 -0
  28. package/dist/types/react/tracks/WigTrack.d.ts +12 -0
  29. package/dist/types/react/tracks/index.d.ts +14 -0
  30. package/dist/types/tracks/annotation/annotationTrackCanvas.d.ts +1 -0
  31. package/dist/types/tracks/baseTrackCanvas.d.ts +2 -0
  32. package/dist/types/tracks/interaction/interactionTrackCanvas.d.ts +1 -0
  33. package/dist/types/tracks/ruler/rulerTrackCanvas.d.ts +1 -0
  34. package/dist/types/tracks/sequence/sequenceTrackCanvas.d.ts +1 -0
  35. package/dist/types/tracks/wig/wigTrackCanvas.d.ts +1 -0
  36. package/dist/types/types.d.ts +2 -0
  37. package/dist/types/ui/components/LoomBrowserShell.d.ts +9 -1
  38. package/package.json +20 -1
package/dist/loom.js CHANGED
@@ -1296,6 +1296,11 @@
1296
1296
  }
1297
1297
  return results;
1298
1298
  }
1299
+ setTheme(theme) {
1300
+ this._config = resolveAnnotationConfig(theme);
1301
+ this.background = theme.palette.background;
1302
+ this.render();
1303
+ }
1299
1304
  serializeConfig(theme) {
1300
1305
  const defaults = resolveAnnotationConfig(theme);
1301
1306
  const overrides = {};
@@ -1617,6 +1622,10 @@
1617
1622
  renderRulerTrack(ctx, this.config, rc);
1618
1623
  }
1619
1624
  }
1625
+ setTheme(theme) {
1626
+ this._config = resolveRulerConfig(theme);
1627
+ this.render();
1628
+ }
1620
1629
  serializeConfig(theme) {
1621
1630
  const defaults = resolveRulerConfig(theme);
1622
1631
  const overrides = {};
@@ -2671,6 +2680,11 @@
2671
2680
  }
2672
2681
  return [];
2673
2682
  }
2683
+ setTheme(theme) {
2684
+ const dataRange = this._config.dataRange;
2685
+ this._config = { ...resolveWigConfig(theme), dataRange };
2686
+ this.render();
2687
+ }
2674
2688
  serializeConfig(theme) {
2675
2689
  const defaults = resolveWigConfig(theme);
2676
2690
  const overrides = {};
@@ -5254,6 +5268,11 @@
5254
5268
  doRender(ctx, _width, _height, rc) {
5255
5269
  renderSequenceTrack(ctx, this._sequence, this._config, rc);
5256
5270
  }
5271
+ setTheme(theme) {
5272
+ this._config = resolveSequenceConfig(theme);
5273
+ this._theme = theme;
5274
+ this.render();
5275
+ }
5257
5276
  serializeConfig(theme) {
5258
5277
  const defaults = resolveSequenceConfig(theme);
5259
5278
  const overrides = {};
@@ -9475,6 +9494,10 @@
9475
9494
  data.push({ name: 'Type', value: feature.type });
9476
9495
  return data;
9477
9496
  }
9497
+ setTheme(theme) {
9498
+ this._config = resolveInteractionConfig(theme);
9499
+ this.render();
9500
+ }
9478
9501
  /** Serialize config for session save/restore, diffed against theme defaults. */
9479
9502
  serializeConfig(theme) {
9480
9503
  const resolved = resolveInteractionConfig(resolveTheme(theme));
@@ -10447,6 +10470,7 @@
10447
10470
  ROIChanged: 'roichanged',
10448
10471
  ROIClick: 'roiclick',
10449
10472
  ROIContextMenu: 'roicontextmenu',
10473
+ ThemeChanged: 'themechange',
10450
10474
  };
10451
10475
  /** Generate a unique track ID: "{type}-{counter}" or "track-{counter}" if type is unknown. */
10452
10476
  let nextTrackId = 0;
@@ -10454,6 +10478,7 @@
10454
10478
  return `${type !== null && type !== void 0 ? type : 'track'}-${nextTrackId++}`;
10455
10479
  }
10456
10480
  class HeadlessGenomeBrowser {
10481
+ get theme() { return this._theme; }
10457
10482
  get locus() { return this._locus; }
10458
10483
  get viewportWidth() { return this._viewportWidth; }
10459
10484
  /** Agent-friendly state projection manager. Lazily created on first access. */
@@ -10479,7 +10504,7 @@
10479
10504
  this.workerProvider = options.workerProvider;
10480
10505
  this.popupProvider = (_g = options.popupProvider) !== null && _g !== void 0 ? _g : undefined;
10481
10506
  this.contextMenuProvider = (_h = options.contextMenuProvider) !== null && _h !== void 0 ? _h : undefined;
10482
- this.theme = resolveTheme(options.theme);
10507
+ this._theme = resolveTheme(options.theme);
10483
10508
  if (options.stateProjection)
10484
10509
  this._state = options.stateProjection;
10485
10510
  }
@@ -11219,6 +11244,14 @@
11219
11244
  }
11220
11245
  return track;
11221
11246
  }
11247
+ /** Apply a new render theme to the browser and all existing tracks. */
11248
+ setTheme(theme) {
11249
+ this._theme = resolveTheme(theme);
11250
+ for (const mt of this.managedTracks) {
11251
+ mt.track.setTheme(this._theme);
11252
+ }
11253
+ this.events.emit(BrowserEvent.ThemeChanged, { theme: this._theme });
11254
+ }
11222
11255
  /** Clean up event listeners, abort in-flight requests, clear tracks and ROIs. */
11223
11256
  dispose() {
11224
11257
  this.events.removeAllListeners();
@@ -13932,6 +13965,102 @@ button svg {
13932
13965
  }
13933
13966
  }
13934
13967
 
13968
+ /**
13969
+ * Built-in RenderTheme presets.
13970
+ *
13971
+ * These are Partial<RenderTheme> objects — pass them to resolveTheme() to get
13972
+ * a fully resolved theme with defaults filled in.
13973
+ *
13974
+ * Usage:
13975
+ * import {resolveTheme} from './renderTheme'
13976
+ * import {modernRenderTheme} from './renderThemePresets'
13977
+ * const theme = resolveTheme(modernRenderTheme)
13978
+ */
13979
+ /** Modern theme — blue/pink palette, rounded exons, system font. */
13980
+ const modernRenderTheme = {
13981
+ palette: {
13982
+ primary: '#4A90D9',
13983
+ secondary: '#D94A7A',
13984
+ accent: '#4A90D9',
13985
+ background: '#ffffff',
13986
+ foreground: '#333333',
13987
+ muted: '#B0B0B0',
13988
+ },
13989
+ fontFamily: 'Inter, system-ui, sans-serif',
13990
+ annotation: {
13991
+ utrColor: '#A8C8E8',
13992
+ altUtrColor: '#E8A8BE',
13993
+ borderColor: 'rgba(0, 0, 0, 0.15)',
13994
+ borderWidth: 0.5,
13995
+ borderRadius: 3,
13996
+ arrowInExonColor: 'rgba(255, 255, 255, 0.7)',
13997
+ labelFont: 'italic 10px Inter, system-ui, sans-serif',
13998
+ featureHeight: 12,
13999
+ expandedRowHeight: 28,
14000
+ margin: 8,
14001
+ },
14002
+ wig: {
14003
+ overflowColor: '#FF6B6B',
14004
+ },
14005
+ sequence: {
14006
+ frameColor1: 'hsl(220, 15%, 90%)',
14007
+ frameColor2: 'hsl(220, 15%, 95%)',
14008
+ startCodonColor: 'hsl(160, 55%, 42%)',
14009
+ stopCodonColor: 'hsl(0, 60%, 55%)',
14010
+ useFillText: true,
14011
+ frameLabelColor: '#444444',
14012
+ codonLabelColor: '#ffffff',
14013
+ frameFont: '600 10px Inter, system-ui, sans-serif',
14014
+ codonBorderRadius: 3,
14015
+ },
14016
+ };
14017
+ /** Dark theme — adapted for dark backgrounds, high contrast. */
14018
+ const darkRenderTheme = {
14019
+ palette: {
14020
+ primary: '#6CB4EE',
14021
+ secondary: '#EE6C9E',
14022
+ accent: '#6a9fd9',
14023
+ background: '#1a1a2e',
14024
+ foreground: '#e0e0e0',
14025
+ muted: '#555555',
14026
+ },
14027
+ nucleotideColors: {
14028
+ A: '#4ade80',
14029
+ C: '#60a5fa',
14030
+ G: '#facc15',
14031
+ T: '#f87171',
14032
+ N: '#666666',
14033
+ },
14034
+ annotation: {
14035
+ utrColor: '#3D6B8E',
14036
+ altUtrColor: '#8E3D5E',
14037
+ borderColor: 'rgba(255, 255, 255, 0.12)',
14038
+ borderWidth: 0.5,
14039
+ borderRadius: 3,
14040
+ arrowInExonColor: 'rgba(0, 0, 0, 0.4)',
14041
+ labelBackground: '#1a1a2e',
14042
+ labelFont: 'italic 10px sans-serif',
14043
+ featureHeight: 12,
14044
+ expandedRowHeight: 28,
14045
+ margin: 8,
14046
+ },
14047
+ wig: {
14048
+ overflowColor: '#FF6B6B',
14049
+ },
14050
+ sequence: {
14051
+ background: '#1a1a2e',
14052
+ frameColor1: 'hsl(230, 15%, 28%)',
14053
+ frameColor2: 'hsl(230, 15%, 22%)',
14054
+ startCodonColor: 'hsl(160, 50%, 35%)',
14055
+ stopCodonColor: 'hsl(0, 55%, 45%)',
14056
+ useFillText: true,
14057
+ frameLabelColor: '#c8c8c8',
14058
+ codonLabelColor: '#ffffff',
14059
+ frameFont: '600 10px sans-serif',
14060
+ codonBorderRadius: 3,
14061
+ },
14062
+ };
14063
+
13935
14064
  /**
13936
14065
  * <loom-browser> — Top-level shell combining navbar + GenomeBrowser.
13937
14066
  *
@@ -14039,6 +14168,19 @@ button svg {
14039
14168
  var _a;
14040
14169
  return (_a = this._browser) === null || _a === void 0 ? void 0 : _a.on(event, handler);
14041
14170
  }
14171
+ /** Switch both the UI shell theme and the render theme in one call. */
14172
+ setTheme(shellTheme) {
14173
+ this.applyTheme(shellTheme);
14174
+ this.setAttribute('theme', shellTheme);
14175
+ if (this._browser) {
14176
+ const shellToRenderTheme = {
14177
+ modern: modernRenderTheme,
14178
+ dark: darkRenderTheme,
14179
+ };
14180
+ const mapped = shellToRenderTheme[shellTheme];
14181
+ this._browser.setTheme(mapped !== null && mapped !== void 0 ? mapped : {});
14182
+ }
14183
+ }
14042
14184
  disconnectedCallback() {
14043
14185
  if (this._browser) {
14044
14186
  this._browser.dispose();
@@ -14055,12 +14197,31 @@ button svg {
14055
14197
  if (!customElements.get('loom-browser')) {
14056
14198
  customElements.define('loom-browser', LoomBrowserShell);
14057
14199
  }
14200
+ const { shellTheme, ruler, genes, sequence, ...browserOptions } = options;
14201
+ // Auto-map shellTheme to matching RenderTheme when theme is not explicitly set
14202
+ if (shellTheme && !browserOptions.theme) {
14203
+ const shellToRenderTheme = {
14204
+ modern: modernRenderTheme,
14205
+ dark: darkRenderTheme,
14206
+ };
14207
+ const mapped = shellToRenderTheme[shellTheme];
14208
+ if (mapped) {
14209
+ browserOptions.theme = mapped;
14210
+ }
14211
+ }
14058
14212
  const shell = document.createElement('loom-browser');
14059
- if (options.shellTheme) {
14060
- shell.setAttribute('theme', options.shellTheme);
14213
+ if (shellTheme) {
14214
+ shell.setAttribute('theme', shellTheme);
14061
14215
  }
14062
14216
  container.appendChild(shell);
14063
- shell.initialize(options);
14217
+ const browser = shell.initialize(browserOptions);
14218
+ // Add default tracks
14219
+ if (ruler !== false)
14220
+ browser.addRuler();
14221
+ if (genes !== false)
14222
+ browser.addGeneTrack({ maxTrackHeight: 150 });
14223
+ if (sequence === true)
14224
+ browser.addSequenceTrack();
14064
14225
  return shell;
14065
14226
  }
14066
14227
 
@@ -14652,148 +14813,6 @@ tr.border-top td {
14652
14813
  customElements.define('loom-browser', LoomBrowserShell);
14653
14814
  }
14654
14815
 
14655
- /**
14656
- * Built-in RenderTheme presets.
14657
- *
14658
- * These are Partial<RenderTheme> objects — pass them to resolveTheme() to get
14659
- * a fully resolved theme with defaults filled in.
14660
- *
14661
- * Usage:
14662
- * import {resolveTheme} from './renderTheme'
14663
- * import {modernRenderTheme} from './renderThemePresets'
14664
- * const theme = resolveTheme(modernRenderTheme)
14665
- */
14666
- /** Modern theme — blue/pink palette, rounded exons, system font. */
14667
- const modernRenderTheme = {
14668
- palette: {
14669
- primary: '#4A90D9',
14670
- secondary: '#D94A7A',
14671
- accent: '#4A90D9',
14672
- background: '#ffffff',
14673
- foreground: '#333333',
14674
- muted: '#B0B0B0',
14675
- },
14676
- fontFamily: 'Inter, system-ui, sans-serif',
14677
- annotation: {
14678
- utrColor: '#A8C8E8',
14679
- altUtrColor: '#E8A8BE',
14680
- borderColor: 'rgba(0, 0, 0, 0.15)',
14681
- borderWidth: 0.5,
14682
- borderRadius: 3,
14683
- arrowInExonColor: 'rgba(255, 255, 255, 0.7)',
14684
- labelFont: 'italic 10px Inter, system-ui, sans-serif',
14685
- featureHeight: 12,
14686
- expandedRowHeight: 28,
14687
- margin: 8,
14688
- },
14689
- wig: {
14690
- overflowColor: '#FF6B6B',
14691
- },
14692
- sequence: {
14693
- frameColor1: 'hsl(220, 15%, 90%)',
14694
- frameColor2: 'hsl(220, 15%, 95%)',
14695
- startCodonColor: 'hsl(160, 55%, 42%)',
14696
- stopCodonColor: 'hsl(0, 60%, 55%)',
14697
- useFillText: true,
14698
- frameLabelColor: '#444444',
14699
- codonLabelColor: '#ffffff',
14700
- frameFont: '600 10px Inter, system-ui, sans-serif',
14701
- codonBorderRadius: 3,
14702
- },
14703
- };
14704
- /** Dark theme — adapted for dark backgrounds, high contrast. */
14705
- const darkRenderTheme = {
14706
- palette: {
14707
- primary: '#6CB4EE',
14708
- secondary: '#EE6C9E',
14709
- accent: '#6a9fd9',
14710
- background: '#1a1a2e',
14711
- foreground: '#e0e0e0',
14712
- muted: '#555555',
14713
- },
14714
- nucleotideColors: {
14715
- A: '#4ade80',
14716
- C: '#60a5fa',
14717
- G: '#facc15',
14718
- T: '#f87171',
14719
- N: '#666666',
14720
- },
14721
- annotation: {
14722
- utrColor: '#3D6B8E',
14723
- altUtrColor: '#8E3D5E',
14724
- borderColor: 'rgba(255, 255, 255, 0.12)',
14725
- borderWidth: 0.5,
14726
- borderRadius: 3,
14727
- arrowInExonColor: 'rgba(0, 0, 0, 0.4)',
14728
- labelBackground: '#1a1a2e',
14729
- labelFont: 'italic 10px sans-serif',
14730
- featureHeight: 12,
14731
- expandedRowHeight: 28,
14732
- margin: 8,
14733
- },
14734
- wig: {
14735
- overflowColor: '#FF6B6B',
14736
- },
14737
- sequence: {
14738
- background: '#1a1a2e',
14739
- frameColor1: 'hsl(230, 15%, 28%)',
14740
- frameColor2: 'hsl(230, 15%, 22%)',
14741
- startCodonColor: 'hsl(160, 50%, 35%)',
14742
- stopCodonColor: 'hsl(0, 55%, 45%)',
14743
- useFillText: true,
14744
- frameLabelColor: '#c8c8c8',
14745
- codonLabelColor: '#ffffff',
14746
- frameFont: '600 10px sans-serif',
14747
- codonBorderRadius: 3,
14748
- },
14749
- };
14750
-
14751
- /**
14752
- * Preset render themes for annotation tracks.
14753
- *
14754
- * Each theme is a Partial<AnnotationRenderConfig> that can be spread over defaults.
14755
- * Usage: { ...defaultAnnotationRenderConfig(), ...modernTheme }
14756
- */
14757
- /** Modern theme — softer colors, rounded exons, strand-based coloring. */
14758
- const modernTheme = {
14759
- color: '#4A90D9',
14760
- altColor: '#D94A7A',
14761
- utrColor: '#A8C8E8',
14762
- altUtrColor: '#E8A8BE',
14763
- borderColor: 'rgba(0, 0, 0, 0.15)',
14764
- borderWidth: 0.5,
14765
- borderRadius: 3,
14766
- intronColor: '#B0B0B0',
14767
- intronLineWidth: 1,
14768
- arrowColor: '#999999',
14769
- arrowInExonColor: 'rgba(255, 255, 255, 0.7)',
14770
- labelColor: '#333333',
14771
- labelFont: 'italic 10px sans-serif',
14772
- featureHeight: 12,
14773
- expandedRowHeight: 28,
14774
- margin: 8,
14775
- };
14776
- /** Dark theme — modern theme adapted for dark backgrounds. */
14777
- const darkTheme = {
14778
- color: '#6CB4EE',
14779
- altColor: '#EE6C9E',
14780
- utrColor: '#3D6B8E',
14781
- altUtrColor: '#8E3D5E',
14782
- borderColor: 'rgba(255, 255, 255, 0.12)',
14783
- borderWidth: 0.5,
14784
- borderRadius: 3,
14785
- intronColor: '#555555',
14786
- intronLineWidth: 1,
14787
- arrowColor: '#666666',
14788
- arrowInExonColor: 'rgba(0, 0, 0, 0.4)',
14789
- labelColor: '#C8C8C8',
14790
- labelBackground: '#1a1a2e',
14791
- labelFont: 'italic 10px sans-serif',
14792
- featureHeight: 12,
14793
- expandedRowHeight: 28,
14794
- margin: 8,
14795
- };
14796
-
14797
14816
  /**
14798
14817
  * Preset render themes for wig tracks.
14799
14818
  *
@@ -15004,7 +15023,6 @@ tr.border-top td {
15004
15023
  exports.createTrackFromSession = createTrackFromSession;
15005
15024
  exports.darkRenderTheme = darkRenderTheme;
15006
15025
  exports.darkSequenceTheme = darkSequenceTheme;
15007
- exports.darkTheme = darkTheme;
15008
15026
  exports.darkWigTheme = darkWigTheme;
15009
15027
  exports.dataSourceCacheKey = dataSourceCacheKey;
15010
15028
  exports.decodeBed = decodeBed;
@@ -15073,7 +15091,6 @@ tr.border-top td {
15073
15091
  exports.matchesSelector = matchesSelector;
15074
15092
  exports.modernRenderTheme = modernRenderTheme;
15075
15093
  exports.modernSequenceTheme = modernSequenceTheme;
15076
- exports.modernTheme = modernTheme;
15077
15094
  exports.modernThemeCSS = modernThemeCSS;
15078
15095
  exports.modernWigTheme = modernWigTheme;
15079
15096
  exports.numericDataMenuItems = numericDataMenuItems;