@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
@@ -15,13 +15,39 @@ import { SideNavVisibilityProvider } from './side-nav/visibility-provider';
15
15
 
16
16
  // ID of the root element that the banner and top bar slots hoist their sizes to. Only internally exported.
17
17
  export const gridRootId = 'unsafe-design-system-page-layout-root';
18
+ export const gridRootFitId = `${gridRootId}-fit`;
19
+ export const gridRootChatFitId = `${gridRootId}-chat-fit`;
18
20
  const styles = {
21
+ widthContainer: "_7cca15wb _1f38hx13 _1bsb1osq",
22
+ mainSpace: "_82d6okmw _1cwmtye8 _7cca15wb _1f38hwoh _vchh1ntv _1bsb1raa",
23
+ chatSpace: "_5to3grho _7cca15wb _1f381mry _1bsbjwgu",
19
24
  legacyRoot: "_1e0c11p5 _1tke1kxc _1lmcq9em _yv0ei47z _2z0516ab _12fk1aio _12qzrxre _1rqteala _xkmgks3h _jbc7rxre _tyve1nco",
20
- root: "_1cwmtye8 _1e0c11p5 _1tke1kxc _1lmcq9em _yv0ei47z _2z0516ab _12ag50j2 _71dlqwpl _12fkqmyk _12qzrxre _1rqt8mqp _xkmggc7l _tyve1i18",
25
+ root: "_1cwmtye8 _1e0c11p5 _1tke1kxc _1bsb4nr3 _1lmcq9em _yv0ei47z _2z0516ab _12ag50j2 _71dl19sb _12fkqmyk _12qzrxre _1rqttswr _xkmggc7l _tyve87m4",
21
26
  safetyRail: "_1ciragmp",
22
27
  safetyRailWithTopLayer: "_1tvnagmp",
23
28
  panelUplift: "_1reozryt _18m9zryt"
24
29
  };
30
+ function LayoutFitContainers({
31
+ children
32
+ }) {
33
+ // CSS cannot use custom properties in a size-query condition. Query the
34
+ // remaining capacity instead: these wrappers subtract configured minimums
35
+ // and occupied tracks, while the actual grid keeps its original host width.
36
+ return /*#__PURE__*/React.createElement("div", {
37
+ "data-layout-width-container": "",
38
+ className: ax([styles.widthContainer])
39
+ }, /*#__PURE__*/React.createElement("style", {
40
+ dangerouslySetInnerHTML: {
41
+ __html: `@property --n_layoutW { syntax: '<length>'; inherits: true; initial-value: 0px; }`
42
+ }
43
+ }), /*#__PURE__*/React.createElement("div", {
44
+ id: gridRootFitId,
45
+ className: ax([styles.mainSpace])
46
+ }, /*#__PURE__*/React.createElement("div", {
47
+ id: gridRootChatFitId,
48
+ className: ax([styles.chatSpace])
49
+ }, children)));
50
+ }
25
51
 
26
52
  /**
27
53
  * The root component of the navigation system. It wraps the underlying components with the necessary contexts allowing to use certain data and hooks
@@ -40,6 +66,7 @@ export function Root({
40
66
  const ref = useRef(null);
41
67
  const isChatPanelLayoutEnabled = fg('platform-dst-chat-panel-layout');
42
68
  const LayoutProvider = isChatPanelLayoutEnabled ? LayoutAreaSizingProvider : React.Fragment;
69
+ const WidthContainer = isChatPanelLayoutEnabled ? LayoutFitContainers : React.Fragment;
43
70
  useEffect(() => {
44
71
  if (process.env.NODE_ENV !== 'production') {
45
72
  const IGNORED_ELEMENTS = ['SCRIPT', 'STYLE'];
@@ -77,10 +104,10 @@ This message will not be displayed in production.
77
104
  label: skipLinksLabel,
78
105
  triggerLabel: skipLinksTriggerLabel,
79
106
  testId: testId
80
- }, /*#__PURE__*/React.createElement("div", {
107
+ }, /*#__PURE__*/React.createElement(WidthContainer, null, /*#__PURE__*/React.createElement("div", {
81
108
  ref: ref,
82
109
  className: ax([isChatPanelLayoutEnabled ? styles.root : styles.legacyRoot, fg('platform-dst-motion-uplift-panel') && styles.panelUplift, fg('platform-dst-top-layer') ? styles.safetyRailWithTopLayer : styles.safetyRail, xcss]),
83
110
  id: gridRootId,
84
111
  "data-testid": testId
85
- }, children))))))))));
112
+ }, children)))))))))));
86
113
  }
@@ -22,6 +22,7 @@ import { DangerouslyHoistSlotSizes } from '../hoist-slot-sizes-context';
22
22
  import { convertResizeBoundToPixels } from '../panel-splitter/convert-resize-bound-to-pixels';
23
23
  import { PanelSplitterProvider } from '../panel-splitter/provider';
24
24
  import { resolveLayoutWidth } from '../resolve-layout-width';
25
+ import { gridRootChatFitId, gridRootId } from '../root';
25
26
  import { useLayoutAreaSizing } from '../use-layout-area-sizing';
26
27
  import { useLayoutId } from '../use-layout-id';
27
28
  import { useResizingWidthCssVarOnRootElement } from '../use-resizing-width-css-var-on-root-element';
@@ -219,6 +220,8 @@ function SideNavInternal({
219
220
  }, [isExpandedOnDesktop, isExpandedOnMobile, toggleVisibilityForChatPanel]);
220
221
  const {
221
222
  state: managedSizing,
223
+ isManaged,
224
+ prepareResize,
222
225
  getResizeBounds: getManagedResizeBounds,
223
226
  startResize,
224
227
  resize,
@@ -324,6 +327,9 @@ function SideNavInternal({
324
327
  type: 'not-active'
325
328
  });
326
329
  const isFlyoutVisible = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open';
330
+ // Flyouts, including their close animation, already have overlay placement.
331
+ // The CSS-first inline allocation must not override it with an ID selector.
332
+ const shouldApplyUnmanagedSizing = !managedSizing && (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) !== 'open' && (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) !== 'triggered-animate-close';
327
333
  const isExpandedOnDesktopRef = useStableRef(isExpandedOnDesktop);
328
334
  const hasPeekStartedRef = useRef(false);
329
335
  const onPeekStartRef = useStableRef(onPeekStart);
@@ -874,7 +880,20 @@ function SideNavInternal({
874
880
  ref: mergedRef,
875
881
  "data-testid": testId,
876
882
  className: 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])
877
- }), /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
883
+ }), isChatPanelLayoutEnabled &&
884
+ /*#__PURE__*/
885
+ // CSS reserves only the nav minimum for chat's fit decision, before effects or lazy loading.
886
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles
887
+ React.createElement("style", null, `
888
+ #${gridRootChatFitId} { --n_fitNav: 0px; }
889
+ ${shouldApplyUnmanagedSizing ? `#${gridRootId} nav[data-layout-slot] { grid-area: main / aside / aside / aside; width: min(90%, ${clampedWidth}); }` : ''}
890
+ @media (min-width: 64rem) {
891
+ @container navigation-main-space (min-width: ${minWidth}) {
892
+ #${gridRootChatFitId} { --n_fitNav: ${isExpandedOnDesktop ? minWidth : '0px'}; }
893
+ ${shouldApplyUnmanagedSizing ? `#${gridRootId} nav[data-layout-slot] { grid-area: side-nav; width: min(${clampedWidth}, calc(100cqw + var(--n_fitNav) - var(--n_chatTrack, 0px))); }` : ''}
894
+ }
895
+ }
896
+ `), /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
878
897
  variableName: sideNavLiveWidthVar,
879
898
  value: "0px",
880
899
  mediaQuery: '@media (min-width: 64rem)',
@@ -894,8 +913,9 @@ function SideNavInternal({
894
913
  panelRef: navRef,
895
914
  panelWidth: renderedWidth,
896
915
  onCompleteResize: onCompleteResize,
897
- onResizeStartInternal: isChatPanelLayoutEnabled && managedSizing ? onResizeStartInternal : undefined,
898
- onResizeInternal: isChatPanelLayoutEnabled && managedSizing ? onResizeInternal : undefined,
916
+ onResizeStartInternal: isChatPanelLayoutEnabled && isManaged ? onResizeStartInternal : undefined,
917
+ onResizeInternal: isChatPanelLayoutEnabled && isManaged ? onResizeInternal : undefined,
918
+ prepareResize: isChatPanelLayoutEnabled ? prepareResize : undefined,
899
919
  getResizeBounds: getResizeBounds,
900
920
  resizingCssVar: panelSplitterResizingVar
901
921
  // Not resizable when in peek (flyout) mode.
@@ -0,0 +1,73 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { bindAll } from 'bind-event-listener';
3
+ /**
4
+ * Observe CSS's responsive modes without loading the drag allocator or publishing
5
+ * measured widths back into CSS. Observe the host and independent occupied tracks;
6
+ * managed panels, TopNav and Banner are deliberately not observed during dragging.
7
+ */
8
+ export function useCssLayoutAreaStates(layoutRef, revision, isEnabled) {
9
+ const [modes, setModes] = useState({});
10
+ useEffect(() => {
11
+ const root = layoutRef === null || layoutRef === void 0 ? void 0 : layoutRef.current;
12
+ if (!root || !isEnabled) {
13
+ return;
14
+ }
15
+ const measure = () => {
16
+ const selectors = {
17
+ 'side-nav': ':scope > nav[data-layout-slot]',
18
+ panel: '[data-layout-with-panel-slot]',
19
+ 'chat-panel': ':scope > [data-layout-chat-panel]'
20
+ };
21
+ const next = {};
22
+ for (const area of ['side-nav', 'panel', 'chat-panel']) {
23
+ const element = root.querySelector(selectors[area]);
24
+ if (element) {
25
+ next[area] = getComputedStyle(element).gridArea.split('/')[0].trim() === area ? 'inline' : 'overlay';
26
+ }
27
+ }
28
+ setModes(previous => ['side-nav', 'panel', 'chat-panel'].every(area => previous[area] === next[area]) ? previous : next);
29
+ };
30
+ const widths = new Map();
31
+ const observer = new ResizeObserver(entries => {
32
+ let changed = false;
33
+ for (const entry of entries) {
34
+ if (widths.get(entry.target) !== entry.contentRect.width) {
35
+ widths.set(entry.target, entry.contentRect.width);
36
+ changed = true;
37
+ }
38
+ }
39
+ if (changed) {
40
+ measure();
41
+ }
42
+ });
43
+ const observeSlots = () => {
44
+ observer.disconnect();
45
+ widths.clear();
46
+ const occupied = Array.from(root.children).filter(element => 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()));
47
+ for (const element of [root, ...occupied]) {
48
+ widths.set(element, element.getBoundingClientRect().width);
49
+ observer.observe(element);
50
+ }
51
+ measure();
52
+ };
53
+ observeSlots();
54
+ const mutations = new MutationObserver(observeSlots);
55
+ mutations.observe(root, {
56
+ childList: true
57
+ });
58
+ const queries = [window.matchMedia('(min-width: 40rem)'), window.matchMedia('(min-width: 64rem)')];
59
+ const unbind = [bindAll(window, [{
60
+ type: 'resize',
61
+ listener: measure
62
+ }]), ...queries.map(query => bindAll(query, [{
63
+ type: 'change',
64
+ listener: measure
65
+ }]))];
66
+ return () => {
67
+ observer.disconnect();
68
+ mutations.disconnect();
69
+ unbind.forEach(cleanup => cleanup());
70
+ };
71
+ }, [isEnabled, layoutRef, revision]);
72
+ return modes;
73
+ }
@@ -53,6 +53,8 @@ export function useLayoutAreaSizing({
53
53
  startResize,
54
54
  resize,
55
55
  completeResize,
56
- getResizeBounds
56
+ getResizeBounds,
57
+ isManaged: context !== null,
58
+ prepareResize: context === null || context === void 0 ? void 0 : context.prepareResize
57
59
  };
58
60
  }
@@ -1,3 +1,4 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  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; } } }; }
2
3
  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; } }
3
4
  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; }
@@ -19,7 +20,7 @@ function getOverlayTargetWidth(area, isSideNavOverlay) {
19
20
  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 : area.preferredOverlayWidth) !== null && _ref3 !== void 0 ? _ref3 : defaultWidth;
20
21
  }
21
22
  export function calculateLayoutAreaStates(_ref4) {
22
- var _states$sideNav$widt, _states$sideNav, _states$chatPanel$wi, _states$chatPanel;
23
+ var _ref5, _resizeSession$overla, _baselineWidths$chat, _panel$liveResize, _states$sideNav$widt, _states$sideNav, _states$chatPanel$wi, _states$chatPanel;
23
24
  var viewportWidth = _ref4.viewportWidth,
24
25
  _ref4$layoutWidth = _ref4.layoutWidth,
25
26
  layoutWidth = _ref4$layoutWidth === void 0 ? viewportWidth : _ref4$layoutWidth,
@@ -29,7 +30,8 @@ export function calculateLayoutAreaStates(_ref4) {
29
30
  occupiedWidth = _ref4$occupiedWidth === void 0 ? 0 : _ref4$occupiedWidth,
30
31
  mainMinWidthBound = _ref4.mainMinWidth,
31
32
  areas = _ref4.areas,
32
- resizeSession = _ref4.resizeSession;
33
+ resizeSession = _ref4.resizeSession,
34
+ initialModes = _ref4.initialModes;
33
35
  var mainMinWidth = resolveLayoutWidth(mainMinWidthBound, viewportWidth);
34
36
  var availableWidth = Math.max(0, layoutWidth - occupiedWidth);
35
37
  var sideNav = areas['side-nav'];
@@ -38,9 +40,20 @@ export function calculateLayoutAreaStates(_ref4) {
38
40
  var sideNavMinWidth = sideNav ? resolveLayoutWidth(sideNav.minWidth, viewportWidth) : 0;
39
41
  var panelMinWidth = panel ? resolveLayoutWidth(panel.minWidth, viewportWidth) : 0;
40
42
  var chatPanelMinWidth = chatPanel ? resolveLayoutWidth(chatPanel.minWidth, viewportWidth) : 0;
41
- var isSideNavOpenInline = Boolean((sideNav === null || sideNav === void 0 ? void 0 : sideNav.isOpen) && !isSideNavOverlay && availableWidth >= mainMinWidth + sideNavMinWidth);
42
- var isChatPanelOpenInline = Boolean((chatPanel === null || chatPanel === void 0 ? void 0 : chatPanel.isOpen) && !isChatPanelOverlay && availableWidth >= mainMinWidth + chatPanelMinWidth + (isSideNavOpenInline ? sideNavMinWidth : 0));
43
- var isPanelInline = Boolean((panel === null || panel === void 0 ? void 0 : panel.isOpen) && availableWidth >= mainMinWidth + panelMinWidth + (isChatPanelOpenInline ? chatPanelMinWidth : 0) + (isSideNavOpenInline ? sideNavMinWidth : 0));
43
+ var resizingArea = resizeSession && areas[resizeSession.area];
44
+ 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);
45
+ 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;
46
+ var layoutModes = (_resizeSession$overla = resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.overlayModes) !== null && _resizeSession$overla !== void 0 ? _resizeSession$overla : initialModes;
47
+ // A growing panel cascades towards inline-start. Chat is on the other side
48
+ // of the local rail, so local growth must reserve its full starting width.
49
+ var shouldCollapseSideNav = Boolean(resizeSession && resizeSession.area !== 'side-nav' && resizeSession.baselineWidths['side-nav'] !== undefined && resizeSession.baselineWidths[resizeSession.area] !== undefined && resizingArea && !isSideNavOverlay && clampTargetWidth({
50
+ target: getTargetWidth(resizingArea, isSideNavOverlay),
51
+ min: resolveLayoutWidth(resizingArea.minWidth, viewportWidth),
52
+ max: resizingArea.maxWidth !== undefined ? resolveLayoutWidth(resizingArea.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY
53
+ }) > 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));
54
+ var isSideNavOpenInline = Boolean((sideNav === null || sideNav === void 0 ? void 0 : sideNav.isOpen) && !shouldCollapseSideNav && (layoutModes ? layoutModes['side-nav'] === 'inline' : !isSideNavOverlay && availableWidth >= mainMinWidth + sideNavMinWidth));
55
+ 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)));
56
+ 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)));
44
57
  var inlineAreas = [isSideNavOpenInline && 'side-nav', isPanelInline && 'panel', isChatPanelOpenInline && 'chat-panel'].filter(function (area) {
45
58
  return Boolean(area);
46
59
  });
@@ -57,8 +70,8 @@ export function calculateLayoutAreaStates(_ref4) {
57
70
  }
58
71
  var min = resolveLayoutWidth(area.minWidth, viewportWidth);
59
72
  var max = area.maxWidth ? resolveLayoutWidth(area.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY;
60
- var baselineWidth = resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.baselineWidths[areaName];
61
- var requestedTarget = resizeSession && areaName !== resizeSession.area && baselineWidth !== undefined ? baselineWidth : getTargetWidth(area, isSideNavOverlay);
73
+ var baselineWidth = baselineWidths === null || baselineWidths === void 0 ? void 0 : baselineWidths[areaName];
74
+ var requestedTarget = resizeSession && areaName !== resizeSession.area ? shouldCollapseSideNav && resizeSession.area === 'chat-panel' ? min : baselineWidth !== null && baselineWidth !== void 0 ? baselineWidth : getTargetWidth(area, isSideNavOverlay) : getTargetWidth(area, isSideNavOverlay);
62
75
  var target = clampTargetWidth({
63
76
  target: requestedTarget,
64
77
  min: min,
@@ -67,28 +80,50 @@ export function calculateLayoutAreaStates(_ref4) {
67
80
  minimums.set(areaName, min);
68
81
  widths.set(areaName, target);
69
82
  }
83
+ // Narrowing Chat moves the shared rail towards inline-end. Give the released
84
+ // space to its inline neighbour so local grows instead of sliding across Main.
85
+ // Use effective (clamped) widths and the session baseline, not each drag frame,
86
+ // so reversing direction and completing a controlled resize do not add it twice.
70
87
  } catch (err) {
71
88
  _iterator.e(err);
72
89
  } finally {
73
90
  _iterator.f();
74
91
  }
92
+ if ((resizeSession === null || resizeSession === void 0 ? void 0 : resizeSession.area) === 'chat-panel' && isChatPanelOpenInline && isPanelInline && panel) {
93
+ var _widths$get, _baselineWidths$chat2, _widths$get2;
94
+ var chatWidth = (_widths$get = widths.get('chat-panel')) !== null && _widths$get !== void 0 ? _widths$get : 0;
95
+ 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);
96
+ var panelMaxWidth = panel.maxWidth !== undefined ? Math.max(panelMinWidth, resolveLayoutWidth(panel.maxWidth, viewportWidth)) : Number.POSITIVE_INFINITY;
97
+ widths.set('panel', Math.min(panelMaxWidth, ((_widths$get2 = widths.get('panel')) !== null && _widths$get2 !== void 0 ? _widths$get2 : 0) + releasedWidth));
98
+ }
99
+ // Continuing to pull the local rail towards Chat after local reaches its
100
+ // minimum gives Main the remaining space available in inline Chat.
101
+ 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) {
102
+ var _widths$get3;
103
+ var remainingDrag = Math.max(0, panelMinWidth - panel.liveResize.width);
104
+ var _chatWidth = (_widths$get3 = widths.get('chat-panel')) !== null && _widths$get3 !== void 0 ? _widths$get3 : 0;
105
+ widths.set('chat-panel', Math.max(chatPanelMinWidth, _chatWidth - remainingDrag));
106
+ }
75
107
  var overflow = Math.max(0, Array.from(widths.values()).reduce(function (total, width) {
76
108
  return total + width;
77
109
  }, 0) - (availableWidth - mainMinWidth));
78
110
  var compressionOrder = ['panel', 'chat-panel', 'side-nav'];
79
- // User resizing consumes only Main's spare width. Viewport changes clear the
80
- // snapshot and retain the normal automatic compression order.
81
- var shrinkOrder = resizeSession ? [resizeSession.area] : compressionOrder;
111
+ // Main gives up spare space first. Only regions beyond the moving rail may
112
+ // then compress: local growth moves towards SideNav, never towards Chat.
113
+ // SideNav and Chat growth can reach both other regions in their direction.
114
+ var shrinkOrder = resizeSession ? resizeSession.area === 'panel' ? ['side-nav', 'panel'] : [].concat(_toConsumableArray(compressionOrder.filter(function (area) {
115
+ return area !== resizeSession.area;
116
+ })), [resizeSession.area]) : compressionOrder;
82
117
  var _iterator2 = _createForOfIteratorHelper(shrinkOrder),
83
118
  _step2;
84
119
  try {
85
120
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
86
- var _widths$get, _minimums$get;
121
+ var _widths$get4, _minimums$get;
87
122
  var _areaName = _step2.value;
88
123
  if (overflow <= 0) {
89
124
  break;
90
125
  }
91
- var width = (_widths$get = widths.get(_areaName)) !== null && _widths$get !== void 0 ? _widths$get : 0;
126
+ var width = (_widths$get4 = widths.get(_areaName)) !== null && _widths$get4 !== void 0 ? _widths$get4 : 0;
92
127
  var _min = (_minimums$get = minimums.get(_areaName)) !== null && _minimums$get !== void 0 ? _minimums$get : 0;
93
128
  var reduction = Math.min(overflow, Math.max(0, width - _min));
94
129
  widths.set(_areaName, width - reduction);
@@ -99,29 +134,32 @@ export function calculateLayoutAreaStates(_ref4) {
99
134
  } finally {
100
135
  _iterator2.f();
101
136
  }
102
- var totalInlineWidth = Array.from(widths.values()).reduce(function (total, width) {
103
- return total + width;
104
- }, 0);
105
137
  var states = {};
106
138
  var _iterator3 = _createForOfIteratorHelper(inlineAreas),
107
139
  _step3;
108
140
  try {
109
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
110
- var _widths$get2, _minimums$get2, _areas$_areaName;
111
- var _areaName2 = _step3.value;
112
- var _width = (_widths$get2 = widths.get(_areaName2)) !== null && _widths$get2 !== void 0 ? _widths$get2 : 0;
113
- var _min2 = (_minimums$get2 = minimums.get(_areaName2)) !== null && _minimums$get2 !== void 0 ? _minimums$get2 : 0;
114
- var maxWidth = (_areas$_areaName = areas[_areaName2]) === null || _areas$_areaName === void 0 ? void 0 : _areas$_areaName.maxWidth;
141
+ var _loop = function _loop() {
142
+ var _widths$get5, _minimums$get2, _areas$areaName;
143
+ var areaName = _step3.value;
144
+ var width = (_widths$get5 = widths.get(areaName)) !== null && _widths$get5 !== void 0 ? _widths$get5 : 0;
145
+ var min = (_minimums$get2 = minimums.get(areaName)) !== null && _minimums$get2 !== void 0 ? _minimums$get2 : 0;
146
+ var maxWidth = (_areas$areaName = areas[areaName]) === null || _areas$areaName === void 0 ? void 0 : _areas$areaName.maxWidth;
115
147
  var configuredMax = maxWidth !== undefined ? resolveLayoutWidth(maxWidth, viewportWidth) : Number.POSITIVE_INFINITY;
116
- states[_areaName2] = {
148
+ states[areaName] = {
117
149
  mode: 'inline',
118
- width: _width,
119
- minWidth: _min2,
150
+ width: width,
151
+ minWidth: min,
120
152
  resizeBounds: {
121
- min: _min2,
122
- max: Math.max(_min2, Math.min(configuredMax, availableWidth - mainMinWidth - totalInlineWidth + _width))
153
+ min: min,
154
+ max: Math.max(min, Math.min(configuredMax, availableWidth - mainMinWidth - inlineAreas.reduce(function (total, sibling) {
155
+ var _widths$get6, _minimums$get3;
156
+ 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);
157
+ }, 0)))
123
158
  }
124
159
  };
160
+ };
161
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
162
+ _loop();
125
163
  }
126
164
  } catch (err) {
127
165
  _iterator3.e(err);
@@ -136,27 +174,27 @@ export function calculateLayoutAreaStates(_ref4) {
136
174
  try {
137
175
  for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
138
176
  var _states$_areaName;
139
- var _areaName3 = _step4.value;
140
- var _area = areas[_areaName3];
141
- if (!(_area !== null && _area !== void 0 && _area.isOpen) || ((_states$_areaName = states[_areaName3]) === null || _states$_areaName === void 0 ? void 0 : _states$_areaName.mode) === 'inline') {
177
+ var _areaName2 = _step4.value;
178
+ var _area = areas[_areaName2];
179
+ 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) {
142
180
  continue;
143
181
  }
144
- var _min3 = resolveLayoutWidth(_area.minWidth, viewportWidth);
145
- var _configuredMax = _area.maxWidth ? resolveLayoutWidth(_area.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY;
182
+ var _min2 = resolveLayoutWidth(_area.minWidth, viewportWidth);
183
+ var configuredMax = _area.maxWidth ? resolveLayoutWidth(_area.maxWidth, viewportWidth) : Number.POSITIVE_INFINITY;
146
184
  // Chat covers Root; SideNav and the local panel overlay Main's grid track.
147
185
  // Occupied tracks and inline chat are not part of that covered region.
148
- var layoutMax = (_areaName3 === 'chat-panel' ? layoutWidth : mainAreaWidth) * 0.9;
149
- var _max = Math.max(0, Math.min(_configuredMax, layoutMax));
150
- var effectiveMin = Math.min(_min3, _max);
186
+ var layoutMax = (_areaName2 === 'chat-panel' ? layoutWidth : mainAreaWidth) * 0.9;
187
+ var _max = Math.max(0, Math.min(configuredMax, layoutMax));
188
+ var effectiveMin = Math.min(_min2, _max);
151
189
  var _target = getOverlayTargetWidth(_area, isSideNavOverlay);
152
- var _width2 = clampTargetWidth({
190
+ var _width = clampTargetWidth({
153
191
  target: _target,
154
192
  min: effectiveMin,
155
193
  max: _max
156
194
  });
157
- states[_areaName3] = {
195
+ states[_areaName2] = {
158
196
  mode: 'overlay',
159
- width: _width2,
197
+ width: _width,
160
198
  minWidth: effectiveMin,
161
199
  resizeBounds: {
162
200
  min: effectiveMin,
@@ -8,7 +8,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
8
8
  import { bind } from 'bind-event-listener';
9
9
  import { fg } from '@atlaskit/platform-feature-flags/fg';
10
10
  import { useSkipLinkInternal } from '../../context/skip-links/use-skip-link-internal';
11
- import { chatPanelLiveWidthVar, chatPanelVar, mainMinimumWidthVar } from './constants';
11
+ import { chatPanelLiveWidthVar, chatPanelVar, localSlotLayers, mainMinimumWidthVar } from './constants';
12
12
  import { convertResizeBoundToPixels } from './panel-splitter/convert-resize-bound-to-pixels';
13
13
  import { PanelSplitterProvider } from './panel-splitter/provider';
14
14
  import { resolveLayoutWidth } from './resolve-layout-width';
@@ -102,6 +102,8 @@ export function ChatPanel(_ref) {
102
102
  onRequestClose: onClose
103
103
  }
104
104
  }),
105
+ isManaged = _useLayoutAreaSizing.isManaged,
106
+ prepareResize = _useLayoutAreaSizing.prepareResize,
105
107
  managedSizing = _useLayoutAreaSizing.state,
106
108
  getManagedResizeBounds = _useLayoutAreaSizing.getResizeBounds,
107
109
  startResize = _useLayoutAreaSizing.startResize,
@@ -191,13 +193,14 @@ export function ChatPanel(_ref) {
191
193
  // Hoist the committed or actively resizing inline width so SideNav can yield
192
194
  // space to ChatPanel without allowing the page layout to overflow.
193
195
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-global-styles
194
- React.createElement("style", null, "\n#".concat(gridRootId, " { ").concat(chatPanelLiveWidthVar, ": var(").concat(panelSplitterResizingVar, ", ").concat(chatPanelVariableWidth, "); }\n")), /*#__PURE__*/React.createElement(PanelSplitterProvider, {
196
+ React.createElement("style", null, managedSizing ? "\n#".concat(gridRootId, " { --n_chatTrack: ").concat(mode === 'inline' ? "".concat(renderedWidth, "px") : '0px', "; ").concat(chatPanelLiveWidthVar, ": var(--n_chatTrack); }\n") : "\n#".concat(gridRootId, " { --n_chatTrack: 0px; ").concat(chatPanelLiveWidthVar, ": 0px; }\n#").concat(gridRootId, " [data-layout-chat-panel] {\n grid-area: 2 / 1 / -1 / -1;\n width: min(calc(var(--n_layoutW) * 0.9), ").concat(chatPanelOverlayVariableWidth, ");\n z-index: ").concat(localSlotLayers.chatPanelOverlay, ";\n background-color: ", "var(--ds-surface-overlay, #FFFFFF)", ";\n ").concat(hasBorder ? "box-shadow: ".concat("var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)", "; border-inline-start: none;") : '', "\n}\n@media (min-width: 40rem) {\n @container navigation-chat-space (min-width: ").concat(minWidth, ") {\n #").concat(gridRootId, " { --n_chatTrack: min(100cqw, var(").concat(panelSplitterResizingVar, ", ").concat(chatPanelVariableWidth, ")); ").concat(chatPanelLiveWidthVar, ": var(--n_chatTrack); }\n #").concat(gridRootId, " [data-layout-chat-panel] {\n grid-area: chat-panel;\n width: min(100cqw, var(").concat(panelSplitterResizingVar, ", ").concat(chatPanelVariableWidth, "));\n z-index: auto;\n background-color: ", "var(--ds-surface, #FFFFFF)", ";\n ").concat(hasBorder ? "box-shadow: initial; border-inline-start: ".concat("var(--ds-border-width, 1px)", " solid ", "var(--ds-border, #0B120E24)", ";") : '', "\n }\n }\n}\n")), /*#__PURE__*/React.createElement(PanelSplitterProvider, {
195
197
  panelId: chatPanelPanelSplitterId,
196
198
  panelRef: ref,
197
199
  panelWidth: renderedWidth,
198
200
  onCompleteResize: onCompleteResize,
199
- onResizeStartInternal: managedSizing ? onResizeStartInternal : undefined,
200
- onResizeInternal: managedSizing ? onResizeInternal : undefined,
201
+ prepareResize: prepareResize,
202
+ onResizeStartInternal: isManaged ? onResizeStartInternal : undefined,
203
+ onResizeInternal: isManaged ? onResizeInternal : undefined,
201
204
  getResizeBounds: getResizeBounds,
202
205
  resizingCssVar: panelSplitterResizingVar,
203
206
  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 var LayoutAreaSizingContext = /*#__PURE__*/createContext(null);