@jbrowse/core 4.1.13 → 4.1.15

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.
@@ -1,2 +1,3 @@
1
1
  export { configSchema } from './configSchema.ts';
2
+ export type { MaybeSerializedFeat } from './types.tsx';
2
3
  export { stateModelFactory } from './stateModelFactory.ts';
@@ -6,6 +6,7 @@ export interface Feat {
6
6
  type?: string;
7
7
  name?: string;
8
8
  id?: string;
9
+ phase?: number;
9
10
  }
10
11
  export interface ParentFeat extends Feat {
11
12
  uniqueId: string;
@@ -33,6 +34,7 @@ export declare function revlist(list: Feat[], seqlen: number): {
33
34
  type?: string;
34
35
  name?: string;
35
36
  id?: string;
37
+ phase?: number;
36
38
  }[];
37
39
  export declare function calculateUTRs(cds: Feat[], exons: Feat[]): {
38
40
  type: string;
@@ -40,6 +42,7 @@ export declare function calculateUTRs(cds: Feat[], exons: Feat[]): {
40
42
  end: number;
41
43
  name?: string;
42
44
  id?: string;
45
+ phase?: number;
43
46
  }[];
44
47
  export declare function calculateUTRs2(cds: Feat[], parentFeat: Feat): {
45
48
  type: string;
@@ -12,6 +12,7 @@ export default class TextSearchManager {
12
12
  pluginManager: PluginManager;
13
13
  adapterCache: QuickLRU<string, BaseTextSearchAdapter>;
14
14
  constructor(pluginManager: PluginManager);
15
+ clearCache(): void;
15
16
  loadTextSearchAdapters(searchScope: SearchScope): Promise<BaseTextSearchAdapter[]>;
16
17
  relevantAdapters(searchScope: SearchScope): ({
17
18
  [x: string]: any;
@@ -9,6 +9,9 @@ export default class TextSearchManager {
9
9
  constructor(pluginManager) {
10
10
  this.pluginManager = pluginManager;
11
11
  }
12
+ clearCache() {
13
+ this.adapterCache.clear();
14
+ }
12
15
  loadTextSearchAdapters(searchScope) {
13
16
  return Promise.all(this.relevantAdapters(searchScope).map(async (conf) => {
14
17
  const adapterId = readConfObject(conf, 'textSearchAdapterId');
@@ -1,3 +1,4 @@
1
1
  export { default } from './assemblyManager.ts';
2
+ export type { AssemblyBaseOpts } from './assemblyManager.ts';
2
3
  export { default as assemblyConfigSchemaFactory } from './assemblyConfigSchema.ts';
3
4
  export type { BaseAssemblyConfigSchema } from './assemblyConfigSchema.ts';
@@ -0,0 +1,4 @@
1
+ export default function DOMPurifySanitizedHTML({ value, className, }: {
2
+ value: string;
3
+ className?: string;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useLayoutEffect, useRef } from 'react';
3
+ import dompurify from 'dompurify';
4
+ export default function DOMPurifySanitizedHTML({ value, className, }) {
5
+ const spanRef = useRef(null);
6
+ useLayoutEffect(() => {
7
+ const el = spanRef.current;
8
+ if (el) {
9
+ for (const a of el.querySelectorAll('a')) {
10
+ a.setAttribute('rel', 'noopener noreferrer');
11
+ a.setAttribute('target', '_blank');
12
+ }
13
+ }
14
+ }, [value]);
15
+ return (_jsx("span", { ref: spanRef, className: className, dangerouslySetInnerHTML: { __html: dompurify.sanitize(value) } }));
16
+ }
@@ -19,6 +19,6 @@ function ButtonComponent(props) {
19
19
  return (_jsx(Button, { ...props, className: classes.buttonRoot, children: props.children }));
20
20
  }
21
21
  const DropDownMenu = observer(function DropDownMenu({ menuTitle, menuItems, }) {
22
- return (_jsxs(CascadingMenuButton, { menuItems: menuItems, color: "inherit", ButtonComponent: ButtonComponent, children: [menuTitle, _jsx(ArrowDropDown, {})] }));
22
+ return (_jsxs(CascadingMenuButton, { menuItems: menuItems, color: "inherit", ButtonComponent: ButtonComponent, anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, transformOrigin: { vertical: 'top', horizontal: 'left' }, children: [menuTitle, _jsx(ArrowDropDown, {})] }));
23
23
  });
24
24
  export default DropDownMenu;
@@ -1,4 +1,3 @@
1
- import type { SvgIconProps } from '@mui/material';
2
1
  export interface MenuDivider {
3
2
  priority?: number;
4
3
  type: 'divider';
@@ -13,7 +12,7 @@ export interface BaseMenuItem {
13
12
  label: React.ReactNode;
14
13
  priority?: number;
15
14
  subLabel?: string;
16
- icon?: React.ComponentType<SvgIconProps>;
15
+ icon?: React.ElementType;
17
16
  disabled?: boolean;
18
17
  helpText?: string;
19
18
  }
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useEffect } from 'react';
3
- import dompurify from 'dompurify';
2
+ import { Suspense, lazy, useLayoutEffect, useRef } from 'react';
4
3
  import escapeHTML from 'escape-html';
5
4
  import { linkify } from "../util/index.js";
6
5
  const htmlTags = [
@@ -36,26 +35,42 @@ const htmlTags = [
36
35
  'u',
37
36
  'ul',
38
37
  ];
39
- let added = false;
38
+ const DOMPurifySanitizedHTML = lazy(() => import("./DOMPurifySanitizedHTML.js"));
40
39
  const full = new RegExp(htmlTags.map(tag => String.raw `<${tag}\b[^>]*>`).join('|'), 'i');
41
40
  function isHTML(str) {
42
41
  return full.test(str);
43
42
  }
44
- export default function SanitizedHTML({ html: pre, className, }) {
45
- const html = linkify(`${pre}`);
46
- const value = isHTML(html) ? html : escapeHTML(html);
47
- useEffect(() => {
48
- if (!added) {
49
- added = true;
50
- dompurify.addHook('afterSanitizeAttributes', node => {
51
- if (node.tagName === 'A') {
52
- node.setAttribute('rel', 'noopener noreferrer');
53
- node.setAttribute('target', '_blank');
43
+ function needsSanitization(str) {
44
+ return str.includes('<') || str.includes('://');
45
+ }
46
+ function SetHTML({ value, className }) {
47
+ const spanRef = useRef(null);
48
+ useLayoutEffect(() => {
49
+ const el = spanRef.current;
50
+ if (el) {
51
+ try {
52
+ el.setHTML(value);
53
+ for (const a of el.querySelectorAll('a')) {
54
+ a.setAttribute('rel', 'noopener noreferrer');
55
+ a.setAttribute('target', '_blank');
54
56
  }
55
- });
57
+ }
58
+ catch (e) {
59
+ console.error(e);
60
+ }
56
61
  }
57
- }, []);
58
- return (_jsx("span", { className: className, dangerouslySetInnerHTML: {
59
- __html: dompurify.sanitize(value),
60
- } }));
62
+ }, [value]);
63
+ return _jsx("span", { ref: spanRef, className: className });
64
+ }
65
+ export default function SanitizedHTML({ html: pre, className, }) {
66
+ const str = `${pre}`;
67
+ if (!needsSanitization(str)) {
68
+ return _jsx("span", { className: className, children: str });
69
+ }
70
+ const html = linkify(str);
71
+ const value = isHTML(html) ? html : escapeHTML(html);
72
+ if (typeof Element !== 'undefined' && Element.prototype.setHTML) {
73
+ return _jsx(SetHTML, { value: value, className: className });
74
+ }
75
+ return (_jsx(Suspense, { fallback: _jsx("span", { className: className }), children: _jsx(DOMPurifySanitizedHTML, { value: value, className: className }) }));
61
76
  }
@@ -107,13 +107,7 @@ export class IntervalTree {
107
107
  const searchNode = new Node(interval);
108
108
  const resultNodes = [];
109
109
  this.treeSearchInterval(this.root, searchNode, resultNodes);
110
- const results = [];
111
- for (const node of resultNodes) {
112
- for (const v of node.values) {
113
- results.push(v);
114
- }
115
- }
116
- return results;
110
+ return resultNodes.flatMap(node => node.values);
117
111
  }
118
112
  recalcMax(node) {
119
113
  let current = node;
@@ -1,8 +1,9 @@
1
1
  import { stitch } from "../BaseFeatureWidget/util.js";
2
2
  export function convertCodingSequenceToPeptides({ cds, sequence, codonTable, }) {
3
+ const phase = cds[0]?.phase ?? 0;
3
4
  const str = stitch(cds, sequence);
4
- let protein = '';
5
- for (let i = 0; i < str.length; i += 3) {
5
+ let protein = phase > 0 ? '&' : '';
6
+ for (let i = phase; i < str.length; i += 3) {
6
7
  protein += codonTable[str.slice(i, i + 3)] || '&';
7
8
  }
8
9
  return protein;
@@ -23,7 +23,7 @@ export declare function useWidthSetter(view: {
23
23
  setWidth: (arg: number) => void;
24
24
  }, padding: string): React.RefObject<HTMLDivElement | null>;
25
25
  export declare function useDebouncedCallback<T>(callback: (...args: T[]) => void, wait?: number): (...args: T[]) => void;
26
- export declare function findParentThat(node: IAnyStateTreeNode, predicate: (thing: IAnyStateTreeNode) => boolean): IStateTreeNode<IAnyStateTreeNode>;
26
+ export declare function findParentThat(node: IAnyStateTreeNode, predicate: (thing: IAnyStateTreeNode) => boolean): (object & IStateTreeNode<import("@jbrowse/mobx-state-tree").IAnyComplexType>) | IStateTreeNode<IAnyStateTreeNode>;
27
27
  export declare function springAnimate(fromValue: number, toValue: number, setValue: (value: number) => void, onFinish?: () => void, precision?: number, tension?: number, friction?: number, clamp?: boolean): (() => void)[];
28
28
  export declare function findParentThatIs<T extends (a: IAnyStateTreeNode) => boolean>(node: IAnyStateTreeNode, predicate: T): TypeTestedByPredicate<T>;
29
29
  export declare function getSession(node: IAnyStateTreeNode): AbstractSessionModel;
@@ -55,7 +55,7 @@ export declare function calculateLayoutBounds(featureStart: number, featureEnd:
55
55
  export declare function iterMap<T, U>(iter: Iterable<T>, func: (arg: T) => U, sizeHint?: number): U[];
56
56
  export declare function findLastIndex<T>(array: T[], predicate: (value: T, index: number, obj: T[]) => boolean): number;
57
57
  export declare function findLast<T>(array: T[], predicate: (value: T, index: number, obj: T[]) => boolean): T | undefined;
58
- export declare function renameRegionIfNeeded(refNameMap: Record<string, string> | undefined, region: Region | Instance<typeof MUIRegion>): Region & {
58
+ export declare function renameRegionIfNeeded(refNameMap: Record<string, string> | undefined, region: Region | Instance<typeof MUIRegion>, getSeqAdapterRefName?: (refName: string) => string): Region & {
59
59
  originalRefName?: string;
60
60
  };
61
61
  export declare function renameRegionsIfNeeded<ARGTYPE extends {
package/esm/util/index.js CHANGED
@@ -336,22 +336,17 @@ export function findLast(array, predicate) {
336
336
  }
337
337
  return undefined;
338
338
  }
339
- export function renameRegionIfNeeded(refNameMap, region) {
339
+ export function renameRegionIfNeeded(refNameMap, region, getSeqAdapterRefName) {
340
340
  if (isStateTreeNode(region) && !isAlive(region)) {
341
341
  return region;
342
342
  }
343
- if (refNameMap?.[region.refName]) {
344
- region = isStateTreeNode(region)
345
- ? { ...getSnapshot(region) }
346
- : { ...region };
347
- const newRef = refNameMap[region.refName];
348
- if (newRef) {
349
- return {
350
- ...region,
351
- refName: newRef,
352
- originalRefName: region.refName,
353
- };
354
- }
343
+ const newRef = refNameMap?.[region.refName];
344
+ if (newRef) {
345
+ return {
346
+ ...(isStateTreeNode(region) ? getSnapshot(region) : region),
347
+ refName: newRef,
348
+ originalRefName: getSeqAdapterRefName?.(region.refName) ?? region.refName,
349
+ };
355
350
  }
356
351
  return region;
357
352
  }
@@ -360,16 +355,21 @@ export async function renameRegionsIfNeeded(assemblyManager, args) {
360
355
  if (!args.sessionId) {
361
356
  throw new Error('sessionId is required');
362
357
  }
363
- const assemblyNames = regions.map(region => region.assemblyName);
364
- const assemblyMaps = Object.fromEntries(await Promise.all([...new Set(assemblyNames)].map(async (assemblyName) => {
365
- return [
366
- assemblyName,
367
- await assemblyManager.getRefNameMapForAdapter(adapterConfig, assemblyName, args),
368
- ];
369
- })));
358
+ const assemblyNames = regions.map(r => r.assemblyName);
359
+ const uniqueAssemblyNames = [...new Set(assemblyNames)];
360
+ const assemblyData = Object.fromEntries(await Promise.all(uniqueAssemblyNames.map(async (name) => [
361
+ name,
362
+ {
363
+ refNameMap: await assemblyManager.getRefNameMapForAdapter(adapterConfig, name, args),
364
+ assembly: assemblyManager.get(name),
365
+ },
366
+ ])));
370
367
  return {
371
368
  ...args,
372
- regions: regions.map((region, i) => renameRegionIfNeeded(assemblyMaps[assemblyNames[i]], region)),
369
+ regions: regions.map((region, i) => {
370
+ const { refNameMap, assembly } = assemblyData[assemblyNames[i]];
371
+ return renameRegionIfNeeded(refNameMap, region, assembly ? r => assembly.getSeqAdapterRefName(r) : undefined);
372
+ }),
373
373
  };
374
374
  }
375
375
  export function minmax(a, b) {
@@ -1,15 +1,7 @@
1
1
  import { RemoteFile } from 'generic-filehandle2';
2
- export interface BinaryRangeResponse {
3
- headers: Record<string, string>;
4
- requestDate: Date;
5
- responseDate: Date;
6
- buffer: Uint8Array;
7
- }
8
2
  export declare function clearCache(): void;
9
3
  export declare class RemoteFileWithRangeCache extends RemoteFile {
4
+ private fetchRange;
5
+ private getCachedRange;
10
6
  fetch(url: string | RequestInfo, init?: RequestInit): Promise<Response>;
11
- fetchBinaryRange(url: string, start: number, end: number, options?: {
12
- headers?: HeadersInit;
13
- stopToken?: string;
14
- }): Promise<BinaryRangeResponse>;
15
7
  }
@@ -1,71 +1,119 @@
1
- import { HttpRangeFetcher } from '@gmod/http-range-fetcher';
2
1
  import { RemoteFile } from 'generic-filehandle2';
3
- const fetchers = {};
4
- function binaryRangeFetch(url, start, end, options = {}) {
5
- const fetcher = fetchers[url];
6
- if (!fetcher) {
7
- throw new Error(`fetch not registered for ${url}`);
2
+ const MAX_CACHE_ENTRIES = 2000;
3
+ const CHUNK_SIZE = 256 * 1024;
4
+ const MAX_CONCURRENT = 20;
5
+ let cache = new Map();
6
+ let activeCount = 0;
7
+ const queue = [];
8
+ function getCached(key) {
9
+ return cache.get(key);
10
+ }
11
+ function putCached(key, buffer) {
12
+ if (cache.size >= MAX_CACHE_ENTRIES) {
13
+ const firstKey = cache.keys().next().value;
14
+ if (firstKey !== undefined) {
15
+ cache.delete(firstKey);
16
+ }
8
17
  }
9
- return fetcher(url, start, end, options);
18
+ cache.set(key, buffer);
10
19
  }
11
- const globalRangeCache = new HttpRangeFetcher({
12
- fetch: binaryRangeFetch,
13
- size: 500 * 1024 ** 2,
14
- chunkSize: 128 * 1024,
15
- maxFetchSize: 100 * 1024 ** 2,
16
- minimumTTL: 24 * 60 * 60 * 1000,
17
- });
18
20
  export function clearCache() {
19
- globalRangeCache.reset();
21
+ cache = new Map();
20
22
  }
21
- export class RemoteFileWithRangeCache extends RemoteFile {
22
- async fetch(url, init) {
23
- const str = String(url);
24
- if (!fetchers[str]) {
25
- fetchers[str] = this.fetchBinaryRange.bind(this);
23
+ function runNext() {
24
+ if (queue.length > 0 && activeCount < MAX_CONCURRENT) {
25
+ activeCount++;
26
+ const next = queue.shift();
27
+ next();
28
+ }
29
+ }
30
+ function limitConcurrency(fn) {
31
+ return new Promise((resolve, reject) => {
32
+ function run() {
33
+ fn().then(val => {
34
+ activeCount--;
35
+ resolve(val);
36
+ runNext();
37
+ }, (err) => {
38
+ activeCount--;
39
+ reject(err);
40
+ runNext();
41
+ });
26
42
  }
27
- const range = new Headers(init?.headers).get('range');
28
- if (range) {
29
- const rangeParse = /bytes=(\d+)-(\d+)/.exec(range);
30
- if (rangeParse) {
31
- const [, start, end] = rangeParse;
32
- const s = Number.parseInt(start, 10);
33
- const e = Number.parseInt(end, 10);
34
- const len = e - s;
35
- const { buffer, headers } = (await globalRangeCache.getRange(`${url}`, s, len + 1));
36
- return new Response(buffer, {
37
- status: 206,
38
- headers,
39
- });
40
- }
43
+ if (activeCount < MAX_CONCURRENT) {
44
+ activeCount++;
45
+ run();
41
46
  }
42
- return super.fetch(url, init);
43
- }
44
- async fetchBinaryRange(url, start, end, options = {}) {
45
- const requestDate = new Date();
47
+ else {
48
+ queue.push(run);
49
+ }
50
+ });
51
+ }
52
+ function cacheKey(url, chunkIndex) {
53
+ return `${url}:${chunkIndex}`;
54
+ }
55
+ export class RemoteFileWithRangeCache extends RemoteFile {
56
+ async fetchRange(url, start, end, signal) {
46
57
  const res = await super.fetch(url, {
47
- ...options,
48
- headers: {
49
- ...options.headers,
50
- range: `bytes=${start}-${end}`,
51
- },
58
+ signal: signal ?? undefined,
59
+ headers: { range: `bytes=${start}-${end}` },
52
60
  });
53
- const responseDate = new Date();
54
61
  if (!res.ok) {
55
62
  const errorMessage = `HTTP ${res.status} fetching ${url} bytes ${start}-${end}`;
56
63
  const hint = ' (should be 206 for range requests)';
57
64
  throw new Error(`${errorMessage}${res.status === 200 ? hint : ''}`);
58
65
  }
59
- const headers = {};
60
- for (const [k, v] of res.headers.entries()) {
61
- headers[k] = v;
66
+ return new Uint8Array(await res.arrayBuffer());
67
+ }
68
+ async getCachedRange(url, start, length, signal) {
69
+ const startChunk = Math.floor(start / CHUNK_SIZE);
70
+ const endChunk = Math.floor((start + length - 1) / CHUNK_SIZE);
71
+ const chunkCount = endChunk - startChunk + 1;
72
+ const chunks = await Promise.all(Array.from({ length: chunkCount }, (_, i) => {
73
+ const idx = startChunk + i;
74
+ const key = cacheKey(url, idx);
75
+ const existing = getCached(key);
76
+ if (existing) {
77
+ return Promise.resolve(existing);
78
+ }
79
+ return limitConcurrency(async () => {
80
+ const alreadyCached = getCached(key);
81
+ if (alreadyCached) {
82
+ return alreadyCached;
83
+ }
84
+ const chunkStart = idx * CHUNK_SIZE;
85
+ const chunkEnd = chunkStart + CHUNK_SIZE - 1;
86
+ const data = await this.fetchRange(url, chunkStart, chunkEnd, signal);
87
+ putCached(key, data);
88
+ return data;
89
+ });
90
+ }));
91
+ const offsetInFirstChunk = start - startChunk * CHUNK_SIZE;
92
+ const result = new Uint8Array(length);
93
+ let written = 0;
94
+ for (const [i, chunk_] of chunks.entries()) {
95
+ const chunk = chunk_;
96
+ const sourceStart = i === 0 ? offsetInFirstChunk : 0;
97
+ const available = chunk.length - sourceStart;
98
+ const needed = length - written;
99
+ const copyLen = Math.min(available, needed);
100
+ result.set(chunk.subarray(sourceStart, sourceStart + copyLen), written);
101
+ written += copyLen;
102
+ }
103
+ return result.subarray(0, written);
104
+ }
105
+ async fetch(url, init) {
106
+ const range = new Headers(init?.headers).get('range');
107
+ if (range) {
108
+ const rangeParse = /bytes=(\d+)-(\d+)/.exec(range);
109
+ if (rangeParse) {
110
+ const [, startStr, endStr] = rangeParse;
111
+ const s = Number.parseInt(startStr, 10);
112
+ const e = Number.parseInt(endStr, 10);
113
+ const buffer = await this.getCachedRange(String(url), s, e - s + 1, init?.signal);
114
+ return new Response(buffer, { status: 206 });
115
+ }
62
116
  }
63
- const arrayBuffer = await res.arrayBuffer();
64
- return {
65
- headers,
66
- requestDate,
67
- responseDate,
68
- buffer: new Uint8Array(arrayBuffer),
69
- };
117
+ return super.fetch(url, init);
70
118
  }
71
119
  }
@@ -7,10 +7,10 @@ import type { BaseInternetAccountModel } from '../../pluggableElementTypes/model
7
7
  import type RpcManager from '../../rpc/RpcManager.ts';
8
8
  import type { MenuItem } from '../../ui/index.ts';
9
9
  import type { Feature } from '../simpleFeature.ts';
10
- import type { IAnyStateTreeNode, IStateTreeNode, IType, Instance, SnapshotIn } from '@jbrowse/mobx-state-tree';
10
+ import type { IAnyStateTreeNode, IStateTreeNode, Instance, SnapshotIn } from '@jbrowse/mobx-state-tree';
11
11
  import type { ThemeOptions } from '@mui/material';
12
12
  export * from './util.ts';
13
- export interface AbstractViewContainer extends IStateTreeNode<IType<any, any, any>> {
13
+ export interface AbstractViewContainer extends IStateTreeNode {
14
14
  views: AbstractViewModel[];
15
15
  removeView(view: AbstractViewModel): void;
16
16
  addView(typeName: string, initialState?: Record<string, unknown>): AbstractViewModel;
@@ -70,11 +70,11 @@ export interface AbstractSessionModel extends AbstractViewContainer {
70
70
  getTrackActionMenuItems?: (config: AnyConfigurationModel, extraTrackActions?: MenuItem[]) => MenuItem[];
71
71
  getTrackActions?: (arg: AnyConfigurationModel) => MenuItem[];
72
72
  getTrackListMenuItems?: (arg: AnyConfigurationModel) => MenuItem[];
73
- addAssembly?: Function;
74
- removeAssembly?: Function;
73
+ addAssembly?: (conf: Record<string, unknown>) => void;
74
+ removeAssembly?: (name: string) => void;
75
75
  textSearchManager?: TextSearchManager;
76
76
  connections: AnyConfigurationModel[];
77
- deleteConnection?: Function;
77
+ deleteConnection?: (arg: AnyConfigurationModel) => void;
78
78
  temporaryAssemblies?: unknown[];
79
79
  addTemporaryAssembly?: (arg: Record<string, unknown>) => void;
80
80
  removeTemporaryAssembly?: (arg: string) => void;
@@ -85,14 +85,16 @@ export interface AbstractSessionModel extends AbstractViewContainer {
85
85
  tracks: AnyConfigurationModel[];
86
86
  configuration: AnyConfigurationModel;
87
87
  }[];
88
- makeConnection?: Function;
89
- breakConnection?: Function;
90
- prepareToBreakConnection?: (arg: AnyConfigurationModel) => any;
88
+ makeConnection?: (arg: AnyConfigurationModel) => void;
89
+ breakConnection?: (arg: AnyConfigurationModel) => void;
90
+ prepareToBreakConnection?: (arg: AnyConfigurationModel) => [() => void, Record<string, number>] | undefined;
91
91
  adminMode?: boolean;
92
- showWidget?: Function;
93
- addWidget?: Function;
92
+ showWidget?: (widget: unknown) => void;
93
+ addWidget?: (typeName: string, id: string, initialState?: Record<string, unknown>, configuration?: {
94
+ type: string;
95
+ }) => Widget;
94
96
  DialogComponent?: DialogComponentType;
95
- DialogProps: any;
97
+ DialogProps: Record<string, unknown> | undefined;
96
98
  queueDialog<T extends DialogComponentType>(callback: (doneCallback: () => void) => [T, React.ComponentProps<T>]): void;
97
99
  name: string;
98
100
  id?: string;
@@ -156,8 +158,8 @@ export interface SessionWithConnectionEditing {
156
158
  export declare function isSessionModelWithConnectionEditing(thing: unknown): thing is SessionWithConnectionEditing;
157
159
  export interface SessionWithSessionPlugins extends AbstractSessionModel {
158
160
  sessionPlugins: JBrowsePlugin[];
159
- addSessionPlugin: Function;
160
- removeSessionPlugin: Function;
161
+ addSessionPlugin: (plugin: BasePlugin) => void;
162
+ removeSessionPlugin: (plugin: Record<string, unknown> | undefined) => void;
161
163
  }
162
164
  export declare function isSessionWithSessionPlugins(thing: unknown): thing is SessionWithSessionPlugins;
163
165
  export interface SelectionContainer extends AbstractSessionModel {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/core",
3
- "version": "4.1.13",
3
+ "version": "4.1.15",
4
4
  "type": "module",
5
5
  "description": "JBrowse 2 core libraries used by plugins",
6
6
  "keywords": [
@@ -476,30 +476,30 @@
476
476
  "@emotion/react": "^11.14.0",
477
477
  "@emotion/serialize": "^1.3.3",
478
478
  "@emotion/utils": "^1.4.2",
479
- "@floating-ui/react": "^0.27.18",
479
+ "@floating-ui/react": "^0.27.19",
480
480
  "@gmod/abortable-promise-cache": "^3.0.4",
481
- "@gmod/bgzf-filehandle": "^6.0.12",
481
+ "@gmod/bgzf-filehandle": "^6.0.18",
482
482
  "@gmod/http-range-fetcher": "^5.0.7",
483
- "@jbrowse/jexl": "^3.0.1",
484
- "@jbrowse/mobx-state-tree": "^5.5.0",
483
+ "@jbrowse/jexl": "^3.0.2",
484
+ "@jbrowse/mobx-state-tree": "^5.6.0",
485
485
  "@jbrowse/quick-lru": "^7.3.5",
486
486
  "@leeoniya/ufuzzy": "^1.0.19",
487
- "@mui/icons-material": "^7.3.8",
488
- "@mui/material": "^7.3.8",
489
- "@mui/system": "^7.3.8",
490
- "@mui/types": "^7.4.11",
491
- "@mui/x-data-grid": "^8.27.1",
487
+ "@mui/icons-material": "^7.3.9",
488
+ "@mui/material": "^7.3.9",
489
+ "@mui/system": "^7.3.9",
490
+ "@mui/types": "^7.4.12",
491
+ "@mui/x-data-grid": "^8.28.2",
492
492
  "@types/file-saver-es": "^2.0.3",
493
493
  "canvas-sequencer-ts": "^3.1.3",
494
494
  "canvas2svg": "^1.0.16",
495
495
  "copy-to-clipboard": "^3.3.3",
496
496
  "deepmerge": "^4.3.1",
497
497
  "detect-node": "^2.1.0",
498
- "dompurify": "^3.3.1",
498
+ "dompurify": "^3.3.3",
499
499
  "escape-html": "^1.0.3",
500
500
  "fast-deep-equal": "^3.1.3",
501
501
  "file-saver-es": "^2.0.5",
502
- "generic-filehandle2": "^2.0.18",
502
+ "generic-filehandle2": "^2.1.4",
503
503
  "idb": "^8.0.3",
504
504
  "librpc-web-mod": "^2.1.1",
505
505
  "mobx": "^6.15.0",