UNPKG

@atlaskit/navigation-system

Version:

The latest navigation system for Atlassian apps.

211 lines • 15.9 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } import { resolveLayoutWidth } from './resolve-layout-width'; function clampTargetWidth(_ref) { var target = _ref.target, min = _ref.min, max = _ref.max; return Math.max(min, Math.min(target, max)); } function getTargetWidth(area, isSideNavOverlay) { var _area$compactDefaultW, _area$liveResize, _ref2, _area$requestedWidth; var defaultWidth = isSideNavOverlay ? (_area$compactDefaultW = area.compactDefaultWidth) !== null && _area$compactDefaultW !== void 0 ? _area$compactDefaultW : area.defaultWidth : area.defaultWidth; return ((_area$liveResize = area.liveResize) === null || _area$liveResize === void 0 ? void 0 : _area$liveResize.mode) === 'inline' ? area.liveResize.width : (_ref2 = (_area$requestedWidth = area.requestedWidth) !== null && _area$requestedWidth !== void 0 ? _area$requestedWidth : area.preferredWidth) !== null && _ref2 !== void 0 ? _ref2 : defaultWidth; } function getOverlayTargetWidth(area, isSideNavOverlay, areaName) { var _area$compactDefaultW2, _area$liveResize2, _ref3, _area$requestedWidth2; var defaultWidth = isSideNavOverlay ? (_area$compactDefaultW2 = area.compactDefaultWidth) !== null && _area$compactDefaultW2 !== void 0 ? _area$compactDefaultW2 : area.defaultWidth : area.defaultWidth; return ((_area$liveResize2 = area.liveResize) === null || _area$liveResize2 === void 0 ? void 0 : _area$liveResize2.mode) === 'overlay' ? area.liveResize.width : (_ref3 = (_area$requestedWidth2 = area.requestedWidth) !== null && _area$requestedWidth2 !== void 0 ? _area$requestedWidth2 : areaName === 'panel' ? area.preferredWidth : area.preferredOverlayWidth) !== null && _ref3 !== void 0 ? _ref3 : defaultWidth; } export function calculateLayoutAreaStates(_ref4) { var _ref5, _resizeSession$overla, _baselineWidths$chat, _panel$liveResize, _states$sideNav$widt, _states$sideNav, _states$chatPanel$wi, _states$chatPanel; var viewportWidth = _ref4.viewportWidth, _ref4$layoutWidth = _ref4.layoutWidth, layoutWidth = _ref4$layoutWidth === void 0 ? viewportWidth : _ref4$layoutWidth, isChatPanelOverlay = _ref4.isChatPanelOverlay, isSideNavOverlay = _ref4.isSideNavOverlay, _ref4$occupiedWidth = _ref4.occupiedWidth, occupiedWidth = _ref4$occupiedWidth === void 0 ? 0 : _ref4$occupiedWidth, mainMinWidthBound = _ref4.mainMinWidth, areas = _ref4.areas, resizeSession = _ref4.resizeSession, initialModes = _ref4.initialModes; var mainMinWidth = resolveLayoutWidth(mainMinWidthBound, viewportWidth); var availableWidth = Math.max(0, layoutWidth - occupiedWidth); var sideNav = areas['side-nav']; var panel = areas.panel; var chatPanel = areas['chat-panel']; var sideNavMinWidth = sideNav ? resolveLayoutWidth(sideNav.minWidth, viewportWidth) : 0; var panelMinWidth = panel ? resolveLayoutWidth(panel.minWidth, viewportWidth) : 0; var chatPanelMinWidth = chatPanel ? resolveLayoutWidth(chatPanel.minWidth, viewportWidth) : 0; var resizingArea = resizeSession && areas[resizeSession.area]; var isAcknowledged = (resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.completedWidth) !== undefined && ((resizingArea === null || resizingArea === void 0 ? void 0 : resizingArea.requestedWidth) === undefined || resizingArea.requestedWidth === resizeSession.completedWidth); var baselineWidths = (_ref5 = isAcknowledged ? resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.completedWidths : undefined) !== null && _ref5 !== void 0 ? _ref5 : resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.baselineWidths; var layoutModes = (_resizeSession$overla = resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.overlayModes) !== null && _resizeSession$overla !== void 0 ? _resizeSession$overla : initialModes; // A growing panel cascades towards inline-start. Chat is on the other side // of the local rail, so local growth must reserve its full starting width. var shouldCollapseSideNav = Boolean(resizeSession && resizeSession.area !== 'side-nav' && resizeSession.baselineWidths['side-nav'] !== undefined && resizeSession.baselineWidths[resizeSession.area] !== undefined && resizingArea && !isSideNavOverlay && clampTargetWidth({ target: getTargetWidth(resizingArea, isSideNavOverlay), min: resolveLayoutWidth(resizingArea.minWidth, viewportWidth), max: resizingArea.maxWidth !== undefined ? resolveLayoutWidth(resizingArea.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY }) > availableWidth - mainMinWidth - sideNavMinWidth - (resizeSession.area === 'panel' ? resizeSession.baselineWidths['chat-panel'] !== undefined ? (_baselineWidths$chat = baselineWidths === null || baselineWidths === void 0 ? void 0 : baselineWidths['chat-panel']) !== null && _baselineWidths$chat !== void 0 ? _baselineWidths$chat : chatPanelMinWidth : 0 : resizeSession.baselineWidths.panel !== undefined ? panelMinWidth : 0)); var isSideNavOpenInline = Boolean((sideNav === null || sideNav === void 0 ? void 0 : sideNav.isOpen) && !shouldCollapseSideNav && (layoutModes ? layoutModes['side-nav'] === 'inline' : !isSideNavOverlay && availableWidth >= mainMinWidth + sideNavMinWidth)); var isChatPanelOpenInline = Boolean((chatPanel === null || chatPanel === void 0 ? void 0 : chatPanel.isOpen) && (!resizeSession || resizeSession.baselineWidths['chat-panel'] !== undefined) && (layoutModes ? layoutModes['chat-panel'] === 'inline' : !isChatPanelOverlay && availableWidth >= mainMinWidth + chatPanelMinWidth + (isSideNavOpenInline ? sideNavMinWidth : 0))); var isPanelInline = Boolean((panel === null || panel === void 0 ? void 0 : panel.isOpen) && (!resizeSession || resizeSession.baselineWidths.panel !== undefined) && (layoutModes ? layoutModes.panel === 'inline' : availableWidth >= mainMinWidth + panelMinWidth + (isChatPanelOpenInline ? chatPanelMinWidth : 0) + (isSideNavOpenInline ? sideNavMinWidth : 0))); var inlineAreas = [isSideNavOpenInline && 'side-nav', isPanelInline && 'panel', isChatPanelOpenInline && 'chat-panel'].filter(function (area) { return Boolean(area); }); var widths = new Map(); var minimums = new Map(); var _iterator = _createForOfIteratorHelper(inlineAreas), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var areaName = _step.value; var area = areas[areaName]; if (!area) { continue; } var min = resolveLayoutWidth(area.minWidth, viewportWidth); var max = area.maxWidth ? resolveLayoutWidth(area.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY; var baselineWidth = baselineWidths === null || baselineWidths === void 0 ? void 0 : baselineWidths[areaName]; var requestedTarget = resizeSession && areaName !== resizeSession.area ? shouldCollapseSideNav && resizeSession.area === 'chat-panel' ? min : baselineWidth !== null && baselineWidth !== void 0 ? baselineWidth : getTargetWidth(area, isSideNavOverlay) : getTargetWidth(area, isSideNavOverlay); var target = clampTargetWidth({ target: requestedTarget, min: min, max: max }); minimums.set(areaName, min); widths.set(areaName, target); } // Narrowing Chat moves the shared rail towards inline-end. Give the released // space to its inline neighbour so local grows instead of sliding across Main. // Use effective (clamped) widths and the session baseline, not each drag frame, // so reversing direction and completing a controlled resize do not add it twice. } catch (err) { _iterator.e(err); } finally { _iterator.f(); } if ((resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.area) === 'chat-panel' && isChatPanelOpenInline && isPanelInline && panel) { var _widths$get, _baselineWidths$chat2, _widths$get2; var chatWidth = (_widths$get = widths.get('chat-panel')) !== null && _widths$get !== void 0 ? _widths$get : 0; var releasedWidth = Math.max(0, ((_baselineWidths$chat2 = baselineWidths === null || baselineWidths === void 0 ? void 0 : baselineWidths['chat-panel']) !== null && _baselineWidths$chat2 !== void 0 ? _baselineWidths$chat2 : chatWidth) - chatWidth); var panelMaxWidth = panel.maxWidth !== undefined ? Math.max(panelMinWidth, resolveLayoutWidth(panel.maxWidth, viewportWidth)) : Number.POSITIVE_INFINITY; widths.set('panel', Math.min(panelMaxWidth, ((_widths$get2 = widths.get('panel')) !== null && _widths$get2 !== void 0 ? _widths$get2 : 0) + releasedWidth)); } // Continuing to pull the local rail towards Chat after local reaches its // minimum gives Main the remaining space available in inline Chat. if ((resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.area) === 'panel' && (panel === null || panel === void 0 || (_panel$liveResize = panel.liveResize) === null || _panel$liveResize === void 0 ? void 0 : _panel$liveResize.mode) === 'inline' && isChatPanelOpenInline) { var _widths$get3; var remainingDrag = Math.max(0, panelMinWidth - panel.liveResize.width); var _chatWidth = (_widths$get3 = widths.get('chat-panel')) !== null && _widths$get3 !== void 0 ? _widths$get3 : 0; widths.set('chat-panel', Math.max(chatPanelMinWidth, _chatWidth - remainingDrag)); } var overflow = Math.max(0, Array.from(widths.values()).reduce(function (total, width) { return total + width; }, 0) - (availableWidth - mainMinWidth)); var compressionOrder = ['panel', 'chat-panel', 'side-nav']; // Main gives up spare space first. Only regions beyond the moving rail may // then compress: local growth moves towards SideNav, never towards Chat. // SideNav and Chat growth can reach both other regions in their direction. var shrinkOrder = resizeSession ? resizeSession.area === 'panel' ? ['side-nav', 'panel'] : [].concat(_toConsumableArray(compressionOrder.filter(function (area) { return area !== resizeSession.area; })), [resizeSession.area]) : compressionOrder; var _iterator2 = _createForOfIteratorHelper(shrinkOrder), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _widths$get4, _minimums$get; var _areaName = _step2.value; if (overflow <= 0) { break; } var width = (_widths$get4 = widths.get(_areaName)) !== null && _widths$get4 !== void 0 ? _widths$get4 : 0; var _min = (_minimums$get = minimums.get(_areaName)) !== null && _minimums$get !== void 0 ? _minimums$get : 0; var reduction = Math.min(overflow, Math.max(0, width - _min)); widths.set(_areaName, width - reduction); overflow -= reduction; } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } var states = {}; var _iterator3 = _createForOfIteratorHelper(inlineAreas), _step3; try { var _loop = function _loop() { var _widths$get5, _minimums$get2, _areas$areaName; var areaName = _step3.value; var width = (_widths$get5 = widths.get(areaName)) !== null && _widths$get5 !== void 0 ? _widths$get5 : 0; var min = (_minimums$get2 = minimums.get(areaName)) !== null && _minimums$get2 !== void 0 ? _minimums$get2 : 0; var maxWidth = (_areas$areaName = areas[areaName]) === null || _areas$areaName === void 0 ? void 0 : _areas$areaName.maxWidth; var configuredMax = maxWidth !== undefined ? resolveLayoutWidth(maxWidth, viewportWidth) : Number.POSITIVE_INFINITY; states[areaName] = { mode: 'inline', width: width, minWidth: min, resizeBounds: { min: min, max: Math.max(min, Math.min(configuredMax, availableWidth - mainMinWidth - inlineAreas.reduce(function (total, sibling) { var _widths$get6, _minimums$get3; return sibling === areaName || sibling === 'side-nav' && areaName !== 'side-nav' ? total : total + (areaName === 'panel' && sibling === 'chat-panel' ? (_widths$get6 = widths.get(sibling)) !== null && _widths$get6 !== void 0 ? _widths$get6 : 0 : (_minimums$get3 = minimums.get(sibling)) !== null && _minimums$get3 !== void 0 ? _minimums$get3 : 0); }, 0))) } }; }; for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { _loop(); } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } var inlineSideNavWidth = (_states$sideNav$widt = (_states$sideNav = states['side-nav']) === null || _states$sideNav === void 0 ? void 0 : _states$sideNav.width) !== null && _states$sideNav$widt !== void 0 ? _states$sideNav$widt : 0; var inlineChatPanelWidth = (_states$chatPanel$wi = (_states$chatPanel = states['chat-panel']) === null || _states$chatPanel === void 0 ? void 0 : _states$chatPanel.width) !== null && _states$chatPanel$wi !== void 0 ? _states$chatPanel$wi : 0; var mainAreaWidth = Math.max(0, availableWidth - inlineSideNavWidth - inlineChatPanelWidth); var _iterator4 = _createForOfIteratorHelper(['side-nav', 'panel', 'chat-panel']), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var _states$_areaName; var _areaName2 = _step4.value; var _area = areas[_areaName2]; if (!(_area !== null && _area !== void 0 && _area.isOpen) || ((_states$_areaName = states[_areaName2]) === null || _states$_areaName === void 0 ? void 0 : _states$_areaName.mode) === 'inline' || _areaName2 === 'side-nav' && shouldCollapseSideNav) { continue; } var _min2 = resolveLayoutWidth(_area.minWidth, viewportWidth); var configuredMax = _area.maxWidth ? resolveLayoutWidth(_area.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY; // Chat covers Root; SideNav and the local panel overlay Main's grid track. // Occupied tracks and inline chat are not part of that covered region. var layoutMax = (_areaName2 === 'chat-panel' ? layoutWidth : mainAreaWidth) * 0.9; var _max = Math.max(0, Math.min(configuredMax, layoutMax)); var effectiveMin = Math.min(_min2, _max); var _target = getOverlayTargetWidth(_area, isSideNavOverlay, _areaName2); var _width = clampTargetWidth({ target: _target, min: effectiveMin, max: _max }); states[_areaName2] = { mode: 'overlay', width: _width, minWidth: effectiveMin, resizeBounds: { min: effectiveMin, max: _max } }; } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } return states; }