UNPKG

@rcsb/rcsb-saguaro

Version:
194 lines (193 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RcsbFvUI = void 0; const tslib_1 = require("tslib"); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = tslib_1.__importDefault(require("react")); const classes = tslib_1.__importStar(require("../../scss/RcsbFvRow.module.scss")); const react_transition_group_1 = require("react-transition-group"); const RcsbFvDefaultConfigValues_1 = require("../RcsbFvConfig/RcsbFvDefaultConfigValues"); const RcsbFvContextManager_1 = require("../RcsbFvContextManager/RcsbFvContextManager"); const rxjs_1 = require("rxjs"); const dom_1 = require("@floating-ui/dom"); const bx_plus_svg_1 = tslib_1.__importDefault(require("./icons/bx-plus.svg")); const bx_minus_svg_1 = tslib_1.__importDefault(require("./icons/bx-minus.svg")); const bx_right_arrow_svg_1 = tslib_1.__importDefault(require("./icons/bx-right-arrow.svg")); const bx_left_arrow_svg_1 = tslib_1.__importDefault(require("./icons/bx-left-arrow.svg")); const bxs_down_arrow_svg_1 = tslib_1.__importDefault(require("./icons/bxs-down-arrow.svg")); class RcsbFvUI extends react_1.default.Component { constructor() { super(...arguments); this.collapseRef = react_1.default.createRef(); this.expandRef = react_1.default.createRef(); /**UI config Object*/ this.config = [{ icon: (0, jsx_runtime_1.jsx)(bx_plus_svg_1.default, Object.assign({}, RcsbFvUI.ICON_PROPS)), callback: this.zoomIn.bind(this), name: "zoom-in" }, { icon: (0, jsx_runtime_1.jsx)(bx_minus_svg_1.default, Object.assign({}, RcsbFvUI.ICON_PROPS)), callback: this.zoomOut.bind(this), name: "zoom-out" }, { icon: (0, jsx_runtime_1.jsx)(bx_right_arrow_svg_1.default, Object.assign({}, RcsbFvUI.ICON_PROPS)), callback: this.move.bind(this, 1), name: "move-right" }, { icon: (0, jsx_runtime_1.jsx)(bx_left_arrow_svg_1.default, Object.assign({}, RcsbFvUI.ICON_PROPS)), callback: this.move.bind(this, -1), name: "move-left" }]; this.hideTask = null; this.state = { collapse: false }; } render() { return ((0, jsx_runtime_1.jsx)("div", { id: this.props.boardId + "_uiDiv" /* RcsbFvDOMConstants.UI_DOM_ID_PREFIX */, className: classes.rcsbUI + " " + classes.rcsbSmoothDivHide, style: { position: "absolute", top: 0, left: 0 }, children: (0, jsx_runtime_1.jsxs)("div", { style: { position: "relative" }, children: [(0, jsx_runtime_1.jsx)(react_transition_group_1.CSSTransition, { in: this.state.collapse, timeout: 300, classNames: classes.rcsbCollapseUI, nodeRef: this.collapseRef, children: (0, jsx_runtime_1.jsx)("div", { style: { position: "absolute" }, className: classes.rcsbCollapsedUIDiv + " " + classes.rcsbCollapseUI, onMouseEnter: this.changeState.bind(this, { collapse: false }), ref: this.collapseRef, children: (0, jsx_runtime_1.jsx)("div", { className: classes.rcsbCollapsedIcon, children: (0, jsx_runtime_1.jsx)(bxs_down_arrow_svg_1.default, Object.assign({}, RcsbFvUI.ICON_PROPS)) }) }) }), (0, jsx_runtime_1.jsx)(react_transition_group_1.CSSTransition, { in: !this.state.collapse, timeout: 300, classNames: classes.rcsbExpandUI, nodeRef: this.expandRef, children: (0, jsx_runtime_1.jsx)("div", { style: { position: "absolute" }, className: classes.rcsbExpandUI, onMouseLeave: this.changeState.bind(this, { collapse: true }), ref: this.expandRef, children: this.config.map(button => { return this.buildButton(button); }) }) })] }) })); } componentDidMount() { this.subscription = this.subscribe(); const refDiv = document.querySelector("#" + this.props.boardId); if (refDiv == null) throw "Main board DOM element not found"; this.refDiv = refDiv; const tooltipDiv = document.querySelector("#" + this.props.boardId + "_uiDiv" /* RcsbFvDOMConstants.UI_DOM_ID_PREFIX */); if (tooltipDiv == null) throw "Tooltip DOM element not found"; this.tooltipDiv = tooltipDiv; } componentWillUnmount() { this.subscription.unsubscribe(); } subscribe() { return this.props.contextManager.subscribe((o) => { switch (o.eventType) { case RcsbFvContextManager_1.EventType.BOARD_HOVER: this.boardHover(o.eventData); break; } }); } boardHover(flag) { if (flag) { this.displayUI(); } else { this.hideUI(); } } displayUI() { if (this.hideTask) this.hideTask.unsubscribe(); const offsetHeight = this.props.boardConfigData.includeAxis === true ? RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.trackAxisHeight + 2 : 0; (0, dom_1.computePosition)(this.refDiv, this.tooltipDiv, { placement: 'right-start', middleware: [{ name: 'middleware', fn(middlewareArguments) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const overflow = yield (0, dom_1.detectOverflow)(middlewareArguments, { rootBoundary: "viewport" }); if (overflow.top > offsetHeight) return { y: overflow.top + middlewareArguments.y - offsetHeight }; return {}; }); }, }] }).then(({ x, y }) => { Object.assign(this.tooltipDiv.style, { left: `${x}px`, top: `${y + offsetHeight}px` }); }); this.tooltipDiv.classList.remove(classes.rcsbSmoothDivHide); this.tooltipDiv.classList.add(classes.rcsbSmoothDivDisplay); } hideUI() { const tooltipDiv = document.querySelector("#" + this.props.boardId + "_uiDiv" /* RcsbFvDOMConstants.UI_DOM_ID_PREFIX */); if (tooltipDiv == null) return; this.hideTask = rxjs_1.asyncScheduler.schedule(() => { tooltipDiv.classList.remove(classes.rcsbSmoothDivDisplay); tooltipDiv.classList.add(classes.rcsbSmoothDivHide); }, 300); } buildButton(buttonConfig) { return ((0, jsx_runtime_1.jsx)("div", { className: classes.rcsbUIButton, children: (0, jsx_runtime_1.jsx)("div", { className: classes.rcsbIcon, onClick: buttonConfig.callback, children: buttonConfig.icon }) }, buttonConfig.name)); } changeState(state) { this.setState(state); } /*************** ** UI methods ** ****************/ zoomIn() { const max = this.props.boardConfigData.range != null ? this.props.boardConfigData.range.max : this.props.boardConfigData.length; if (max == null) return; const currentDomain = this.props.xScale.domain(); const deltaZoom = Math.floor((currentDomain[1] - currentDomain[0]) * 0.1); const x = currentDomain[0] + deltaZoom; const y = currentDomain[1] - deltaZoom; if ((y - x) > 20) this.setDomain({ domain: [x, y] }); } zoomOut() { const max = this.props.boardConfigData.range != null ? this.props.boardConfigData.range.max : this.props.boardConfigData.length; const min = this.props.boardConfigData.range != null ? this.props.boardConfigData.range.min : 1; if (max == null) return; const currentDomain = this.props.xScale.domain(); const deltaZoom = Math.floor((currentDomain[1] - currentDomain[0]) * 0.1); const x = currentDomain[0] - deltaZoom > (min - RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView) ? currentDomain[0] - deltaZoom : (min - RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView); const y = currentDomain[1] + deltaZoom < max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView ? currentDomain[1] + deltaZoom : max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView; if ((y - x) < (max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView)) this.setDomain({ domain: [x, y] }); else this.setDomain({ domain: [(min - RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView), max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView] }); } move(direction) { const max = this.props.boardConfigData.range != null ? this.props.boardConfigData.range.max : this.props.boardConfigData.length; const min = this.props.boardConfigData.range != null ? this.props.boardConfigData.range.min : 1; if (max == null) return; const currentDomain = this.props.xScale.domain(); let deltaZoom = Math.floor((currentDomain[1] - currentDomain[0]) * 0.1); if (currentDomain[0] + direction * deltaZoom < (min - RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView)) deltaZoom = currentDomain[0] - (min - RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView); else if (currentDomain[1] + direction * deltaZoom > (max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView)) deltaZoom = max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView - currentDomain[1]; const x = currentDomain[0] + direction * deltaZoom; const y = currentDomain[1] + direction * deltaZoom; if ((y - x) < (max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView)) this.setDomain({ domain: [x, y] }); else this.setDomain({ domain: [(min - RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView), max + RcsbFvDefaultConfigValues_1.RcsbFvDefaultConfigValues.increasedView] }); } /**Force all board track annotation cells to set xScale. Called when a new track has been added*/ setScale() { if (this.props.xScale != null) { this.props.contextManager.next({ eventType: RcsbFvContextManager_1.EventType.SCALE, eventData: this.props.boardId }); } } /**Update d3 xScale domain * @param domainData new xScale domain * */ setDomain(domainData) { this.props.xScale.domain(domainData.domain); this.setScale(); } } exports.RcsbFvUI = RcsbFvUI; RcsbFvUI.ICON_PROPS = { width: 16, height: 16, viewBox: "0 0 24 24" };