UNPKG

@jbrowse/core

Version:

JBrowse 2 core libraries used by plugins

1,047 lines (1,046 loc) 34.1 kB
"use strict"; 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);