@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
1,047 lines (1,046 loc) • 34.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeAbortableReaction = exports.blobToDataURL = exports.isFeature = exports.SimpleFeature = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.rIC = exports.complementTable = exports.isElectron = void 0;
exports.useDebounce = useDebounce;
exports.useWidthSetter = useWidthSetter;
exports.useDebouncedCallback = useDebouncedCallback;
exports.findParentThat = findParentThat;
exports.springAnimate = springAnimate;
exports.findParentThatIs = findParentThatIs;
exports.getSession = getSession;
exports.getContainingView = getContainingView;
exports.getContainingTrack = getContainingTrack;
exports.getContainingDisplay = getContainingDisplay;
exports.assembleLocString = assembleLocString;
exports.assembleLocStringFast = assembleLocStringFast;
exports.parseLocStringOneBased = parseLocStringOneBased;
exports.parseLocString = parseLocString;
exports.compareLocs = compareLocs;
exports.compareLocStrings = compareLocStrings;
exports.clamp = clamp;
exports.bpToPx = bpToPx;
exports.radToDeg = radToDeg;
exports.degToRad = degToRad;
exports.polarToCartesian = polarToCartesian;
exports.cartesianToPolar = cartesianToPolar;
exports.featureSpanPx = featureSpanPx;
exports.bpSpanPx = bpSpanPx;
exports.iterMap = iterMap;
exports.findLastIndex = findLastIndex;
exports.findLast = findLast;
exports.renameRegionIfNeeded = renameRegionIfNeeded;
exports.renameRegionsIfNeeded = renameRegionsIfNeeded;
exports.minmax = minmax;
exports.shorten = shorten;
exports.shorten2 = shorten2;
exports.stringify = stringify;
exports.revcom = revcom;
exports.reverse = reverse;
exports.complement = complement;
exports.measureText = measureText;
exports.getFrame = getFrame;
exports.generateCodonTable = generateCodonTable;
exports.updateStatus = updateStatus;
exports.updateStatus2 = updateStatus2;
exports.hashCode = hashCode;
exports.objectHash = objectHash;
exports.bytesForRegions = bytesForRegions;
exports.isSupportedIndexingAdapter = isSupportedIndexingAdapter;
exports.getBpDisplayStr = getBpDisplayStr;
exports.getProgressDisplayStr = getProgressDisplayStr;
exports.toLocale = toLocale;
exports.getTickDisplayStr = getTickDisplayStr;
exports.getViewParams = getViewParams;
exports.getLayoutId = getLayoutId;
exports.useLocalStorage = useLocalStorage;
exports.getUriLink = getUriLink;
exports.getStr = getStr;
exports.coarseStripHTML = coarseStripHTML;
exports.linkify = linkify;
exports.measureGridWidth = measureGridWidth;
exports.getEnv = getEnv;
exports.localStorageGetItem = localStorageGetItem;
exports.localStorageSetItem = localStorageSetItem;
exports.max = max;
exports.min = min;
exports.sum = sum;
exports.avg = avg;
exports.groupBy = groupBy;
exports.notEmpty = notEmpty;
exports.mergeIntervals = mergeIntervals;
exports.gatherOverlaps = gatherOverlaps;
exports.stripAlpha = stripAlpha;
exports.getStrokeProps = getStrokeProps;
exports.getFillProps = getFillProps;
exports.renderToStaticMarkup = renderToStaticMarkup;
exports.isGzip = isGzip;
exports.fetchAndMaybeUnzip = fetchAndMaybeUnzip;
exports.fetchAndMaybeUnzipText = fetchAndMaybeUnzipText;
exports.isObject = isObject;
exports.localStorageGetNumber = localStorageGetNumber;
exports.localStorageGetBoolean = localStorageGetBoolean;
exports.localStorageSetBoolean = localStorageSetBoolean;
exports.forEachWithStopTokenCheck = forEachWithStopTokenCheck;
exports.testAdapter = testAdapter;
const react_1 = require("react");
const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
const useMeasure_1 = __importDefault(require("@jbrowse/core/util/useMeasure"));
const mobx_state_tree_1 = require("mobx-state-tree");
const react_dom_1 = require("react-dom");
const client_1 = require("react-dom/client");
const colord_1 = require("./colord");
const stopToken_1 = require("./stopToken");
const types_1 = require("./types");
__exportStar(require("./types"), exports);
__exportStar(require("./when"), exports);
__exportStar(require("./range"), exports);
__exportStar(require("./dedupe"), exports);
__exportStar(require("./offscreenCanvasPonyfill"), exports);
__exportStar(require("./offscreenCanvasUtils"), exports);
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = (0, react_1.useState)(value);
(0, react_1.useEffect)(() => {
const handle = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handle);
};
}, [value, delay]);
return debouncedValue;
}
function useWidthSetter(view, padding) {
const [ref, { width }] = (0, useMeasure_1.default)();
(0, react_1.useEffect)(() => {
if (width && (0, mobx_state_tree_1.isAlive)(view)) {
requestAnimationFrame(() => {
view.setWidth(width - Number.parseInt(padding, 10) * 2);
});
}
}, [padding, view, width]);
return ref;
}
function useDebouncedCallback(callback, wait = 400) {
const argsRef = (0, react_1.useRef)(null);
const timeout = (0, react_1.useRef)(null);
(0, react_1.useEffect)(() => {
if (timeout.current) {
clearTimeout(timeout.current);
}
}, []);
return function debouncedCallback(...args) {
argsRef.current = args;
if (timeout.current) {
clearTimeout(timeout.current);
}
timeout.current = setTimeout(() => {
if (argsRef.current) {
callback(...argsRef.current);
}
}, wait);
};
}
function findParentThat(node, predicate) {
if (!(0, mobx_state_tree_1.hasParent)(node)) {
throw new Error('node does not have parent');
}
let currentNode = (0, mobx_state_tree_1.getParent)(node);
while (currentNode && (0, mobx_state_tree_1.isAlive)(currentNode)) {
if (predicate(currentNode)) {
return currentNode;
}
if ((0, mobx_state_tree_1.hasParent)(currentNode)) {
currentNode = (0, mobx_state_tree_1.getParent)(currentNode);
}
else {
break;
}
}
throw new Error('no matching node found');
}
function springAnimate(fromValue, toValue, setValue, onFinish = () => { }, precision = 0, tension = 400, friction = 20, clamp = true) {
const mass = 1;
if (!precision) {
precision = Math.abs(toValue - fromValue) / 1000;
}
let animationFrameId;
function update(animation) {
const time = Date.now();
let position = animation.lastPosition;
let lastTime = animation.lastTime || time;
let velocity = animation.lastVelocity || 0;
if (time > lastTime + 64) {
lastTime = time;
}
const numSteps = Math.floor(time - lastTime);
for (let i = 0; i < numSteps; ++i) {
const force = -tension * (position - toValue);
const damping = -friction * velocity;
const acceleration = (force + damping) / mass;
velocity += (acceleration * 1) / 1000;
position += (velocity * 1) / 1000;
}
const isVelocity = Math.abs(velocity) <= precision;
const isDisplacement = tension !== 0 ? Math.abs(toValue - position) <= precision : true;
const isOvershooting = clamp && tension !== 0
? fromValue < toValue
? position > toValue
: position < toValue
: false;
const endOfAnimation = isOvershooting || (isVelocity && isDisplacement);
if (endOfAnimation) {
setValue(toValue);
onFinish();
}
else {
setValue(position);
animationFrameId = requestAnimationFrame(() => {
update({
lastPosition: position,
lastTime: time,
lastVelocity: velocity,
});
});
}
}
return [
() => {
update({ lastPosition: fromValue });
},
() => {
cancelAnimationFrame(animationFrameId);
},
];
}
function findParentThatIs(node, predicate) {
return findParentThat(node, predicate);
}
function getSession(node) {
try {
return findParentThatIs(node, types_1.isSessionModel);
}
catch (e) {
throw new Error('no session model found!');
}
}
function getContainingView(node) {
try {
return findParentThatIs(node, types_1.isViewModel);
}
catch (e) {
throw new Error('no containing view found');
}
}
function getContainingTrack(node) {
try {
return findParentThatIs(node, types_1.isTrackModel);
}
catch (e) {
throw new Error('no containing track found');
}
}
function getContainingDisplay(node) {
try {
return findParentThatIs(node, types_1.isDisplayModel);
}
catch (e) {
throw new Error('no containing display found');
}
}
function assembleLocString(region) {
return assembleLocStringFast(region, toLocale);
}
function assembleLocStringFast(region, cb = (n) => n) {
const { assemblyName, refName, start, end, reversed } = region;
const assemblyNameString = assemblyName ? `{${assemblyName}}` : '';
let startString;
if (start !== undefined) {
startString = `:${cb(start + 1)}`;
}
else if (end !== undefined) {
startString = ':1';
}
else {
startString = '';
}
let endString;
if (end !== undefined) {
endString = start !== undefined && start + 1 === end ? '' : `..${cb(end)}`;
}
else {
endString = start !== undefined ? '..' : '';
}
let rev = '';
if (reversed) {
rev = '[rev]';
}
return `${assemblyNameString}${refName}${startString}${endString}${rev}`;
}
function parseLocStringOneBased(locString, isValidRefName) {
if (!locString) {
throw new Error('no location string provided, could not parse');
}
let reversed = false;
if (locString.endsWith('[rev]')) {
reversed = true;
locString = locString.replace(/\[rev]$/, '');
}
locString = locString.replace(/\s/, '');
const assemblyMatch = /({(.+)})?(.+)/.exec(locString);
if (!assemblyMatch) {
throw new Error(`invalid location string: "${locString}"`);
}
const [, , assemblyName2, location2] = assemblyMatch;
const assemblyName = assemblyName2;
const location = location2;
if (!assemblyName && location.startsWith('{}')) {
throw new Error(`no assembly name was provided in location "${location}"`);
}
const lastColonIdx = location.lastIndexOf(':');
if (lastColonIdx === -1) {
if (isValidRefName(location, assemblyName)) {
return {
assemblyName,
refName: location,
reversed,
};
}
throw new Error(`Unknown reference sequence "${location}"`);
}
const prefix = location.slice(0, lastColonIdx);
const suffix = location.slice(lastColonIdx + 1);
if (isValidRefName(prefix, assemblyName) &&
isValidRefName(location, assemblyName)) {
throw new Error(`ambiguous location string: "${locString}"`);
}
else if (isValidRefName(prefix, assemblyName)) {
if (suffix) {
const rangeMatch = /^(-?(\d+|\d{1,3}(,\d{3})*))(\.\.|-)(-?(\d+|\d{1,3}(,\d{3})*))$/.exec(suffix);
const singleMatch = /^(-?(\d+|\d{1,3}(,\d{3})*))(\.\.|-)?$/.exec(suffix);
if (rangeMatch) {
const [, start, , , , end] = rangeMatch;
if (start !== undefined && end !== undefined) {
return {
assemblyName,
refName: prefix,
start: +start.replaceAll(',', ''),
end: +end.replaceAll(',', ''),
reversed,
};
}
}
else if (singleMatch) {
const [, start, , , separator] = singleMatch;
if (start !== undefined) {
if (separator) {
return {
assemblyName,
refName: prefix,
start: +start.replaceAll(',', ''),
reversed,
};
}
return {
assemblyName,
refName: prefix,
start: +start.replaceAll(',', ''),
end: +start.replaceAll(',', ''),
reversed,
};
}
}
else {
throw new Error(`could not parse range "${suffix}" on location "${locString}"`);
}
}
else {
return {
assemblyName,
refName: prefix,
reversed,
};
}
}
else if (isValidRefName(location, assemblyName)) {
return {
assemblyName,
refName: location,
reversed,
};
}
throw new Error(`unknown reference sequence name in location "${locString}"`);
}
function parseLocString(locString, isValidRefName) {
const parsed = parseLocStringOneBased(locString, isValidRefName);
if (typeof parsed.start === 'number') {
parsed.start -= 1;
}
return parsed;
}
function compareLocs(locA, locB) {
const assemblyComp = locA.assemblyName || locB.assemblyName
? (locA.assemblyName || '').localeCompare(locB.assemblyName || '')
: 0;
if (assemblyComp) {
return assemblyComp;
}
const refComp = locA.refName || locB.refName
? (locA.refName || '').localeCompare(locB.refName || '')
: 0;
if (refComp) {
return refComp;
}
if (locA.start !== undefined && locB.start !== undefined) {
const startComp = locA.start - locB.start;
if (startComp) {
return startComp;
}
}
if (locA.end !== undefined && locB.end !== undefined) {
const endComp = locA.end - locB.end;
if (endComp) {
return endComp;
}
}
return 0;
}
function compareLocStrings(a, b, isValidRefName) {
const locA = parseLocString(a, isValidRefName);
const locB = parseLocString(b, isValidRefName);
return compareLocs(locA, locB);
}
function clamp(num, min, max) {
if (num < min) {
return min;
}
if (num > max) {
return max;
}
return num;
}
function roundToNearestPointOne(num) {
return Math.round(num * 10) / 10;
}
function bpToPx(bp, { reversed, end = 0, start = 0, }, bpPerPx) {
return roundToNearestPointOne((reversed ? end - bp : bp - start) / bpPerPx);
}
const oneEightyOverPi = 180 / Math.PI;
const piOverOneEighty = Math.PI / 180;
function radToDeg(radians) {
return (radians * oneEightyOverPi) % 360;
}
function degToRad(degrees) {
return (degrees * piOverOneEighty) % (2 * Math.PI);
}
function polarToCartesian(rho, theta) {
return [rho * Math.cos(theta), rho * Math.sin(theta)];
}
function cartesianToPolar(x, y) {
const rho = Math.sqrt(x * x + y * y);
const theta = Math.atan(y / x);
return [rho, theta];
}
function featureSpanPx(feature, region, bpPerPx) {
return bpSpanPx(feature.get('start'), feature.get('end'), region, bpPerPx);
}
function bpSpanPx(leftBp, rightBp, region, bpPerPx) {
const start = bpToPx(leftBp, region, bpPerPx);
const end = bpToPx(rightBp, region, bpPerPx);
return region.reversed ? [end, start] : [start, end];
}
function iterMap(iter, func, sizeHint) {
const results = Array.from({ length: sizeHint || 0 });
let counter = 0;
for (const item of iter) {
results[counter] = func(item);
counter += 1;
}
return results;
}
function findLastIndex(array, predicate) {
let l = array.length;
while (l--) {
if (predicate(array[l], l, array)) {
return l;
}
}
return -1;
}
function findLast(array, predicate) {
let l = array.length;
while (l--) {
if (predicate(array[l], l, array)) {
return array[l];
}
}
return undefined;
}
function renameRegionIfNeeded(refNameMap, region) {
if ((0, mobx_state_tree_1.isStateTreeNode)(region) && !(0, mobx_state_tree_1.isAlive)(region)) {
return region;
}
if (refNameMap === null || refNameMap === void 0 ? void 0 : refNameMap[region.refName]) {
region = (0, mobx_state_tree_1.isStateTreeNode)(region)
? { ...(0, mobx_state_tree_1.getSnapshot)(region) }
: { ...region };
const newRef = refNameMap[region.refName];
if (newRef) {
return { ...region, refName: newRef, originalRefName: region.refName };
}
}
return region;
}
async function renameRegionsIfNeeded(assemblyManager, args) {
const { regions = [], adapterConfig } = args;
if (!args.sessionId) {
throw new Error('sessionId is required');
}
const assemblyNames = regions.map(region => region.assemblyName);
const assemblyMaps = Object.fromEntries(await Promise.all([...new Set(assemblyNames)].map(async (assemblyName) => {
return [
assemblyName,
await assemblyManager.getRefNameMapForAdapter(adapterConfig, assemblyName, args),
];
})));
return {
...args,
regions: regions.map((region, i) => renameRegionIfNeeded(assemblyMaps[assemblyNames[i]], region)),
};
}
function minmax(a, b) {
return [Math.min(a, b), Math.max(a, b)];
}
function shorten(name, max = 70, short = 30) {
return name.length > max
? `${name.slice(0, short)}...${name.slice(-short)}`
: name;
}
function shorten2(name, max = 70) {
return name.length > max ? `${name.slice(0, max)}...` : name;
}
function stringify({ refName, coord, assemblyName, oob, }, useAssemblyName) {
return [
assemblyName && useAssemblyName ? `{${assemblyName}}` : '',
refName
? `${shorten(refName)}:${toLocale(coord)}${oob ? ' (out of bounds)' : ''}`
: '',
].join('');
}
exports.isElectron = /electron/i.test(typeof navigator !== 'undefined' ? navigator.userAgent : '');
exports.complementTable = {
S: 'S',
w: 'w',
T: 'A',
r: 'y',
a: 't',
N: 'N',
K: 'M',
x: 'x',
d: 'h',
Y: 'R',
V: 'B',
y: 'r',
M: 'K',
h: 'd',
k: 'm',
C: 'G',
g: 'c',
t: 'a',
A: 'T',
n: 'n',
W: 'W',
X: 'X',
m: 'k',
v: 'b',
B: 'V',
s: 's',
H: 'D',
c: 'g',
D: 'H',
b: 'v',
R: 'Y',
G: 'C',
};
function revcom(str) {
var _a;
let revcomped = '';
for (let i = str.length - 1; i >= 0; i--) {
revcomped += (_a = exports.complementTable[str[i]]) !== null && _a !== void 0 ? _a : str[i];
}
return revcomped;
}
function reverse(str) {
let reversed = '';
for (let i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
return reversed;
}
function complement(str) {
var _a;
let comp = '';
for (const element of str) {
comp += (_a = exports.complementTable[element]) !== null && _a !== void 0 ? _a : element;
}
return comp;
}
exports.rIC = typeof jest === 'undefined'
?
typeof window !== 'undefined' && window.requestIdleCallback
? window.requestIdleCallback
: (cb) => setTimeout(() => {
cb();
}, 1)
: (cb) => {
cb();
};
const widths = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2796875, 0.2765625, 0.3546875, 0.5546875, 0.5546875, 0.8890625, 0.665625, 0.190625, 0.3328125, 0.3328125, 0.3890625, 0.5828125, 0.2765625, 0.3328125, 0.2765625, 0.3015625, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.2765625, 0.2765625, 0.584375, 0.5828125, 0.584375, 0.5546875, 1.0140625, 0.665625, 0.665625, 0.721875, 0.721875, 0.665625, 0.609375, 0.7765625, 0.721875, 0.2765625, 0.5, 0.665625, 0.5546875, 0.8328125, 0.721875, 0.7765625, 0.665625, 0.7765625, 0.721875, 0.665625, 0.609375, 0.721875, 0.665625, 0.94375, 0.665625, 0.665625, 0.609375, 0.2765625, 0.3546875, 0.2765625, 0.4765625, 0.5546875, 0.3328125, 0.5546875, 0.5546875, 0.5, 0.5546875, 0.5546875, 0.2765625, 0.5546875, 0.5546875, 0.221875, 0.240625, 0.5, 0.221875, 0.8328125, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.3328125, 0.5, 0.2765625, 0.5546875, 0.5, 0.721875, 0.5, 0.5, 0.5, 0.3546875, 0.259375, 0.353125, 0.5890625];
function measureText(str, fontSize = 10) {
var _a;
const avg = 0.5279276315789471;
const s = String(str);
let total = 0;
for (let i = 0; i < s.length; i++) {
const code = s.charCodeAt(i);
total += (_a = widths[code]) !== null && _a !== void 0 ? _a : avg;
}
return total * fontSize;
}
function getFrame(start, end, strand, phase) {
return strand === 1
? (((start + phase) % 3) + 1)
: (-1 * ((end - phase) % 3) - 1);
}
exports.defaultStarts = ['ATG'];
exports.defaultStops = ['TAA', 'TAG', 'TGA'];
exports.defaultCodonTable = {
TCA: 'S',
TCC: 'S',
TCG: 'S',
TCT: 'S',
TTC: 'F',
TTT: 'F',
TTA: 'L',
TTG: 'L',
TAC: 'Y',
TAT: 'Y',
TAA: '*',
TAG: '*',
TGC: 'C',
TGT: 'C',
TGA: '*',
TGG: 'W',
CTA: 'L',
CTC: 'L',
CTG: 'L',
CTT: 'L',
CCA: 'P',
CCC: 'P',
CCG: 'P',
CCT: 'P',
CAC: 'H',
CAT: 'H',
CAA: 'Q',
CAG: 'Q',
CGA: 'R',
CGC: 'R',
CGG: 'R',
CGT: 'R',
ATA: 'I',
ATC: 'I',
ATT: 'I',
ATG: 'M',
ACA: 'T',
ACC: 'T',
ACG: 'T',
ACT: 'T',
AAC: 'N',
AAT: 'N',
AAA: 'K',
AAG: 'K',
AGC: 'S',
AGT: 'S',
AGA: 'R',
AGG: 'R',
GTA: 'V',
GTC: 'V',
GTG: 'V',
GTT: 'V',
GCA: 'A',
GCC: 'A',
GCG: 'A',
GCT: 'A',
GAC: 'D',
GAT: 'D',
GAA: 'E',
GAG: 'E',
GGA: 'G',
GGC: 'G',
GGG: 'G',
GGT: 'G',
};
function generateCodonTable(table) {
const tempCodonTable = {};
for (const codon of Object.keys(table)) {
const aa = table[codon];
const nucs = [];
for (let i = 0; i < 3; i++) {
const nuc = codon.charAt(i);
nucs[i] = [];
nucs[i][0] = nuc.toUpperCase();
nucs[i][1] = nuc.toLowerCase();
}
for (let i = 0; i < 2; i++) {
const n0 = nucs[0][i];
for (let j = 0; j < 2; j++) {
const n1 = nucs[1][j];
for (let k = 0; k < 2; k++) {
const n2 = nucs[2][k];
const triplet = n0 + n1 + n2;
tempCodonTable[triplet] = aa;
}
}
}
}
return tempCodonTable;
}
async function updateStatus(msg, cb, fn) {
cb(msg);
const res = await fn();
cb('');
return res;
}
async function updateStatus2(msg, cb, stopToken, fn) {
cb(msg);
const res = await fn();
(0, stopToken_1.checkStopToken)(stopToken);
cb('');
return res;
}
function hashCode(str) {
let hash = 0;
if (str.length === 0) {
return hash;
}
for (let i = 0; i < str.length; i++) {
const chr = str.charCodeAt(i);
hash = (hash << 5) - hash + chr;
hash |= 0;
}
return hash;
}
function objectHash(obj) {
return `${hashCode(JSON.stringify(obj))}`;
}
async function bytesForRegions(regions, index) {
const blockResults = await Promise.all(regions.map(r => index.blocksForRange(r.refName, r.start, r.end)));
return blockResults
.flat()
.map(block => ({
start: block.minv.blockPosition,
end: block.maxv.blockPosition + 65535,
}))
.reduce((a, b) => a + b.end - b.start, 0);
}
function isSupportedIndexingAdapter(type = '') {
return [
'Gff3TabixAdapter',
'VcfTabixAdapter',
'Gff3Adapter',
'VcfAdapter',
].includes(type);
}
function getBpDisplayStr(total) {
if (Math.floor(total / 1000000) > 0) {
return `${r(total / 1000000)}Mbp`;
}
else if (Math.floor(total / 1000) > 0) {
return `${r(total / 1000)}Kbp`;
}
else {
return `${Math.floor(total)}bp`;
}
}
function r(s) {
return toLocale(Number.parseFloat(s.toPrecision(3)));
}
function getProgressDisplayStr(current, total) {
if (Math.floor(total / 1000000) > 0) {
return `${r(current / 1000000)}/${r(total / 1000000)}Mb`;
}
else if (Math.floor(total / 1000) > 0) {
return `${r(current / 1000)}/${r(total / 1000)}Kb`;
}
else {
return `${r(current)}/${r(total)}}bytes`;
}
}
function toLocale(n) {
return n.toLocaleString('en-US');
}
function getTickDisplayStr(totalBp, bpPerPx) {
return Math.floor(bpPerPx / 1000) > 0
? `${toLocale(Number.parseFloat((totalBp / 1000000).toFixed(2)))}M`
: toLocale(Math.floor(totalBp));
}
function getViewParams(model, exportSVG) {
const { dynamicBlocks, staticBlocks, offsetPx } = getContainingView(model);
const b = (dynamicBlocks === null || dynamicBlocks === void 0 ? void 0 : dynamicBlocks.contentBlocks[0]) || {};
const staticblock = (staticBlocks === null || staticBlocks === void 0 ? void 0 : staticBlocks.contentBlocks[0]) || {};
const staticblock1 = (staticBlocks === null || staticBlocks === void 0 ? void 0 : staticBlocks.contentBlocks[1]) || {};
return {
offsetPx: exportSVG ? 0 : offsetPx - staticblock.offsetPx,
offsetPx1: exportSVG ? 0 : offsetPx - staticblock1.offsetPx,
start: b.start,
end: b.end,
};
}
function getLayoutId({ sessionId, layoutId, }) {
return `${sessionId}-${layoutId}`;
}
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = (0, react_1.useState)(() => {
if (typeof window === 'undefined') {
return initialValue;
}
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
}
catch (error) {
console.error(error);
return initialValue;
}
});
const setValue = (value) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
if (typeof window !== 'undefined') {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
}
catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
function getUriLink(value) {
const { uri, baseUri = '' } = value;
let href;
try {
href = new URL(uri, baseUri).href;
}
catch (e) {
href = uri;
}
return href;
}
function getStr(obj) {
return isObject(obj)
? (0, types_1.isUriLocation)(obj)
? getUriLink(obj)
: JSON.stringify(obj)
: String(obj);
}
function coarseStripHTML(s) {
return s.replaceAll(/(<([^>]+)>)/gi, '');
}
function linkify(s) {
const pattern = /(^|[\s\n]|<[A-Za-z]*\/?>)((?:https?|ftp):\/\/[-A-Z0-9+\u0026\u2019@#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026@#/%=~()_|])/gi;
return s.replaceAll(pattern, '$1<a href=\'$2\' target="_blank">$2</a>');
}
function measureGridWidth(elements, args) {
const { padding = 30, minWidth = 80, fontSize = 12, maxWidth = 1000, stripHTML = false, } = args || {};
return max(elements
.map(element => getStr(element))
.map(str => (stripHTML ? coarseStripHTML(str) : str))
.map(str => measureText(str, fontSize))
.map(n => Math.min(Math.max(n + padding, minWidth), maxWidth)));
}
function getEnv(obj) {
return (0, mobx_state_tree_1.getEnv)(obj);
}
function localStorageGetItem(item) {
return typeof localStorage !== 'undefined'
? localStorage.getItem(item)
: undefined;
}
function localStorageSetItem(str, item) {
if (typeof localStorage !== 'undefined') {
localStorage.setItem(str, item);
}
}
function max(arr, init = Number.NEGATIVE_INFINITY) {
let max = init;
for (const entry of arr) {
max = Math.max(entry, max);
}
return max;
}
function min(arr, init = Number.POSITIVE_INFINITY) {
let min = init;
for (const entry of arr) {
min = Math.min(entry, min);
}
return min;
}
function sum(arr) {
let sum = 0;
for (const entry of arr) {
sum += entry;
}
return sum;
}
function avg(arr) {
return sum(arr) / arr.length;
}
function groupBy(array, predicate) {
const result = {};
for (const value of array) {
const t = predicate(value);
if (!result[t]) {
result[t] = [];
}
result[t].push(value);
}
return result;
}
function notEmpty(value) {
return value !== null && value !== undefined;
}
function mergeIntervals(intervals, w = 5000) {
if (intervals.length <= 1) {
return intervals;
}
const stack = [];
let top = null;
intervals = intervals.sort((a, b) => a.start - b.start);
stack.push(intervals[0]);
for (let i = 1; i < intervals.length; i++) {
top = stack.at(-1);
if (top.end + w < intervals[i].start - w) {
stack.push(intervals[i]);
}
else if (top.end < intervals[i].end) {
top.end = Math.max(top.end, intervals[i].end);
stack.pop();
stack.push(top);
}
}
return stack;
}
function gatherOverlaps(regions, w = 5000) {
const memo = {};
for (const x of regions) {
if (!memo[x.refName]) {
memo[x.refName] = [];
}
memo[x.refName].push(x);
}
return Object.values(memo).flatMap(group => mergeIntervals(group.sort((a, b) => a.start - b.start), w));
}
function stripAlpha(str) {
return (0, colord_1.colord)(str).alpha(1).toHex();
}
function getStrokeProps(str) {
if (str) {
const c = (0, colord_1.colord)(str);
return {
strokeOpacity: c.alpha(),
stroke: c.alpha(1).toHex(),
};
}
else {
return {};
}
}
function getFillProps(str) {
if (str) {
const c = (0, colord_1.colord)(str);
return {
fillOpacity: c.alpha(),
fill: c.alpha(1).toHex(),
};
}
else {
return {};
}
}
function renderToStaticMarkup(node) {
const div = document.createElement('div');
(0, react_dom_1.flushSync)(() => {
(0, client_1.createRoot)(div).render(node);
});
return div.innerHTML.replaceAll(/\brgba\((.+?),[^,]+?\)/g, 'rgb($1)');
}
function isGzip(buf) {
return buf[0] === 31 && buf[1] === 139 && buf[2] === 8;
}
async function fetchAndMaybeUnzip(loc, opts = {}) {
const { statusCallback = () => { } } = opts;
const buf = await updateStatus('Downloading file', statusCallback, () => loc.readFile(opts));
return isGzip(buf)
? await updateStatus('Unzipping', statusCallback, () => (0, bgzf_filehandle_1.unzip)(buf))
: buf;
}
async function fetchAndMaybeUnzipText(loc, opts) {
const buffer = await fetchAndMaybeUnzip(loc, opts);
if (buffer.length > 536870888) {
throw new Error('Data exceeds maximum string length (512MB)');
}
return new TextDecoder('utf8', { fatal: true }).decode(buffer);
}
function isObject(x) {
return typeof x === 'object' && x !== null;
}
function localStorageGetNumber(key, defaultVal) {
var _a;
return +((_a = localStorageGetItem(key)) !== null && _a !== void 0 ? _a : defaultVal);
}
function localStorageGetBoolean(key, defaultVal) {
return Boolean(JSON.parse(localStorageGetItem(key) || JSON.stringify(defaultVal)));
}
function localStorageSetBoolean(key, value) {
localStorageSetItem(key, JSON.stringify(value));
}
function forEachWithStopTokenCheck(iter, stopToken, arg, durationMs = 400) {
let start = performance.now();
let i = 0;
for (const t of iter) {
if (performance.now() - start > durationMs) {
(0, stopToken_1.checkStopToken)(stopToken);
start = performance.now();
}
arg(t, i++);
}
}
function testAdapter(fileName, regex, adapterHint, expected) {
return (regex.test(fileName) && !adapterHint) || adapterHint === expected;
}
var simpleFeature_1 = require("./simpleFeature");
Object.defineProperty(exports, "SimpleFeature", { enumerable: true, get: function () { return __importDefault(simpleFeature_1).default; } });
Object.defineProperty(exports, "isFeature", { enumerable: true, get: function () { return simpleFeature_1.isFeature; } });
var blobToDataURL_1 = require("./blobToDataURL");
Object.defineProperty(exports, "blobToDataURL", { enumerable: true, get: function () { return blobToDataURL_1.blobToDataURL; } });
var makeAbortableReaction_1 = require("./makeAbortableReaction");
Object.defineProperty(exports, "makeAbortableReaction", { enumerable: true, get: function () { return makeAbortableReaction_1.makeAbortableReaction; } });
__exportStar(require("./aborting"), exports);