@atlaskit/navigation-system 4.3.0 → 4.5.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 +28 -0
- package/dist/cjs/ui/page-layout/root.js +8 -3
- package/dist/cjs/ui/page-layout/side-nav/is-side-nav-shortcut-enabled-context.js +36 -0
- package/dist/cjs/ui/page-layout/side-nav/side-nav.js +55 -3
- package/dist/cjs/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.js +59 -0
- package/dist/es2019/ui/page-layout/root.js +7 -3
- package/dist/es2019/ui/page-layout/side-nav/is-side-nav-shortcut-enabled-context.js +29 -0
- package/dist/es2019/ui/page-layout/side-nav/side-nav.js +54 -3
- package/dist/es2019/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.js +54 -0
- package/dist/esm/ui/page-layout/root.js +8 -3
- package/dist/esm/ui/page-layout/side-nav/is-side-nav-shortcut-enabled-context.js +28 -0
- package/dist/esm/ui/page-layout/side-nav/side-nav.js +54 -3
- package/dist/esm/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.js +53 -0
- package/dist/types/ui/page-layout/root.d.ts +19 -1
- package/dist/types/ui/page-layout/side-nav/is-side-nav-shortcut-enabled-context.d.ts +13 -0
- package/dist/types/ui/page-layout/side-nav/side-nav.d.ts +24 -1
- package/dist/types/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.d.ts +6 -0
- package/dist/types-ts4.5/ui/page-layout/root.d.ts +19 -1
- package/dist/types-ts4.5/ui/page-layout/side-nav/is-side-nav-shortcut-enabled-context.d.ts +13 -0
- package/dist/types-ts4.5/ui/page-layout/side-nav/side-nav.d.ts +24 -1
- package/dist/types-ts4.5/ui/page-layout/side-nav/use-side-nav-toggle-keyboard-shortcut.d.ts +6 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @atlassian/navigation-system
|
|
2
2
|
|
|
3
|
+
## 4.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`8a71ce992f8c8`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8a71ce992f8c8) -
|
|
8
|
+
`SideNav` now provides a built-in keyboard shortcut for expanding and collapsing. This is behind
|
|
9
|
+
the feature gate `navx-full-height-sidebar`.
|
|
10
|
+
- The shortcut key is `Ctrl` + `[`.
|
|
11
|
+
- The shortcut is not enabled by default.
|
|
12
|
+
- The prop `isSideNavShortcutEnabled` has been added to `Root`, as a way to control whether the
|
|
13
|
+
shortcut is enabled (whether the keyboard event listener is binded). It defaults to `false`.
|
|
14
|
+
- The prop `canToggleWithShortcut()` has been added to `SideNav`, as a way to run additional
|
|
15
|
+
checks after the shortcut is pressed, before the side nav is toggled.
|
|
16
|
+
- The shortcut will also be ignored if there are any open modals. This check is behind the feature
|
|
17
|
+
gate `platform-dst-open-layer-observer-layer-type`.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
|
|
23
|
+
## 4.4.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- [`327d6a06eebb2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/327d6a06eebb2) -
|
|
28
|
+
Adds `onPeekStart` and `onPeekEnd` callbacks to the `SideNav` to use for monitoring when users
|
|
29
|
+
peek at the side navigation when it is collapsed.
|
|
30
|
+
|
|
3
31
|
## 4.3.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
|
@@ -15,6 +15,7 @@ var _skipLinksProvider = require("../../context/skip-links/skip-links-provider")
|
|
|
15
15
|
var _topNavStartContextProvider = require("../../context/top-nav-start/top-nav-start-context-provider");
|
|
16
16
|
var _hoistSlotSizesContext = require("./hoist-slot-sizes-context");
|
|
17
17
|
var _elementContext = require("./side-nav/element-context");
|
|
18
|
+
var _isSideNavShortcutEnabledContext = require("./side-nav/is-side-nav-shortcut-enabled-context");
|
|
18
19
|
var _toggleButtonProvider = require("./side-nav/toggle-button-provider");
|
|
19
20
|
var _visibilityProvider = require("./side-nav/visibility-provider");
|
|
20
21
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
@@ -36,7 +37,9 @@ function Root(_ref) {
|
|
|
36
37
|
_ref$skipLinksLabel = _ref.skipLinksLabel,
|
|
37
38
|
skipLinksLabel = _ref$skipLinksLabel === void 0 ? 'Skip to:' : _ref$skipLinksLabel,
|
|
38
39
|
testId = _ref.testId,
|
|
39
|
-
defaultSideNavCollapsed = _ref.defaultSideNavCollapsed
|
|
40
|
+
defaultSideNavCollapsed = _ref.defaultSideNavCollapsed,
|
|
41
|
+
_ref$isSideNavShortcu = _ref.isSideNavShortcutEnabled,
|
|
42
|
+
isSideNavShortcutEnabled = _ref$isSideNavShortcu === void 0 ? false : _ref$isSideNavShortcu;
|
|
40
43
|
var ref = (0, _react.useRef)(null);
|
|
41
44
|
(0, _react.useEffect)(function () {
|
|
42
45
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -53,7 +56,9 @@ function Root(_ref) {
|
|
|
53
56
|
}, []);
|
|
54
57
|
return /*#__PURE__*/_react.default.createElement(_visibilityProvider.SideNavVisibilityProvider, {
|
|
55
58
|
defaultCollapsed: defaultSideNavCollapsed
|
|
56
|
-
}, /*#__PURE__*/_react.default.createElement(_toggleButtonProvider.SideNavToggleButtonProvider, null, /*#__PURE__*/_react.default.createElement(_elementContext.SideNavElementProvider, null, /*#__PURE__*/_react.default.createElement(
|
|
59
|
+
}, /*#__PURE__*/_react.default.createElement(_toggleButtonProvider.SideNavToggleButtonProvider, null, /*#__PURE__*/_react.default.createElement(_elementContext.SideNavElementProvider, null, /*#__PURE__*/_react.default.createElement(_isSideNavShortcutEnabledContext.IsSideNavShortcutEnabledProvider, {
|
|
60
|
+
isSideNavShortcutEnabled: isSideNavShortcutEnabled
|
|
61
|
+
}, /*#__PURE__*/_react.default.createElement(_topNavStartContextProvider.TopNavStartProvider, null, /*#__PURE__*/_react.default.createElement(_openLayerObserver.OpenLayerObserver, null, /*#__PURE__*/_react.default.createElement(_hoistSlotSizesContext.DangerouslyHoistSlotSizes.Provider, {
|
|
57
62
|
value: UNSAFE_dangerouslyHoistSlotSizes
|
|
58
63
|
}, /*#__PURE__*/_react.default.createElement(_skipLinksProvider.SkipLinksProvider, {
|
|
59
64
|
label: skipLinksLabel,
|
|
@@ -63,5 +68,5 @@ function Root(_ref) {
|
|
|
63
68
|
className: (0, _runtime.ax)([styles.root, xcss]),
|
|
64
69
|
id: gridRootId,
|
|
65
70
|
"data-testid": testId
|
|
66
|
-
}, children))))))));
|
|
71
|
+
}, children)))))))));
|
|
67
72
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.IsSideNavShortcutEnabledProvider = IsSideNavShortcutEnabledProvider;
|
|
8
|
+
exports.useIsSideNavShortcutEnabled = useIsSideNavShortcutEnabled;
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
11
|
+
/**
|
|
12
|
+
* Context for whether the side nav toggle shortcut is enabled.
|
|
13
|
+
*
|
|
14
|
+
* Used to share the `isSideNavShortcutEnabled` prop value from `Root` with other components,
|
|
15
|
+
* so the visual keyboard shortcut in tooltips can be conditionally displayed.
|
|
16
|
+
*/
|
|
17
|
+
var IsSideNavShortcutEnabledContext = /*#__PURE__*/(0, _react.createContext)(false);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Provider for the `IsSideNavShortcutEnabledContext`.
|
|
21
|
+
*/
|
|
22
|
+
function IsSideNavShortcutEnabledProvider(_ref) {
|
|
23
|
+
var children = _ref.children,
|
|
24
|
+
isSideNavShortcutEnabled = _ref.isSideNavShortcutEnabled;
|
|
25
|
+
return /*#__PURE__*/_react.default.createElement(IsSideNavShortcutEnabledContext.Provider, {
|
|
26
|
+
value: isSideNavShortcutEnabled
|
|
27
|
+
}, children);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns the value of the `isSideNavShortcutEnabled` prop from the `Root` component, which
|
|
32
|
+
* is shared through context.
|
|
33
|
+
*/
|
|
34
|
+
function useIsSideNavShortcutEnabled() {
|
|
35
|
+
return (0, _react.useContext)(IsSideNavShortcutEnabledContext);
|
|
36
|
+
}
|
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
value: true
|
|
8
8
|
});
|
|
9
9
|
exports.SideNav = SideNav;
|
|
10
|
+
exports.onPeekStartDelayMs = void 0;
|
|
10
11
|
require("./side-nav.compiled.css");
|
|
11
12
|
var _react = _interopRequireWildcard(require("react"));
|
|
12
13
|
var React = _react;
|
|
@@ -17,6 +18,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
17
18
|
var _bindEventListener = require("bind-event-listener");
|
|
18
19
|
var _reactDom = require("react-dom");
|
|
19
20
|
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
|
|
21
|
+
var _useStableRef = _interopRequireDefault(require("@atlaskit/ds-lib/use-stable-ref"));
|
|
20
22
|
var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
|
|
21
23
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
22
24
|
var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
|
|
@@ -34,6 +36,7 @@ var _elementContext = require("./element-context");
|
|
|
34
36
|
var _flyoutCloseDelayMs = require("./flyout-close-delay-ms");
|
|
35
37
|
var _toggleButtonContext = require("./toggle-button-context");
|
|
36
38
|
var _useExpandSideNav = require("./use-expand-side-nav");
|
|
39
|
+
var _useSideNavToggleKeyboardShortcut = require("./use-side-nav-toggle-keyboard-shortcut");
|
|
37
40
|
var _useSideNavVisibility2 = require("./use-side-nav-visibility");
|
|
38
41
|
var _useSideNavVisibilityCallbacks = require("./use-side-nav-visibility-callbacks");
|
|
39
42
|
var _useToggleSideNav = require("./use-toggle-side-nav");
|
|
@@ -77,6 +80,7 @@ var styles = {
|
|
|
77
80
|
fullHeightSidebar: "_165t56xv _180k1wjm _26vxoned _1mt19dtb"
|
|
78
81
|
};
|
|
79
82
|
var fallbackDefaultWidth = 320;
|
|
83
|
+
var onPeekStartDelayMs = exports.onPeekStartDelayMs = 500;
|
|
80
84
|
|
|
81
85
|
/**
|
|
82
86
|
* We need an additional component layer so we can wrap the side nav in a `OpenLayerObserver` and have access to the
|
|
@@ -95,7 +99,10 @@ function SideNavInternal(_ref) {
|
|
|
95
99
|
skipLinkLabel = _ref$skipLinkLabel === void 0 ? label : _ref$skipLinkLabel,
|
|
96
100
|
onExpand = _ref.onExpand,
|
|
97
101
|
onCollapse = _ref.onCollapse,
|
|
98
|
-
|
|
102
|
+
onPeekStart = _ref.onPeekStart,
|
|
103
|
+
onPeekEnd = _ref.onPeekEnd,
|
|
104
|
+
providedId = _ref.id,
|
|
105
|
+
canToggleWithShortcut = _ref.canToggleWithShortcut;
|
|
99
106
|
var id = (0, _idUtils.useLayoutId)({
|
|
100
107
|
providedId: providedId
|
|
101
108
|
});
|
|
@@ -161,6 +168,16 @@ function SideNavInternal(_ref) {
|
|
|
161
168
|
type: 'not-active'
|
|
162
169
|
});
|
|
163
170
|
var isFlyoutVisible = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open';
|
|
171
|
+
var isExpandedOnDesktopRef = (0, _useStableRef.default)(isExpandedOnDesktop);
|
|
172
|
+
var hasPeekStartedRef = (0, _react.useRef)(false);
|
|
173
|
+
var onPeekStartRef = (0, _useStableRef.default)(onPeekStart);
|
|
174
|
+
var onPeekEndRef = (0, _useStableRef.default)(onPeekEnd);
|
|
175
|
+
var onPeekStartTimeoutIdRef = (0, _react.useRef)(undefined);
|
|
176
|
+
(0, _react.useEffect)(function () {
|
|
177
|
+
return function () {
|
|
178
|
+
clearTimeout(onPeekStartTimeoutIdRef.current);
|
|
179
|
+
};
|
|
180
|
+
}, []);
|
|
164
181
|
var updateFlyoutState = (0, _react.useMemo)(function () {
|
|
165
182
|
function tryAbortPendingClose() {
|
|
166
183
|
if (flyoutStateRef.current.type === 'waiting-for-close') {
|
|
@@ -168,6 +185,7 @@ function SideNavInternal(_ref) {
|
|
|
168
185
|
}
|
|
169
186
|
}
|
|
170
187
|
function open() {
|
|
188
|
+
var prevFlyoutState = flyoutStateRef.current;
|
|
171
189
|
tryAbortPendingClose();
|
|
172
190
|
flyoutStateRef.current = {
|
|
173
191
|
type: 'open'
|
|
@@ -180,8 +198,24 @@ function SideNavInternal(_ref) {
|
|
|
180
198
|
}
|
|
181
199
|
return currentState;
|
|
182
200
|
});
|
|
201
|
+
|
|
202
|
+
// Avoid redundant calls to `onPeekStart()`
|
|
203
|
+
if (prevFlyoutState.type === 'not-active') {
|
|
204
|
+
clearTimeout(onPeekStartTimeoutIdRef.current);
|
|
205
|
+
onPeekStartTimeoutIdRef.current = setTimeout(function () {
|
|
206
|
+
var _onPeekStartRef$curre;
|
|
207
|
+
// If the flyout isn't still open after ~500ms then we won't count the peek
|
|
208
|
+
// As we want to track user intention rather than all hovers
|
|
209
|
+
if (isExpandedOnDesktopRef.current || flyoutStateRef.current.type !== 'open') {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
hasPeekStartedRef.current = true;
|
|
213
|
+
(_onPeekStartRef$curre = onPeekStartRef.current) === null || _onPeekStartRef$curre === void 0 || _onPeekStartRef$curre.call(onPeekStartRef);
|
|
214
|
+
}, onPeekStartDelayMs);
|
|
215
|
+
}
|
|
183
216
|
}
|
|
184
217
|
function close() {
|
|
218
|
+
var prevFlyoutState = flyoutStateRef.current;
|
|
185
219
|
tryAbortPendingClose();
|
|
186
220
|
flyoutStateRef.current = {
|
|
187
221
|
type: 'not-active'
|
|
@@ -194,6 +228,15 @@ function SideNavInternal(_ref) {
|
|
|
194
228
|
}
|
|
195
229
|
return currentState;
|
|
196
230
|
});
|
|
231
|
+
|
|
232
|
+
// Avoid redundant calls to `onPeekEnd()`
|
|
233
|
+
if (prevFlyoutState.type !== 'not-active' && hasPeekStartedRef.current) {
|
|
234
|
+
var _onPeekEndRef$current;
|
|
235
|
+
hasPeekStartedRef.current = false;
|
|
236
|
+
(_onPeekEndRef$current = onPeekEndRef.current) === null || _onPeekEndRef$current === void 0 || _onPeekEndRef$current.call(onPeekEndRef, {
|
|
237
|
+
trigger: isExpandedOnDesktopRef.current ? 'side-nav-expand' : 'mouse-leave'
|
|
238
|
+
});
|
|
239
|
+
}
|
|
197
240
|
}
|
|
198
241
|
return function onAction(action) {
|
|
199
242
|
if (action === 'drag-from-flyout-started') {
|
|
@@ -252,7 +295,7 @@ function SideNavInternal(_ref) {
|
|
|
252
295
|
return;
|
|
253
296
|
}
|
|
254
297
|
};
|
|
255
|
-
}, [openLayerObserver, setSideNavState]);
|
|
298
|
+
}, [isExpandedOnDesktopRef, onPeekEndRef, onPeekStartRef, openLayerObserver, setSideNavState]);
|
|
256
299
|
var toggleVisibilityByScreenResize = (0, _useToggleSideNav.useToggleSideNav)({
|
|
257
300
|
trigger: 'screen-resize'
|
|
258
301
|
});
|
|
@@ -604,6 +647,9 @@ function SideNavInternal(_ref) {
|
|
|
604
647
|
}
|
|
605
648
|
devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
|
|
606
649
|
}
|
|
650
|
+
(0, _useSideNavToggleKeyboardShortcut.useSideNavToggleKeyboardShortcut)({
|
|
651
|
+
canToggleWithShortcut: canToggleWithShortcut
|
|
652
|
+
});
|
|
607
653
|
(0, _useResizingWidthCssVarOnRootElement.useResizingWidthCssVarOnRootElement)({
|
|
608
654
|
isEnabled: true,
|
|
609
655
|
cssVar: panelSplitterResizingVar,
|
|
@@ -703,6 +749,9 @@ function SideNav(_ref8) {
|
|
|
703
749
|
skipLinkLabel = _ref8$skipLinkLabel === void 0 ? label : _ref8$skipLinkLabel,
|
|
704
750
|
onExpand = _ref8.onExpand,
|
|
705
751
|
onCollapse = _ref8.onCollapse,
|
|
752
|
+
onPeekStart = _ref8.onPeekStart,
|
|
753
|
+
onPeekEnd = _ref8.onPeekEnd,
|
|
754
|
+
canToggleWithShortcut = _ref8.canToggleWithShortcut,
|
|
706
755
|
id = _ref8.id;
|
|
707
756
|
return /*#__PURE__*/React.createElement(_openLayerObserver.OpenLayerObserverNamespaceProvider, {
|
|
708
757
|
namespace: openLayerObserverSideNavNamespace
|
|
@@ -714,6 +763,9 @@ function SideNav(_ref8) {
|
|
|
714
763
|
skipLinkLabel: skipLinkLabel,
|
|
715
764
|
onExpand: onExpand,
|
|
716
765
|
onCollapse: onCollapse,
|
|
717
|
-
|
|
766
|
+
onPeekStart: onPeekStart,
|
|
767
|
+
onPeekEnd: onPeekEnd,
|
|
768
|
+
id: id,
|
|
769
|
+
canToggleWithShortcut: canToggleWithShortcut
|
|
718
770
|
}, children));
|
|
719
771
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.useSideNavToggleKeyboardShortcut = useSideNavToggleKeyboardShortcut;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _bindEventListener = require("bind-event-listener");
|
|
10
|
+
var _useStableRef = _interopRequireDefault(require("@atlaskit/ds-lib/use-stable-ref"));
|
|
11
|
+
var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
|
|
12
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
13
|
+
var _isSideNavShortcutEnabledContext = require("./is-side-nav-shortcut-enabled-context");
|
|
14
|
+
var _useToggleSideNav = require("./use-toggle-side-nav");
|
|
15
|
+
/**
|
|
16
|
+
* Binds the keyboard shortcut to toggle the side nav.
|
|
17
|
+
*/
|
|
18
|
+
function useSideNavToggleKeyboardShortcut(_ref) {
|
|
19
|
+
var canToggleWithShortcut = _ref.canToggleWithShortcut;
|
|
20
|
+
var openLayerObserver = (0, _openLayerObserver.useOpenLayerObserver)();
|
|
21
|
+
var toggleVisibilityByShortcut = (0, _useToggleSideNav.useToggleSideNav)({
|
|
22
|
+
trigger: 'keyboard'
|
|
23
|
+
});
|
|
24
|
+
var canToggleWithShortcutStableRef = (0, _useStableRef.default)(canToggleWithShortcut);
|
|
25
|
+
var isSideNavShortcutEnabled = (0, _isSideNavShortcutEnabledContext.useIsSideNavShortcutEnabled)();
|
|
26
|
+
(0, _react.useEffect)(function () {
|
|
27
|
+
if (!(0, _platformFeatureFlags.fg)('navx-full-height-sidebar')) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!isSideNavShortcutEnabled) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
return (0, _bindEventListener.bind)(window, {
|
|
34
|
+
type: 'keydown',
|
|
35
|
+
listener: function listener(event) {
|
|
36
|
+
if (event.ctrlKey && event.key === '[') {
|
|
37
|
+
if (canToggleWithShortcutStableRef.current && !canToggleWithShortcutStableRef.current()) {
|
|
38
|
+
// Return early if the callback returns false.
|
|
39
|
+
// If the callback is not provided, we assume the shortcut is enabled.
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (event.repeat) {
|
|
43
|
+
// Ignore repeated keydown events from holding down the keys
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (openLayerObserver.getCount({
|
|
47
|
+
type: 'modal'
|
|
48
|
+
}) > 0 && (0, _platformFeatureFlags.fg)('platform-dst-open-layer-observer-layer-type')) {
|
|
49
|
+
// Return early if there are any open modals
|
|
50
|
+
// This check is behind the layer type FG, as `getCount` will return the count of all layers when
|
|
51
|
+
// the FG is disabled - meaning we would ignore the shortcut if there is any open layer (not just modals).
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
toggleVisibilityByShortcut();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}, [canToggleWithShortcutStableRef, openLayerObserver, toggleVisibilityByShortcut, isSideNavShortcutEnabled]);
|
|
59
|
+
}
|
|
@@ -7,6 +7,7 @@ import { SkipLinksProvider } from '../../context/skip-links/skip-links-provider'
|
|
|
7
7
|
import { TopNavStartProvider } from '../../context/top-nav-start/top-nav-start-context-provider';
|
|
8
8
|
import { DangerouslyHoistSlotSizes } from './hoist-slot-sizes-context';
|
|
9
9
|
import { SideNavElementProvider } from './side-nav/element-context';
|
|
10
|
+
import { IsSideNavShortcutEnabledProvider } from './side-nav/is-side-nav-shortcut-enabled-context';
|
|
10
11
|
import { SideNavToggleButtonProvider } from './side-nav/toggle-button-provider';
|
|
11
12
|
import { SideNavVisibilityProvider } from './side-nav/visibility-provider';
|
|
12
13
|
|
|
@@ -26,7 +27,8 @@ export function Root({
|
|
|
26
27
|
UNSAFE_dangerouslyHoistSlotSizes = false,
|
|
27
28
|
skipLinksLabel = 'Skip to:',
|
|
28
29
|
testId,
|
|
29
|
-
defaultSideNavCollapsed
|
|
30
|
+
defaultSideNavCollapsed,
|
|
31
|
+
isSideNavShortcutEnabled = false
|
|
30
32
|
}) {
|
|
31
33
|
const ref = useRef(null);
|
|
32
34
|
useEffect(() => {
|
|
@@ -53,7 +55,9 @@ This message will not be displayed in production.
|
|
|
53
55
|
}, []);
|
|
54
56
|
return /*#__PURE__*/React.createElement(SideNavVisibilityProvider, {
|
|
55
57
|
defaultCollapsed: defaultSideNavCollapsed
|
|
56
|
-
}, /*#__PURE__*/React.createElement(SideNavToggleButtonProvider, null, /*#__PURE__*/React.createElement(SideNavElementProvider, null, /*#__PURE__*/React.createElement(
|
|
58
|
+
}, /*#__PURE__*/React.createElement(SideNavToggleButtonProvider, null, /*#__PURE__*/React.createElement(SideNavElementProvider, null, /*#__PURE__*/React.createElement(IsSideNavShortcutEnabledProvider, {
|
|
59
|
+
isSideNavShortcutEnabled: isSideNavShortcutEnabled
|
|
60
|
+
}, /*#__PURE__*/React.createElement(TopNavStartProvider, null, /*#__PURE__*/React.createElement(OpenLayerObserver, null, /*#__PURE__*/React.createElement(DangerouslyHoistSlotSizes.Provider, {
|
|
57
61
|
value: UNSAFE_dangerouslyHoistSlotSizes
|
|
58
62
|
}, /*#__PURE__*/React.createElement(SkipLinksProvider, {
|
|
59
63
|
label: skipLinksLabel,
|
|
@@ -63,5 +67,5 @@ This message will not be displayed in production.
|
|
|
63
67
|
className: ax([styles.root, xcss]),
|
|
64
68
|
id: gridRootId,
|
|
65
69
|
"data-testid": testId
|
|
66
|
-
}, children))))))));
|
|
70
|
+
}, children)))))))));
|
|
67
71
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context for whether the side nav toggle shortcut is enabled.
|
|
5
|
+
*
|
|
6
|
+
* Used to share the `isSideNavShortcutEnabled` prop value from `Root` with other components,
|
|
7
|
+
* so the visual keyboard shortcut in tooltips can be conditionally displayed.
|
|
8
|
+
*/
|
|
9
|
+
const IsSideNavShortcutEnabledContext = /*#__PURE__*/createContext(false);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Provider for the `IsSideNavShortcutEnabledContext`.
|
|
13
|
+
*/
|
|
14
|
+
export function IsSideNavShortcutEnabledProvider({
|
|
15
|
+
children,
|
|
16
|
+
isSideNavShortcutEnabled
|
|
17
|
+
}) {
|
|
18
|
+
return /*#__PURE__*/React.createElement(IsSideNavShortcutEnabledContext.Provider, {
|
|
19
|
+
value: isSideNavShortcutEnabled
|
|
20
|
+
}, children);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns the value of the `isSideNavShortcutEnabled` prop from the `Root` component, which
|
|
25
|
+
* is shared through context.
|
|
26
|
+
*/
|
|
27
|
+
export function useIsSideNavShortcutEnabled() {
|
|
28
|
+
return useContext(IsSideNavShortcutEnabledContext);
|
|
29
|
+
}
|
|
@@ -7,6 +7,7 @@ import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, u
|
|
|
7
7
|
import { bind } from 'bind-event-listener';
|
|
8
8
|
import { flushSync } from 'react-dom';
|
|
9
9
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
10
|
+
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
10
11
|
import { OpenLayerObserverNamespaceProvider, useOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
11
12
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
13
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
@@ -24,6 +25,7 @@ import { useSideNavRef } from './element-context';
|
|
|
24
25
|
import { sideNavFlyoutCloseDelayMs } from './flyout-close-delay-ms';
|
|
25
26
|
import { SideNavToggleButtonElement } from './toggle-button-context';
|
|
26
27
|
import { useExpandSideNav } from './use-expand-side-nav';
|
|
28
|
+
import { useSideNavToggleKeyboardShortcut } from './use-side-nav-toggle-keyboard-shortcut';
|
|
27
29
|
import { useSideNavVisibility } from './use-side-nav-visibility';
|
|
28
30
|
import { useSideNavVisibilityCallbacks } from './use-side-nav-visibility-callbacks';
|
|
29
31
|
import { useToggleSideNav } from './use-toggle-side-nav';
|
|
@@ -64,6 +66,7 @@ const styles = {
|
|
|
64
66
|
fullHeightSidebar: "_165t56xv _180k1wjm _26vxoned _1mt19dtb"
|
|
65
67
|
};
|
|
66
68
|
const fallbackDefaultWidth = 320;
|
|
69
|
+
export const onPeekStartDelayMs = 500;
|
|
67
70
|
|
|
68
71
|
/**
|
|
69
72
|
* We need an additional component layer so we can wrap the side nav in a `OpenLayerObserver` and have access to the
|
|
@@ -78,7 +81,10 @@ function SideNavInternal({
|
|
|
78
81
|
skipLinkLabel = label,
|
|
79
82
|
onExpand,
|
|
80
83
|
onCollapse,
|
|
81
|
-
|
|
84
|
+
onPeekStart,
|
|
85
|
+
onPeekEnd,
|
|
86
|
+
id: providedId,
|
|
87
|
+
canToggleWithShortcut
|
|
82
88
|
}) {
|
|
83
89
|
var _sideNavState$lastTri;
|
|
84
90
|
const id = useLayoutId({
|
|
@@ -142,6 +148,16 @@ function SideNavInternal({
|
|
|
142
148
|
type: 'not-active'
|
|
143
149
|
});
|
|
144
150
|
const isFlyoutVisible = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open';
|
|
151
|
+
const isExpandedOnDesktopRef = useStableRef(isExpandedOnDesktop);
|
|
152
|
+
const hasPeekStartedRef = useRef(false);
|
|
153
|
+
const onPeekStartRef = useStableRef(onPeekStart);
|
|
154
|
+
const onPeekEndRef = useStableRef(onPeekEnd);
|
|
155
|
+
const onPeekStartTimeoutIdRef = useRef(undefined);
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
return () => {
|
|
158
|
+
clearTimeout(onPeekStartTimeoutIdRef.current);
|
|
159
|
+
};
|
|
160
|
+
}, []);
|
|
145
161
|
const updateFlyoutState = useMemo(() => {
|
|
146
162
|
function tryAbortPendingClose() {
|
|
147
163
|
if (flyoutStateRef.current.type === 'waiting-for-close') {
|
|
@@ -149,6 +165,7 @@ function SideNavInternal({
|
|
|
149
165
|
}
|
|
150
166
|
}
|
|
151
167
|
function open() {
|
|
168
|
+
const prevFlyoutState = flyoutStateRef.current;
|
|
152
169
|
tryAbortPendingClose();
|
|
153
170
|
flyoutStateRef.current = {
|
|
154
171
|
type: 'open'
|
|
@@ -162,8 +179,24 @@ function SideNavInternal({
|
|
|
162
179
|
}
|
|
163
180
|
return currentState;
|
|
164
181
|
});
|
|
182
|
+
|
|
183
|
+
// Avoid redundant calls to `onPeekStart()`
|
|
184
|
+
if (prevFlyoutState.type === 'not-active') {
|
|
185
|
+
clearTimeout(onPeekStartTimeoutIdRef.current);
|
|
186
|
+
onPeekStartTimeoutIdRef.current = setTimeout(() => {
|
|
187
|
+
var _onPeekStartRef$curre;
|
|
188
|
+
// If the flyout isn't still open after ~500ms then we won't count the peek
|
|
189
|
+
// As we want to track user intention rather than all hovers
|
|
190
|
+
if (isExpandedOnDesktopRef.current || flyoutStateRef.current.type !== 'open') {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
hasPeekStartedRef.current = true;
|
|
194
|
+
(_onPeekStartRef$curre = onPeekStartRef.current) === null || _onPeekStartRef$curre === void 0 ? void 0 : _onPeekStartRef$curre.call(onPeekStartRef);
|
|
195
|
+
}, onPeekStartDelayMs);
|
|
196
|
+
}
|
|
165
197
|
}
|
|
166
198
|
function close() {
|
|
199
|
+
const prevFlyoutState = flyoutStateRef.current;
|
|
167
200
|
tryAbortPendingClose();
|
|
168
201
|
flyoutStateRef.current = {
|
|
169
202
|
type: 'not-active'
|
|
@@ -177,6 +210,15 @@ function SideNavInternal({
|
|
|
177
210
|
}
|
|
178
211
|
return currentState;
|
|
179
212
|
});
|
|
213
|
+
|
|
214
|
+
// Avoid redundant calls to `onPeekEnd()`
|
|
215
|
+
if (prevFlyoutState.type !== 'not-active' && hasPeekStartedRef.current) {
|
|
216
|
+
var _onPeekEndRef$current;
|
|
217
|
+
hasPeekStartedRef.current = false;
|
|
218
|
+
(_onPeekEndRef$current = onPeekEndRef.current) === null || _onPeekEndRef$current === void 0 ? void 0 : _onPeekEndRef$current.call(onPeekEndRef, {
|
|
219
|
+
trigger: isExpandedOnDesktopRef.current ? 'side-nav-expand' : 'mouse-leave'
|
|
220
|
+
});
|
|
221
|
+
}
|
|
180
222
|
}
|
|
181
223
|
return function onAction(action) {
|
|
182
224
|
if (action === 'drag-from-flyout-started') {
|
|
@@ -235,7 +277,7 @@ function SideNavInternal({
|
|
|
235
277
|
return;
|
|
236
278
|
}
|
|
237
279
|
};
|
|
238
|
-
}, [openLayerObserver, setSideNavState]);
|
|
280
|
+
}, [isExpandedOnDesktopRef, onPeekEndRef, onPeekStartRef, openLayerObserver, setSideNavState]);
|
|
239
281
|
const toggleVisibilityByScreenResize = useToggleSideNav({
|
|
240
282
|
trigger: 'screen-resize'
|
|
241
283
|
});
|
|
@@ -593,6 +635,9 @@ function SideNavInternal({
|
|
|
593
635
|
}
|
|
594
636
|
devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
|
|
595
637
|
}
|
|
638
|
+
useSideNavToggleKeyboardShortcut({
|
|
639
|
+
canToggleWithShortcut
|
|
640
|
+
});
|
|
596
641
|
useResizingWidthCssVarOnRootElement({
|
|
597
642
|
isEnabled: true,
|
|
598
643
|
cssVar: panelSplitterResizingVar,
|
|
@@ -695,6 +740,9 @@ export function SideNav({
|
|
|
695
740
|
// Default value is defined in `SideNavInternal`
|
|
696
741
|
onExpand,
|
|
697
742
|
onCollapse,
|
|
743
|
+
onPeekStart,
|
|
744
|
+
onPeekEnd,
|
|
745
|
+
canToggleWithShortcut,
|
|
698
746
|
id
|
|
699
747
|
}) {
|
|
700
748
|
return /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
@@ -707,6 +755,9 @@ export function SideNav({
|
|
|
707
755
|
skipLinkLabel: skipLinkLabel,
|
|
708
756
|
onExpand: onExpand,
|
|
709
757
|
onCollapse: onCollapse,
|
|
710
|
-
|
|
758
|
+
onPeekStart: onPeekStart,
|
|
759
|
+
onPeekEnd: onPeekEnd,
|
|
760
|
+
id: id,
|
|
761
|
+
canToggleWithShortcut: canToggleWithShortcut
|
|
711
762
|
}, children));
|
|
712
763
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { bind } from 'bind-event-listener';
|
|
3
|
+
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
4
|
+
import { useOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
5
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
|
+
import { useIsSideNavShortcutEnabled } from './is-side-nav-shortcut-enabled-context';
|
|
7
|
+
import { useToggleSideNav } from './use-toggle-side-nav';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Binds the keyboard shortcut to toggle the side nav.
|
|
11
|
+
*/
|
|
12
|
+
export function useSideNavToggleKeyboardShortcut({
|
|
13
|
+
canToggleWithShortcut
|
|
14
|
+
}) {
|
|
15
|
+
const openLayerObserver = useOpenLayerObserver();
|
|
16
|
+
const toggleVisibilityByShortcut = useToggleSideNav({
|
|
17
|
+
trigger: 'keyboard'
|
|
18
|
+
});
|
|
19
|
+
const canToggleWithShortcutStableRef = useStableRef(canToggleWithShortcut);
|
|
20
|
+
const isSideNavShortcutEnabled = useIsSideNavShortcutEnabled();
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!fg('navx-full-height-sidebar')) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!isSideNavShortcutEnabled) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
return bind(window, {
|
|
29
|
+
type: 'keydown',
|
|
30
|
+
listener(event) {
|
|
31
|
+
if (event.ctrlKey && event.key === '[') {
|
|
32
|
+
if (canToggleWithShortcutStableRef.current && !canToggleWithShortcutStableRef.current()) {
|
|
33
|
+
// Return early if the callback returns false.
|
|
34
|
+
// If the callback is not provided, we assume the shortcut is enabled.
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (event.repeat) {
|
|
38
|
+
// Ignore repeated keydown events from holding down the keys
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (openLayerObserver.getCount({
|
|
42
|
+
type: 'modal'
|
|
43
|
+
}) > 0 && fg('platform-dst-open-layer-observer-layer-type')) {
|
|
44
|
+
// Return early if there are any open modals
|
|
45
|
+
// This check is behind the layer type FG, as `getCount` will return the count of all layers when
|
|
46
|
+
// the FG is disabled - meaning we would ignore the shortcut if there is any open layer (not just modals).
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
toggleVisibilityByShortcut();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}, [canToggleWithShortcutStableRef, openLayerObserver, toggleVisibilityByShortcut, isSideNavShortcutEnabled]);
|
|
54
|
+
}
|
|
@@ -7,6 +7,7 @@ import { SkipLinksProvider } from '../../context/skip-links/skip-links-provider'
|
|
|
7
7
|
import { TopNavStartProvider } from '../../context/top-nav-start/top-nav-start-context-provider';
|
|
8
8
|
import { DangerouslyHoistSlotSizes } from './hoist-slot-sizes-context';
|
|
9
9
|
import { SideNavElementProvider } from './side-nav/element-context';
|
|
10
|
+
import { IsSideNavShortcutEnabledProvider } from './side-nav/is-side-nav-shortcut-enabled-context';
|
|
10
11
|
import { SideNavToggleButtonProvider } from './side-nav/toggle-button-provider';
|
|
11
12
|
import { SideNavVisibilityProvider } from './side-nav/visibility-provider';
|
|
12
13
|
|
|
@@ -28,7 +29,9 @@ export function Root(_ref) {
|
|
|
28
29
|
_ref$skipLinksLabel = _ref.skipLinksLabel,
|
|
29
30
|
skipLinksLabel = _ref$skipLinksLabel === void 0 ? 'Skip to:' : _ref$skipLinksLabel,
|
|
30
31
|
testId = _ref.testId,
|
|
31
|
-
defaultSideNavCollapsed = _ref.defaultSideNavCollapsed
|
|
32
|
+
defaultSideNavCollapsed = _ref.defaultSideNavCollapsed,
|
|
33
|
+
_ref$isSideNavShortcu = _ref.isSideNavShortcutEnabled,
|
|
34
|
+
isSideNavShortcutEnabled = _ref$isSideNavShortcu === void 0 ? false : _ref$isSideNavShortcu;
|
|
32
35
|
var ref = useRef(null);
|
|
33
36
|
useEffect(function () {
|
|
34
37
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -45,7 +48,9 @@ export function Root(_ref) {
|
|
|
45
48
|
}, []);
|
|
46
49
|
return /*#__PURE__*/React.createElement(SideNavVisibilityProvider, {
|
|
47
50
|
defaultCollapsed: defaultSideNavCollapsed
|
|
48
|
-
}, /*#__PURE__*/React.createElement(SideNavToggleButtonProvider, null, /*#__PURE__*/React.createElement(SideNavElementProvider, null, /*#__PURE__*/React.createElement(
|
|
51
|
+
}, /*#__PURE__*/React.createElement(SideNavToggleButtonProvider, null, /*#__PURE__*/React.createElement(SideNavElementProvider, null, /*#__PURE__*/React.createElement(IsSideNavShortcutEnabledProvider, {
|
|
52
|
+
isSideNavShortcutEnabled: isSideNavShortcutEnabled
|
|
53
|
+
}, /*#__PURE__*/React.createElement(TopNavStartProvider, null, /*#__PURE__*/React.createElement(OpenLayerObserver, null, /*#__PURE__*/React.createElement(DangerouslyHoistSlotSizes.Provider, {
|
|
49
54
|
value: UNSAFE_dangerouslyHoistSlotSizes
|
|
50
55
|
}, /*#__PURE__*/React.createElement(SkipLinksProvider, {
|
|
51
56
|
label: skipLinksLabel,
|
|
@@ -55,5 +60,5 @@ export function Root(_ref) {
|
|
|
55
60
|
className: ax([styles.root, xcss]),
|
|
56
61
|
id: gridRootId,
|
|
57
62
|
"data-testid": testId
|
|
58
|
-
}, children))))))));
|
|
63
|
+
}, children)))))))));
|
|
59
64
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context for whether the side nav toggle shortcut is enabled.
|
|
5
|
+
*
|
|
6
|
+
* Used to share the `isSideNavShortcutEnabled` prop value from `Root` with other components,
|
|
7
|
+
* so the visual keyboard shortcut in tooltips can be conditionally displayed.
|
|
8
|
+
*/
|
|
9
|
+
var IsSideNavShortcutEnabledContext = /*#__PURE__*/createContext(false);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Provider for the `IsSideNavShortcutEnabledContext`.
|
|
13
|
+
*/
|
|
14
|
+
export function IsSideNavShortcutEnabledProvider(_ref) {
|
|
15
|
+
var children = _ref.children,
|
|
16
|
+
isSideNavShortcutEnabled = _ref.isSideNavShortcutEnabled;
|
|
17
|
+
return /*#__PURE__*/React.createElement(IsSideNavShortcutEnabledContext.Provider, {
|
|
18
|
+
value: isSideNavShortcutEnabled
|
|
19
|
+
}, children);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the value of the `isSideNavShortcutEnabled` prop from the `Root` component, which
|
|
24
|
+
* is shared through context.
|
|
25
|
+
*/
|
|
26
|
+
export function useIsSideNavShortcutEnabled() {
|
|
27
|
+
return useContext(IsSideNavShortcutEnabledContext);
|
|
28
|
+
}
|
|
@@ -11,6 +11,7 @@ import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, u
|
|
|
11
11
|
import { bind } from 'bind-event-listener';
|
|
12
12
|
import { flushSync } from 'react-dom';
|
|
13
13
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
14
|
+
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
14
15
|
import { OpenLayerObserverNamespaceProvider, useOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
15
16
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
16
17
|
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
@@ -28,6 +29,7 @@ import { useSideNavRef } from './element-context';
|
|
|
28
29
|
import { sideNavFlyoutCloseDelayMs } from './flyout-close-delay-ms';
|
|
29
30
|
import { SideNavToggleButtonElement } from './toggle-button-context';
|
|
30
31
|
import { useExpandSideNav } from './use-expand-side-nav';
|
|
32
|
+
import { useSideNavToggleKeyboardShortcut } from './use-side-nav-toggle-keyboard-shortcut';
|
|
31
33
|
import { useSideNavVisibility } from './use-side-nav-visibility';
|
|
32
34
|
import { useSideNavVisibilityCallbacks } from './use-side-nav-visibility-callbacks';
|
|
33
35
|
import { useToggleSideNav } from './use-toggle-side-nav';
|
|
@@ -68,6 +70,7 @@ var styles = {
|
|
|
68
70
|
fullHeightSidebar: "_165t56xv _180k1wjm _26vxoned _1mt19dtb"
|
|
69
71
|
};
|
|
70
72
|
var fallbackDefaultWidth = 320;
|
|
73
|
+
export var onPeekStartDelayMs = 500;
|
|
71
74
|
|
|
72
75
|
/**
|
|
73
76
|
* We need an additional component layer so we can wrap the side nav in a `OpenLayerObserver` and have access to the
|
|
@@ -86,7 +89,10 @@ function SideNavInternal(_ref) {
|
|
|
86
89
|
skipLinkLabel = _ref$skipLinkLabel === void 0 ? label : _ref$skipLinkLabel,
|
|
87
90
|
onExpand = _ref.onExpand,
|
|
88
91
|
onCollapse = _ref.onCollapse,
|
|
89
|
-
|
|
92
|
+
onPeekStart = _ref.onPeekStart,
|
|
93
|
+
onPeekEnd = _ref.onPeekEnd,
|
|
94
|
+
providedId = _ref.id,
|
|
95
|
+
canToggleWithShortcut = _ref.canToggleWithShortcut;
|
|
90
96
|
var id = useLayoutId({
|
|
91
97
|
providedId: providedId
|
|
92
98
|
});
|
|
@@ -152,6 +158,16 @@ function SideNavInternal(_ref) {
|
|
|
152
158
|
type: 'not-active'
|
|
153
159
|
});
|
|
154
160
|
var isFlyoutVisible = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open';
|
|
161
|
+
var isExpandedOnDesktopRef = useStableRef(isExpandedOnDesktop);
|
|
162
|
+
var hasPeekStartedRef = useRef(false);
|
|
163
|
+
var onPeekStartRef = useStableRef(onPeekStart);
|
|
164
|
+
var onPeekEndRef = useStableRef(onPeekEnd);
|
|
165
|
+
var onPeekStartTimeoutIdRef = useRef(undefined);
|
|
166
|
+
useEffect(function () {
|
|
167
|
+
return function () {
|
|
168
|
+
clearTimeout(onPeekStartTimeoutIdRef.current);
|
|
169
|
+
};
|
|
170
|
+
}, []);
|
|
155
171
|
var updateFlyoutState = useMemo(function () {
|
|
156
172
|
function tryAbortPendingClose() {
|
|
157
173
|
if (flyoutStateRef.current.type === 'waiting-for-close') {
|
|
@@ -159,6 +175,7 @@ function SideNavInternal(_ref) {
|
|
|
159
175
|
}
|
|
160
176
|
}
|
|
161
177
|
function open() {
|
|
178
|
+
var prevFlyoutState = flyoutStateRef.current;
|
|
162
179
|
tryAbortPendingClose();
|
|
163
180
|
flyoutStateRef.current = {
|
|
164
181
|
type: 'open'
|
|
@@ -171,8 +188,24 @@ function SideNavInternal(_ref) {
|
|
|
171
188
|
}
|
|
172
189
|
return currentState;
|
|
173
190
|
});
|
|
191
|
+
|
|
192
|
+
// Avoid redundant calls to `onPeekStart()`
|
|
193
|
+
if (prevFlyoutState.type === 'not-active') {
|
|
194
|
+
clearTimeout(onPeekStartTimeoutIdRef.current);
|
|
195
|
+
onPeekStartTimeoutIdRef.current = setTimeout(function () {
|
|
196
|
+
var _onPeekStartRef$curre;
|
|
197
|
+
// If the flyout isn't still open after ~500ms then we won't count the peek
|
|
198
|
+
// As we want to track user intention rather than all hovers
|
|
199
|
+
if (isExpandedOnDesktopRef.current || flyoutStateRef.current.type !== 'open') {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
hasPeekStartedRef.current = true;
|
|
203
|
+
(_onPeekStartRef$curre = onPeekStartRef.current) === null || _onPeekStartRef$curre === void 0 || _onPeekStartRef$curre.call(onPeekStartRef);
|
|
204
|
+
}, onPeekStartDelayMs);
|
|
205
|
+
}
|
|
174
206
|
}
|
|
175
207
|
function close() {
|
|
208
|
+
var prevFlyoutState = flyoutStateRef.current;
|
|
176
209
|
tryAbortPendingClose();
|
|
177
210
|
flyoutStateRef.current = {
|
|
178
211
|
type: 'not-active'
|
|
@@ -185,6 +218,15 @@ function SideNavInternal(_ref) {
|
|
|
185
218
|
}
|
|
186
219
|
return currentState;
|
|
187
220
|
});
|
|
221
|
+
|
|
222
|
+
// Avoid redundant calls to `onPeekEnd()`
|
|
223
|
+
if (prevFlyoutState.type !== 'not-active' && hasPeekStartedRef.current) {
|
|
224
|
+
var _onPeekEndRef$current;
|
|
225
|
+
hasPeekStartedRef.current = false;
|
|
226
|
+
(_onPeekEndRef$current = onPeekEndRef.current) === null || _onPeekEndRef$current === void 0 || _onPeekEndRef$current.call(onPeekEndRef, {
|
|
227
|
+
trigger: isExpandedOnDesktopRef.current ? 'side-nav-expand' : 'mouse-leave'
|
|
228
|
+
});
|
|
229
|
+
}
|
|
188
230
|
}
|
|
189
231
|
return function onAction(action) {
|
|
190
232
|
if (action === 'drag-from-flyout-started') {
|
|
@@ -243,7 +285,7 @@ function SideNavInternal(_ref) {
|
|
|
243
285
|
return;
|
|
244
286
|
}
|
|
245
287
|
};
|
|
246
|
-
}, [openLayerObserver, setSideNavState]);
|
|
288
|
+
}, [isExpandedOnDesktopRef, onPeekEndRef, onPeekStartRef, openLayerObserver, setSideNavState]);
|
|
247
289
|
var toggleVisibilityByScreenResize = useToggleSideNav({
|
|
248
290
|
trigger: 'screen-resize'
|
|
249
291
|
});
|
|
@@ -595,6 +637,9 @@ function SideNavInternal(_ref) {
|
|
|
595
637
|
}
|
|
596
638
|
devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
|
|
597
639
|
}
|
|
640
|
+
useSideNavToggleKeyboardShortcut({
|
|
641
|
+
canToggleWithShortcut: canToggleWithShortcut
|
|
642
|
+
});
|
|
598
643
|
useResizingWidthCssVarOnRootElement({
|
|
599
644
|
isEnabled: true,
|
|
600
645
|
cssVar: panelSplitterResizingVar,
|
|
@@ -694,6 +739,9 @@ export function SideNav(_ref8) {
|
|
|
694
739
|
skipLinkLabel = _ref8$skipLinkLabel === void 0 ? label : _ref8$skipLinkLabel,
|
|
695
740
|
onExpand = _ref8.onExpand,
|
|
696
741
|
onCollapse = _ref8.onCollapse,
|
|
742
|
+
onPeekStart = _ref8.onPeekStart,
|
|
743
|
+
onPeekEnd = _ref8.onPeekEnd,
|
|
744
|
+
canToggleWithShortcut = _ref8.canToggleWithShortcut,
|
|
697
745
|
id = _ref8.id;
|
|
698
746
|
return /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
|
|
699
747
|
namespace: openLayerObserverSideNavNamespace
|
|
@@ -705,6 +753,9 @@ export function SideNav(_ref8) {
|
|
|
705
753
|
skipLinkLabel: skipLinkLabel,
|
|
706
754
|
onExpand: onExpand,
|
|
707
755
|
onCollapse: onCollapse,
|
|
708
|
-
|
|
756
|
+
onPeekStart: onPeekStart,
|
|
757
|
+
onPeekEnd: onPeekEnd,
|
|
758
|
+
id: id,
|
|
759
|
+
canToggleWithShortcut: canToggleWithShortcut
|
|
709
760
|
}, children));
|
|
710
761
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { bind } from 'bind-event-listener';
|
|
3
|
+
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
4
|
+
import { useOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
5
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
|
+
import { useIsSideNavShortcutEnabled } from './is-side-nav-shortcut-enabled-context';
|
|
7
|
+
import { useToggleSideNav } from './use-toggle-side-nav';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Binds the keyboard shortcut to toggle the side nav.
|
|
11
|
+
*/
|
|
12
|
+
export function useSideNavToggleKeyboardShortcut(_ref) {
|
|
13
|
+
var canToggleWithShortcut = _ref.canToggleWithShortcut;
|
|
14
|
+
var openLayerObserver = useOpenLayerObserver();
|
|
15
|
+
var toggleVisibilityByShortcut = useToggleSideNav({
|
|
16
|
+
trigger: 'keyboard'
|
|
17
|
+
});
|
|
18
|
+
var canToggleWithShortcutStableRef = useStableRef(canToggleWithShortcut);
|
|
19
|
+
var isSideNavShortcutEnabled = useIsSideNavShortcutEnabled();
|
|
20
|
+
useEffect(function () {
|
|
21
|
+
if (!fg('navx-full-height-sidebar')) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!isSideNavShortcutEnabled) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
return bind(window, {
|
|
28
|
+
type: 'keydown',
|
|
29
|
+
listener: function listener(event) {
|
|
30
|
+
if (event.ctrlKey && event.key === '[') {
|
|
31
|
+
if (canToggleWithShortcutStableRef.current && !canToggleWithShortcutStableRef.current()) {
|
|
32
|
+
// Return early if the callback returns false.
|
|
33
|
+
// If the callback is not provided, we assume the shortcut is enabled.
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (event.repeat) {
|
|
37
|
+
// Ignore repeated keydown events from holding down the keys
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (openLayerObserver.getCount({
|
|
41
|
+
type: 'modal'
|
|
42
|
+
}) > 0 && fg('platform-dst-open-layer-observer-layer-type')) {
|
|
43
|
+
// Return early if there are any open modals
|
|
44
|
+
// This check is behind the layer type FG, as `getCount` will return the count of all layers when
|
|
45
|
+
// the FG is disabled - meaning we would ignore the shortcut if there is any open layer (not just modals).
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
toggleVisibilityByShortcut();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}, [canToggleWithShortcutStableRef, openLayerObserver, toggleVisibilityByShortcut, isSideNavShortcutEnabled]);
|
|
53
|
+
}
|
|
@@ -9,7 +9,7 @@ export declare const gridRootId = "unsafe-design-system-page-layout-root";
|
|
|
9
9
|
* The root component of the navigation system. It wraps the underlying components with the necessary contexts allowing to use certain data and hooks
|
|
10
10
|
* @param skipLinksLabel - The very first element of the layout is a skip links container that can be accessed by pressing Tab button and holds the links to the other sections of the layout thus improving accessibility. This parameter defines the header text for this container
|
|
11
11
|
*/
|
|
12
|
-
export declare function Root({ children, xcss, UNSAFE_dangerouslyHoistSlotSizes, skipLinksLabel, testId, defaultSideNavCollapsed, }: {
|
|
12
|
+
export declare function Root({ children, xcss, UNSAFE_dangerouslyHoistSlotSizes, skipLinksLabel, testId, defaultSideNavCollapsed, isSideNavShortcutEnabled, }: {
|
|
13
13
|
/**
|
|
14
14
|
* For rendering the layout areas, e.g. TopNav, SideNav, Main.
|
|
15
15
|
* They should be rendered as immediate children.
|
|
@@ -47,4 +47,22 @@ export declare function Root({ children, xcss, UNSAFE_dangerouslyHoistSlotSizes,
|
|
|
47
47
|
* __Note:__ When provided, the `defaultCollapsed` props on `SideNav` and `SideNavToggleButton` will be ignored.
|
|
48
48
|
*/
|
|
49
49
|
defaultSideNavCollapsed?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Controls whether the side nav toggle shortcut is enabled. This will be used to bind the keyboard event listener,
|
|
52
|
+
* and to display the keyboard shortcuts in the appropriate tooltips (`SideNavToggleButton`, `SideNavPanelSplitter`).
|
|
53
|
+
*
|
|
54
|
+
* The shortcut key is `Ctrl` + `[`.
|
|
55
|
+
*
|
|
56
|
+
* The shortcut is not enabled by default.
|
|
57
|
+
*
|
|
58
|
+
* The shortcut will also be ignored if there are any open ADS modal dialogs (`@atlaskit/modal-dialog`). This is behind
|
|
59
|
+
* the `platform-dst-open-layer-observer-layer-type` feature flag.
|
|
60
|
+
*
|
|
61
|
+
* `SideNav` has another prop `canToggleWithShortcut()` that can be used to run additional checks after the shortcut
|
|
62
|
+
* is pressed, before the SideNav is toggled. You can use this to conditionally disable the shortcut based on your
|
|
63
|
+
* your own custom checks, e.g. if there is a legacy dialog open.
|
|
64
|
+
*
|
|
65
|
+
* Note: The built-in keyboard shortcut is behind the `navx-full-height-sidebar` feature flag.
|
|
66
|
+
*/
|
|
67
|
+
isSideNavShortcutEnabled?: boolean;
|
|
50
68
|
}): JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Provider for the `IsSideNavShortcutEnabledContext`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function IsSideNavShortcutEnabledProvider({ children, isSideNavShortcutEnabled, }: {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
isSideNavShortcutEnabled: boolean;
|
|
8
|
+
}): React.JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the value of the `isSideNavShortcutEnabled` prop from the `Root` component, which
|
|
11
|
+
* is shared through context.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useIsSideNavShortcutEnabled(): boolean;
|
|
@@ -53,7 +53,30 @@ type SideNavProps = CommonSlotProps & {
|
|
|
53
53
|
* Note: The trigger parameter is only provided when the `navx-full-height-sidebar` feature flag is enabled.
|
|
54
54
|
*/
|
|
55
55
|
onCollapse?: VisibilityCallback;
|
|
56
|
+
/**
|
|
57
|
+
* Called when the side nav begins peeking / flyout.
|
|
58
|
+
*/
|
|
59
|
+
onPeekStart?: () => void;
|
|
60
|
+
/**
|
|
61
|
+
* Called when the side nav stops peeking / flyout.
|
|
62
|
+
*/
|
|
63
|
+
onPeekEnd?: (args: {
|
|
64
|
+
trigger: 'mouse-leave' | 'side-nav-expand';
|
|
65
|
+
}) => void;
|
|
66
|
+
/**
|
|
67
|
+
* Whether the side nav should be toggled in response to the built-in keyboard shortcut. Use this callback to
|
|
68
|
+
* conditionally disable the shortcut based on your own custom checks, e.g. if there is a legacy dialog open.
|
|
69
|
+
*
|
|
70
|
+
* This prop will do nothing if `isSideNavShortcutEnabled` on Root is not set to `true`, as the keyboard event
|
|
71
|
+
* listener is only binded if `isSideNavShortcutEnabled` is `true`.
|
|
72
|
+
*
|
|
73
|
+
* The shortcut key is `Ctrl` + `[`.
|
|
74
|
+
*
|
|
75
|
+
* Note: The built-in keyboard shortcut is behind the `navx-full-height-sidebar` feature flag.
|
|
76
|
+
*/
|
|
77
|
+
canToggleWithShortcut?: () => boolean;
|
|
56
78
|
};
|
|
79
|
+
export declare const onPeekStartDelayMs = 500;
|
|
57
80
|
/**
|
|
58
81
|
* The side navigation layout area. It will show on the left (inline start) of the screen.
|
|
59
82
|
*
|
|
@@ -64,5 +87,5 @@ type SideNavProps = CommonSlotProps & {
|
|
|
64
87
|
*/
|
|
65
88
|
export declare function SideNav({ children, defaultCollapsed, defaultWidth, testId, label, // Default value is defined in `SideNavInternal`
|
|
66
89
|
skipLinkLabel, // Default value is defined in `SideNavInternal`
|
|
67
|
-
onExpand, onCollapse, id, }: SideNavProps): JSX.Element;
|
|
90
|
+
onExpand, onCollapse, onPeekStart, onPeekEnd, canToggleWithShortcut, id, }: SideNavProps): JSX.Element;
|
|
68
91
|
export {};
|
|
@@ -9,7 +9,7 @@ export declare const gridRootId = "unsafe-design-system-page-layout-root";
|
|
|
9
9
|
* The root component of the navigation system. It wraps the underlying components with the necessary contexts allowing to use certain data and hooks
|
|
10
10
|
* @param skipLinksLabel - The very first element of the layout is a skip links container that can be accessed by pressing Tab button and holds the links to the other sections of the layout thus improving accessibility. This parameter defines the header text for this container
|
|
11
11
|
*/
|
|
12
|
-
export declare function Root({ children, xcss, UNSAFE_dangerouslyHoistSlotSizes, skipLinksLabel, testId, defaultSideNavCollapsed, }: {
|
|
12
|
+
export declare function Root({ children, xcss, UNSAFE_dangerouslyHoistSlotSizes, skipLinksLabel, testId, defaultSideNavCollapsed, isSideNavShortcutEnabled, }: {
|
|
13
13
|
/**
|
|
14
14
|
* For rendering the layout areas, e.g. TopNav, SideNav, Main.
|
|
15
15
|
* They should be rendered as immediate children.
|
|
@@ -47,4 +47,22 @@ export declare function Root({ children, xcss, UNSAFE_dangerouslyHoistSlotSizes,
|
|
|
47
47
|
* __Note:__ When provided, the `defaultCollapsed` props on `SideNav` and `SideNavToggleButton` will be ignored.
|
|
48
48
|
*/
|
|
49
49
|
defaultSideNavCollapsed?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Controls whether the side nav toggle shortcut is enabled. This will be used to bind the keyboard event listener,
|
|
52
|
+
* and to display the keyboard shortcuts in the appropriate tooltips (`SideNavToggleButton`, `SideNavPanelSplitter`).
|
|
53
|
+
*
|
|
54
|
+
* The shortcut key is `Ctrl` + `[`.
|
|
55
|
+
*
|
|
56
|
+
* The shortcut is not enabled by default.
|
|
57
|
+
*
|
|
58
|
+
* The shortcut will also be ignored if there are any open ADS modal dialogs (`@atlaskit/modal-dialog`). This is behind
|
|
59
|
+
* the `platform-dst-open-layer-observer-layer-type` feature flag.
|
|
60
|
+
*
|
|
61
|
+
* `SideNav` has another prop `canToggleWithShortcut()` that can be used to run additional checks after the shortcut
|
|
62
|
+
* is pressed, before the SideNav is toggled. You can use this to conditionally disable the shortcut based on your
|
|
63
|
+
* your own custom checks, e.g. if there is a legacy dialog open.
|
|
64
|
+
*
|
|
65
|
+
* Note: The built-in keyboard shortcut is behind the `navx-full-height-sidebar` feature flag.
|
|
66
|
+
*/
|
|
67
|
+
isSideNavShortcutEnabled?: boolean;
|
|
50
68
|
}): JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Provider for the `IsSideNavShortcutEnabledContext`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function IsSideNavShortcutEnabledProvider({ children, isSideNavShortcutEnabled, }: {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
isSideNavShortcutEnabled: boolean;
|
|
8
|
+
}): React.JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the value of the `isSideNavShortcutEnabled` prop from the `Root` component, which
|
|
11
|
+
* is shared through context.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useIsSideNavShortcutEnabled(): boolean;
|
|
@@ -53,7 +53,30 @@ type SideNavProps = CommonSlotProps & {
|
|
|
53
53
|
* Note: The trigger parameter is only provided when the `navx-full-height-sidebar` feature flag is enabled.
|
|
54
54
|
*/
|
|
55
55
|
onCollapse?: VisibilityCallback;
|
|
56
|
+
/**
|
|
57
|
+
* Called when the side nav begins peeking / flyout.
|
|
58
|
+
*/
|
|
59
|
+
onPeekStart?: () => void;
|
|
60
|
+
/**
|
|
61
|
+
* Called when the side nav stops peeking / flyout.
|
|
62
|
+
*/
|
|
63
|
+
onPeekEnd?: (args: {
|
|
64
|
+
trigger: 'mouse-leave' | 'side-nav-expand';
|
|
65
|
+
}) => void;
|
|
66
|
+
/**
|
|
67
|
+
* Whether the side nav should be toggled in response to the built-in keyboard shortcut. Use this callback to
|
|
68
|
+
* conditionally disable the shortcut based on your own custom checks, e.g. if there is a legacy dialog open.
|
|
69
|
+
*
|
|
70
|
+
* This prop will do nothing if `isSideNavShortcutEnabled` on Root is not set to `true`, as the keyboard event
|
|
71
|
+
* listener is only binded if `isSideNavShortcutEnabled` is `true`.
|
|
72
|
+
*
|
|
73
|
+
* The shortcut key is `Ctrl` + `[`.
|
|
74
|
+
*
|
|
75
|
+
* Note: The built-in keyboard shortcut is behind the `navx-full-height-sidebar` feature flag.
|
|
76
|
+
*/
|
|
77
|
+
canToggleWithShortcut?: () => boolean;
|
|
56
78
|
};
|
|
79
|
+
export declare const onPeekStartDelayMs = 500;
|
|
57
80
|
/**
|
|
58
81
|
* The side navigation layout area. It will show on the left (inline start) of the screen.
|
|
59
82
|
*
|
|
@@ -64,5 +87,5 @@ type SideNavProps = CommonSlotProps & {
|
|
|
64
87
|
*/
|
|
65
88
|
export declare function SideNav({ children, defaultCollapsed, defaultWidth, testId, label, // Default value is defined in `SideNavInternal`
|
|
66
89
|
skipLinkLabel, // Default value is defined in `SideNavInternal`
|
|
67
|
-
onExpand, onCollapse, id, }: SideNavProps): JSX.Element;
|
|
90
|
+
onExpand, onCollapse, onPeekStart, onPeekEnd, canToggleWithShortcut, id, }: SideNavProps): JSX.Element;
|
|
68
91
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/navigation-system",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "The latest navigation system for Atlassian apps.",
|
|
5
5
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
6
6
|
"author": "Atlassian Pty Ltd",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@atlaskit/css": "^0.15.0",
|
|
73
73
|
"@atlaskit/ds-lib": "^5.1.0",
|
|
74
74
|
"@atlaskit/icon": "^28.5.0",
|
|
75
|
-
"@atlaskit/layering": "^3.
|
|
75
|
+
"@atlaskit/layering": "^3.2.0",
|
|
76
76
|
"@atlaskit/logo": "^19.9.0",
|
|
77
77
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
78
78
|
"@atlaskit/popup": "^4.4.0",
|
|
@@ -107,6 +107,7 @@
|
|
|
107
107
|
"@atlaskit/link": "^3.2.0",
|
|
108
108
|
"@atlaskit/lozenge": "^13.0.0",
|
|
109
109
|
"@atlaskit/menu": "^8.4.0",
|
|
110
|
+
"@atlaskit/modal-dialog": "^14.6.0",
|
|
110
111
|
"@atlaskit/onboarding": "^14.4.0",
|
|
111
112
|
"@atlaskit/page-header": "^12.1.0",
|
|
112
113
|
"@atlaskit/page-layout": "^4.2.0",
|
|
@@ -118,6 +119,7 @@
|
|
|
118
119
|
"@atlassian/gemini": "^1.20.0",
|
|
119
120
|
"@atlassian/search-dialog": "^9.7.0",
|
|
120
121
|
"@atlassian/ssr-tests": "^0.3.0",
|
|
122
|
+
"@atlassian/testing-library": "^0.4.0",
|
|
121
123
|
"@axe-core/playwright": "^4.8.0",
|
|
122
124
|
"@testing-library/react": "^13.4.0",
|
|
123
125
|
"@testing-library/react-hooks": "^8.0.1",
|
|
@@ -184,6 +186,9 @@
|
|
|
184
186
|
},
|
|
185
187
|
"platform_dst_side_nav_remove_custom_tooltip": {
|
|
186
188
|
"type": "boolean"
|
|
189
|
+
},
|
|
190
|
+
"platform-dst-open-layer-observer-layer-type": {
|
|
191
|
+
"type": "boolean"
|
|
187
192
|
}
|
|
188
193
|
},
|
|
189
194
|
"homepage": "https://atlassian.design/components/navigation-system"
|