@atlaskit/page-layout 1.3.8 → 1.3.10
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 +13 -0
- package/dist/cjs/common/constants.js +8 -4
- package/dist/cjs/common/hooks/index.js +0 -3
- package/dist/cjs/common/hooks/use-is-sidebar-collapsing.js +3 -12
- package/dist/cjs/common/hooks/use-is-sidebar-dragging.js +3 -12
- package/dist/cjs/common/safe-local-storage.js +2 -13
- package/dist/cjs/common/utils.js +0 -35
- package/dist/cjs/components/index.js +0 -13
- package/dist/cjs/components/resize-control/grab-area.js +8 -17
- package/dist/cjs/components/resize-control/index.js +33 -84
- package/dist/cjs/components/resize-control/resize-button.js +9 -24
- package/dist/cjs/components/resize-control/shadow.js +3 -7
- package/dist/cjs/components/skip-links/index.js +0 -2
- package/dist/cjs/components/skip-links/skip-link-components.js +18 -48
- package/dist/cjs/components/skip-links/use-custom-skip-link.js +3 -8
- package/dist/cjs/components/slots/banner-slot.js +10 -21
- package/dist/cjs/components/slots/content.js +3 -6
- package/dist/cjs/components/slots/internal/left-sidebar-inner.js +9 -14
- package/dist/cjs/components/slots/internal/left-sidebar-outer.js +10 -22
- package/dist/cjs/components/slots/internal/resizable-children-wrapper.js +10 -15
- package/dist/cjs/components/slots/internal/slot-focus-ring.js +5 -8
- package/dist/cjs/components/slots/left-panel.js +9 -20
- package/dist/cjs/components/slots/left-sidebar-without-resize.js +6 -18
- package/dist/cjs/components/slots/left-sidebar.js +39 -75
- package/dist/cjs/components/slots/main.js +9 -23
- package/dist/cjs/components/slots/page-layout.js +7 -16
- package/dist/cjs/components/slots/right-panel.js +9 -20
- package/dist/cjs/components/slots/right-sidebar.js +9 -21
- package/dist/cjs/components/slots/slot-dimensions.js +1 -5
- package/dist/cjs/components/slots/top-navigation.js +10 -21
- package/dist/cjs/controllers/index.js +0 -6
- package/dist/cjs/controllers/sidebar-resize-context.js +6 -21
- package/dist/cjs/controllers/sidebar-resize-controller.js +34 -50
- package/dist/cjs/controllers/skip-link-context.js +2 -12
- package/dist/cjs/controllers/skip-link-controller.js +6 -22
- package/dist/cjs/controllers/use-page-layout-grid.js +6 -12
- package/dist/cjs/controllers/use-update-css-vars.js +0 -3
- package/dist/cjs/index.js +0 -3
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/common/constants.js +8 -4
- package/dist/es2019/common/hooks/use-is-sidebar-collapsing.js +0 -4
- package/dist/es2019/common/hooks/use-is-sidebar-dragging.js +0 -4
- package/dist/es2019/common/safe-local-storage.js +2 -12
- package/dist/es2019/common/utils.js +4 -20
- package/dist/es2019/components/resize-control/grab-area.js +7 -8
- package/dist/es2019/components/resize-control/index.js +26 -43
- package/dist/es2019/components/resize-control/resize-button.js +7 -11
- package/dist/es2019/components/resize-control/shadow.js +3 -3
- package/dist/es2019/components/skip-links/skip-link-components.js +16 -31
- package/dist/es2019/components/slots/banner-slot.js +1 -3
- package/dist/es2019/components/slots/content.js +2 -2
- package/dist/es2019/components/slots/internal/left-sidebar-inner.js +5 -5
- package/dist/es2019/components/slots/internal/left-sidebar-outer.js +1 -4
- package/dist/es2019/components/slots/internal/resizable-children-wrapper.js +4 -4
- package/dist/es2019/components/slots/internal/slot-focus-ring.js +3 -3
- package/dist/es2019/components/slots/left-panel.js +1 -3
- package/dist/es2019/components/slots/left-sidebar-without-resize.js +1 -2
- package/dist/es2019/components/slots/left-sidebar.js +25 -40
- package/dist/es2019/components/slots/main.js +4 -5
- package/dist/es2019/components/slots/page-layout.js +1 -3
- package/dist/es2019/components/slots/right-panel.js +1 -3
- package/dist/es2019/components/slots/right-sidebar.js +3 -5
- package/dist/es2019/components/slots/top-navigation.js +1 -3
- package/dist/es2019/controllers/sidebar-resize-context.js +7 -5
- package/dist/es2019/controllers/sidebar-resize-controller.js +14 -16
- package/dist/es2019/controllers/skip-link-context.js +0 -1
- package/dist/es2019/controllers/skip-link-controller.js +3 -7
- package/dist/es2019/controllers/use-page-layout-grid.js +4 -5
- package/dist/es2019/controllers/use-update-css-vars.js +0 -2
- package/dist/es2019/version.json +1 -1
- package/dist/esm/common/constants.js +8 -4
- package/dist/esm/common/hooks/use-is-sidebar-collapsing.js +3 -8
- package/dist/esm/common/hooks/use-is-sidebar-dragging.js +3 -8
- package/dist/esm/common/safe-local-storage.js +2 -12
- package/dist/esm/common/utils.js +0 -22
- package/dist/esm/components/resize-control/grab-area.js +9 -14
- package/dist/esm/components/resize-control/index.js +33 -72
- package/dist/esm/components/resize-control/resize-button.js +10 -15
- package/dist/esm/components/resize-control/shadow.js +3 -3
- package/dist/esm/components/skip-links/skip-link-components.js +19 -39
- package/dist/esm/components/skip-links/use-custom-skip-link.js +2 -4
- package/dist/esm/components/slots/banner-slot.js +9 -11
- package/dist/esm/components/slots/content.js +3 -3
- package/dist/esm/components/slots/internal/left-sidebar-inner.js +9 -9
- package/dist/esm/components/slots/internal/left-sidebar-outer.js +9 -12
- package/dist/esm/components/slots/internal/resizable-children-wrapper.js +10 -10
- package/dist/esm/components/slots/internal/slot-focus-ring.js +5 -5
- package/dist/esm/components/slots/left-panel.js +8 -10
- package/dist/esm/components/slots/left-sidebar-without-resize.js +7 -9
- package/dist/esm/components/slots/left-sidebar.js +40 -65
- package/dist/esm/components/slots/main.js +10 -13
- package/dist/esm/components/slots/page-layout.js +6 -10
- package/dist/esm/components/slots/right-panel.js +8 -10
- package/dist/esm/components/slots/right-sidebar.js +10 -12
- package/dist/esm/components/slots/slot-dimensions.js +1 -1
- package/dist/esm/components/slots/top-navigation.js +9 -11
- package/dist/esm/controllers/sidebar-resize-context.js +6 -11
- package/dist/esm/controllers/sidebar-resize-controller.js +34 -38
- package/dist/esm/controllers/skip-link-context.js +2 -4
- package/dist/esm/controllers/skip-link-controller.js +6 -12
- package/dist/esm/controllers/use-page-layout-grid.js +6 -8
- package/dist/esm/controllers/use-update-css-vars.js +0 -2
- package/dist/esm/version.json +1 -1
- package/dist/types/common/types.d.ts +4 -4
- package/dist/types/controllers/skip-link-controller.d.ts +4 -2
- package/package.json +10 -9
|
@@ -1,75 +1,59 @@
|
|
|
1
1
|
import { DEFAULT_LEFT_SIDEBAR_WIDTH, DIMENSIONS, LEFT_PANEL_WIDTH, PAGE_LAYOUT_LS_KEY, PAGE_LAYOUT_SLOT_SELECTOR } from './constants';
|
|
2
2
|
import safeLocalStorage from './safe-local-storage';
|
|
3
|
-
const emptyGridState = DIMENSIONS.reduce((acc, currentValue) => ({
|
|
3
|
+
const emptyGridState = DIMENSIONS.reduce((acc, currentValue) => ({
|
|
4
|
+
...acc,
|
|
4
5
|
[currentValue]: 0
|
|
5
6
|
}), {});
|
|
6
|
-
|
|
7
7
|
const mergeGridStateIntoStorage = (key, value) => {
|
|
8
8
|
const storageValue = JSON.parse(safeLocalStorage().getItem(PAGE_LAYOUT_LS_KEY) || '{}');
|
|
9
|
-
|
|
10
9
|
if (value !== null && typeof value === 'object') {
|
|
11
|
-
storageValue[key] = {
|
|
10
|
+
storageValue[key] = {
|
|
11
|
+
...storageValue[key],
|
|
12
12
|
...value
|
|
13
13
|
};
|
|
14
14
|
} else {
|
|
15
15
|
storageValue[key] = value;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
17
|
safeLocalStorage().setItem(PAGE_LAYOUT_LS_KEY, JSON.stringify(storageValue));
|
|
19
18
|
};
|
|
20
|
-
|
|
21
19
|
const getGridStateFromStorage = key => {
|
|
22
20
|
const storageValue = JSON.parse(safeLocalStorage().getItem(PAGE_LAYOUT_LS_KEY) || '{}');
|
|
23
21
|
return storageValue[key];
|
|
24
22
|
};
|
|
25
|
-
|
|
26
23
|
const removeFromGridStateInStorage = (key, secondKey) => {
|
|
27
24
|
const storageValue = JSON.parse(safeLocalStorage().getItem(PAGE_LAYOUT_LS_KEY) || '{}');
|
|
28
|
-
|
|
29
25
|
if (secondKey && storageValue[key]) {
|
|
30
26
|
delete storageValue[key][secondKey];
|
|
31
27
|
} else {
|
|
32
28
|
delete storageValue[key];
|
|
33
29
|
}
|
|
34
|
-
|
|
35
30
|
safeLocalStorage().setItem(PAGE_LAYOUT_LS_KEY, JSON.stringify(storageValue));
|
|
36
31
|
};
|
|
37
|
-
|
|
38
32
|
const resolveDimension = (key, dimension = 0, shouldPersist = false) => {
|
|
39
33
|
if (shouldPersist) {
|
|
40
34
|
const cachedGridState = getGridStateFromStorage('gridState');
|
|
41
35
|
return cachedGridState && Object.keys(cachedGridState).length > 0 && cachedGridState[key] ? cachedGridState[key] : dimension;
|
|
42
36
|
}
|
|
43
|
-
|
|
44
37
|
return dimension;
|
|
45
38
|
};
|
|
46
|
-
|
|
47
39
|
const getLeftPanelWidth = () => {
|
|
48
40
|
if (typeof window === 'undefined') {
|
|
49
41
|
return 0;
|
|
50
42
|
}
|
|
51
|
-
|
|
52
43
|
return parseInt(window.getComputedStyle(document.documentElement).getPropertyValue(`--${LEFT_PANEL_WIDTH}`), 10) || 0;
|
|
53
44
|
};
|
|
54
|
-
|
|
55
45
|
const getLeftSidebarPercentage = (currentWidth, maxWidth) => {
|
|
56
46
|
const total = (currentWidth - DEFAULT_LEFT_SIDEBAR_WIDTH) / (maxWidth - DEFAULT_LEFT_SIDEBAR_WIDTH);
|
|
57
|
-
|
|
58
47
|
if (total < 0) {
|
|
59
48
|
return 0;
|
|
60
49
|
}
|
|
61
|
-
|
|
62
50
|
if (total > 1) {
|
|
63
51
|
return 100;
|
|
64
52
|
}
|
|
65
|
-
|
|
66
53
|
return Math.floor(total * 100);
|
|
67
54
|
};
|
|
68
|
-
|
|
69
55
|
const getPageLayoutSlotSelector = slotName => ({
|
|
70
56
|
[PAGE_LAYOUT_SLOT_SELECTOR]: slotName
|
|
71
57
|
});
|
|
72
|
-
|
|
73
58
|
const getPageLayoutSlotCSSSelector = slotName => `[${PAGE_LAYOUT_SLOT_SELECTOR}='${slotName}']`;
|
|
74
|
-
|
|
75
59
|
export { emptyGridState, mergeGridStateIntoStorage, getGridStateFromStorage, removeFromGridStateInStorage, resolveDimension, getLeftPanelWidth, getLeftSidebarPercentage, getPageLayoutSlotSelector, getPageLayoutSlotCSSSelector };
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
|
|
3
2
|
/** @jsx jsx */
|
|
3
|
+
|
|
4
4
|
import { css, jsx } from '@emotion/react';
|
|
5
5
|
import { B100, B200 } from '@atlaskit/theme/colors';
|
|
6
6
|
import { GRAB_AREA_LINE_SELECTOR, GRAB_AREA_SELECTOR } from '../../common/constants';
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Determines the color of the grab line.
|
|
10
9
|
*
|
|
@@ -51,8 +50,8 @@ const grabAreaLineSelector = {
|
|
|
51
50
|
};
|
|
52
51
|
const grabAreaSelector = {
|
|
53
52
|
[GRAB_AREA_SELECTOR]: true
|
|
54
|
-
};
|
|
55
|
-
|
|
53
|
+
};
|
|
54
|
+
// TODO: Consider allowing this to be controlled using arrow keys
|
|
56
55
|
const GrabArea = ({
|
|
57
56
|
testId,
|
|
58
57
|
isLeftSidebarCollapsed,
|
|
@@ -60,11 +59,11 @@ const GrabArea = ({
|
|
|
60
59
|
}) => jsx("button", _extends({}, grabAreaSelector, {
|
|
61
60
|
"data-testid": testId,
|
|
62
61
|
type: "button",
|
|
63
|
-
css: [grabAreaStyles, isLeftSidebarCollapsed && grabAreaCollapsedStyles]
|
|
64
|
-
|
|
62
|
+
css: [grabAreaStyles, isLeftSidebarCollapsed && grabAreaCollapsedStyles]
|
|
63
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
65
64
|
}, rest), jsx("span", _extends({
|
|
66
65
|
css: lineStyles
|
|
67
|
-
}, grabAreaLineSelector)));
|
|
68
|
-
|
|
66
|
+
}, grabAreaLineSelector)));
|
|
69
67
|
|
|
68
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
70
69
|
export default GrabArea;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
|
|
3
2
|
/** @jsx jsx */
|
|
4
3
|
import { useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
5
4
|
import { css, jsx } from '@emotion/react';
|
|
@@ -26,7 +25,6 @@ const resizeControlStyles = css({
|
|
|
26
25
|
const showResizeButtonStyles = css({
|
|
27
26
|
'--ds--resize-button--opacity': 1
|
|
28
27
|
});
|
|
29
|
-
|
|
30
28
|
const ResizeControl = ({
|
|
31
29
|
testId,
|
|
32
30
|
overrides,
|
|
@@ -45,37 +43,33 @@ const ResizeControl = ({
|
|
|
45
43
|
isLeftSidebarCollapsed,
|
|
46
44
|
isResizing
|
|
47
45
|
} = leftSidebarState;
|
|
48
|
-
const x = useRef(leftSidebarState[VAR_LEFT_SIDEBAR_WIDTH]);
|
|
49
|
-
|
|
46
|
+
const x = useRef(leftSidebarState[VAR_LEFT_SIDEBAR_WIDTH]);
|
|
47
|
+
// Distance of mouse from left sidebar onMouseDown
|
|
50
48
|
const offset = useRef(0);
|
|
51
49
|
const keyboardEventTimeout = useRef();
|
|
52
50
|
const [isGrabAreaFocused, setIsGrabAreaFocused] = useState(false);
|
|
53
51
|
const unbindEvents = useRef(null);
|
|
54
|
-
|
|
55
52
|
const toggleSideBar = e => {
|
|
56
53
|
if (isResizing) {
|
|
57
54
|
return;
|
|
58
55
|
}
|
|
59
|
-
|
|
60
56
|
if (isLeftSidebarCollapsed) {
|
|
61
57
|
expandLeftSidebar();
|
|
62
58
|
} else {
|
|
63
59
|
collapseLeftSidebar();
|
|
64
|
-
}
|
|
65
|
-
// "clicked" using enter/space on keyboard.
|
|
66
|
-
|
|
60
|
+
}
|
|
67
61
|
|
|
62
|
+
// Bring focus to the resize button if the grab area is
|
|
63
|
+
// "clicked" using enter/space on keyboard.
|
|
68
64
|
if (e && e.nativeEvent.detail === 0) {
|
|
69
65
|
const resizeButton = document.querySelector(`[${RESIZE_BUTTON_SELECTOR}]`);
|
|
70
66
|
resizeButton && resizeButton.focus();
|
|
71
67
|
}
|
|
72
68
|
};
|
|
73
|
-
|
|
74
69
|
const onMouseDown = event => {
|
|
75
70
|
if (isLeftSidebarCollapsed) {
|
|
76
71
|
return;
|
|
77
72
|
}
|
|
78
|
-
|
|
79
73
|
offset.current = event.clientX - leftSidebarState[VAR_LEFT_SIDEBAR_WIDTH] - getLeftPanelWidth();
|
|
80
74
|
unbindEvents.current = bindAll(document, [{
|
|
81
75
|
type: 'mousemove',
|
|
@@ -85,16 +79,15 @@ const ResizeControl = ({
|
|
|
85
79
|
listener: onMouseUp
|
|
86
80
|
}]);
|
|
87
81
|
document.documentElement.setAttribute(IS_SIDEBAR_DRAGGING, 'true');
|
|
88
|
-
const newLeftbarState = {
|
|
82
|
+
const newLeftbarState = {
|
|
83
|
+
...leftSidebarState,
|
|
89
84
|
isResizing: true
|
|
90
85
|
};
|
|
91
86
|
setLeftSidebarState(newLeftbarState);
|
|
92
87
|
onResizeStart && onResizeStart(newLeftbarState);
|
|
93
88
|
};
|
|
94
|
-
|
|
95
89
|
const cancelDrag = shouldCollapse => {
|
|
96
90
|
var _unbindEvents$current;
|
|
97
|
-
|
|
98
91
|
onMouseMove.cancel();
|
|
99
92
|
(_unbindEvents$current = unbindEvents.current) === null || _unbindEvents$current === void 0 ? void 0 : _unbindEvents$current.call(unbindEvents);
|
|
100
93
|
unbindEvents.current = null;
|
|
@@ -102,7 +95,6 @@ const ResizeControl = ({
|
|
|
102
95
|
offset.current = 0;
|
|
103
96
|
collapseLeftSidebar(undefined, true);
|
|
104
97
|
};
|
|
105
|
-
|
|
106
98
|
const onMouseMove = rafSchd(event => {
|
|
107
99
|
// Allow the sidebar to be 50% of the available page width
|
|
108
100
|
const maxWidth = Math.round(window.innerWidth / 2);
|
|
@@ -111,44 +103,40 @@ const ResizeControl = ({
|
|
|
111
103
|
leftSidebarWidth
|
|
112
104
|
} = leftSidebarState;
|
|
113
105
|
const invalidDrag = event.clientX < 0;
|
|
114
|
-
|
|
115
106
|
if (invalidDrag) {
|
|
116
107
|
cancelDrag();
|
|
117
108
|
}
|
|
118
|
-
|
|
119
109
|
const delta = Math.max(Math.min(event.clientX - leftSidebarWidth - leftPanelWidth, maxWidth - leftSidebarWidth - leftPanelWidth), COLLAPSED_LEFT_SIDEBAR_WIDTH - leftSidebarWidth - leftPanelWidth);
|
|
120
110
|
x.current = Math.max(leftSidebarWidth + delta - offset.current, COLLAPSED_LEFT_SIDEBAR_WIDTH);
|
|
121
111
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${x.current}px`);
|
|
122
112
|
});
|
|
123
|
-
|
|
124
113
|
const cleanupAfterResize = () => {
|
|
125
114
|
var _unbindEvents$current2;
|
|
126
|
-
|
|
127
115
|
x.current = 0;
|
|
128
116
|
offset.current = 0;
|
|
129
117
|
(_unbindEvents$current2 = unbindEvents.current) === null || _unbindEvents$current2 === void 0 ? void 0 : _unbindEvents$current2.call(unbindEvents);
|
|
130
118
|
unbindEvents.current = null;
|
|
131
119
|
};
|
|
132
|
-
|
|
133
120
|
let updatedLeftSidebarState = {};
|
|
134
|
-
|
|
135
121
|
const onMouseUp = event => {
|
|
136
122
|
if (isLeftSidebarCollapsed) {
|
|
137
123
|
return;
|
|
138
124
|
}
|
|
125
|
+
document.documentElement.removeAttribute(IS_SIDEBAR_DRAGGING);
|
|
139
126
|
|
|
140
|
-
|
|
127
|
+
// If it is dragged to below the threshold,
|
|
141
128
|
// collapse the navigation
|
|
142
|
-
|
|
143
129
|
if (x.current < MIN_LEFT_SIDEBAR_DRAG_THRESHOLD) {
|
|
144
130
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${COLLAPSED_LEFT_SIDEBAR_WIDTH}px`);
|
|
145
131
|
collapseLeftSidebar(undefined, true);
|
|
146
|
-
}
|
|
132
|
+
}
|
|
133
|
+
// If it is dragged to position in between the
|
|
147
134
|
// min threshold and default width
|
|
148
135
|
// expand the nav to the default width
|
|
149
136
|
else if (x.current > MIN_LEFT_SIDEBAR_DRAG_THRESHOLD && x.current < DEFAULT_LEFT_SIDEBAR_WIDTH) {
|
|
150
137
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${DEFAULT_LEFT_SIDEBAR_WIDTH}px`);
|
|
151
|
-
updatedLeftSidebarState = {
|
|
138
|
+
updatedLeftSidebarState = {
|
|
139
|
+
...leftSidebarState,
|
|
152
140
|
isResizing: false,
|
|
153
141
|
[VAR_LEFT_SIDEBAR_WIDTH]: DEFAULT_LEFT_SIDEBAR_WIDTH,
|
|
154
142
|
lastLeftSidebarWidth: DEFAULT_LEFT_SIDEBAR_WIDTH
|
|
@@ -156,14 +144,14 @@ const ResizeControl = ({
|
|
|
156
144
|
setLeftSidebarState(updatedLeftSidebarState);
|
|
157
145
|
} else {
|
|
158
146
|
// otherwise resize it to the desired width
|
|
159
|
-
updatedLeftSidebarState = {
|
|
147
|
+
updatedLeftSidebarState = {
|
|
148
|
+
...leftSidebarState,
|
|
160
149
|
isResizing: false,
|
|
161
150
|
[VAR_LEFT_SIDEBAR_WIDTH]: x.current,
|
|
162
151
|
lastLeftSidebarWidth: x.current
|
|
163
152
|
};
|
|
164
153
|
setLeftSidebarState(updatedLeftSidebarState);
|
|
165
154
|
}
|
|
166
|
-
|
|
167
155
|
requestAnimationFrame(() => {
|
|
168
156
|
onMouseMove.cancel();
|
|
169
157
|
setIsGrabAreaFocused(false);
|
|
@@ -171,27 +159,22 @@ const ResizeControl = ({
|
|
|
171
159
|
cleanupAfterResize();
|
|
172
160
|
});
|
|
173
161
|
};
|
|
174
|
-
|
|
175
162
|
const onKeyDown = event => {
|
|
176
163
|
if (isLeftSidebarCollapsed || !isGrabAreaFocused) {
|
|
177
164
|
return false;
|
|
178
165
|
}
|
|
179
|
-
|
|
180
166
|
const {
|
|
181
167
|
key
|
|
182
168
|
} = event;
|
|
183
169
|
const isLeftOrTopArrow = key === 'ArrowLeft' || key === 'ArrowUp' || key === 'Left' || key === 'Up';
|
|
184
170
|
const isRightOrBottomArrow = key === 'ArrowRight' || key === 'ArrowDown' || key === 'Right' || key === 'Down';
|
|
185
171
|
const isSpaceOrEnter = key === 'Enter' || key === 'Spacebar' || key === ' ';
|
|
186
|
-
|
|
187
172
|
if (isSpaceOrEnter) {
|
|
188
173
|
toggleSideBar(event);
|
|
189
174
|
event.preventDefault();
|
|
190
175
|
}
|
|
191
|
-
|
|
192
176
|
if (isLeftOrTopArrow || isRightOrBottomArrow) {
|
|
193
177
|
event.preventDefault(); // prevent content scroll
|
|
194
|
-
|
|
195
178
|
onResizeStart && onResizeStart(leftSidebarState);
|
|
196
179
|
const step = 10;
|
|
197
180
|
const stepValue = isLeftOrTopArrow ? -step : step;
|
|
@@ -201,7 +184,6 @@ const ResizeControl = ({
|
|
|
201
184
|
const maxWidth = Math.round(window.innerWidth / 2) - getLeftPanelWidth();
|
|
202
185
|
const hasModifierKey = event.metaKey || event.altKey || event.ctrlKey || event.shiftKey;
|
|
203
186
|
let width = leftSidebarWidth + stepValue;
|
|
204
|
-
|
|
205
187
|
if (width <= DEFAULT_LEFT_SIDEBAR_WIDTH) {
|
|
206
188
|
width = DEFAULT_LEFT_SIDEBAR_WIDTH;
|
|
207
189
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${DEFAULT_LEFT_SIDEBAR_WIDTH - 20}px`);
|
|
@@ -210,15 +192,16 @@ const ResizeControl = ({
|
|
|
210
192
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${maxWidth + 20}px`);
|
|
211
193
|
} else if (hasModifierKey) {
|
|
212
194
|
width = isRightOrBottomArrow ? maxWidth : DEFAULT_LEFT_SIDEBAR_WIDTH;
|
|
213
|
-
}
|
|
214
|
-
// the browser schedule the setTimeout call in an efficient manner
|
|
215
|
-
|
|
195
|
+
}
|
|
216
196
|
|
|
197
|
+
// Nesting the setTimeout within requestAnimationFrame helps
|
|
198
|
+
// the browser schedule the setTimeout call in an efficient manner
|
|
217
199
|
requestAnimationFrame(() => {
|
|
218
200
|
keyboardEventTimeout.current = window.setTimeout(() => {
|
|
219
201
|
keyboardEventTimeout.current && clearTimeout(keyboardEventTimeout.current);
|
|
220
202
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${width}px`);
|
|
221
|
-
const updatedLeftSidebarState = {
|
|
203
|
+
const updatedLeftSidebarState = {
|
|
204
|
+
...leftSidebarState,
|
|
222
205
|
[VAR_LEFT_SIDEBAR_WIDTH]: width,
|
|
223
206
|
lastLeftSidebarWidth: width
|
|
224
207
|
};
|
|
@@ -228,7 +211,6 @@ const ResizeControl = ({
|
|
|
228
211
|
});
|
|
229
212
|
}
|
|
230
213
|
};
|
|
231
|
-
|
|
232
214
|
const onFocus = useCallback(() => {
|
|
233
215
|
setIsGrabAreaFocused(true);
|
|
234
216
|
}, []);
|
|
@@ -238,17 +220,18 @@ const ResizeControl = ({
|
|
|
238
220
|
const resizeButton = {
|
|
239
221
|
render: (Component, props) => jsx(Component, props),
|
|
240
222
|
...(overrides && overrides.ResizeButton)
|
|
241
|
-
};
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// This width is calculated once only on mount.
|
|
242
226
|
// This means resizing the window will cause this value to be incorrect for screen reader users,
|
|
243
227
|
// however this comes with a substantial performance gain and so is considered acceptable.
|
|
244
|
-
|
|
245
228
|
const maxAriaWidth = useMemo(() => {
|
|
246
229
|
const innerWidth = typeof window === 'undefined' ? 0 : window.innerWidth;
|
|
247
230
|
return Math.round(innerWidth / 2) - getLeftPanelWidth();
|
|
248
231
|
}, []);
|
|
249
232
|
const leftSidebarPercentageExpanded = getLeftSidebarPercentage(leftSidebarState.leftSidebarWidth, maxAriaWidth);
|
|
250
|
-
/* eslint-disable jsx-a11y/role-supports-aria-props */
|
|
251
233
|
|
|
234
|
+
/* eslint-disable jsx-a11y/role-supports-aria-props */
|
|
252
235
|
return jsx("div", _extends({}, cssSelector, {
|
|
253
236
|
css: [resizeControlStyles, (isGrabAreaFocused || isLeftSidebarCollapsed) && showResizeButtonStyles]
|
|
254
237
|
}), jsx(Shadow, {
|
|
@@ -274,7 +257,7 @@ const ResizeControl = ({
|
|
|
274
257
|
testId: testId && `${testId}-resize-button`
|
|
275
258
|
}));
|
|
276
259
|
/* eslint-enable jsx-a11y/role-supports-aria-props */
|
|
277
|
-
};
|
|
278
|
-
|
|
260
|
+
};
|
|
279
261
|
|
|
262
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
280
263
|
export default ResizeControl;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
|
|
3
2
|
/** @jsx jsx */
|
|
3
|
+
|
|
4
4
|
import { css, jsx } from '@emotion/react';
|
|
5
5
|
import ChevronRight from '@atlaskit/icon/glyph/chevron-right';
|
|
6
6
|
import { easeOut } from '@atlaskit/motion/curves';
|
|
@@ -24,7 +24,6 @@ const resizeIconButtonStyles = css({
|
|
|
24
24
|
backgroundColor: `var(--ds-surface-overlay, ${N0})`,
|
|
25
25
|
border: 0,
|
|
26
26
|
borderRadius: '50%',
|
|
27
|
-
|
|
28
27
|
/**
|
|
29
28
|
* TODO: https://product-fabric.atlassian.net/browse/DSP-3392
|
|
30
29
|
* This shadow needs further investigation,
|
|
@@ -34,7 +33,6 @@ const resizeIconButtonStyles = css({
|
|
|
34
33
|
boxShadow: `0 0 0 1px ${N30A}, 0 2px 4px 1px ${N30A}`,
|
|
35
34
|
color: `var(--ds-text-subtle, ${N200})`,
|
|
36
35
|
cursor: 'pointer',
|
|
37
|
-
|
|
38
36
|
/**
|
|
39
37
|
* The fallback value of 0 ensures that the button is hidden by default,
|
|
40
38
|
* unless some parent (or the button itself) overrides it.
|
|
@@ -62,13 +60,10 @@ const resizeIconButtonExpandedStyles = css({
|
|
|
62
60
|
transform: 'rotate(180deg)',
|
|
63
61
|
transformOrigin: 7
|
|
64
62
|
});
|
|
65
|
-
|
|
66
63
|
const preventDefault = event => event.preventDefault();
|
|
67
|
-
|
|
68
64
|
const cssSelector = {
|
|
69
65
|
[RESIZE_BUTTON_SELECTOR]: true
|
|
70
66
|
};
|
|
71
|
-
|
|
72
67
|
const ResizeButton = ({
|
|
73
68
|
isLeftSidebarCollapsed,
|
|
74
69
|
label,
|
|
@@ -80,16 +75,17 @@ const ResizeButton = ({
|
|
|
80
75
|
"aria-label": label,
|
|
81
76
|
type: "button",
|
|
82
77
|
css: [resizeIconButtonStyles, !isLeftSidebarCollapsed && resizeIconButtonExpandedStyles],
|
|
83
|
-
"data-testid": testId
|
|
78
|
+
"data-testid": testId
|
|
79
|
+
// Prevents focus staying attached to the button
|
|
84
80
|
// when pressed
|
|
85
81
|
,
|
|
86
|
-
onMouseDown: preventDefault
|
|
87
|
-
|
|
82
|
+
onMouseDown: preventDefault
|
|
83
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
88
84
|
}, props), jsx(ChevronRight, {
|
|
89
85
|
label: ""
|
|
90
86
|
}), jsx("div", {
|
|
91
87
|
css: increaseHitAreaStyles
|
|
92
|
-
}));
|
|
93
|
-
|
|
88
|
+
}));
|
|
94
89
|
|
|
90
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
95
91
|
export default ResizeButton;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
+
|
|
2
3
|
import { css, jsx } from '@emotion/react';
|
|
3
4
|
import { easeOut } from '@atlaskit/motion';
|
|
4
5
|
import { useIsSidebarDragging } from '../../common/hooks';
|
|
@@ -29,7 +30,6 @@ const draggingStyles = css({
|
|
|
29
30
|
background: `var(--ds-background-neutral-subtle, ${`linear-gradient(${direction}, ${colorStops})`})`,
|
|
30
31
|
opacity: 0.8
|
|
31
32
|
});
|
|
32
|
-
|
|
33
33
|
const Shadow = ({
|
|
34
34
|
testId
|
|
35
35
|
}) => {
|
|
@@ -38,7 +38,7 @@ const Shadow = ({
|
|
|
38
38
|
"data-testid": testId,
|
|
39
39
|
css: [shadowStyles, isDragging && draggingStyles]
|
|
40
40
|
});
|
|
41
|
-
};
|
|
42
|
-
|
|
41
|
+
};
|
|
43
42
|
|
|
43
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
44
44
|
export default Shadow;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @repo/internal/dom-events/no-unsafe-event-listeners */
|
|
2
|
-
|
|
3
2
|
/** @jsx jsx */
|
|
3
|
+
|
|
4
4
|
import { css, jsx } from '@emotion/react';
|
|
5
5
|
import { easeOut, prefersReducedMotion } from '@atlaskit/motion';
|
|
6
6
|
import { N30A, N60A } from '@atlaskit/theme/colors';
|
|
@@ -19,7 +19,6 @@ const skipLinkStyles = css({
|
|
|
19
19
|
borderRadius: 3,
|
|
20
20
|
boxShadow: `var(--ds-shadow-overlay, ${`0 0 0 1px ${N30A}, 0 2px 10px ${N30A}, 0 0 20px -4px ${N60A}`})`,
|
|
21
21
|
opacity: 0,
|
|
22
|
-
|
|
23
22
|
/* Do the transform when focused */
|
|
24
23
|
transform: 'translateY(-50%)',
|
|
25
24
|
transition: `transform 0.3s ${easeOut}`,
|
|
@@ -46,14 +45,13 @@ const skipLinkListStyles = css({
|
|
|
46
45
|
const skipLinkListItemStyles = css({
|
|
47
46
|
marginTop: 0
|
|
48
47
|
});
|
|
49
|
-
|
|
50
48
|
const assignIndex = (num, arr) => {
|
|
51
49
|
if (!arr.includes(num)) {
|
|
52
50
|
return num;
|
|
53
51
|
}
|
|
54
|
-
|
|
55
52
|
return assignIndex(num + 1, arr);
|
|
56
53
|
};
|
|
54
|
+
|
|
57
55
|
/**
|
|
58
56
|
* The default label will be used when the `skipLinksLabel` attribute is not
|
|
59
57
|
* provided or the attribute is an empty string. If a string comprised only of
|
|
@@ -61,51 +59,41 @@ const assignIndex = (num, arr) => {
|
|
|
61
59
|
* default label will still be used in `title` attribute of the skip links
|
|
62
60
|
* themselves.
|
|
63
61
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
62
|
export const SkipLinkWrapper = ({
|
|
67
63
|
skipLinksLabel
|
|
68
64
|
}) => {
|
|
69
65
|
const {
|
|
70
66
|
skipLinksData
|
|
71
67
|
} = useSkipLinks();
|
|
72
|
-
|
|
73
68
|
if (skipLinksData.length === 0) {
|
|
74
69
|
return null;
|
|
75
70
|
}
|
|
76
|
-
|
|
77
71
|
const sortSkipLinks = arr => {
|
|
78
72
|
const customLinks = arr.filter(link => Number.isInteger(link.listIndex));
|
|
79
|
-
|
|
80
73
|
if (customLinks.length === 0) {
|
|
81
74
|
return arr;
|
|
82
75
|
}
|
|
83
|
-
|
|
84
76
|
const usedIndexes = customLinks.map(a => a.listIndex);
|
|
85
77
|
const regularLinksWithIdx = arr.filter(link => link.listIndex === undefined).map((link, idx, currArr) => {
|
|
86
78
|
const listIndex = assignIndex(idx, usedIndexes);
|
|
87
79
|
usedIndexes.push(listIndex);
|
|
88
|
-
return {
|
|
80
|
+
return {
|
|
81
|
+
...link,
|
|
89
82
|
listIndex
|
|
90
83
|
};
|
|
91
84
|
});
|
|
92
85
|
return [...customLinks, ...regularLinksWithIdx].sort((a, b) => a.listIndex - b.listIndex);
|
|
93
86
|
};
|
|
94
|
-
|
|
95
87
|
const escapeHandler = event => {
|
|
96
88
|
if (event.keyCode === 27) {
|
|
97
89
|
const container = document.querySelector(`[${PAGE_LAYOUT_CONTAINER_SELECTOR}="true"]`);
|
|
98
|
-
|
|
99
90
|
if (container !== null) {
|
|
100
91
|
container.focus();
|
|
101
92
|
}
|
|
102
93
|
}
|
|
103
94
|
};
|
|
104
|
-
|
|
105
95
|
const attachEscHandler = () => window.addEventListener('keydown', escapeHandler, false);
|
|
106
|
-
|
|
107
96
|
const removeEscHandler = () => window.removeEventListener('keydown', escapeHandler, false);
|
|
108
|
-
|
|
109
97
|
const emptyLabelOverride = !!(skipLinksLabel !== null && skipLinksLabel !== void 0 && skipLinksLabel.match(/^\s+$/));
|
|
110
98
|
const label = skipLinksLabel || DEFAULT_I18N_PROPS_SKIP_LINKS;
|
|
111
99
|
return jsx("div", {
|
|
@@ -127,41 +115,38 @@ export const SkipLinkWrapper = ({
|
|
|
127
115
|
title: emptyLabelOverride ? `${DEFAULT_I18N_PROPS_SKIP_LINKS} ${skipLinkTitle}` : `${label} ${skipLinkTitle}`
|
|
128
116
|
}, skipLinkTitle))));
|
|
129
117
|
};
|
|
130
|
-
|
|
131
118
|
const handleBlur = event => {
|
|
132
119
|
// @ts-ignore
|
|
133
|
-
event.target.removeAttribute('tabindex');
|
|
134
|
-
|
|
120
|
+
event.target.removeAttribute('tabindex');
|
|
121
|
+
// @ts-ignore
|
|
135
122
|
event.target.removeEventListener('blur', handleBlur);
|
|
136
123
|
};
|
|
137
|
-
|
|
138
124
|
const focusTargetRef = href => event => {
|
|
139
125
|
event.preventDefault();
|
|
140
|
-
const targetRef = document.querySelector(href);
|
|
126
|
+
const targetRef = document.querySelector(href);
|
|
141
127
|
|
|
142
|
-
|
|
128
|
+
// @ts-ignore
|
|
129
|
+
const key = event.which || event.keycode;
|
|
130
|
+
// if it is a keypress and the key is not
|
|
143
131
|
// space or enter, just ignore it.
|
|
144
|
-
|
|
145
132
|
if (key && key !== 13 && key !== 32) {
|
|
146
133
|
return;
|
|
147
134
|
}
|
|
148
|
-
|
|
149
135
|
if (targetRef) {
|
|
150
|
-
targetRef.setAttribute('tabindex', '-1');
|
|
151
|
-
|
|
152
|
-
targetRef.addEventListener('blur', handleBlur);
|
|
153
|
-
|
|
136
|
+
targetRef.setAttribute('tabindex', '-1');
|
|
137
|
+
// @ts-ignore
|
|
138
|
+
targetRef.addEventListener('blur', handleBlur);
|
|
139
|
+
// @ts-ignore
|
|
154
140
|
targetRef.focus();
|
|
155
141
|
document.activeElement && document.activeElement.scrollIntoView({
|
|
156
142
|
behavior: 'smooth'
|
|
157
143
|
});
|
|
158
144
|
window.scrollTo(0, 0);
|
|
159
145
|
}
|
|
160
|
-
|
|
161
146
|
return false;
|
|
162
|
-
};
|
|
163
|
-
|
|
147
|
+
};
|
|
164
148
|
|
|
149
|
+
// eslint-disable-next-line @repo/internal/react/require-jsdoc
|
|
165
150
|
export const SkipLink = ({
|
|
166
151
|
href,
|
|
167
152
|
children,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
|
|
3
2
|
/** @jsx jsx */
|
|
4
3
|
import { useEffect } from 'react';
|
|
5
4
|
import { css, jsx } from '@emotion/react';
|
|
@@ -19,6 +18,7 @@ const bannerFixedStyles = css({
|
|
|
19
18
|
right: RIGHT_PANEL_WIDTH,
|
|
20
19
|
left: LEFT_PANEL_WIDTH
|
|
21
20
|
});
|
|
21
|
+
|
|
22
22
|
/**
|
|
23
23
|
* __Banner__
|
|
24
24
|
*
|
|
@@ -27,7 +27,6 @@ const bannerFixedStyles = css({
|
|
|
27
27
|
* - [Examples](https://atlassian.design/components/page-layout/examples)
|
|
28
28
|
* - [Code](https://atlassian.design/components/page-layout/code)
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
const Banner = props => {
|
|
32
31
|
const {
|
|
33
32
|
children,
|
|
@@ -62,5 +61,4 @@ const Banner = props => {
|
|
|
62
61
|
value: bannerHeight
|
|
63
62
|
}), children));
|
|
64
63
|
};
|
|
65
|
-
|
|
66
64
|
export default Banner;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
+
|
|
2
3
|
import { css, jsx } from '@emotion/react';
|
|
3
4
|
import { CONTENT } from '../../common/constants';
|
|
4
5
|
const contentStyles = css({
|
|
@@ -7,6 +8,7 @@ const contentStyles = css({
|
|
|
7
8
|
position: 'relative',
|
|
8
9
|
gridArea: CONTENT
|
|
9
10
|
});
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* __Content__
|
|
12
14
|
*
|
|
@@ -15,7 +17,6 @@ const contentStyles = css({
|
|
|
15
17
|
* - [Examples](https://atlassian.design/components/page-layout/examples)
|
|
16
18
|
* - [Code](https://atlassian.design/components/page-layout/code)
|
|
17
19
|
*/
|
|
18
|
-
|
|
19
20
|
const Content = props => {
|
|
20
21
|
const {
|
|
21
22
|
children,
|
|
@@ -26,5 +27,4 @@ const Content = props => {
|
|
|
26
27
|
css: contentStyles
|
|
27
28
|
}, children);
|
|
28
29
|
};
|
|
29
|
-
|
|
30
30
|
export default Content;
|