@atlaskit/navigation-system 11.3.0 → 11.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/ui/page-layout/calculate-layout-area-states.js +76 -37
  3. package/dist/cjs/ui/page-layout/chat-panel.js +6 -3
  4. package/dist/cjs/ui/page-layout/layout-area-sizing-context.js +2 -2
  5. package/dist/cjs/ui/page-layout/layout-area-sizing-provider.js +243 -247
  6. package/dist/cjs/ui/page-layout/layout-area-sizing-runtime.js +468 -0
  7. package/dist/cjs/ui/page-layout/main/main.js +1 -1
  8. package/dist/cjs/ui/page-layout/panel-splitter/panel-splitter.js +239 -99
  9. package/dist/cjs/ui/page-layout/panel-splitter/provider.js +3 -1
  10. package/dist/cjs/ui/page-layout/root.compiled.css +14 -3
  11. package/dist/cjs/ui/page-layout/root.js +43 -17
  12. package/dist/cjs/ui/page-layout/side-nav/side-nav.js +14 -3
  13. package/dist/cjs/ui/page-layout/use-css-layout-area-states.js +117 -0
  14. package/dist/cjs/ui/page-layout/use-layout-area-sizing.js +3 -1
  15. package/dist/es2019/ui/page-layout/calculate-layout-area-states.js +51 -17
  16. package/dist/es2019/ui/page-layout/chat-panel.js +29 -5
  17. package/dist/es2019/ui/page-layout/layout-area-sizing-context.js +2 -2
  18. package/dist/es2019/ui/page-layout/layout-area-sizing-provider.js +171 -241
  19. package/dist/es2019/ui/page-layout/layout-area-sizing-runtime.js +419 -0
  20. package/dist/es2019/ui/page-layout/main/main.js +2 -2
  21. package/dist/es2019/ui/page-layout/panel-splitter/panel-splitter.js +60 -10
  22. package/dist/es2019/ui/page-layout/panel-splitter/provider.js +3 -1
  23. package/dist/es2019/ui/page-layout/root.compiled.css +14 -3
  24. package/dist/es2019/ui/page-layout/root.js +30 -3
  25. package/dist/es2019/ui/page-layout/side-nav/side-nav.js +23 -3
  26. package/dist/es2019/ui/page-layout/use-css-layout-area-states.js +73 -0
  27. package/dist/es2019/ui/page-layout/use-layout-area-sizing.js +3 -1
  28. package/dist/esm/ui/page-layout/calculate-layout-area-states.js +75 -37
  29. package/dist/esm/ui/page-layout/chat-panel.js +7 -4
  30. package/dist/esm/ui/page-layout/layout-area-sizing-context.js +2 -2
  31. package/dist/esm/ui/page-layout/layout-area-sizing-provider.js +243 -248
  32. package/dist/esm/ui/page-layout/layout-area-sizing-runtime.js +459 -0
  33. package/dist/esm/ui/page-layout/main/main.js +2 -2
  34. package/dist/esm/ui/page-layout/panel-splitter/panel-splitter.js +238 -98
  35. package/dist/esm/ui/page-layout/panel-splitter/provider.js +3 -1
  36. package/dist/esm/ui/page-layout/root.compiled.css +14 -3
  37. package/dist/esm/ui/page-layout/root.js +42 -16
  38. package/dist/esm/ui/page-layout/side-nav/side-nav.js +14 -3
  39. package/dist/esm/ui/page-layout/use-css-layout-area-states.js +110 -0
  40. package/dist/esm/ui/page-layout/use-layout-area-sizing.js +3 -1
  41. package/dist/types/ui/page-layout/calculate-layout-area-states.d.ts +7 -2
  42. package/dist/types/ui/page-layout/layout-area-sizing-context.d.ts +10 -3
  43. package/dist/types/ui/page-layout/layout-area-sizing-provider.d.ts +6 -0
  44. package/dist/types/ui/page-layout/layout-area-sizing-runtime.d.ts +8 -0
  45. package/dist/types/ui/page-layout/panel-splitter/panel-splitter-context.d.ts +4 -0
  46. package/dist/types/ui/page-layout/panel-splitter/provider.d.ts +1 -1
  47. package/dist/types/ui/page-layout/root.d.ts +2 -0
  48. package/dist/types/ui/page-layout/use-css-layout-area-states.d.ts +8 -0
  49. package/dist/types/ui/page-layout/use-layout-area-sizing.d.ts +2 -0
  50. package/package.json +12 -6
@@ -31,6 +31,7 @@ var _hoistSlotSizesContext = require("../hoist-slot-sizes-context");
31
31
  var _convertResizeBoundToPixels = require("../panel-splitter/convert-resize-bound-to-pixels");
32
32
  var _provider = require("../panel-splitter/provider");
33
33
  var _resolveLayoutWidth = require("../resolve-layout-width");
34
+ var _root = require("../root");
34
35
  var _useLayoutAreaSizing2 = require("../use-layout-area-sizing");
35
36
  var _useLayoutId = require("../use-layout-id");
36
37
  var _useResizingWidthCssVarOnRootElement = require("../use-resizing-width-css-var-on-root-element");
@@ -256,6 +257,8 @@ function SideNavInternal(_ref) {
256
257
  }
257
258
  }),
258
259
  managedSizing = _useLayoutAreaSizing.state,
260
+ isManaged = _useLayoutAreaSizing.isManaged,
261
+ prepareResize = _useLayoutAreaSizing.prepareResize,
259
262
  getManagedResizeBounds = _useLayoutAreaSizing.getResizeBounds,
260
263
  startResize = _useLayoutAreaSizing.startResize,
261
264
  resize = _useLayoutAreaSizing.resize,
@@ -353,6 +356,9 @@ function SideNavInternal(_ref) {
353
356
  type: 'not-active'
354
357
  });
355
358
  var isFlyoutVisible = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open';
359
+ // Flyouts, including their close animation, already have overlay placement.
360
+ // The CSS-first inline allocation must not override it with an ID selector.
361
+ var shouldApplyUnmanagedSizing = !managedSizing && (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) !== 'open' && (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) !== 'triggered-animate-close';
356
362
  var isExpandedOnDesktopRef = (0, _useStableRef.default)(isExpandedOnDesktop);
357
363
  var hasPeekStartedRef = (0, _react.useRef)(false);
358
364
  var onPeekStartRef = (0, _useStableRef.default)(onPeekStart);
@@ -892,7 +898,11 @@ function SideNavInternal(_ref) {
892
898
  ref: mergedRef,
893
899
  "data-testid": testId,
894
900
  className: (0, _runtime.ax)([styles.root, isChatPanelLayoutEnabled && styles.chatPanelSizing, isChatPanelLayoutEnabled && (managedSizing === null || managedSizing === void 0 ? void 0 : managedSizing.mode) === 'overlay' && styles.managedOverlay, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, isMotionUpliftEnabled && motionUpliftStyles.animationRTLSupport, shouldShowSidebarToggleAnimation && isMotionUpliftEnabled && motionUpliftStyles.animationBaseStyles, isExpandedOnMobile && shouldShowSidebarToggleAnimation && isMotionUpliftEnabled && motionUpliftStyles.expandAnimationMobile, !isExpandedOnMobile && shouldShowSidebarToggleAnimation && isMotionUpliftEnabled && motionUpliftStyles.collapseAnimationMobile, isExpandedOnDesktop && shouldShowSidebarToggleAnimation && isMotionUpliftEnabled && motionUpliftStyles.expandAnimationDesktop, !isExpandedOnDesktop && shouldShowSidebarToggleAnimation && isMotionUpliftEnabled && motionUpliftStyles.collapseAnimationDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && isMotionUpliftEnabled && motionUpliftStyles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !isMotionUpliftEnabled && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && isMotionUpliftEnabled && motionUpliftStyles.flyoutAnimateClosed, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isMotionUpliftEnabled && styles.flyoutAnimateClosed])
895
- }), /*#__PURE__*/_react.default.createElement(_dangerouslyHoistCssVarToDocumentRoot.DangerouslyHoistCssVarToDocumentRoot, {
901
+ }), isChatPanelLayoutEnabled &&
902
+ /*#__PURE__*/
903
+ // CSS reserves only the nav minimum for chat's fit decision, before effects or lazy loading.
904
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles
905
+ _react.default.createElement("style", null, "\n#".concat(_root.gridRootChatFitId, " { --n_fitNav: 0px; }\n").concat(shouldApplyUnmanagedSizing ? "#".concat(_root.gridRootId, " nav[data-layout-slot] { grid-area: main / aside / aside / aside; width: min(90%, ").concat(clampedWidth, "); }") : '', "\n@media (min-width: 64rem) {\n @container navigation-main-space (min-width: ").concat(minWidth, ") {\n #").concat(_root.gridRootChatFitId, " { --n_fitNav: ").concat(isExpandedOnDesktop ? minWidth : '0px', "; }\n ").concat(shouldApplyUnmanagedSizing ? "#".concat(_root.gridRootId, " nav[data-layout-slot] { grid-area: side-nav; width: min(").concat(clampedWidth, ", calc(100cqw + var(--n_fitNav) - var(--n_chatTrack, 0px))); }") : '', "\n }\n}\n")), /*#__PURE__*/_react.default.createElement(_dangerouslyHoistCssVarToDocumentRoot.DangerouslyHoistCssVarToDocumentRoot, {
896
906
  variableName: _constants.sideNavLiveWidthVar,
897
907
  value: "0px",
898
908
  mediaQuery: '@media (min-width: 64rem)',
@@ -912,8 +922,9 @@ function SideNavInternal(_ref) {
912
922
  panelRef: navRef,
913
923
  panelWidth: renderedWidth,
914
924
  onCompleteResize: onCompleteResize,
915
- onResizeStartInternal: isChatPanelLayoutEnabled && managedSizing ? onResizeStartInternal : undefined,
916
- onResizeInternal: isChatPanelLayoutEnabled && managedSizing ? onResizeInternal : undefined,
925
+ onResizeStartInternal: isChatPanelLayoutEnabled && isManaged ? onResizeStartInternal : undefined,
926
+ onResizeInternal: isChatPanelLayoutEnabled && isManaged ? onResizeInternal : undefined,
927
+ prepareResize: isChatPanelLayoutEnabled ? prepareResize : undefined,
917
928
  getResizeBounds: getResizeBounds,
918
929
  resizingCssVar: panelSplitterResizingVar
919
930
  // Not resizable when in peek (flyout) mode.
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useCssLayoutAreaStates = useCssLayoutAreaStates;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _react = require("react");
11
+ var _bindEventListener = require("bind-event-listener");
12
+ 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; } } }; }
13
+ 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; } }
14
+ 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; }
15
+ /**
16
+ * Observe CSS's responsive modes without loading the drag allocator or publishing
17
+ * measured widths back into CSS. Observe the host and independent occupied tracks;
18
+ * managed panels, TopNav and Banner are deliberately not observed during dragging.
19
+ */
20
+ function useCssLayoutAreaStates(layoutRef, revision, isEnabled) {
21
+ var _useState = (0, _react.useState)({}),
22
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
23
+ modes = _useState2[0],
24
+ setModes = _useState2[1];
25
+ (0, _react.useEffect)(function () {
26
+ var root = layoutRef === null || layoutRef === void 0 ? void 0 : layoutRef.current;
27
+ if (!root || !isEnabled) {
28
+ return;
29
+ }
30
+ var measure = function measure() {
31
+ var selectors = {
32
+ 'side-nav': ':scope > nav[data-layout-slot]',
33
+ panel: '[data-layout-with-panel-slot]',
34
+ 'chat-panel': ':scope > [data-layout-chat-panel]'
35
+ };
36
+ var next = {};
37
+ var _iterator = _createForOfIteratorHelper(['side-nav', 'panel', 'chat-panel']),
38
+ _step;
39
+ try {
40
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
41
+ var area = _step.value;
42
+ var element = root.querySelector(selectors[area]);
43
+ if (element) {
44
+ next[area] = getComputedStyle(element).gridArea.split('/')[0].trim() === area ? 'inline' : 'overlay';
45
+ }
46
+ }
47
+ } catch (err) {
48
+ _iterator.e(err);
49
+ } finally {
50
+ _iterator.f();
51
+ }
52
+ setModes(function (previous) {
53
+ return ['side-nav', 'panel', 'chat-panel'].every(function (area) {
54
+ return previous[area] === next[area];
55
+ }) ? previous : next;
56
+ });
57
+ };
58
+ var widths = new Map();
59
+ var observer = new ResizeObserver(function (entries) {
60
+ var changed = false;
61
+ var _iterator2 = _createForOfIteratorHelper(entries),
62
+ _step2;
63
+ try {
64
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
65
+ var entry = _step2.value;
66
+ if (widths.get(entry.target) !== entry.contentRect.width) {
67
+ widths.set(entry.target, entry.contentRect.width);
68
+ changed = true;
69
+ }
70
+ }
71
+ } catch (err) {
72
+ _iterator2.e(err);
73
+ } finally {
74
+ _iterator2.f();
75
+ }
76
+ if (changed) {
77
+ measure();
78
+ }
79
+ });
80
+ var observeSlots = function observeSlots() {
81
+ observer.disconnect();
82
+ widths.clear();
83
+ var occupied = Array.from(root.children).filter(function (element) {
84
+ return element.matches('[data-layout-slot]:not(nav):not(header):not([role="main"]):not([data-layout-chat-panel])') && ['aside', 'ribbon', 'panel'].includes(getComputedStyle(element).gridArea.split('/')[0].trim());
85
+ });
86
+ for (var _i = 0, _arr = [root].concat((0, _toConsumableArray2.default)(occupied)); _i < _arr.length; _i++) {
87
+ var element = _arr[_i];
88
+ widths.set(element, element.getBoundingClientRect().width);
89
+ observer.observe(element);
90
+ }
91
+ measure();
92
+ };
93
+ observeSlots();
94
+ var mutations = new MutationObserver(observeSlots);
95
+ mutations.observe(root, {
96
+ childList: true
97
+ });
98
+ var queries = [window.matchMedia('(min-width: 40rem)'), window.matchMedia('(min-width: 64rem)')];
99
+ var unbind = [(0, _bindEventListener.bindAll)(window, [{
100
+ type: 'resize',
101
+ listener: measure
102
+ }])].concat((0, _toConsumableArray2.default)(queries.map(function (query) {
103
+ return (0, _bindEventListener.bindAll)(query, [{
104
+ type: 'change',
105
+ listener: measure
106
+ }]);
107
+ })));
108
+ return function () {
109
+ observer.disconnect();
110
+ mutations.disconnect();
111
+ unbind.forEach(function (cleanup) {
112
+ return cleanup();
113
+ });
114
+ };
115
+ }, [isEnabled, layoutRef, revision]);
116
+ return modes;
117
+ }
@@ -68,6 +68,8 @@ function useLayoutAreaSizing(_ref) {
68
68
  startResize: startResize,
69
69
  resize: resize,
70
70
  completeResize: completeResize,
71
- getResizeBounds: getResizeBounds
71
+ getResizeBounds: getResizeBounds,
72
+ isManaged: context !== null,
73
+ prepareResize: context === null || context === void 0 ? void 0 : context.prepareResize
72
74
  };
73
75
  }
@@ -24,9 +24,10 @@ export function calculateLayoutAreaStates({
24
24
  occupiedWidth = 0,
25
25
  mainMinWidth: mainMinWidthBound,
26
26
  areas,
27
- resizeSession
27
+ resizeSession,
28
+ initialModes
28
29
  }) {
29
- var _states$sideNav$widt, _states$sideNav, _states$chatPanel$wi, _states$chatPanel;
30
+ var _ref3, _resizeSession$overla, _baselineWidths$chat, _panel$liveResize, _states$sideNav$widt, _states$sideNav, _states$chatPanel$wi, _states$chatPanel;
30
31
  const mainMinWidth = resolveLayoutWidth(mainMinWidthBound, viewportWidth);
31
32
  const availableWidth = Math.max(0, layoutWidth - occupiedWidth);
32
33
  const sideNav = areas['side-nav'];
@@ -35,9 +36,20 @@ export function calculateLayoutAreaStates({
35
36
  const sideNavMinWidth = sideNav ? resolveLayoutWidth(sideNav.minWidth, viewportWidth) : 0;
36
37
  const panelMinWidth = panel ? resolveLayoutWidth(panel.minWidth, viewportWidth) : 0;
37
38
  const chatPanelMinWidth = chatPanel ? resolveLayoutWidth(chatPanel.minWidth, viewportWidth) : 0;
38
- const isSideNavOpenInline = Boolean((sideNav === null || sideNav === void 0 ? void 0 : sideNav.isOpen) && !isSideNavOverlay && availableWidth >= mainMinWidth + sideNavMinWidth);
39
- const isChatPanelOpenInline = Boolean((chatPanel === null || chatPanel === void 0 ? void 0 : chatPanel.isOpen) && !isChatPanelOverlay && availableWidth >= mainMinWidth + chatPanelMinWidth + (isSideNavOpenInline ? sideNavMinWidth : 0));
40
- const isPanelInline = Boolean((panel === null || panel === void 0 ? void 0 : panel.isOpen) && availableWidth >= mainMinWidth + panelMinWidth + (isChatPanelOpenInline ? chatPanelMinWidth : 0) + (isSideNavOpenInline ? sideNavMinWidth : 0));
39
+ const resizingArea = resizeSession && areas[resizeSession.area];
40
+ const 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);
41
+ const baselineWidths = (_ref3 = isAcknowledged ? resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.completedWidths : undefined) !== null && _ref3 !== void 0 ? _ref3 : resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.baselineWidths;
42
+ const layoutModes = (_resizeSession$overla = resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.overlayModes) !== null && _resizeSession$overla !== void 0 ? _resizeSession$overla : initialModes;
43
+ // A growing panel cascades towards inline-start. Chat is on the other side
44
+ // of the local rail, so local growth must reserve its full starting width.
45
+ const shouldCollapseSideNav = Boolean(resizeSession && resizeSession.area !== 'side-nav' && resizeSession.baselineWidths['side-nav'] !== undefined && resizeSession.baselineWidths[resizeSession.area] !== undefined && resizingArea && !isSideNavOverlay && clampTargetWidth({
46
+ target: getTargetWidth(resizingArea, isSideNavOverlay),
47
+ min: resolveLayoutWidth(resizingArea.minWidth, viewportWidth),
48
+ max: resizingArea.maxWidth !== undefined ? resolveLayoutWidth(resizingArea.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY
49
+ }) > 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));
50
+ const isSideNavOpenInline = Boolean((sideNav === null || sideNav === void 0 ? void 0 : sideNav.isOpen) && !shouldCollapseSideNav && (layoutModes ? layoutModes['side-nav'] === 'inline' : !isSideNavOverlay && availableWidth >= mainMinWidth + sideNavMinWidth));
51
+ const 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)));
52
+ const 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)));
41
53
  const inlineAreas = [isSideNavOpenInline && 'side-nav', isPanelInline && 'panel', isChatPanelOpenInline && 'chat-panel'].filter(area => Boolean(area));
42
54
  const widths = new Map();
43
55
  const minimums = new Map();
@@ -48,8 +60,8 @@ export function calculateLayoutAreaStates({
48
60
  }
49
61
  const min = resolveLayoutWidth(area.minWidth, viewportWidth);
50
62
  const max = area.maxWidth ? resolveLayoutWidth(area.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY;
51
- const baselineWidth = resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.baselineWidths[areaName];
52
- const requestedTarget = resizeSession && areaName !== resizeSession.area && baselineWidth !== undefined ? baselineWidth : getTargetWidth(area, isSideNavOverlay);
63
+ const baselineWidth = baselineWidths === null || baselineWidths === void 0 ? void 0 : baselineWidths[areaName];
64
+ const requestedTarget = resizeSession && areaName !== resizeSession.area ? shouldCollapseSideNav && resizeSession.area === 'chat-panel' ? min : baselineWidth !== null && baselineWidth !== void 0 ? baselineWidth : getTargetWidth(area, isSideNavOverlay) : getTargetWidth(area, isSideNavOverlay);
53
65
  const target = clampTargetWidth({
54
66
  target: requestedTarget,
55
67
  min,
@@ -58,27 +70,46 @@ export function calculateLayoutAreaStates({
58
70
  minimums.set(areaName, min);
59
71
  widths.set(areaName, target);
60
72
  }
73
+ // Narrowing Chat moves the shared rail towards inline-end. Give the released
74
+ // space to its inline neighbour so local grows instead of sliding across Main.
75
+ // Use effective (clamped) widths and the session baseline, not each drag frame,
76
+ // so reversing direction and completing a controlled resize do not add it twice.
77
+ if ((resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.area) === 'chat-panel' && isChatPanelOpenInline && isPanelInline && panel) {
78
+ var _widths$get, _baselineWidths$chat2, _widths$get2;
79
+ const chatWidth = (_widths$get = widths.get('chat-panel')) !== null && _widths$get !== void 0 ? _widths$get : 0;
80
+ const 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);
81
+ const panelMaxWidth = panel.maxWidth !== undefined ? Math.max(panelMinWidth, resolveLayoutWidth(panel.maxWidth, viewportWidth)) : Number.POSITIVE_INFINITY;
82
+ widths.set('panel', Math.min(panelMaxWidth, ((_widths$get2 = widths.get('panel')) !== null && _widths$get2 !== void 0 ? _widths$get2 : 0) + releasedWidth));
83
+ }
84
+ // Continuing to pull the local rail towards Chat after local reaches its
85
+ // minimum gives Main the remaining space available in inline Chat.
86
+ if ((resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.area) === 'panel' && (panel === null || panel === void 0 ? void 0 : (_panel$liveResize = panel.liveResize) === null || _panel$liveResize === void 0 ? void 0 : _panel$liveResize.mode) === 'inline' && isChatPanelOpenInline) {
87
+ var _widths$get3;
88
+ const remainingDrag = Math.max(0, panelMinWidth - panel.liveResize.width);
89
+ const chatWidth = (_widths$get3 = widths.get('chat-panel')) !== null && _widths$get3 !== void 0 ? _widths$get3 : 0;
90
+ widths.set('chat-panel', Math.max(chatPanelMinWidth, chatWidth - remainingDrag));
91
+ }
61
92
  let overflow = Math.max(0, Array.from(widths.values()).reduce((total, width) => total + width, 0) - (availableWidth - mainMinWidth));
62
93
  const compressionOrder = ['panel', 'chat-panel', 'side-nav'];
63
- // User resizing consumes only Main's spare width. Viewport changes clear the
64
- // snapshot and retain the normal automatic compression order.
65
- const shrinkOrder = resizeSession ? [resizeSession.area] : compressionOrder;
94
+ // Main gives up spare space first. Only regions beyond the moving rail may
95
+ // then compress: local growth moves towards SideNav, never towards Chat.
96
+ // SideNav and Chat growth can reach both other regions in their direction.
97
+ const shrinkOrder = resizeSession ? resizeSession.area === 'panel' ? ['side-nav', 'panel'] : [...compressionOrder.filter(area => area !== resizeSession.area), resizeSession.area] : compressionOrder;
66
98
  for (const areaName of shrinkOrder) {
67
- var _widths$get, _minimums$get;
99
+ var _widths$get4, _minimums$get;
68
100
  if (overflow <= 0) {
69
101
  break;
70
102
  }
71
- const width = (_widths$get = widths.get(areaName)) !== null && _widths$get !== void 0 ? _widths$get : 0;
103
+ const width = (_widths$get4 = widths.get(areaName)) !== null && _widths$get4 !== void 0 ? _widths$get4 : 0;
72
104
  const min = (_minimums$get = minimums.get(areaName)) !== null && _minimums$get !== void 0 ? _minimums$get : 0;
73
105
  const reduction = Math.min(overflow, Math.max(0, width - min));
74
106
  widths.set(areaName, width - reduction);
75
107
  overflow -= reduction;
76
108
  }
77
- const totalInlineWidth = Array.from(widths.values()).reduce((total, width) => total + width, 0);
78
109
  const states = {};
79
110
  for (const areaName of inlineAreas) {
80
- var _widths$get2, _minimums$get2, _areas$areaName;
81
- const width = (_widths$get2 = widths.get(areaName)) !== null && _widths$get2 !== void 0 ? _widths$get2 : 0;
111
+ var _widths$get5, _minimums$get2, _areas$areaName;
112
+ const width = (_widths$get5 = widths.get(areaName)) !== null && _widths$get5 !== void 0 ? _widths$get5 : 0;
82
113
  const min = (_minimums$get2 = minimums.get(areaName)) !== null && _minimums$get2 !== void 0 ? _minimums$get2 : 0;
83
114
  const maxWidth = (_areas$areaName = areas[areaName]) === null || _areas$areaName === void 0 ? void 0 : _areas$areaName.maxWidth;
84
115
  const configuredMax = maxWidth !== undefined ? resolveLayoutWidth(maxWidth, viewportWidth) : Number.POSITIVE_INFINITY;
@@ -88,7 +119,10 @@ export function calculateLayoutAreaStates({
88
119
  minWidth: min,
89
120
  resizeBounds: {
90
121
  min,
91
- max: Math.max(min, Math.min(configuredMax, availableWidth - mainMinWidth - totalInlineWidth + width))
122
+ max: Math.max(min, Math.min(configuredMax, availableWidth - mainMinWidth - inlineAreas.reduce((total, sibling) => {
123
+ var _widths$get6, _minimums$get3;
124
+ 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);
125
+ }, 0)))
92
126
  }
93
127
  };
94
128
  }
@@ -98,7 +132,7 @@ export function calculateLayoutAreaStates({
98
132
  for (const areaName of ['side-nav', 'panel', 'chat-panel']) {
99
133
  var _states$areaName;
100
134
  const area = areas[areaName];
101
- if (!(area !== null && area !== void 0 && area.isOpen) || ((_states$areaName = states[areaName]) === null || _states$areaName === void 0 ? void 0 : _states$areaName.mode) === 'inline') {
135
+ if (!(area !== null && area !== void 0 && area.isOpen) || ((_states$areaName = states[areaName]) === null || _states$areaName === void 0 ? void 0 : _states$areaName.mode) === 'inline' || areaName === 'side-nav' && shouldCollapseSideNav) {
102
136
  continue;
103
137
  }
104
138
  const min = resolveLayoutWidth(area.minWidth, viewportWidth);
@@ -6,7 +6,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
6
6
  import { bind } from 'bind-event-listener';
7
7
  import { fg } from '@atlaskit/platform-feature-flags/fg';
8
8
  import { useSkipLinkInternal } from '../../context/skip-links/use-skip-link-internal';
9
- import { chatPanelLiveWidthVar, chatPanelVar, mainMinimumWidthVar } from './constants';
9
+ import { chatPanelLiveWidthVar, chatPanelVar, localSlotLayers, mainMinimumWidthVar } from './constants';
10
10
  import { convertResizeBoundToPixels } from './panel-splitter/convert-resize-bound-to-pixels';
11
11
  import { PanelSplitterProvider } from './panel-splitter/provider';
12
12
  import { resolveLayoutWidth } from './resolve-layout-width';
@@ -78,6 +78,8 @@ export function ChatPanel({
78
78
  const [overlayWidth, setOverlayWidth] = useState(compactDefaultWidth);
79
79
  const [isInline, setIsInline] = useState(false);
80
80
  const {
81
+ isManaged,
82
+ prepareResize,
81
83
  state: managedSizing,
82
84
  getResizeBounds: getManagedResizeBounds,
83
85
  startResize,
@@ -181,15 +183,37 @@ export function ChatPanel({
181
183
  // Hoist the committed or actively resizing inline width so SideNav can yield
182
184
  // space to ChatPanel without allowing the page layout to overflow.
183
185
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles
184
- React.createElement("style", null, `
185
- #${gridRootId} { ${chatPanelLiveWidthVar}: var(${panelSplitterResizingVar}, ${chatPanelVariableWidth}); }
186
+ React.createElement("style", null, managedSizing ? `
187
+ #${gridRootId} { --n_chatTrack: ${mode === 'inline' ? `${renderedWidth}px` : '0px'}; ${chatPanelLiveWidthVar}: var(--n_chatTrack); }
188
+ ` : `
189
+ #${gridRootId} { --n_chatTrack: 0px; ${chatPanelLiveWidthVar}: 0px; }
190
+ #${gridRootId} [data-layout-chat-panel] {
191
+ grid-area: 2 / 1 / -1 / -1;
192
+ width: min(calc(var(--n_layoutW) * 0.9), ${chatPanelOverlayVariableWidth});
193
+ z-index: ${localSlotLayers.chatPanelOverlay};
194
+ background-color: ${"var(--ds-surface-overlay, #FFFFFF)"};
195
+ ${hasBorder ? `box-shadow: ${"var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)"}; border-inline-start: none;` : ''}
196
+ }
197
+ @media (min-width: 40rem) {
198
+ @container navigation-chat-space (min-width: ${minWidth}) {
199
+ #${gridRootId} { --n_chatTrack: min(100cqw, var(${panelSplitterResizingVar}, ${chatPanelVariableWidth})); ${chatPanelLiveWidthVar}: var(--n_chatTrack); }
200
+ #${gridRootId} [data-layout-chat-panel] {
201
+ grid-area: chat-panel;
202
+ width: min(100cqw, var(${panelSplitterResizingVar}, ${chatPanelVariableWidth}));
203
+ z-index: auto;
204
+ background-color: ${"var(--ds-surface, #FFFFFF)"};
205
+ ${hasBorder ? `box-shadow: initial; border-inline-start: ${"var(--ds-border-width, 1px)"} solid ${"var(--ds-border, #0B120E24)"};` : ''}
206
+ }
207
+ }
208
+ }
186
209
  `), /*#__PURE__*/React.createElement(PanelSplitterProvider, {
187
210
  panelId: chatPanelPanelSplitterId,
188
211
  panelRef: ref,
189
212
  panelWidth: renderedWidth,
190
213
  onCompleteResize: onCompleteResize,
191
- onResizeStartInternal: managedSizing ? onResizeStartInternal : undefined,
192
- onResizeInternal: managedSizing ? onResizeInternal : undefined,
214
+ prepareResize: prepareResize,
215
+ onResizeStartInternal: isManaged ? onResizeStartInternal : undefined,
216
+ onResizeInternal: isManaged ? onResizeInternal : undefined,
193
217
  getResizeBounds: getResizeBounds,
194
218
  resizingCssVar: panelSplitterResizingVar,
195
219
  position: "start"
@@ -1,8 +1,8 @@
1
1
  import { createContext } from 'react';
2
2
 
3
3
  /**
4
- * Effective sibling widths held fixed during and after a user resize, until the
5
- * layout dimensions or configuration change. This is not a resize history.
4
+ * One resize transaction. Keep its starting widths for controlled rejection,
5
+ * and its resulting widths for synchronous or delayed acknowledgement.
6
6
  */
7
7
 
8
8
  export const LayoutAreaSizingContext = /*#__PURE__*/createContext(null);