UNPKG

@jbrowse/plugin-linear-genome-view

Version:

JBrowse 2 linear genome view

169 lines (168 loc) 6.65 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useEffect, useState } from 'react'; import { Menu } from '@jbrowse/core/ui'; import { makeStyles } from '@jbrowse/core/util/tss-react'; import { observer } from 'mobx-react'; const useStyles = makeStyles()(theme => ({ refLabel: { fontSize: 11, position: 'absolute', left: 2, top: -1, fontWeight: 'bold', lineHeight: 'normal', zIndex: 1, background: theme.palette.background.paper, cursor: 'pointer', overflow: 'hidden', whiteSpace: 'nowrap', '&:hover': { background: theme.palette.grey[300], }, }, b0: { left: 0, zIndex: 100, }, })); const ScalebarRefNameLabels = observer(function ScalebarRefNameLabels({ model, }) { const { classes, cx } = useStyles(); const { staticBlocks, offsetPx, scalebarDisplayPrefix } = model; const [menuState, setMenuState] = useState(); useEffect(() => { model.setIsScalebarRefNameMenuOpen(!!menuState); }, [model, menuState]); let lastLeftBlock = staticBlocks.blocks.findIndex(b => b.type === 'ContentBlock'); if (lastLeftBlock < 0) { lastLeftBlock = 0; } staticBlocks.forEach((block, i) => { if (block.type === 'ContentBlock' && block.offsetPx - offsetPx < 0) { lastLeftBlock = i; } }); const val = scalebarDisplayPrefix(); const b0 = staticBlocks.blocks[0]; const regionEndPx = new Map(); for (const block of staticBlocks.blocks) { if (block.type === 'ContentBlock' && block.regionNumber !== undefined) { const endPx = block.offsetPx + block.widthPx; const current = regionEndPx.get(block.regionNumber); if (current === undefined || endPx > current) { regionEndPx.set(block.regionNumber, endPx); } } } return (_jsxs(_Fragment, { children: [b0?.type !== 'ContentBlock' && val ? (_jsx("span", { className: cx(classes.b0, classes.refLabel), children: val })) : null, staticBlocks.map((block, index) => { const { offsetPx: blockOffsetPx, isLeftEndOfDisplayedRegion, key, type, refName, regionNumber, } = block; const last = index === lastLeftBlock; const regEndPx = regionNumber !== undefined ? regionEndPx.get(regionNumber) : undefined; const labelStartPx = last ? offsetPx : blockOffsetPx; const maxWidth = regEndPx !== undefined ? regEndPx - labelStartPx - 2 : undefined; const minLabelWidth = 20; const hasEnoughSpace = maxWidth === undefined || maxWidth >= minLabelWidth; return type === 'ContentBlock' && (isLeftEndOfDisplayedRegion || last) && hasEnoughSpace ? (_jsxs("span", { style: { left: last ? Math.max(0, -offsetPx) : blockOffsetPx - offsetPx - 1, paddingLeft: last ? 0 : 1, maxWidth: maxWidth !== undefined && maxWidth > 0 ? maxWidth : undefined, }, className: classes.refLabel, "data-testid": `refLabel-${refName}`, onMouseDown: () => { model.setScalebarRefNameClickPending(true); }, onClick: event => { model.setScalebarRefNameClickPending(false); setMenuState({ anchorEl: event.currentTarget, refName, regionNumber: regionNumber, }); }, children: [last && val ? `${val}:` : '', refName] }, `refLabel-${key}-${index}`)) : null; }), menuState ? (_jsx(RefNameMenu, { model: model, menuState: menuState, onClose: () => { setMenuState(undefined); } })) : null] })); }); function RefNameMenu({ model, menuState, onClose, }) { const { displayedRegions } = model; const { refName, regionNumber } = menuState; const numRegions = displayedRegions.length; function moveRegion(fromIndex, toIndex) { const regions = [...displayedRegions]; const [removed] = regions.splice(fromIndex, 1); regions.splice(toIndex, 0, removed); model.setDisplayedRegions(regions); } function removeRegion(index) { const regions = displayedRegions.filter((_, i) => i !== index); model.setDisplayedRegions(regions); } const actionItems = [ ...(regionNumber > 0 ? [ { label: 'Move left', onClick: () => { moveRegion(regionNumber, regionNumber - 1); }, }, ] : []), ...(regionNumber < numRegions - 1 ? [ { label: 'Move right', onClick: () => { moveRegion(regionNumber, regionNumber + 1); }, }, ] : []), ...(numRegions > 2 && regionNumber > 0 ? [ { label: 'Move to far left', onClick: () => { moveRegion(regionNumber, 0); }, }, ] : []), ...(numRegions > 2 && regionNumber < numRegions - 1 ? [ { label: 'Move to far right', onClick: () => { moveRegion(regionNumber, numRegions - 1); }, }, ] : []), { label: 'Remove this region from view', onClick: () => { removeRegion(regionNumber); }, }, ]; return (_jsx(Menu, { anchorEl: menuState.anchorEl, open: true, onClose: onClose, onMenuItemClick: (_, callback) => { callback(); onClose(); }, menuItems: [ { label: `Focus on ${refName}`, onClick: () => { model.navTo({ refName }); }, }, ...(numRegions > 1 ? [ { label: 'Actions', subMenu: actionItems, }, ] : []), ] })); } export default ScalebarRefNameLabels;