@atlaskit/navigation-system 11.3.3 → 11.4.0
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.
- package/CHANGELOG.md +26 -0
- package/README.md +20 -0
- package/constellation/layout/code.mdx +1 -1
- package/constellation/layout/examples.mdx +4 -16
- package/constellation/layout/images/layout-anatomy-dark.png +0 -0
- package/constellation/layout/images/layout-anatomy-light.png +0 -0
- package/constellation/layout/images/layout-do-dark.png +0 -0
- package/constellation/layout/images/layout-do-light.png +0 -0
- package/constellation/layout/images/layout-dont-dark.png +0 -0
- package/constellation/layout/images/layout-dont-light.png +0 -0
- package/constellation/layout/images/layout-example-dark.png +0 -0
- package/constellation/layout/images/layout-example-light.png +0 -0
- package/constellation/layout/images/layout-example-sideNav-dark.png +0 -0
- package/constellation/layout/images/layout-example-sideNav-light.png +0 -0
- package/constellation/layout/images/layout-example-topNav-1-dark.png +0 -0
- package/constellation/layout/images/layout-example-topNav-1-light.png +0 -0
- package/constellation/layout/usage.mdx +1 -2
- package/constellation/top-nav-items/examples.mdx +7 -13
- package/dist/cjs/entry-points/layout/panel-layout.js +19 -0
- package/dist/cjs/ui/page-layout/calculate-layout-area-states.js +4 -4
- package/dist/cjs/ui/page-layout/chat-panel.js +1 -1
- package/dist/cjs/ui/page-layout/constants.js +15 -1
- package/dist/cjs/ui/page-layout/get-panel-layout-defaults.js +22 -0
- package/dist/cjs/ui/page-layout/layout-area-sizing-provider.js +2 -1
- package/dist/cjs/ui/page-layout/layout-area-sizing-runtime.js +5 -4
- package/dist/cjs/ui/page-layout/local-panel-surface.compiled.css +26 -0
- package/dist/cjs/ui/page-layout/local-panel-surface.js +206 -0
- package/dist/cjs/ui/page-layout/main/main.js +5 -2
- package/dist/cjs/ui/page-layout/main-min-width-context.js +10 -0
- package/dist/cjs/ui/page-layout/panel-layout-shell.compiled.css +27 -0
- package/dist/cjs/ui/page-layout/panel-layout-shell.js +67 -0
- package/dist/cjs/ui/page-layout/panel-layout.js +162 -0
- package/dist/cjs/ui/page-layout/panel-splitter/panel-splitter.js +12 -5
- package/dist/cjs/ui/page-layout/root.js +3 -1
- package/dist/cjs/ui/page-layout/side-nav/bind-open-layer-change.js +56 -0
- package/dist/cjs/ui/page-layout/side-nav/side-nav.js +167 -57
- package/dist/cjs/ui/page-layout/side-nav/toggle-button.js +8 -1
- package/dist/cjs/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.js +15 -1
- package/dist/cjs/ui/page-layout/top-nav/top-nav-end.js +3 -2
- package/dist/cjs/ui/page-layout/top-nav/top-nav-middle.js +2 -1
- package/dist/es2019/entry-points/layout/panel-layout.js +2 -0
- package/dist/es2019/ui/page-layout/calculate-layout-area-states.js +4 -4
- package/dist/es2019/ui/page-layout/chat-panel.js +2 -2
- package/dist/es2019/ui/page-layout/constants.js +14 -0
- package/dist/es2019/ui/page-layout/get-panel-layout-defaults.js +16 -0
- package/dist/es2019/ui/page-layout/layout-area-sizing-provider.js +2 -1
- package/dist/es2019/ui/page-layout/layout-area-sizing-runtime.js +4 -3
- package/dist/es2019/ui/page-layout/local-panel-surface.compiled.css +26 -0
- package/dist/es2019/ui/page-layout/local-panel-surface.js +193 -0
- package/dist/es2019/ui/page-layout/main/main.js +6 -3
- package/dist/es2019/ui/page-layout/main-min-width-context.js +5 -0
- package/dist/es2019/ui/page-layout/panel-layout-shell.compiled.css +27 -0
- package/dist/es2019/ui/page-layout/panel-layout-shell.js +74 -0
- package/dist/es2019/ui/page-layout/panel-layout.js +147 -0
- package/dist/es2019/ui/page-layout/panel-splitter/panel-splitter.js +12 -5
- package/dist/es2019/ui/page-layout/root.js +3 -1
- package/dist/es2019/ui/page-layout/side-nav/bind-open-layer-change.js +51 -0
- package/dist/es2019/ui/page-layout/side-nav/side-nav.js +123 -10
- package/dist/es2019/ui/page-layout/side-nav/toggle-button.js +8 -1
- package/dist/es2019/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.js +15 -1
- package/dist/es2019/ui/page-layout/top-nav/top-nav-end.js +3 -2
- package/dist/es2019/ui/page-layout/top-nav/top-nav-middle.js +2 -1
- package/dist/esm/entry-points/layout/panel-layout.js +2 -0
- package/dist/esm/ui/page-layout/calculate-layout-area-states.js +4 -4
- package/dist/esm/ui/page-layout/chat-panel.js +2 -2
- package/dist/esm/ui/page-layout/constants.js +14 -0
- package/dist/esm/ui/page-layout/get-panel-layout-defaults.js +16 -0
- package/dist/esm/ui/page-layout/layout-area-sizing-provider.js +2 -1
- package/dist/esm/ui/page-layout/layout-area-sizing-runtime.js +4 -3
- package/dist/esm/ui/page-layout/local-panel-surface.compiled.css +26 -0
- package/dist/esm/ui/page-layout/local-panel-surface.js +197 -0
- package/dist/esm/ui/page-layout/main/main.js +6 -3
- package/dist/esm/ui/page-layout/main-min-width-context.js +5 -0
- package/dist/esm/ui/page-layout/panel-layout-shell.compiled.css +27 -0
- package/dist/esm/ui/page-layout/panel-layout-shell.js +59 -0
- package/dist/esm/ui/page-layout/panel-layout.js +154 -0
- package/dist/esm/ui/page-layout/panel-splitter/panel-splitter.js +12 -5
- package/dist/esm/ui/page-layout/root.js +3 -1
- package/dist/esm/ui/page-layout/side-nav/bind-open-layer-change.js +50 -0
- package/dist/esm/ui/page-layout/side-nav/side-nav.js +168 -58
- package/dist/esm/ui/page-layout/side-nav/toggle-button.js +8 -1
- package/dist/esm/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.js +15 -1
- package/dist/esm/ui/page-layout/top-nav/top-nav-end.js +3 -2
- package/dist/esm/ui/page-layout/top-nav/top-nav-middle.js +2 -1
- package/dist/types/entry-points/layout/panel-layout.d.ts +3 -0
- package/dist/types/ui/page-layout/constants.d.ts +12 -0
- package/dist/types/ui/page-layout/get-panel-layout-defaults.d.ts +10 -0
- package/dist/types/ui/page-layout/layout-area-sizing-context.d.ts +5 -1
- package/dist/types/ui/page-layout/local-panel-surface.d.ts +32 -0
- package/dist/types/ui/page-layout/main-min-width-context.d.ts +2 -0
- package/dist/types/ui/page-layout/panel-layout-shell.d.ts +47 -0
- package/dist/types/ui/page-layout/panel-layout.d.ts +74 -0
- package/dist/types/ui/page-layout/side-nav/bind-open-layer-change.d.ts +17 -0
- package/layout/panel-layout/package.json +10 -0
- package/package.json +6 -6
- package/constellation/layout/images/layout-example-topNav-2-dark.png +0 -0
- package/constellation/layout/images/layout-example-topNav-2-light.png +0 -0
|
@@ -14,9 +14,10 @@ import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
|
14
14
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter';
|
|
15
15
|
// eslint-disable-next-line @atlaskit/design-system/no-emotion-primitives -- TODO: migrate to @atlaskit/primitives/compiled
|
|
16
16
|
|
|
17
|
+
import { hasOpenDialogOrPopover } from '@atlaskit/top-layer/page-surface/has-open-dialog-or-popover';
|
|
17
18
|
import { useSkipLinkInternal } from '../../../context/skip-links/use-skip-link-internal';
|
|
18
19
|
import { TopNavStartElement } from '../../../context/top-nav-start/top-nav-start-element';
|
|
19
|
-
import { UNSAFE_sideNavLayoutVar, mainMinimumWidthVar, openLayerObserverSideNavNamespace, sideNavLiveWidthVar, sideNavPanelSplitterId, sideNavVar } from '../constants';
|
|
20
|
+
import { UNSAFE_sideNavLayoutVar, defaultMainMinWidth, mainMinimumWidthVar, openLayerObserverSideNavNamespace, sideNavLiveWidthVar, sideNavPanelSplitterId, sideNavVar } from '../constants';
|
|
20
21
|
import { DangerouslyHoistCssVarToDocumentRoot } from '../dangerously-hoist-css-var-to-document-root';
|
|
21
22
|
import { DangerouslyHoistSlotSizes } from '../hoist-slot-sizes-context';
|
|
22
23
|
import { convertResizeBoundToPixels } from '../panel-splitter/convert-resize-bound-to-pixels';
|
|
@@ -27,6 +28,7 @@ import { useLayoutAreaSizing } from '../use-layout-area-sizing';
|
|
|
27
28
|
import { useLayoutId } from '../use-layout-id';
|
|
28
29
|
import { useResizingWidthCssVarOnRootElement } from '../use-resizing-width-css-var-on-root-element';
|
|
29
30
|
import { useSafeDefaultWidth } from '../use-safe-default-width';
|
|
31
|
+
import { bindOpenLayerChange } from './bind-open-layer-change';
|
|
30
32
|
import { sideNavFlyoutCloseDelayMs } from './flyout-close-delay-ms';
|
|
31
33
|
import { SetSideNavVisibilityState } from './set-side-nav-visibility-state';
|
|
32
34
|
import { SideNavToggleButtonElement } from './side-nav-toggle-button-element';
|
|
@@ -53,6 +55,54 @@ function getPixelCustomProperty(element, propertyName, fallback) {
|
|
|
53
55
|
* Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
|
|
54
56
|
*/
|
|
55
57
|
const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
58
|
+
const textEntryInputTypes = new Set(['text', 'search', 'email', 'url', 'tel', 'password', 'number']);
|
|
59
|
+
function isEditableContent({
|
|
60
|
+
element
|
|
61
|
+
}) {
|
|
62
|
+
if (element instanceof HTMLElement && typeof element.isContentEditable === 'boolean') {
|
|
63
|
+
return element.isContentEditable;
|
|
64
|
+
}
|
|
65
|
+
// Fallback for DOM implementations without `isContentEditable`.
|
|
66
|
+
const editingHost = element.closest('[contenteditable]');
|
|
67
|
+
return editingHost !== null && editingHost.getAttribute('contenteditable') !== 'false';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Returns `true` for an element that the user can type text into.
|
|
72
|
+
*/
|
|
73
|
+
function isTextEntryElement({
|
|
74
|
+
element
|
|
75
|
+
}) {
|
|
76
|
+
if (element instanceof HTMLInputElement) {
|
|
77
|
+
return textEntryInputTypes.has(element.type) && !element.readOnly && !element.disabled;
|
|
78
|
+
}
|
|
79
|
+
if (element instanceof HTMLTextAreaElement) {
|
|
80
|
+
return !element.readOnly && !element.disabled;
|
|
81
|
+
}
|
|
82
|
+
return isEditableContent({
|
|
83
|
+
element
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Used when the `platform-dst-top-layer` gate is on.
|
|
89
|
+
*
|
|
90
|
+
* The flyout stays open while a layer opened from the side nav is open, or while the user
|
|
91
|
+
* is typing in a text field inside the side nav (for example while renaming an item inline).
|
|
92
|
+
*/
|
|
93
|
+
function isFlyoutHeldOpen({
|
|
94
|
+
nav
|
|
95
|
+
}) {
|
|
96
|
+
if (hasOpenDialogOrPopover({
|
|
97
|
+
within: nav
|
|
98
|
+
})) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
const activeElement = nav.ownerDocument.activeElement;
|
|
102
|
+
return activeElement !== null && nav.contains(activeElement) && isTextEntryElement({
|
|
103
|
+
element: activeElement
|
|
104
|
+
});
|
|
105
|
+
}
|
|
56
106
|
const styles = {
|
|
57
107
|
root: "_191wglyw _t51zglyw _bfhk1bhr _16qs130s _vchhusvi _4t3ieqxy _152timx3 _kqsw1if8 _1bsb1ego _1pbycs5v _14b5hc79 _qilnk0mc _p5clia51 _4ap3vuon _scbpglyw _89fi1b6c",
|
|
58
108
|
chatPanelSizing: "_1bsbhc79",
|
|
@@ -288,7 +338,7 @@ function SideNavInternal({
|
|
|
288
338
|
const isLocalPanelInline = localPanel && getComputedStyle(localPanel).gridArea === 'panel';
|
|
289
339
|
const localPanelWidth = isLocalPanelInline ? localPanel.getBoundingClientRect().width : 0;
|
|
290
340
|
const mainContentWidth = mainWidth - localPanelWidth;
|
|
291
|
-
const mainMinimumWidth = getPixelCustomProperty(main, mainMinimumWidthVar,
|
|
341
|
+
const mainMinimumWidth = getPixelCustomProperty(main, mainMinimumWidthVar, defaultMainMinWidth);
|
|
292
342
|
const availableWidth = Math.max(0, mainContentWidth - mainMinimumWidth);
|
|
293
343
|
const availableInlineWidth = Math.floor(sideNavWidth + availableWidth);
|
|
294
344
|
const constrainedMaxWidth = maxWidth ? Math.min(convertResizeBoundToPixels(maxWidth), availableInlineWidth) : availableInlineWidth;
|
|
@@ -322,7 +372,9 @@ function SideNavInternal({
|
|
|
322
372
|
const toggleButtonElement = useContext(SideNavToggleButtonElement);
|
|
323
373
|
const topNavStartElement = useContext(TopNavStartElement);
|
|
324
374
|
const devTimeOnlyAttributes = {};
|
|
325
|
-
const openLayerObserver = useOpenLayerObserver(
|
|
375
|
+
const openLayerObserver = useOpenLayerObserver({
|
|
376
|
+
isEnabled: !fg('platform-dst-top-layer')
|
|
377
|
+
});
|
|
326
378
|
const flyoutStateRef = useRef({
|
|
327
379
|
type: 'not-active'
|
|
328
380
|
});
|
|
@@ -402,6 +454,17 @@ function SideNavInternal({
|
|
|
402
454
|
});
|
|
403
455
|
}
|
|
404
456
|
}
|
|
457
|
+
function canClose() {
|
|
458
|
+
if (!fg('platform-dst-top-layer')) {
|
|
459
|
+
return (openLayerObserver === null || openLayerObserver === void 0 ? void 0 : openLayerObserver.getCount({
|
|
460
|
+
namespace: openLayerObserverSideNavNamespace
|
|
461
|
+
})) === 0;
|
|
462
|
+
}
|
|
463
|
+
const nav = navRef.current;
|
|
464
|
+
return !(nav && isFlyoutHeldOpen({
|
|
465
|
+
nav
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
405
468
|
return function onAction(action) {
|
|
406
469
|
if (action === 'drag-from-flyout-started') {
|
|
407
470
|
open();
|
|
@@ -443,9 +506,7 @@ function SideNavInternal({
|
|
|
443
506
|
}
|
|
444
507
|
if (action === 'ready-to-close') {
|
|
445
508
|
// If there are no open layers, we can close the flyout.
|
|
446
|
-
if ((
|
|
447
|
-
namespace: openLayerObserverSideNavNamespace
|
|
448
|
-
})) === 0) {
|
|
509
|
+
if (canClose()) {
|
|
449
510
|
close();
|
|
450
511
|
return;
|
|
451
512
|
}
|
|
@@ -787,6 +848,52 @@ function SideNavInternal({
|
|
|
787
848
|
namespace: openLayerObserverSideNavNamespace
|
|
788
849
|
});
|
|
789
850
|
}, [openLayerObserver, updateFlyoutState]);
|
|
851
|
+
const focusOutTimeoutIdRef = useRef(undefined);
|
|
852
|
+
useEffect(() => {
|
|
853
|
+
// The same as the open layer observer `onChange` above, for when the `platform-dst-top-layer`
|
|
854
|
+
// gate is on. Top-layer surfaces opened from the side nav are DOM descendants of it.
|
|
855
|
+
const nav = navRef.current;
|
|
856
|
+
if (!nav || !fg('platform-dst-top-layer')) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
function closeIfReady() {
|
|
860
|
+
if (flyoutStateRef.current.type !== 'ready-to-close' || !nav) {
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
if (isFlyoutHeldOpen({
|
|
864
|
+
nav
|
|
865
|
+
})) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
updateFlyoutState('force-close');
|
|
869
|
+
}
|
|
870
|
+
const unbindLayerChange = bindOpenLayerChange({
|
|
871
|
+
within: nav,
|
|
872
|
+
onChange: closeIfReady
|
|
873
|
+
});
|
|
874
|
+
const unbindFocusOut = bind(nav, {
|
|
875
|
+
type: 'focusout',
|
|
876
|
+
listener() {
|
|
877
|
+
// Wait for focus to move before checking where it went.
|
|
878
|
+
clearTimeout(focusOutTimeoutIdRef.current);
|
|
879
|
+
focusOutTimeoutIdRef.current = setTimeout(closeIfReady, 0);
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
// Removing the focused text field (for example when an inline rename ends) fires no
|
|
884
|
+
// `focusout` in some browsers, so also check again when content inside the side nav changes.
|
|
885
|
+
const removalObserver = new MutationObserver(closeIfReady);
|
|
886
|
+
removalObserver.observe(nav, {
|
|
887
|
+
childList: true,
|
|
888
|
+
subtree: true
|
|
889
|
+
});
|
|
890
|
+
return function cleanup() {
|
|
891
|
+
unbindLayerChange();
|
|
892
|
+
unbindFocusOut();
|
|
893
|
+
removalObserver.disconnect();
|
|
894
|
+
clearTimeout(focusOutTimeoutIdRef.current);
|
|
895
|
+
};
|
|
896
|
+
}, [updateFlyoutState]);
|
|
790
897
|
useEffect(() => {
|
|
791
898
|
// Clear flyout close timer if being unmounted
|
|
792
899
|
return function cleanupPendingFlyoutClose() {
|
|
@@ -953,9 +1060,7 @@ export function SideNav({
|
|
|
953
1060
|
canToggleWithShortcut,
|
|
954
1061
|
id
|
|
955
1062
|
}) {
|
|
956
|
-
|
|
957
|
-
namespace: openLayerObserverSideNavNamespace
|
|
958
|
-
}, /*#__PURE__*/React.createElement(SideNavInternal, {
|
|
1063
|
+
const sideNav = /*#__PURE__*/React.createElement(SideNavInternal, {
|
|
959
1064
|
defaultCollapsed: defaultCollapsed,
|
|
960
1065
|
defaultWidth: defaultWidth,
|
|
961
1066
|
minWidth: minWidth,
|
|
@@ -969,5 +1074,13 @@ export function SideNav({
|
|
|
969
1074
|
onPeekEnd: onPeekEnd,
|
|
970
1075
|
id: id,
|
|
971
1076
|
canToggleWithShortcut: canToggleWithShortcut
|
|
972
|
-
}, children)
|
|
1077
|
+
}, children);
|
|
1078
|
+
|
|
1079
|
+
// Top-layer surfaces are found through the DOM, so the namespace is only needed when the gate is off.
|
|
1080
|
+
if (fg('platform-dst-top-layer')) {
|
|
1081
|
+
return sideNav;
|
|
1082
|
+
}
|
|
1083
|
+
return /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
1084
|
+
namespace: openLayerObserverSideNavNamespace
|
|
1085
|
+
}, sideNav);
|
|
973
1086
|
}
|
|
@@ -7,6 +7,8 @@ import { useAnalyticsEvents } from '@atlaskit/analytics-next/useAnalyticsEvents'
|
|
|
7
7
|
import SidebarCollapseIcon from '@atlaskit/icon/core/sidebar-collapse';
|
|
8
8
|
import SidebarExpandIcon from '@atlaskit/icon/core/sidebar-expand';
|
|
9
9
|
import { useOpenLayerObserver } from '@atlaskit/layering/use-open-layer-observer';
|
|
10
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
11
|
+
import { requestClosePopovers } from '@atlaskit/top-layer/page-surface/request-close-popovers';
|
|
10
12
|
import { IconButton } from '../../top-nav-items/themed/icon-button';
|
|
11
13
|
import { SideNavToggleButtonAttachRef } from './side-nav-toggle-button-attach-ref';
|
|
12
14
|
import { sideNavToggleTooltipKeyboardShortcut } from './side-nav-toggle-tooltip-keyboard-shortcut';
|
|
@@ -86,12 +88,17 @@ export const SideNavToggleButton = ({
|
|
|
86
88
|
const {
|
|
87
89
|
createAnalyticsEvent
|
|
88
90
|
} = useAnalyticsEvents();
|
|
89
|
-
const openLayerObserver = useOpenLayerObserver(
|
|
91
|
+
const openLayerObserver = useOpenLayerObserver({
|
|
92
|
+
isEnabled: !fg('platform-dst-top-layer')
|
|
93
|
+
});
|
|
90
94
|
const handleClick = useCallback((event, analyticsEvent) => {
|
|
91
95
|
onClick === null || onClick === void 0 ? void 0 : onClick(event, analyticsEvent, {
|
|
92
96
|
isSideNavVisible: isSideNavExpanded
|
|
93
97
|
});
|
|
94
98
|
toggleVisibility();
|
|
99
|
+
|
|
100
|
+
// Not gated. Top-layer tooltips (`platform-dst-top-layer-tooltip`) are not known to the observer.
|
|
101
|
+
requestClosePopovers();
|
|
95
102
|
openLayerObserver === null || openLayerObserver === void 0 ? void 0 : openLayerObserver.closeLayers();
|
|
96
103
|
}, [isSideNavExpanded, onClick, openLayerObserver, toggleVisibility]);
|
|
97
104
|
const handlePointerEnter = useCallback(() => {
|
|
@@ -2,6 +2,9 @@ import { useEffect } from 'react';
|
|
|
2
2
|
import { bind } from 'bind-event-listener';
|
|
3
3
|
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
4
4
|
import { useOpenLayerObserver } from '@atlaskit/layering/use-open-layer-observer';
|
|
5
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
6
|
+
import { hasOpenDialogOrPopover } from '@atlaskit/top-layer/page-surface/has-open-dialog-or-popover';
|
|
7
|
+
import { requestClosePopovers } from '@atlaskit/top-layer/page-surface/request-close-popovers';
|
|
5
8
|
import { useIsSideNavShortcutEnabled } from './use-is-side-nav-shortcut-enabled';
|
|
6
9
|
import { useToggleSideNav } from './use-toggle-side-nav';
|
|
7
10
|
|
|
@@ -11,7 +14,9 @@ import { useToggleSideNav } from './use-toggle-side-nav';
|
|
|
11
14
|
export function useSideNavToggleKeyboardShortcut({
|
|
12
15
|
canToggleWithShortcut
|
|
13
16
|
}) {
|
|
14
|
-
const openLayerObserver = useOpenLayerObserver(
|
|
17
|
+
const openLayerObserver = useOpenLayerObserver({
|
|
18
|
+
isEnabled: !fg('platform-dst-top-layer')
|
|
19
|
+
});
|
|
15
20
|
const toggleVisibilityByShortcut = useToggleSideNav({
|
|
16
21
|
trigger: 'keyboard'
|
|
17
22
|
});
|
|
@@ -34,12 +39,21 @@ export function useSideNavToggleKeyboardShortcut({
|
|
|
34
39
|
// Ignore repeated keydown events from holding down the keys
|
|
35
40
|
return;
|
|
36
41
|
}
|
|
42
|
+
if (fg('platform-dst-top-layer') && hasOpenDialogOrPopover({
|
|
43
|
+
type: 'modal'
|
|
44
|
+
})) {
|
|
45
|
+
// Return early if there are any open modal dialogs
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
37
48
|
if (openLayerObserver && openLayerObserver.getCount({
|
|
38
49
|
type: 'modal'
|
|
39
50
|
}) > 0) {
|
|
40
51
|
// Return early if there are any open modals
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
54
|
+
|
|
55
|
+
// Not gated. Top-layer tooltips (`platform-dst-top-layer-tooltip`) are not known to the observer.
|
|
56
|
+
requestClosePopovers();
|
|
43
57
|
openLayerObserver === null || openLayerObserver === void 0 ? void 0 : openLayerObserver.closeLayers();
|
|
44
58
|
toggleVisibilityByShortcut();
|
|
45
59
|
}
|
|
@@ -58,7 +58,8 @@ export function TopNavEnd({
|
|
|
58
58
|
|
|
59
59
|
// The shared provider also covers the mobile overflow popup itself. Keep the
|
|
60
60
|
// previous content-only namespace coverage when the layout gate is disabled.
|
|
61
|
-
|
|
61
|
+
// The observer is not used when the top-layer gate is on, so no provider is needed.
|
|
62
|
+
const actions = fg('platform-dst-chat-panel-layout') || fg('platform-dst-top-layer') ? children : /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
62
63
|
namespace: openLayerObserverTopNavEndNamespace
|
|
63
64
|
}, children);
|
|
64
65
|
const content = /*#__PURE__*/React.createElement("nav", {
|
|
@@ -88,7 +89,7 @@ export function TopNavEnd({
|
|
|
88
89
|
}) : /*#__PURE__*/React.createElement(List, {
|
|
89
90
|
xcss: cx(listStyles.root, listStyles.hideOnSmallViewport)
|
|
90
91
|
}, actions), hasPersistentItems && persistentItems);
|
|
91
|
-
return fg('platform-dst-chat-panel-layout') ? /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
92
|
+
return fg('platform-dst-chat-panel-layout') && !fg('platform-dst-top-layer') ? /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
92
93
|
namespace: openLayerObserverTopNavEndNamespace
|
|
93
94
|
}, content) : content;
|
|
94
95
|
}
|
|
@@ -3,6 +3,7 @@ import "./top-nav-middle.compiled.css";
|
|
|
3
3
|
import { ax, ix } from "@compiled/react/runtime";
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { OpenLayerObserverNamespaceProvider } from '@atlaskit/layering/open-layer-observer-namespace-provider';
|
|
6
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
6
7
|
import { openLayerObserverTopNavMiddleNamespace } from '../constants';
|
|
7
8
|
const styles = {
|
|
8
9
|
root: "_zulpu2gc _yyhycs5v _1bsb1osq _4cvr1h6o _1e0c1txw _1bahh9n0 _181n11p5 _1j8b15b0 _lagd1bp4 _1t4c1ris _12e8h9n0"
|
|
@@ -21,7 +22,7 @@ export function TopNavMiddle({
|
|
|
21
22
|
}) {
|
|
22
23
|
return /*#__PURE__*/React.createElement("div", {
|
|
23
24
|
className: ax([styles.root])
|
|
24
|
-
}, /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
25
|
+
}, fg('platform-dst-top-layer') ? children : /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
25
26
|
namespace: openLayerObserverTopNavMiddleNamespace
|
|
26
27
|
}, children));
|
|
27
28
|
}
|
|
@@ -12,12 +12,12 @@ function clampTargetWidth(_ref) {
|
|
|
12
12
|
function getTargetWidth(area, isSideNavOverlay) {
|
|
13
13
|
var _area$compactDefaultW, _area$liveResize, _ref2, _area$requestedWidth;
|
|
14
14
|
var defaultWidth = isSideNavOverlay ? (_area$compactDefaultW = area.compactDefaultWidth) !== null && _area$compactDefaultW !== void 0 ? _area$compactDefaultW : area.defaultWidth : area.defaultWidth;
|
|
15
|
-
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.
|
|
15
|
+
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;
|
|
16
16
|
}
|
|
17
|
-
function getOverlayTargetWidth(area, isSideNavOverlay) {
|
|
17
|
+
function getOverlayTargetWidth(area, isSideNavOverlay, areaName) {
|
|
18
18
|
var _area$compactDefaultW2, _area$liveResize2, _ref3, _area$requestedWidth2;
|
|
19
19
|
var defaultWidth = isSideNavOverlay ? (_area$compactDefaultW2 = area.compactDefaultWidth) !== null && _area$compactDefaultW2 !== void 0 ? _area$compactDefaultW2 : area.defaultWidth : area.defaultWidth;
|
|
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
|
+
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;
|
|
21
21
|
}
|
|
22
22
|
export function calculateLayoutAreaStates(_ref4) {
|
|
23
23
|
var _ref5, _resizeSession$overla, _baselineWidths$chat, _panel$liveResize, _states$sideNav$widt, _states$sideNav, _states$chatPanel$wi, _states$chatPanel;
|
|
@@ -186,7 +186,7 @@ export function calculateLayoutAreaStates(_ref4) {
|
|
|
186
186
|
var layoutMax = (_areaName2 === 'chat-panel' ? layoutWidth : mainAreaWidth) * 0.9;
|
|
187
187
|
var _max = Math.max(0, Math.min(configuredMax, layoutMax));
|
|
188
188
|
var effectiveMin = Math.min(_min2, _max);
|
|
189
|
-
var _target = getOverlayTargetWidth(_area, isSideNavOverlay);
|
|
189
|
+
var _target = getOverlayTargetWidth(_area, isSideNavOverlay, _areaName2);
|
|
190
190
|
var _width = clampTargetWidth({
|
|
191
191
|
target: _target,
|
|
192
192
|
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, localSlotLayers, mainMinimumWidthVar } from './constants';
|
|
11
|
+
import { chatPanelLiveWidthVar, chatPanelVar, defaultMainMinWidth, 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';
|
|
@@ -152,7 +152,7 @@ export function ChatPanel(_ref) {
|
|
|
152
152
|
var localPanel = main.querySelector('[data-layout-with-panel-slot]');
|
|
153
153
|
var isLocalPanelInline = localPanel && getComputedStyle(localPanel).gridArea === 'panel';
|
|
154
154
|
var localPanelWidth = isLocalPanelInline ? localPanel.getBoundingClientRect().width : 0;
|
|
155
|
-
var mainMinimumWidth = getPixelCustomProperty(main, mainMinimumWidthVar,
|
|
155
|
+
var mainMinimumWidth = getPixelCustomProperty(main, mainMinimumWidthVar, defaultMainMinWidth);
|
|
156
156
|
var mainContentWidth = mainWidth - localPanelWidth;
|
|
157
157
|
var availableWidth = Math.max(0, mainContentWidth - mainMinimumWidth);
|
|
158
158
|
var availableInlineWidth = Math.floor(chatPanelWidth + availableWidth);
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* We have chosen to ignore this rule to prevent duplicating them across the different slots, and to provide a high level view of them and how they relate.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Default minimum width of Main, in pixels, before a custom minimum is registered.
|
|
9
|
+
*/
|
|
10
|
+
export var defaultMainMinWidth = 320;
|
|
11
|
+
|
|
7
12
|
// These are "compressed" to discourage usage.
|
|
8
13
|
export var sideNavVar = '--n_sNvw';
|
|
9
14
|
export var asideVar = '--n_asDw';
|
|
@@ -15,6 +20,15 @@ export var bannerMountedVar = '--n_bnrM';
|
|
|
15
20
|
export var topNavMountedVar = '--n_tNvM';
|
|
16
21
|
export var ribbonVar = '--n_rbnW';
|
|
17
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Rendered border-box width of the local PanelLayout surface, in both inline and overlay modes.
|
|
25
|
+
* Published on document.documentElement after mounting when Root opts into
|
|
26
|
+
* UNSAFE_dangerouslyHoistSlotSizes. Only the primary Root should opt in.
|
|
27
|
+
* Use `var(${localPanelWidthVar}, 0px)` for external controls, not for width persistence
|
|
28
|
+
* or sizing the panel itself. The property is removed when the surface unmounts.
|
|
29
|
+
*/
|
|
30
|
+
export var localPanelWidthVar = '--n_localPanelWidth';
|
|
31
|
+
|
|
18
32
|
/**
|
|
19
33
|
* Captures the current width of the side navigation, at all times, including during resizing.
|
|
20
34
|
*
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
|
+
var DEFAULT_PANEL_WIDTH = 365;
|
|
3
|
+
var DEFAULT_PANEL_WIDTH_WITH_CHAT_PANEL_LAYOUT = 400;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Local-panel defaults in pixels, used only when no explicit preference exists.
|
|
7
|
+
* Keep the existing desktop width until chat layout rolls out. Compact sizing is independent.
|
|
8
|
+
* These are requested defaults, not measurements of an open panel.
|
|
9
|
+
*/
|
|
10
|
+
export function getPanelLayoutDefaults() {
|
|
11
|
+
return {
|
|
12
|
+
panelWidth: fg('platform-dst-chat-panel-layout') ? DEFAULT_PANEL_WIDTH_WITH_CHAT_PANEL_LAYOUT : DEFAULT_PANEL_WIDTH,
|
|
13
|
+
compactPanelWidth: 320,
|
|
14
|
+
panelMinWidth: 320
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -4,6 +4,7 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
4
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; }
|
|
5
5
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import { bind, bindAll } from 'bind-event-listener';
|
|
7
|
+
import { defaultMainMinWidth } from './constants';
|
|
7
8
|
import { LayoutAreaSizingContext } from './layout-area-sizing-context';
|
|
8
9
|
import { layoutAreaStateContexts } from './layout-area-state-contexts';
|
|
9
10
|
import { useCssLayoutAreaStates } from './use-css-layout-area-states';
|
|
@@ -65,7 +66,7 @@ export function LayoutAreaSizingProvider(_ref) {
|
|
|
65
66
|
listener: dismissOlderOverlay
|
|
66
67
|
});
|
|
67
68
|
}, [chatPanelMode, lastOpenedOverlay, sideNavMode]);
|
|
68
|
-
var mainMinWidth = useRef(
|
|
69
|
+
var mainMinWidth = useRef(defaultMainMinWidth);
|
|
69
70
|
var loadRef = useRef(function () {});
|
|
70
71
|
var ready = useRef(false);
|
|
71
72
|
var waiting = useRef([]);
|
|
@@ -8,11 +8,11 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
8
8
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
9
|
import { bind } from 'bind-event-listener';
|
|
10
10
|
import { calculateLayoutAreaStates } from './calculate-layout-area-states';
|
|
11
|
+
import { defaultMainMinWidth } from './constants';
|
|
11
12
|
import { LayoutAreaSizingContext } from './layout-area-sizing-context';
|
|
12
13
|
import { layoutAreaStateContexts } from './layout-area-state-contexts';
|
|
13
14
|
import { resolveLayoutWidth } from './resolve-layout-width';
|
|
14
15
|
import { useOccupiedLayoutWidth } from './use-occupied-layout-width';
|
|
15
|
-
var defaultMainMinWidth = 320;
|
|
16
16
|
function useStableAreaState(state) {
|
|
17
17
|
var _ref = state !== null && state !== void 0 ? state : {},
|
|
18
18
|
mode = _ref.mode,
|
|
@@ -304,7 +304,7 @@ export function LayoutAreaSizingRuntime(_ref2) {
|
|
|
304
304
|
if (!existing) {
|
|
305
305
|
return current;
|
|
306
306
|
}
|
|
307
|
-
if (mode === 'overlay') {
|
|
307
|
+
if (mode === 'overlay' && area !== 'panel') {
|
|
308
308
|
return _objectSpread(_objectSpread({}, current), {}, _defineProperty({}, area, _objectSpread(_objectSpread({}, existing), {}, {
|
|
309
309
|
liveResize: undefined,
|
|
310
310
|
preferredOverlayWidth: width
|
|
@@ -312,7 +312,8 @@ export function LayoutAreaSizingRuntime(_ref2) {
|
|
|
312
312
|
}
|
|
313
313
|
return _objectSpread(_objectSpread({}, current), {}, _defineProperty({}, area, _objectSpread(_objectSpread({}, existing), {}, {
|
|
314
314
|
liveResize: undefined,
|
|
315
|
-
|
|
315
|
+
// Local panels have one preference, regardless of the resized mode.
|
|
316
|
+
preferredWidth: width
|
|
316
317
|
})));
|
|
317
318
|
});
|
|
318
319
|
}, [captureSiblingWidths]);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
._nd5l1c6w{grid-area:panel}
|
|
2
|
+
._nd5l1gzg{grid-area:main}
|
|
3
|
+
._nd5l32aw{grid-area:var(--p_lclPnlSsrArea,main)}
|
|
4
|
+
._y44v1mph{animation:var(--ds-panel-content-enter,.15s cubic-bezier(.4,1,.6,1) FadeIn0to100)}
|
|
5
|
+
._y44vf1qi{animation:var(--ds-panel-content-exit,50ms cubic-bezier(.6,0,.8,.6) FadeOut100to0)}
|
|
6
|
+
._191wbqna{border-inline-start:var(--p_lclPnlSsrBorder,none)}
|
|
7
|
+
._191wglyw{border-inline-start:none}
|
|
8
|
+
._191wia51{border-inline-start:var(--ds-border-width,1px) solid var(--ds-border,#0b120e24)}._10fph9n0{justify-self:end}
|
|
9
|
+
._152tidpf{inset-block-start:0}
|
|
10
|
+
._16qs130s{box-shadow:var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f)}
|
|
11
|
+
._16qs1dhr{box-shadow:var(--p_lclPnlSsrShadow,var(--ds-shadow-overlay,0 8px 9pt #1e1f2126,0 0 1px #1e1f214f))}
|
|
12
|
+
._16qsglyw{box-shadow:none}
|
|
13
|
+
._18m91wug{overflow-y:auto}
|
|
14
|
+
._1bsb13q4{width:min(90%,var(--p_lclPnlRsz,var(--p_lclPnlW)))}
|
|
15
|
+
._1bsb1c5w{width:var(--p_lclPnlRsz,var(--p_lclPnlW))}
|
|
16
|
+
._1bsb1cku{width:var(--p_lclPnlSsrWidth,min(90%,var(--p_lclPnlSsrPreferredW)))}
|
|
17
|
+
._1reo1wug{overflow-x:auto}
|
|
18
|
+
._4t3i1osq{height:100%}
|
|
19
|
+
._4t3ieqxy{height:calc(100vh - var(--n_bnrM, 0px) - var(--n_tNvM, 0px))}
|
|
20
|
+
._bfhk1bhr{background-color:var(--ds-surface-overlay,#fff)}
|
|
21
|
+
._bfhk1g1j{background-color:var(--p_lclPnlSsrBackground,var(--ds-surface-overlay,#fff))}
|
|
22
|
+
._bfhkvuon{background-color:var(--ds-surface,#fff)}
|
|
23
|
+
._ju25dn4k{animation-delay:var(--ds-duration-xshort,.1s)}
|
|
24
|
+
._kqsw1if8{position:sticky}
|
|
25
|
+
._vchhusvi{box-sizing:border-box}
|
|
26
|
+
@media (prefers-reduced-motion:no-preference){._k1af14vv{animation:var(--ds-panel-exit-right,.2s cubic-bezier(0,.4,0,1) SlideOut100PercentRight)}[dir=rtl] ._105aeydr{animation:var(--ds-panel-exit-left,.2s cubic-bezier(0,.4,0,1) SlideOut100PercentLeft)}._bq641n9t{position:fixed}@starting-style{._1kmh1n9t{position:fixed}}._k1af1nn1{animation:var(--ds-panel-enter-right,.25s cubic-bezier(0,.4,0,1) SlideIn100PercentRight)}._10t81ia4{transition-property:position}._xrrp147i{transition-duration:var(--ds-duration-instant,0ms)}._1wsa1ign{transition-delay:var(--ds-duration-short,.15s)}._1vrh1a5r{transition-behavior:allow-discrete}[dir=rtl] ._105abamb{animation:var(--ds-panel-enter-left,.25s cubic-bezier(0,.4,0,1) SlideIn100PercentLeft)}}
|