@jbrowse/plugin-linear-genome-view 4.1.3 → 4.1.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 (42) hide show
  1. package/esm/BaseLinearDisplay/components/FloatingLabels.js +3 -4
  2. package/esm/BaseLinearDisplay/components/LoadingOverlay.d.ts +2 -1
  3. package/esm/BaseLinearDisplay/components/LoadingOverlay.js +2 -2
  4. package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.d.ts +1 -0
  5. package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.js +2 -2
  6. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +1 -0
  7. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +1 -1
  8. package/esm/BaseLinearDisplay/components/util.d.ts +8 -8
  9. package/esm/BaseLinearDisplay/components/util.js +25 -35
  10. package/esm/BaseLinearDisplay/model.d.ts +18 -8
  11. package/esm/BaseLinearDisplay/models/SvgFloatingLabels.d.ts +8 -0
  12. package/esm/BaseLinearDisplay/models/SvgFloatingLabels.js +19 -0
  13. package/esm/BaseLinearDisplay/models/configSchema.d.ts +2 -2
  14. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -0
  15. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +3 -0
  16. package/esm/BaseLinearDisplay/models/util.d.ts +0 -13
  17. package/esm/BaseLinearDisplay/renderSvg.js +8 -4
  18. package/esm/BaseLinearDisplay/types.d.ts +0 -4
  19. package/esm/BasicTrack/configSchema.d.ts +8 -8
  20. package/esm/FeatureTrack/configSchema.d.ts +8 -8
  21. package/esm/LinearBareDisplay/configSchema.d.ts +3 -3
  22. package/esm/LinearBareDisplay/model.d.ts +18 -8
  23. package/esm/LinearBasicDisplay/configSchema.d.ts +3 -3
  24. package/esm/LinearBasicDisplay/model.d.ts +18 -8
  25. package/esm/LinearFeatureDisplay/configSchema.d.ts +3 -3
  26. package/esm/LinearFeatureDisplay/model.d.ts +22 -10
  27. package/esm/LinearGenomeView/components/ExportSvgDialog.js +18 -6
  28. package/esm/LinearGenomeView/components/SearchResultsTable.js +2 -7
  29. package/esm/LinearGenomeView/lazyDialogs.d.ts +23 -0
  30. package/esm/LinearGenomeView/lazyDialogs.js +5 -0
  31. package/esm/LinearGenomeView/menuItems.js +1 -5
  32. package/esm/LinearGenomeView/model.d.ts +2 -1
  33. package/esm/LinearGenomeView/model.js +64 -13
  34. package/esm/LinearGenomeView/types.d.ts +1 -0
  35. package/esm/index.d.ts +23 -12
  36. package/esm/index.js +1 -0
  37. package/esm/searchUtils.js +4 -1
  38. package/package.json +5 -5
  39. package/esm/BaseLinearDisplay/models/calculateLabelPositions.d.ts +0 -24
  40. package/esm/BaseLinearDisplay/models/calculateLabelPositions.js +0 -60
  41. package/esm/BaseLinearDisplay/models/renderSvg.d.ts +0 -3
  42. package/esm/BaseLinearDisplay/models/renderSvg.js +0 -55
@@ -0,0 +1,23 @@
1
+ export declare const ReturnToImportFormDialog: import("react").LazyExoticComponent<({ model, handleClose, }: {
2
+ model: {
3
+ clearView: () => void;
4
+ };
5
+ handleClose: () => void;
6
+ }) => import("react/jsx-runtime").JSX.Element>;
7
+ export declare const SequenceSearchDialog: import("react").LazyExoticComponent<({ model, handleClose, }: {
8
+ model: {
9
+ assemblyNames: string[];
10
+ showTrack: (trackId: string) => void;
11
+ };
12
+ handleClose: () => void;
13
+ }) => import("react/jsx-runtime").JSX.Element>;
14
+ export declare const ExportSvgDialog: import("react").LazyExoticComponent<typeof import("./components/ExportSvgDialog.tsx").default>;
15
+ export declare const GetSequenceDialog: import("react").LazyExoticComponent<({ model, handleClose, }: {
16
+ model: {
17
+ leftOffset?: import("./types.ts").BpOffset;
18
+ rightOffset?: import("./types.ts").BpOffset;
19
+ getSelectedRegions: (left?: import("./types.ts").BpOffset, right?: import("./types.ts").BpOffset) => import("@jbrowse/core/util").Region[];
20
+ setOffsets: (left?: import("./types.ts").BpOffset, right?: import("./types.ts").BpOffset) => void;
21
+ };
22
+ handleClose: () => void;
23
+ }) => import("react/jsx-runtime").JSX.Element>;
@@ -0,0 +1,5 @@
1
+ import { lazy } from 'react';
2
+ export const ReturnToImportFormDialog = lazy(() => import('@jbrowse/core/ui/ReturnToImportFormDialog'));
3
+ export const SequenceSearchDialog = lazy(() => import("./components/SequenceSearchDialog.js"));
4
+ export const ExportSvgDialog = lazy(() => import("./components/ExportSvgDialog.js"));
5
+ export const GetSequenceDialog = lazy(() => import("./components/GetSequenceDialog.js"));
@@ -1,4 +1,3 @@
1
- import { lazy } from 'react';
2
1
  import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons';
3
2
  import { getSession, isSessionWithAddTracks, toLocale, } from '@jbrowse/core/util';
4
3
  import CenterFocusStrongIcon from '@mui/icons-material/CenterFocusStrong';
@@ -12,10 +11,7 @@ import SearchIcon from '@mui/icons-material/Search';
12
11
  import SyncAltIcon from '@mui/icons-material/SyncAlt';
13
12
  import VisibilityIcon from '@mui/icons-material/Visibility';
14
13
  import ZoomInIcon from '@mui/icons-material/ZoomIn';
15
- const ReturnToImportFormDialog = lazy(() => import('@jbrowse/core/ui/ReturnToImportFormDialog'));
16
- const SequenceSearchDialog = lazy(() => import("./components/SequenceSearchDialog.js"));
17
- const ExportSvgDialog = lazy(() => import("./components/ExportSvgDialog.js"));
18
- const GetSequenceDialog = lazy(() => import("./components/GetSequenceDialog.js"));
14
+ import { ExportSvgDialog, GetSequenceDialog, ReturnToImportFormDialog, SequenceSearchDialog, } from "./lazyDialogs.js";
19
15
  function toLocaleRounded(n) {
20
16
  return toLocale(Math.round(n));
21
17
  }
@@ -86,6 +86,8 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
86
86
  readonly trackHeightsWithResizeHandles: number;
87
87
  readonly height: number;
88
88
  readonly totalBp: number;
89
+ getNonElidedRegionCount(bpPerPx: number): number;
90
+ getInterRegionPaddingPx(bpPerPx: number): number;
89
91
  readonly maxBpPerPx: number;
90
92
  readonly minBpPerPx: number;
91
93
  readonly error: unknown;
@@ -144,7 +146,6 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
144
146
  end: number;
145
147
  }[];
146
148
  horizontalScroll(distance: number): number;
147
- center(): void;
148
149
  showAllRegions(): void;
149
150
  showAllRegionsInAssembly(assemblyName?: string): void;
150
151
  setDraggingTrackId(idx?: string): void;
@@ -21,6 +21,9 @@ import { setupKeyboardHandler } from "./keyboardHandler.js";
21
21
  import { buildMenuItems, buildRubberBandMenuItems, buildRubberbandClickMenuItems, rewriteOnClicks, } from "./menuItems.js";
22
22
  import { calculateVisibleLocStrings, expandRegion, generateLocations, parseLocStrings, } from "./util.js";
23
23
  const SearchResultsDialog = lazy(() => import("./components/SearchResultsDialog.js"));
24
+ function getCenteredOffsetPx(contentPx, viewportPx) {
25
+ return Math.round(contentPx / 2 - viewportPx / 2);
26
+ }
24
27
  export function stateModelFactory(pluginManager) {
25
28
  return types
26
29
  .compose('LinearGenomeView', BaseViewModel, types.model({
@@ -201,8 +204,29 @@ export function stateModelFactory(pluginManager) {
201
204
  get totalBp() {
202
205
  return sum(self.displayedRegions.map(r => r.end - r.start));
203
206
  },
207
+ getNonElidedRegionCount(bpPerPx) {
208
+ if (bpPerPx <= 0) {
209
+ return self.displayedRegions.length;
210
+ }
211
+ return self.displayedRegions.filter(r => (r.end - r.start) / bpPerPx >= self.minimumBlockWidth).length;
212
+ },
213
+ getInterRegionPaddingPx(bpPerPx) {
214
+ const nonElidedCount = this.getNonElidedRegionCount(bpPerPx);
215
+ const numPaddings = Math.max(0, nonElidedCount - 1);
216
+ return numPaddings * self.interRegionPaddingWidth;
217
+ },
204
218
  get maxBpPerPx() {
205
- return this.totalBp / (self.width * 0.9);
219
+ if (this.totalBp === 0 || self.width === 0) {
220
+ return 1;
221
+ }
222
+ const naiveBpPerPx = this.totalBp / (self.width * 0.9);
223
+ const totalPaddingPx = this.getInterRegionPaddingPx(naiveBpPerPx);
224
+ const targetWidth = self.width * 0.9;
225
+ const availableForBp = targetWidth - totalPaddingPx;
226
+ if (availableForBp <= 0) {
227
+ return naiveBpPerPx;
228
+ }
229
+ return this.totalBp / availableForBp;
206
230
  },
207
231
  get minBpPerPx() {
208
232
  return 1 / 50;
@@ -238,7 +262,11 @@ export function stateModelFactory(pluginManager) {
238
262
  return -self.width + rightPadding;
239
263
  },
240
264
  get displayedRegionsTotalPx() {
241
- return this.totalBp / self.bpPerPx;
265
+ if (self.bpPerPx === 0) {
266
+ return 0;
267
+ }
268
+ const totalPaddingPx = this.getInterRegionPaddingPx(self.bpPerPx);
269
+ return this.totalBp / self.bpPerPx + totalPaddingPx;
242
270
  },
243
271
  renderProps() {
244
272
  return {
@@ -462,17 +490,9 @@ export function stateModelFactory(pluginManager) {
462
490
  const newOffsetPx = self.scrollTo(self.offsetPx + distance);
463
491
  return newOffsetPx - oldOffsetPx;
464
492
  },
465
- center() {
466
- const numPaddings = Math.max(0, self.displayedRegions.length - 1);
467
- const totalPaddingPx = numPaddings * self.interRegionPaddingWidth;
468
- const totalContentPx = self.totalBp / self.bpPerPx + totalPaddingPx;
469
- const centerPx = totalContentPx / 2;
470
- const targetOffsetPx = Math.round(centerPx - self.width / 2);
471
- self.scrollTo(targetOffsetPx);
472
- },
473
493
  showAllRegions() {
474
494
  self.bpPerPx = clamp(self.maxBpPerPx, self.minBpPerPx, self.maxBpPerPx);
475
- this.center();
495
+ self.scrollTo(getCenteredOffsetPx(self.displayedRegionsTotalPx, self.width));
476
496
  },
477
497
  showAllRegionsInAssembly(assemblyName) {
478
498
  const session = getSession(self);
@@ -492,7 +512,7 @@ export function stateModelFactory(pluginManager) {
492
512
  }
493
513
  this.setDisplayedRegions(regions);
494
514
  self.zoomTo(self.maxBpPerPx);
495
- this.center();
515
+ self.scrollTo(getCenteredOffsetPx(self.displayedRegionsTotalPx, self.width));
496
516
  },
497
517
  setDraggingTrackId(idx) {
498
518
  self.draggingTrackId = idx;
@@ -522,7 +542,38 @@ export function stateModelFactory(pluginManager) {
522
542
  const { renderToSvg } = await import("./svgcomponents/SVGLinearGenomeView.js");
523
543
  const html = await renderToSvg(self, opts);
524
544
  const { saveAs } = await import('file-saver-es');
525
- saveAs(new Blob([html], { type: 'image/svg+xml' }), opts.filename || 'image.svg');
545
+ if (opts.format === 'png') {
546
+ const img = new Image();
547
+ const svgBlob = new Blob([html], { type: 'image/svg+xml' });
548
+ const url = URL.createObjectURL(svgBlob);
549
+ await new Promise((resolve, reject) => {
550
+ img.onload = () => {
551
+ const canvas = document.createElement('canvas');
552
+ canvas.width = img.width;
553
+ canvas.height = img.height;
554
+ const ctx = canvas.getContext('2d');
555
+ ctx.drawImage(img, 0, 0);
556
+ URL.revokeObjectURL(url);
557
+ canvas.toBlob(blob => {
558
+ if (blob) {
559
+ saveAs(blob, opts.filename || 'image.png');
560
+ resolve();
561
+ }
562
+ else {
563
+ reject(new Error(`Failed to create PNG. The image may be too large (${img.width}x${img.height}). Try reducing the view size or use SVG format.`));
564
+ }
565
+ }, 'image/png');
566
+ };
567
+ img.onerror = () => {
568
+ URL.revokeObjectURL(url);
569
+ reject(new Error('Failed to load SVG for PNG conversion'));
570
+ };
571
+ img.src = url;
572
+ });
573
+ }
574
+ else {
575
+ saveAs(new Blob([html], { type: 'image/svg+xml' }), opts.filename || 'image.svg');
576
+ }
526
577
  },
527
578
  }))
528
579
  .actions(self => {
@@ -11,6 +11,7 @@ export interface BpOffset {
11
11
  }
12
12
  export interface ExportSvgOptions {
13
13
  rasterizeLayers?: boolean;
14
+ format?: 'svg' | 'png';
14
15
  filename?: string;
15
16
  Wrapper?: React.FC<{
16
17
  children: React.ReactNode;
package/esm/index.d.ts CHANGED
@@ -41,6 +41,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
41
41
  statusMessage?: string;
42
42
  reactElement?: React.ReactElement;
43
43
  isRenderingPending?: boolean;
44
+ displayHeight?: number;
44
45
  };
45
46
  }) => import("react/jsx-runtime").JSX.Element;
46
47
  renderProps: any;
@@ -59,10 +60,11 @@ export default class LinearGenomeViewPlugin extends Plugin {
59
60
  beforeDestroy(): void;
60
61
  } & {
61
62
  readonly statusMessage: any;
63
+ readonly displayHeight: number | undefined;
62
64
  } & {
63
65
  afterAttach(): void;
64
66
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
65
- configuration: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
67
+ configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
66
68
  maxFeatureScreenDensity: {
67
69
  type: string;
68
70
  description: string;
@@ -89,7 +91,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
89
91
  description: string;
90
92
  defaultValue: never[];
91
93
  };
92
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
94
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
93
95
  showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
94
96
  showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
95
97
  }, {
@@ -380,6 +382,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
380
382
  statusMessage?: string;
381
383
  reactElement?: React.ReactElement;
382
384
  isRenderingPending?: boolean;
385
+ displayHeight?: number;
383
386
  };
384
387
  }) => import("react/jsx-runtime").JSX.Element;
385
388
  renderProps: any;
@@ -398,6 +401,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
398
401
  beforeDestroy(): void;
399
402
  } & {
400
403
  readonly statusMessage: any;
404
+ readonly displayHeight: number | undefined;
401
405
  } & {
402
406
  afterAttach(): void;
403
407
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>> & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/mobx-state-tree").IMapType<import("@jbrowse/mobx-state-tree").IModelType<{
@@ -424,6 +428,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
424
428
  statusMessage?: string;
425
429
  reactElement?: React.ReactElement;
426
430
  isRenderingPending?: boolean;
431
+ displayHeight?: number;
427
432
  };
428
433
  }) => import("react/jsx-runtime").JSX.Element;
429
434
  renderProps: any;
@@ -442,6 +447,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
442
447
  beforeDestroy(): void;
443
448
  } & {
444
449
  readonly statusMessage: any;
450
+ readonly displayHeight: number | undefined;
445
451
  } & {
446
452
  afterAttach(): void;
447
453
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>>;
@@ -455,7 +461,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
455
461
  [x: string]: any;
456
462
  } & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
457
463
  } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
458
- } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
464
+ } & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
459
465
  maxFeatureScreenDensity: {
460
466
  type: string;
461
467
  description: string;
@@ -482,7 +488,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
482
488
  description: string;
483
489
  defaultValue: never[];
484
490
  };
485
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>>;
491
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>>;
486
492
  showLegend: boolean | undefined;
487
493
  showTooltips: boolean | undefined;
488
494
  } & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -772,6 +778,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
772
778
  statusMessage?: string;
773
779
  reactElement?: React.ReactElement;
774
780
  isRenderingPending?: boolean;
781
+ displayHeight?: number;
775
782
  };
776
783
  }) => import("react/jsx-runtime").JSX.Element;
777
784
  renderProps: any;
@@ -790,10 +797,11 @@ export default class LinearGenomeViewPlugin extends Plugin {
790
797
  beforeDestroy(): void;
791
798
  } & {
792
799
  readonly statusMessage: any;
800
+ readonly displayHeight: number | undefined;
793
801
  } & {
794
802
  afterAttach(): void;
795
803
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
796
- configuration: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
804
+ configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
797
805
  maxFeatureScreenDensity: {
798
806
  type: string;
799
807
  description: string;
@@ -820,7 +828,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
820
828
  description: string;
821
829
  defaultValue: never[];
822
830
  };
823
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
831
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
824
832
  showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
825
833
  showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
826
834
  }, {
@@ -1119,6 +1127,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
1119
1127
  statusMessage?: string;
1120
1128
  reactElement?: React.ReactElement;
1121
1129
  isRenderingPending?: boolean;
1130
+ displayHeight?: number;
1122
1131
  };
1123
1132
  }) => import("react/jsx-runtime").JSX.Element;
1124
1133
  renderProps: any;
@@ -1137,10 +1146,11 @@ export default class LinearGenomeViewPlugin extends Plugin {
1137
1146
  beforeDestroy(): void;
1138
1147
  } & {
1139
1148
  readonly statusMessage: any;
1149
+ readonly displayHeight: number | undefined;
1140
1150
  } & {
1141
1151
  afterAttach(): void;
1142
1152
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
1143
- configuration: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
1153
+ configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
1144
1154
  maxFeatureScreenDensity: {
1145
1155
  type: string;
1146
1156
  description: string;
@@ -1167,7 +1177,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
1167
1177
  description: string;
1168
1178
  defaultValue: never[];
1169
1179
  };
1170
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
1180
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
1171
1181
  showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
1172
1182
  showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
1173
1183
  }>>, {
@@ -1181,7 +1191,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
1181
1191
  showLegend: boolean | undefined;
1182
1192
  showTooltips: boolean | undefined;
1183
1193
  }>;
1184
- baseLinearDisplayConfigSchema: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
1194
+ baseLinearDisplayConfigSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
1185
1195
  maxFeatureScreenDensity: {
1186
1196
  type: string;
1187
1197
  description: string;
@@ -1208,7 +1218,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
1208
1218
  description: string;
1209
1219
  defaultValue: never[];
1210
1220
  };
1211
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, "displayId">>;
1221
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
1212
1222
  SearchBox: ({ model, showHelp, }: {
1213
1223
  showHelp?: boolean;
1214
1224
  model: import("./index.ts").LinearGenomeViewModel;
@@ -1220,13 +1230,13 @@ export default class LinearGenomeViewPlugin extends Plugin {
1220
1230
  model: import("./index.ts").LinearGenomeViewModel;
1221
1231
  }) => import("react/jsx-runtime").JSX.Element;
1222
1232
  };
1223
- configurationSchema: import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaType<{
1233
+ configurationSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
1224
1234
  trackLabels: {
1225
1235
  type: string;
1226
1236
  defaultValue: string;
1227
1237
  model: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
1228
1238
  };
1229
- }, import("node_modules/@jbrowse/core/src/configuration/configurationSchema.ts").ConfigurationSchemaOptions<undefined, undefined>>;
1239
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
1230
1240
  install(pluginManager: PluginManager): void;
1231
1241
  configure(pluginManager: PluginManager): void;
1232
1242
  }
@@ -1235,6 +1245,7 @@ export { configSchemaFactory as linearBareDisplayConfigSchemaFactory, stateModel
1235
1245
  export { BaseLinearDisplay, BaseLinearDisplayComponent, BlockMsg, FeatureDensityMixin, FloatingLegend, NonBlockCanvasDisplayComponent, NonBlockCanvasDisplayMixin, SVGLegend, TooLargeMessage, TrackHeightMixin, baseLinearDisplayConfigSchema, calculateSvgLegendWidth, createSubfeatureLabelMetadata, drawCanvasImageData, } from './BaseLinearDisplay/index.ts';
1236
1246
  export type { NonBlockCanvasDisplayMixinType, NonBlockCanvasDisplayModel, } from './BaseLinearDisplay/index.ts';
1237
1247
  export { type LinearGenomeViewModel, type LinearGenomeViewStateModel, RefNameAutocomplete, SearchBox, } from './LinearGenomeView/index.ts';
1248
+ export { fetchResults } from './searchUtils.ts';
1238
1249
  export type { BpOffset, ExportSvgOptions, HighlightType, InitState, NavLocation, VolatileGuide, } from './LinearGenomeView/types.ts';
1239
1250
  export { SVGGridlines, SVGRuler, SVGTracks, renderToSvg, } from './LinearGenomeView/svgcomponents/SVGLinearGenomeView.tsx';
1240
1251
  export { totalHeight } from './LinearGenomeView/svgcomponents/util.ts';
package/esm/index.js CHANGED
@@ -55,6 +55,7 @@ export default class LinearGenomeViewPlugin extends Plugin {
55
55
  export { configSchemaFactory as linearBareDisplayConfigSchemaFactory, stateModelFactory as linearBareDisplayStateModelFactory, } from "./LinearBareDisplay/index.js";
56
56
  export { BaseLinearDisplay, BaseLinearDisplayComponent, BlockMsg, FeatureDensityMixin, FloatingLegend, NonBlockCanvasDisplayComponent, NonBlockCanvasDisplayMixin, SVGLegend, TooLargeMessage, TrackHeightMixin, baseLinearDisplayConfigSchema, calculateSvgLegendWidth, createSubfeatureLabelMetadata, drawCanvasImageData, } from "./BaseLinearDisplay/index.js";
57
57
  export { RefNameAutocomplete, SearchBox, } from "./LinearGenomeView/index.js";
58
+ export { fetchResults } from "./searchUtils.js";
58
59
  export { SVGGridlines, SVGRuler, SVGTracks, renderToSvg, } from "./LinearGenomeView/svgcomponents/SVGLinearGenomeView.js";
59
60
  export { totalHeight } from "./LinearGenomeView/svgcomponents/util.js";
60
61
  export { configSchema as linearBasicDisplayConfigSchemaFactory, modelFactory as linearBasicDisplayModelFactory, } from "./LinearBasicDisplay/index.js";
@@ -1,5 +1,5 @@
1
1
  import BaseResult from '@jbrowse/core/TextSearch/BaseResults';
2
- import { dedupe, getSession } from '@jbrowse/core/util';
2
+ import { dedupe, getEnv, getSession } from '@jbrowse/core/util';
3
3
  export async function navToOption({ option, model, assemblyName, }) {
4
4
  const location = option.getLocation();
5
5
  const trackId = option.getTrackId();
@@ -9,6 +9,9 @@ export async function navToOption({ option, model, assemblyName, }) {
9
9
  model.showTrack(trackId);
10
10
  }
11
11
  }
12
+ const session = getSession(model);
13
+ const { pluginManager } = getEnv(session);
14
+ await pluginManager.evaluateAsyncExtensionPoint('LinearGenomeView-searchResultSelected', undefined, { session, result: option, model, assemblyName });
12
15
  }
13
16
  export async function handleSelectedRegion({ input, model, assembly, }) {
14
17
  const allRefs = assembly.allRefNamesWithLowerCase || [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-linear-genome-view",
3
- "version": "4.1.3",
3
+ "version": "4.1.4",
4
4
  "type": "module",
5
5
  "description": "JBrowse 2 linear genome view",
6
6
  "keywords": [
@@ -22,15 +22,15 @@
22
22
  ],
23
23
  "dependencies": {
24
24
  "@jbrowse/mobx-state-tree": "^5.5.0",
25
- "@mui/icons-material": "^7.3.7",
26
- "@mui/material": "^7.3.7",
25
+ "@mui/icons-material": "^7.3.8",
26
+ "@mui/material": "^7.3.8",
27
27
  "@types/file-saver-es": "^2.0.3",
28
28
  "copy-to-clipboard": "^3.3.3",
29
29
  "file-saver-es": "^2.0.5",
30
30
  "mobx": "^6.15.0",
31
31
  "mobx-react": "^9.2.1",
32
- "@jbrowse/product-core": "^4.1.3",
33
- "@jbrowse/core": "^4.1.3"
32
+ "@jbrowse/product-core": "^4.1.4",
33
+ "@jbrowse/core": "^4.1.4"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=18.0.0",
@@ -1,24 +0,0 @@
1
- import type { LinearGenomeViewModel } from '../../LinearGenomeView/index.ts';
2
- import type { BaseLinearDisplayModel } from '../model.ts';
3
- import type { Assembly } from '@jbrowse/core/assemblyManager/assembly';
4
- export interface RenderProps {
5
- rendererType: any;
6
- renderArgs: Record<string, any>;
7
- renderProps: Record<string, any>;
8
- displayError: unknown;
9
- rpcManager: {
10
- call: (...args: unknown[]) => void;
11
- };
12
- cannotBeRenderedReason: string;
13
- }
14
- export interface LabelData {
15
- key: string;
16
- label: string;
17
- description: string;
18
- leftPos: number;
19
- topPos: number;
20
- }
21
- export interface ErrorProps {
22
- displayError: string;
23
- }
24
- export declare function calculateLabelPositions(model: BaseLinearDisplayModel, view: LinearGenomeViewModel, assembly: Assembly | undefined, offsetPx: number): LabelData[];
@@ -1,60 +0,0 @@
1
- import { clamp, measureText } from '@jbrowse/core/util';
2
- export function calculateLabelPositions(model, view, assembly, offsetPx) {
3
- if (!assembly) {
4
- return [];
5
- }
6
- const fontSize = 11;
7
- const result = [];
8
- for (const [key, val] of model.layoutFeatures.entries()) {
9
- if (!val?.[4]) {
10
- continue;
11
- }
12
- const [left, , right, bottom, feature] = val;
13
- const { refName, description, label, totalLayoutWidth } = feature;
14
- if (!label) {
15
- continue;
16
- }
17
- const r0 = assembly.getCanonicalRefName2(refName);
18
- const px1 = view.bpToPx({
19
- refName: r0,
20
- coord: left,
21
- })?.offsetPx;
22
- const px2 = view.bpToPx({
23
- refName: r0,
24
- coord: right,
25
- })?.offsetPx;
26
- if (px1 === undefined) {
27
- continue;
28
- }
29
- const leftPx = px2 !== undefined ? Math.min(px1, px2) : px1;
30
- const rightPx = px2 !== undefined ? Math.max(px1, px2) : px1;
31
- const labelWidth = getCachedMeasureText(label, fontSize);
32
- const effectiveRightPx = totalLayoutWidth !== undefined ? leftPx + totalLayoutWidth : rightPx;
33
- const leftPos = clamp(0, leftPx - offsetPx, effectiveRightPx - offsetPx - labelWidth);
34
- const topPos = bottom - 14 * (+!!description + +!!label);
35
- result.push({
36
- key,
37
- label,
38
- description: description || '',
39
- leftPos,
40
- topPos,
41
- });
42
- }
43
- return result;
44
- }
45
- const textMeasureCache = new Map();
46
- function getCachedMeasureText(text, fontSize) {
47
- const key = `${text}:${fontSize}`;
48
- let width = textMeasureCache.get(key);
49
- if (width === undefined) {
50
- width = measureText(text, fontSize);
51
- if (textMeasureCache.size > 500) {
52
- const firstKey = textMeasureCache.keys().next().value;
53
- if (firstKey) {
54
- textMeasureCache.delete(firstKey);
55
- }
56
- }
57
- textMeasureCache.set(key, width);
58
- }
59
- return width;
60
- }
@@ -1,3 +0,0 @@
1
- import type { BaseLinearDisplayModel } from '../model.ts';
2
- import type { ExportSvgDisplayOptions } from '../types.ts';
3
- export declare function renderBaseLinearDisplaySvg(self: BaseLinearDisplayModel, opts: ExportSvgDisplayOptions): Promise<import("react/jsx-runtime").JSX.Element>;
@@ -1,55 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Fragment } from 'react';
3
- import { ReactRendering, getContainingView, getSession, } from '@jbrowse/core/util';
4
- import { calculateLabelPositions } from "./calculateLabelPositions.js";
5
- import BlockState, { renderBlockData } from "./serverSideRenderedBlock.js";
6
- import { getId } from "./util.js";
7
- import { ErrorBox } from "../../LinearGenomeView/SVGErrorBox.js";
8
- export async function renderBaseLinearDisplaySvg(self, opts) {
9
- const { height, id } = self;
10
- const { overrideHeight } = opts;
11
- const view = getContainingView(self);
12
- const { offsetPx: viewOffsetPx, roundedDynamicBlocks, width } = view;
13
- if (self.error) {
14
- return _jsx(ErrorBox, { error: self.error, width: width, height: height });
15
- }
16
- const renderings = await Promise.all(roundedDynamicBlocks.map(async (block) => {
17
- const blockState = BlockState.create({
18
- key: block.key,
19
- region: block,
20
- });
21
- const cannotBeRenderedReason = self.regionCannotBeRenderedText(block) ||
22
- self.regionCannotBeRendered(block);
23
- if (cannotBeRenderedReason) {
24
- return [
25
- block,
26
- {
27
- reactElement: (_jsxs(_Fragment, { children: [_jsx("rect", { x: 0, y: 0, width: width, height: 20, fill: "#aaa" }), _jsx("text", { x: 0, y: 15, children: cannotBeRenderedReason })] })),
28
- },
29
- ];
30
- }
31
- const { rpcManager, renderArgs, renderProps, renderingProps, rendererType, } = renderBlockData(blockState, self);
32
- return [
33
- block,
34
- await rendererType.renderInClient(rpcManager, {
35
- ...renderArgs,
36
- ...renderProps,
37
- renderingProps,
38
- exportSVG: opts,
39
- theme: opts.theme || renderProps.theme,
40
- }),
41
- ];
42
- }));
43
- const { assemblyManager } = getSession(self);
44
- const { offsetPx } = view;
45
- const assemblyName = view.assemblyNames[0];
46
- const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined;
47
- const labelData = calculateLabelPositions(self, view, assembly, offsetPx);
48
- const labelsClipId = getId(id, 'labels');
49
- return (_jsxs(_Fragment, { children: [renderings.map(([block, rendering], index) => {
50
- const { offsetPx, widthPx } = block;
51
- const offset = offsetPx - viewOffsetPx;
52
- const clipid = getId(id, index);
53
- return (_jsxs(Fragment, { children: [_jsx("defs", { children: _jsx("clipPath", { id: clipid, children: _jsx("rect", { x: 0, y: 0, width: widthPx, height: overrideHeight || height }) }) }), _jsx("g", { transform: `translate(${offset} 0)`, children: _jsx("g", { clipPath: `url(#${clipid})`, children: _jsx(ReactRendering, { rendering: rendering }) }) })] }, `frag-${index}`));
54
- }), _jsx("defs", { children: _jsx("clipPath", { id: labelsClipId, children: _jsx("rect", { x: 0, y: 0, width: width, height: overrideHeight || height }) }) }), _jsx("g", { clipPath: `url(#${labelsClipId})`, children: labelData.map(({ key, label, description, leftPos, topPos }) => (_jsxs("g", { transform: `translate(${leftPos}, ${topPos})`, children: [_jsx("text", { x: 0, y: 11, fontSize: 11, fill: "currentColor", style: { pointerEvents: 'none' }, children: label }), description ? (_jsx("text", { x: 0, y: 25, fontSize: 11, fill: "blue", style: { pointerEvents: 'none' }, children: description })) : null] }, `label-${key}`))) })] }));
55
- }