UNPKG

flexlayout-react-v7-react-19

Version:

A multi-tab docking layout manager

150 lines 6.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTabOverflow = void 0; const React = require("react"); const Rect_1 = require("../Rect"); const TabSetNode_1 = require("../model/TabSetNode"); const Orientation_1 = require("../Orientation"); /** @internal */ const useTabOverflow = (node, orientation, toolbarRef, stickyButtonsRef) => { const firstRender = React.useRef(true); const tabsTruncated = React.useRef(false); const lastRect = React.useRef(new Rect_1.Rect(0, 0, 0, 0)); const selfRef = React.useRef(null); const [position, setPosition] = React.useState(0); const userControlledLeft = React.useRef(false); const [hiddenTabs, setHiddenTabs] = React.useState([]); const lastHiddenCount = React.useRef(0); // if selected node or tabset/border rectangle change then unset usercontrolled (so selected tab will be kept in view) React.useLayoutEffect(() => { userControlledLeft.current = false; }, [node.getSelectedNode(), node.getRect().width, node.getRect().height]); React.useLayoutEffect(() => { updateVisibleTabs(); }); const instance = selfRef.current; React.useEffect(() => { if (!instance) { return; } instance.addEventListener("wheel", onWheel, { passive: false }); return () => { instance.removeEventListener("wheel", onWheel); }; }, [instance]); // needed to prevent default mouse wheel over tabset/border (cannot do with react event?) const onWheel = (event) => { event.preventDefault(); }; const getNear = (rect) => { if (orientation === Orientation_1.Orientation.HORZ) { return rect.x; } else { return rect.y; } }; const getFar = (rect) => { if (orientation === Orientation_1.Orientation.HORZ) { return rect.getRight(); } else { return rect.getBottom(); } }; const getSize = (rect) => { if (orientation === Orientation_1.Orientation.HORZ) { return rect.width; } else { return rect.height; } }; const updateVisibleTabs = () => { const tabMargin = 2; if (firstRender.current === true) { tabsTruncated.current = false; } const nodeRect = node instanceof TabSetNode_1.TabSetNode ? node.getRect() : node.getTabHeaderRect(); let lastChild = node.getChildren()[node.getChildren().length - 1]; const stickyButtonsSize = stickyButtonsRef.current === null ? 0 : getSize(stickyButtonsRef.current.getBoundingClientRect()); if (firstRender.current === true || (lastHiddenCount.current === 0 && hiddenTabs.length !== 0) || nodeRect.width !== lastRect.current.width || // incase rect changed between first render and second nodeRect.height !== lastRect.current.height) { lastHiddenCount.current = hiddenTabs.length; lastRect.current = nodeRect; const enabled = node instanceof TabSetNode_1.TabSetNode ? node.isEnableTabStrip() === true : true; let endPos = getFar(nodeRect) - stickyButtonsSize; if (toolbarRef.current !== null) { endPos -= getSize(toolbarRef.current.getBoundingClientRect()); } if (enabled && node.getChildren().length > 0) { if (hiddenTabs.length === 0 && position === 0 && getFar(lastChild.getTabRect()) + tabMargin < endPos) { return; // nothing to do all tabs are shown in available space } let shiftPos = 0; const selectedTab = node.getSelectedNode(); if (selectedTab && !userControlledLeft.current) { const selectedRect = selectedTab.getTabRect(); const selectedStart = getNear(selectedRect) - tabMargin; const selectedEnd = getFar(selectedRect) + tabMargin; // when selected tab is larger than available space then align left if (getSize(selectedRect) + 2 * tabMargin >= endPos - getNear(nodeRect)) { shiftPos = getNear(nodeRect) - selectedStart; } else { if (selectedEnd > endPos || selectedStart < getNear(nodeRect)) { if (selectedStart < getNear(nodeRect)) { shiftPos = getNear(nodeRect) - selectedStart; } // use second if statement to prevent tab moving back then forwards if not enough space for single tab if (selectedEnd + shiftPos > endPos) { shiftPos = endPos - selectedEnd; } } } } const extraSpace = Math.max(0, endPos - (getFar(lastChild.getTabRect()) + tabMargin + shiftPos)); const newPosition = Math.min(0, position + shiftPos + extraSpace); // find hidden tabs const diff = newPosition - position; const hidden = []; for (let i = 0; i < node.getChildren().length; i++) { const child = node.getChildren()[i]; if (getNear(child.getTabRect()) + diff < getNear(nodeRect) || getFar(child.getTabRect()) + diff > endPos) { hidden.push({ node: child, index: i }); } } if (hidden.length > 0) { tabsTruncated.current = true; } firstRender.current = false; // need to do a second render setHiddenTabs(hidden); setPosition(newPosition); } } else { firstRender.current = true; } }; const onMouseWheel = (event) => { let delta = 0; if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) { delta = -event.deltaX; } else { delta = -event.deltaY; } if (event.deltaMode === 1) { // DOM_DELTA_LINE 0x01 The delta values are specified in lines. delta *= 40; } setPosition(position + delta); userControlledLeft.current = true; event.stopPropagation(); }; return { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated: tabsTruncated.current }; }; exports.useTabOverflow = useTabOverflow; //# sourceMappingURL=TabOverflowHook.js.map