@atlaskit/page-layout 1.6.1 → 1.6.3
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/dist/cjs/common/hooks/use-is-sidebar-dragging.js +3 -0
- package/dist/cjs/components/resize-control/index.js +83 -28
- package/dist/cjs/components/slots/main.js +0 -1
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/common/hooks/use-is-sidebar-dragging.js +3 -0
- package/dist/es2019/components/resize-control/index.js +73 -23
- package/dist/es2019/components/slots/main.js +0 -1
- package/dist/es2019/version.json +1 -1
- package/dist/esm/common/hooks/use-is-sidebar-dragging.js +3 -0
- package/dist/esm/components/resize-control/index.js +85 -30
- package/dist/esm/components/slots/main.js +0 -1
- package/dist/esm/version.json +1 -1
- package/dist/types-ts4.5/common/constants.d.ts +47 -0
- package/dist/types-ts4.5/common/hooks/index.d.ts +2 -0
- package/dist/types-ts4.5/common/hooks/use-is-sidebar-collapsing.d.ts +2 -0
- package/dist/types-ts4.5/common/hooks/use-is-sidebar-dragging.d.ts +2 -0
- package/dist/types-ts4.5/common/safe-local-storage.d.ts +2 -0
- package/dist/types-ts4.5/common/types.d.ts +117 -0
- package/dist/types-ts4.5/common/utils.d.ts +13 -0
- package/dist/types-ts4.5/components/index.d.ts +12 -0
- package/dist/types-ts4.5/components/resize-control/grab-area.d.ts +9 -0
- package/dist/types-ts4.5/components/resize-control/index.d.ts +4 -0
- package/dist/types-ts4.5/components/resize-control/resize-button.d.ts +4 -0
- package/dist/types-ts4.5/components/resize-control/shadow.d.ts +6 -0
- package/dist/types-ts4.5/components/resize-control/types.d.ts +25 -0
- package/dist/types-ts4.5/components/skip-links/index.d.ts +2 -0
- package/dist/types-ts4.5/components/skip-links/skip-link-components.d.ts +18 -0
- package/dist/types-ts4.5/components/skip-links/types.d.ts +8 -0
- package/dist/types-ts4.5/components/skip-links/use-custom-skip-link.d.ts +2 -0
- package/dist/types-ts4.5/components/slots/banner-slot.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/content.d.ts +23 -0
- package/dist/types-ts4.5/components/slots/internal/left-sidebar-inner.d.ts +10 -0
- package/dist/types-ts4.5/components/slots/internal/left-sidebar-outer.d.ts +13 -0
- package/dist/types-ts4.5/components/slots/internal/resizable-children-wrapper.d.ts +11 -0
- package/dist/types-ts4.5/components/slots/internal/slot-focus-ring.d.ts +20 -0
- package/dist/types-ts4.5/components/slots/left-panel.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/left-sidebar-without-resize.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/left-sidebar.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/main.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/page-layout.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/right-panel.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/right-sidebar.d.ts +12 -0
- package/dist/types-ts4.5/components/slots/slot-dimensions.d.ts +7 -0
- package/dist/types-ts4.5/components/slots/top-navigation.d.ts +12 -0
- package/dist/types-ts4.5/controllers/index.d.ts +6 -0
- package/dist/types-ts4.5/controllers/sidebar-resize-context.d.ts +42 -0
- package/dist/types-ts4.5/controllers/sidebar-resize-controller.d.ts +3 -0
- package/dist/types-ts4.5/controllers/skip-link-context.d.ts +5 -0
- package/dist/types-ts4.5/controllers/skip-link-controller.d.ts +4 -0
- package/dist/types-ts4.5/controllers/types.d.ts +22 -0
- package/dist/types-ts4.5/controllers/use-page-layout-grid.d.ts +3 -0
- package/dist/types-ts4.5/controllers/use-update-css-vars.d.ts +2 -0
- package/dist/types-ts4.5/index.d.ts +4 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @atlaskit/page-layout
|
|
2
2
|
|
|
3
|
+
## 1.6.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`4bbc131de00`](https://bitbucket.org/atlassian/atlassian-frontend/commits/4bbc131de00) - #### Fix: Resizing pages with `<iframe>`s
|
|
8
|
+
|
|
9
|
+
Pages that contain `<iframe>` elements will now have a smoother resizing experience. `<iframe>` elements consume user events (eg `mousemove`) when the user is over the top of them. This is problematic for resizing as we need to have the latest user pointer movements to resize the sidebar. Now, while a resize is happening, `pointer-events` are blocked on `<iframe>` elements to prevent the `<iframe>` consuming user events.
|
|
10
|
+
|
|
11
|
+
#### Fix: User cursor while resizing
|
|
12
|
+
|
|
13
|
+
While resizing the users cursor will now always be `ew-resize`. Previously the cursor could change depending on what element the users pointer was over
|
|
14
|
+
|
|
15
|
+
#### Fix: Resizing will no longer change user selection
|
|
16
|
+
|
|
17
|
+
A user can select parts of a page (eg select a paragraph of text). Previously, in some cases, a user's selection could change due to a resizing operation. This has been fixed so that a resizing operation will no longer change a user's selection
|
|
18
|
+
|
|
19
|
+
#### Fix: `onResizeEnd`
|
|
20
|
+
|
|
21
|
+
`onResizeEnd` will no longer incorrectly get an empty object `{}` if the user resized into the collapsed state
|
|
22
|
+
|
|
23
|
+
## 1.6.2
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- [`9d00501a414`](https://bitbucket.org/atlassian/atlassian-frontend/commits/9d00501a414) - Ensure legacy types are published for TS 4.5-4.8
|
|
28
|
+
|
|
3
29
|
## 1.6.1
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
|
@@ -15,6 +15,9 @@ var getIsDragging = function getIsDragging() {
|
|
|
15
15
|
}
|
|
16
16
|
return document.documentElement.getAttribute(_constants.IS_SIDEBAR_DRAGGING) === 'true';
|
|
17
17
|
};
|
|
18
|
+
|
|
19
|
+
// TODO: I think this should be derived from the sidebar state,
|
|
20
|
+
// and not indirectly from observing an attribute change
|
|
18
21
|
var useIsSidebarDragging = function useIsSidebarDragging() {
|
|
19
22
|
var _useState = (0, _react.useState)(getIsDragging),
|
|
20
23
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
@@ -31,6 +31,33 @@ var resizeControlStyles = (0, _react2.css)({
|
|
|
31
31
|
var showResizeButtonStyles = (0, _react2.css)({
|
|
32
32
|
'--ds--resize-button--opacity': 1
|
|
33
33
|
});
|
|
34
|
+
|
|
35
|
+
// @ts-expect-error adding `!important` to style rules is currently a type error
|
|
36
|
+
var globalResizingStyles = (0, _react2.css)({
|
|
37
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
38
|
+
'*': {
|
|
39
|
+
// Setting the cursor to be `ew-resize` on all elements so that even if the user
|
|
40
|
+
// pointer slips off the resize handle, the cursor will still be the resize cursor
|
|
41
|
+
cursor: 'ew-resize !important',
|
|
42
|
+
// Blocking selection while resizing
|
|
43
|
+
// Notes:
|
|
44
|
+
// - This prevents a user selection being caused by resizing
|
|
45
|
+
// - Safari + Firefox → all good
|
|
46
|
+
// - Chrome → This will undo the current selection while resizing (not ideal)
|
|
47
|
+
// - The current selection will resume after resizing
|
|
48
|
+
userSelect: 'none !important'
|
|
49
|
+
},
|
|
50
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
51
|
+
iframe: {
|
|
52
|
+
// Disabling pointer events on iframes when resizing
|
|
53
|
+
// as iframes will swallower user events when the user is over them
|
|
54
|
+
pointerEvents: 'none !important'
|
|
55
|
+
}
|
|
56
|
+
// Note: We _could_ also disable `pointer-events` on all elements during resizing.
|
|
57
|
+
// However, to minimize risk we are just disabling `pointer-events` on iframes
|
|
58
|
+
// as that change is actually needed to fix resizing with iframes
|
|
59
|
+
});
|
|
60
|
+
|
|
34
61
|
var ResizeControl = function ResizeControl(_ref) {
|
|
35
62
|
var testId = _ref.testId,
|
|
36
63
|
overrides = _ref.overrides,
|
|
@@ -56,6 +83,13 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
56
83
|
isGrabAreaFocused = _useState2[0],
|
|
57
84
|
setIsGrabAreaFocused = _useState2[1];
|
|
58
85
|
var unbindEvents = (0, _react.useRef)(null);
|
|
86
|
+
|
|
87
|
+
// Used in some cases to ensure function references don't have to change
|
|
88
|
+
// TODO: more functions could use `stableSidebarState` rather than `leftSidebarState`
|
|
89
|
+
var stableSidebarState = (0, _react.useRef)(leftSidebarState);
|
|
90
|
+
(0, _react.useEffect)(function () {
|
|
91
|
+
stableSidebarState.current = leftSidebarState;
|
|
92
|
+
}, [leftSidebarState]);
|
|
59
93
|
var toggleSideBar = function toggleSideBar(e) {
|
|
60
94
|
if (isResizing) {
|
|
61
95
|
return;
|
|
@@ -90,7 +124,11 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
90
124
|
offset.current = event.clientX - leftSidebarState[_constants.VAR_LEFT_SIDEBAR_WIDTH] - (0, _utils.getLeftPanelWidth)();
|
|
91
125
|
unbindEvents.current = (0, _bindEventListener.bindAll)(window, [{
|
|
92
126
|
type: 'mousemove',
|
|
93
|
-
listener:
|
|
127
|
+
listener: function listener(event) {
|
|
128
|
+
onUpdateResize({
|
|
129
|
+
clientX: event.clientX
|
|
130
|
+
});
|
|
131
|
+
}
|
|
94
132
|
}, {
|
|
95
133
|
type: 'mouseup',
|
|
96
134
|
listener: onFinishResizing
|
|
@@ -155,37 +193,45 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
155
193
|
offset.current = 0;
|
|
156
194
|
collapseLeftSidebar(undefined, true);
|
|
157
195
|
};
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
196
|
+
|
|
197
|
+
// It is important that `onUpdateResize` is a stable function reference, so that:
|
|
198
|
+
// 1. we ensure we are correctly throttling with `requestAnimationFrame`
|
|
199
|
+
// 2. that a `onUpdateResize` will cancel the one and only pending frame
|
|
200
|
+
// To help ensure `onUpdateResize` is stable, we are putting the last state into a ref
|
|
201
|
+
var _useState3 = (0, _react.useState)(function () {
|
|
202
|
+
return (0, _rafSchd.default)(function (_ref2) {
|
|
203
|
+
var clientX = _ref2.clientX;
|
|
204
|
+
// Allow the sidebar to be 50% of the available page width
|
|
205
|
+
var maxWidth = Math.round(window.innerWidth / 2);
|
|
206
|
+
var leftPanelWidth = (0, _utils.getLeftPanelWidth)();
|
|
207
|
+
var leftSidebarWidth = stableSidebarState.current.leftSidebarWidth;
|
|
208
|
+
var hasResizedOffLeftOfScreen = clientX < 0;
|
|
209
|
+
if (hasResizedOffLeftOfScreen) {
|
|
210
|
+
onResizeOffLeftOfScreen();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
var delta = Math.max(Math.min(clientX - leftSidebarWidth - leftPanelWidth, maxWidth - leftSidebarWidth - leftPanelWidth), _constants.COLLAPSED_LEFT_SIDEBAR_WIDTH - leftSidebarWidth - leftPanelWidth);
|
|
214
|
+
sidebarWidth.current = Math.max(leftSidebarWidth + delta - offset.current, _constants.COLLAPSED_LEFT_SIDEBAR_WIDTH);
|
|
215
|
+
document.documentElement.style.setProperty("--".concat(_constants.VAR_LEFT_SIDEBAR_WIDTH), "".concat(sidebarWidth.current, "px"));
|
|
216
|
+
});
|
|
217
|
+
}),
|
|
218
|
+
_useState4 = (0, _slicedToArray2.default)(_useState3, 1),
|
|
219
|
+
onUpdateResize = _useState4[0];
|
|
180
220
|
var onFinishResizing = function onFinishResizing() {
|
|
221
|
+
var _unbindEvents$current2;
|
|
181
222
|
if (isLeftSidebarCollapsed) {
|
|
182
223
|
return;
|
|
183
224
|
}
|
|
184
225
|
document.documentElement.removeAttribute(_constants.IS_SIDEBAR_DRAGGING);
|
|
185
226
|
|
|
227
|
+
// TODO: the control flow is pretty strange as the first codepath which calls `collapseLeftSidebar()`
|
|
228
|
+
// does not return an updated state snapshot.
|
|
229
|
+
var updatedLeftSidebarState = null;
|
|
230
|
+
|
|
186
231
|
// If it is dragged to below the threshold,
|
|
187
232
|
// collapse the navigation
|
|
188
233
|
if (sidebarWidth.current < _constants.MIN_LEFT_SIDEBAR_DRAG_THRESHOLD) {
|
|
234
|
+
// TODO: for this codepath, `onCollapse` occurs before `onResizeEnd` which seems wrong
|
|
189
235
|
document.documentElement.style.setProperty("--".concat(_constants.VAR_LEFT_SIDEBAR_WIDTH), "".concat(_constants.COLLAPSED_LEFT_SIDEBAR_WIDTH, "px"));
|
|
190
236
|
collapseLeftSidebar(undefined, true);
|
|
191
237
|
}
|
|
@@ -207,11 +253,18 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
207
253
|
}, (0, _defineProperty2.default)(_objectSpread3, _constants.VAR_LEFT_SIDEBAR_WIDTH, sidebarWidth.current), (0, _defineProperty2.default)(_objectSpread3, "lastLeftSidebarWidth", sidebarWidth.current), _objectSpread3));
|
|
208
254
|
setLeftSidebarState(updatedLeftSidebarState);
|
|
209
255
|
}
|
|
256
|
+
(_unbindEvents$current2 = unbindEvents.current) === null || _unbindEvents$current2 === void 0 ? void 0 : _unbindEvents$current2.call(unbindEvents);
|
|
257
|
+
unbindEvents.current = null;
|
|
258
|
+
onUpdateResize.cancel();
|
|
259
|
+
sidebarWidth.current = 0;
|
|
260
|
+
offset.current = 0;
|
|
261
|
+
|
|
262
|
+
// TODO: no idea why this is in an animation frame
|
|
210
263
|
requestAnimationFrame(function () {
|
|
211
|
-
|
|
264
|
+
var _updatedLeftSidebarSt;
|
|
212
265
|
setIsGrabAreaFocused(false);
|
|
213
|
-
|
|
214
|
-
|
|
266
|
+
// Note: the `collapseSidebar` codepath does not return state, so we need to pull it from the ref
|
|
267
|
+
onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd((_updatedLeftSidebarSt = updatedLeftSidebarState) !== null && _updatedLeftSidebarSt !== void 0 ? _updatedLeftSidebarSt : stableSidebarState.current);
|
|
215
268
|
});
|
|
216
269
|
};
|
|
217
270
|
var onKeyDown = function onKeyDown(event) {
|
|
@@ -281,7 +334,7 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
281
334
|
var leftSidebarPercentageExpanded = (0, _utils.getLeftSidebarPercentage)(leftSidebarState.leftSidebarWidth, maxAriaWidth);
|
|
282
335
|
|
|
283
336
|
/* eslint-disable jsx-a11y/role-supports-aria-props */
|
|
284
|
-
return (0, _react2.jsx)("div", (0, _extends2.default)({}, cssSelector, {
|
|
337
|
+
return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)("div", (0, _extends2.default)({}, cssSelector, {
|
|
285
338
|
css: [resizeControlStyles, (isGrabAreaFocused || isLeftSidebarCollapsed) && showResizeButtonStyles]
|
|
286
339
|
}), (0, _react2.jsx)(_shadow.default, {
|
|
287
340
|
testId: testId && "".concat(testId, "-shadow")
|
|
@@ -304,7 +357,9 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
304
357
|
label: resizeButtonLabel,
|
|
305
358
|
onClick: toggleSideBar,
|
|
306
359
|
testId: testId && "".concat(testId, "-resize-button")
|
|
307
|
-
}))
|
|
360
|
+
})), leftSidebarState.isResizing ? (0, _react2.jsx)(_react2.Global, {
|
|
361
|
+
styles: globalResizingStyles
|
|
362
|
+
}) : null);
|
|
308
363
|
/* eslint-enable jsx-a11y/role-supports-aria-props */
|
|
309
364
|
};
|
|
310
365
|
|
|
@@ -28,7 +28,6 @@ var mainStyles = (0, _react2.css)({
|
|
|
28
28
|
transition: "margin-left ".concat(_constants.TRANSITION_DURATION, "ms ").concat(_curves.easeOut, " 0s")
|
|
29
29
|
});
|
|
30
30
|
var draggingStyles = (0, _react2.css)({
|
|
31
|
-
cursor: 'ew-resize',
|
|
32
31
|
// Make sure drag to resize remains snappy.
|
|
33
32
|
transition: 'none'
|
|
34
33
|
});
|
package/dist/cjs/version.json
CHANGED
|
@@ -7,6 +7,9 @@ const getIsDragging = () => {
|
|
|
7
7
|
}
|
|
8
8
|
return document.documentElement.getAttribute(IS_SIDEBAR_DRAGGING) === 'true';
|
|
9
9
|
};
|
|
10
|
+
|
|
11
|
+
// TODO: I think this should be derived from the sidebar state,
|
|
12
|
+
// and not indirectly from observing an attribute change
|
|
10
13
|
const useIsSidebarDragging = () => {
|
|
11
14
|
const [isDragging, setIsDragging] = useState(getIsDragging);
|
|
12
15
|
useEffect(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
/** @jsx jsx */
|
|
3
|
-
import { useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
4
|
-
import { css, jsx } from '@emotion/react';
|
|
3
|
+
import { Fragment, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { css, Global, jsx } from '@emotion/react';
|
|
5
5
|
import { bindAll } from 'bind-event-listener';
|
|
6
6
|
import rafSchd from 'raf-schd';
|
|
7
7
|
import { COLLAPSED_LEFT_SIDEBAR_WIDTH, DEFAULT_LEFT_SIDEBAR_WIDTH, IS_SIDEBAR_DRAGGING, MIN_LEFT_SIDEBAR_DRAG_THRESHOLD, RESIZE_BUTTON_SELECTOR, RESIZE_CONTROL_SELECTOR, VAR_LEFT_SIDEBAR_WIDTH } from '../../common/constants';
|
|
@@ -25,6 +25,33 @@ const resizeControlStyles = css({
|
|
|
25
25
|
const showResizeButtonStyles = css({
|
|
26
26
|
'--ds--resize-button--opacity': 1
|
|
27
27
|
});
|
|
28
|
+
|
|
29
|
+
// @ts-expect-error adding `!important` to style rules is currently a type error
|
|
30
|
+
const globalResizingStyles = css({
|
|
31
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
32
|
+
'*': {
|
|
33
|
+
// Setting the cursor to be `ew-resize` on all elements so that even if the user
|
|
34
|
+
// pointer slips off the resize handle, the cursor will still be the resize cursor
|
|
35
|
+
cursor: 'ew-resize !important',
|
|
36
|
+
// Blocking selection while resizing
|
|
37
|
+
// Notes:
|
|
38
|
+
// - This prevents a user selection being caused by resizing
|
|
39
|
+
// - Safari + Firefox → all good
|
|
40
|
+
// - Chrome → This will undo the current selection while resizing (not ideal)
|
|
41
|
+
// - The current selection will resume after resizing
|
|
42
|
+
userSelect: 'none !important'
|
|
43
|
+
},
|
|
44
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
45
|
+
iframe: {
|
|
46
|
+
// Disabling pointer events on iframes when resizing
|
|
47
|
+
// as iframes will swallower user events when the user is over them
|
|
48
|
+
pointerEvents: 'none !important'
|
|
49
|
+
}
|
|
50
|
+
// Note: We _could_ also disable `pointer-events` on all elements during resizing.
|
|
51
|
+
// However, to minimize risk we are just disabling `pointer-events` on iframes
|
|
52
|
+
// as that change is actually needed to fix resizing with iframes
|
|
53
|
+
});
|
|
54
|
+
|
|
28
55
|
const ResizeControl = ({
|
|
29
56
|
testId,
|
|
30
57
|
overrides,
|
|
@@ -49,6 +76,13 @@ const ResizeControl = ({
|
|
|
49
76
|
const keyboardEventTimeout = useRef();
|
|
50
77
|
const [isGrabAreaFocused, setIsGrabAreaFocused] = useState(false);
|
|
51
78
|
const unbindEvents = useRef(null);
|
|
79
|
+
|
|
80
|
+
// Used in some cases to ensure function references don't have to change
|
|
81
|
+
// TODO: more functions could use `stableSidebarState` rather than `leftSidebarState`
|
|
82
|
+
const stableSidebarState = useRef(leftSidebarState);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
stableSidebarState.current = leftSidebarState;
|
|
85
|
+
}, [leftSidebarState]);
|
|
52
86
|
const toggleSideBar = e => {
|
|
53
87
|
if (isResizing) {
|
|
54
88
|
return;
|
|
@@ -83,7 +117,11 @@ const ResizeControl = ({
|
|
|
83
117
|
offset.current = event.clientX - leftSidebarState[VAR_LEFT_SIDEBAR_WIDTH] - getLeftPanelWidth();
|
|
84
118
|
unbindEvents.current = bindAll(window, [{
|
|
85
119
|
type: 'mousemove',
|
|
86
|
-
listener:
|
|
120
|
+
listener: function (event) {
|
|
121
|
+
onUpdateResize({
|
|
122
|
+
clientX: event.clientX
|
|
123
|
+
});
|
|
124
|
+
}
|
|
87
125
|
}, {
|
|
88
126
|
type: 'mouseup',
|
|
89
127
|
listener: onFinishResizing
|
|
@@ -149,39 +187,42 @@ const ResizeControl = ({
|
|
|
149
187
|
offset.current = 0;
|
|
150
188
|
collapseLeftSidebar(undefined, true);
|
|
151
189
|
};
|
|
152
|
-
|
|
190
|
+
|
|
191
|
+
// It is important that `onUpdateResize` is a stable function reference, so that:
|
|
192
|
+
// 1. we ensure we are correctly throttling with `requestAnimationFrame`
|
|
193
|
+
// 2. that a `onUpdateResize` will cancel the one and only pending frame
|
|
194
|
+
// To help ensure `onUpdateResize` is stable, we are putting the last state into a ref
|
|
195
|
+
const [onUpdateResize] = useState(() => rafSchd(({
|
|
196
|
+
clientX
|
|
197
|
+
}) => {
|
|
153
198
|
// Allow the sidebar to be 50% of the available page width
|
|
154
199
|
const maxWidth = Math.round(window.innerWidth / 2);
|
|
155
200
|
const leftPanelWidth = getLeftPanelWidth();
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
} = leftSidebarState;
|
|
159
|
-
const hasResizedOffLeftOfScreen = event.clientX < 0;
|
|
201
|
+
const leftSidebarWidth = stableSidebarState.current.leftSidebarWidth;
|
|
202
|
+
const hasResizedOffLeftOfScreen = clientX < 0;
|
|
160
203
|
if (hasResizedOffLeftOfScreen) {
|
|
161
204
|
onResizeOffLeftOfScreen();
|
|
162
205
|
return;
|
|
163
206
|
}
|
|
164
|
-
const delta = Math.max(Math.min(
|
|
207
|
+
const delta = Math.max(Math.min(clientX - leftSidebarWidth - leftPanelWidth, maxWidth - leftSidebarWidth - leftPanelWidth), COLLAPSED_LEFT_SIDEBAR_WIDTH - leftSidebarWidth - leftPanelWidth);
|
|
165
208
|
sidebarWidth.current = Math.max(leftSidebarWidth + delta - offset.current, COLLAPSED_LEFT_SIDEBAR_WIDTH);
|
|
166
209
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${sidebarWidth.current}px`);
|
|
167
|
-
});
|
|
168
|
-
const cleanupAfterResize = () => {
|
|
169
|
-
var _unbindEvents$current2;
|
|
170
|
-
sidebarWidth.current = 0;
|
|
171
|
-
offset.current = 0;
|
|
172
|
-
(_unbindEvents$current2 = unbindEvents.current) === null || _unbindEvents$current2 === void 0 ? void 0 : _unbindEvents$current2.call(unbindEvents);
|
|
173
|
-
unbindEvents.current = null;
|
|
174
|
-
};
|
|
175
|
-
let updatedLeftSidebarState = {};
|
|
210
|
+
}));
|
|
176
211
|
const onFinishResizing = () => {
|
|
212
|
+
var _unbindEvents$current2;
|
|
177
213
|
if (isLeftSidebarCollapsed) {
|
|
178
214
|
return;
|
|
179
215
|
}
|
|
180
216
|
document.documentElement.removeAttribute(IS_SIDEBAR_DRAGGING);
|
|
181
217
|
|
|
218
|
+
// TODO: the control flow is pretty strange as the first codepath which calls `collapseLeftSidebar()`
|
|
219
|
+
// does not return an updated state snapshot.
|
|
220
|
+
let updatedLeftSidebarState = null;
|
|
221
|
+
|
|
182
222
|
// If it is dragged to below the threshold,
|
|
183
223
|
// collapse the navigation
|
|
184
224
|
if (sidebarWidth.current < MIN_LEFT_SIDEBAR_DRAG_THRESHOLD) {
|
|
225
|
+
// TODO: for this codepath, `onCollapse` occurs before `onResizeEnd` which seems wrong
|
|
185
226
|
document.documentElement.style.setProperty(`--${VAR_LEFT_SIDEBAR_WIDTH}`, `${COLLAPSED_LEFT_SIDEBAR_WIDTH}px`);
|
|
186
227
|
collapseLeftSidebar(undefined, true);
|
|
187
228
|
}
|
|
@@ -207,11 +248,18 @@ const ResizeControl = ({
|
|
|
207
248
|
};
|
|
208
249
|
setLeftSidebarState(updatedLeftSidebarState);
|
|
209
250
|
}
|
|
251
|
+
(_unbindEvents$current2 = unbindEvents.current) === null || _unbindEvents$current2 === void 0 ? void 0 : _unbindEvents$current2.call(unbindEvents);
|
|
252
|
+
unbindEvents.current = null;
|
|
253
|
+
onUpdateResize.cancel();
|
|
254
|
+
sidebarWidth.current = 0;
|
|
255
|
+
offset.current = 0;
|
|
256
|
+
|
|
257
|
+
// TODO: no idea why this is in an animation frame
|
|
210
258
|
requestAnimationFrame(() => {
|
|
211
|
-
|
|
259
|
+
var _updatedLeftSidebarSt;
|
|
212
260
|
setIsGrabAreaFocused(false);
|
|
213
|
-
|
|
214
|
-
|
|
261
|
+
// Note: the `collapseSidebar` codepath does not return state, so we need to pull it from the ref
|
|
262
|
+
onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd((_updatedLeftSidebarSt = updatedLeftSidebarState) !== null && _updatedLeftSidebarSt !== void 0 ? _updatedLeftSidebarSt : stableSidebarState.current);
|
|
215
263
|
});
|
|
216
264
|
};
|
|
217
265
|
const onKeyDown = event => {
|
|
@@ -287,7 +335,7 @@ const ResizeControl = ({
|
|
|
287
335
|
const leftSidebarPercentageExpanded = getLeftSidebarPercentage(leftSidebarState.leftSidebarWidth, maxAriaWidth);
|
|
288
336
|
|
|
289
337
|
/* eslint-disable jsx-a11y/role-supports-aria-props */
|
|
290
|
-
return jsx("div", _extends({}, cssSelector, {
|
|
338
|
+
return jsx(Fragment, null, jsx("div", _extends({}, cssSelector, {
|
|
291
339
|
css: [resizeControlStyles, (isGrabAreaFocused || isLeftSidebarCollapsed) && showResizeButtonStyles]
|
|
292
340
|
}), jsx(Shadow, {
|
|
293
341
|
testId: testId && `${testId}-shadow`
|
|
@@ -310,7 +358,9 @@ const ResizeControl = ({
|
|
|
310
358
|
label: resizeButtonLabel,
|
|
311
359
|
onClick: toggleSideBar,
|
|
312
360
|
testId: testId && `${testId}-resize-button`
|
|
313
|
-
}))
|
|
361
|
+
})), leftSidebarState.isResizing ? jsx(Global, {
|
|
362
|
+
styles: globalResizingStyles
|
|
363
|
+
}) : null);
|
|
314
364
|
/* eslint-enable jsx-a11y/role-supports-aria-props */
|
|
315
365
|
};
|
|
316
366
|
|
package/dist/es2019/version.json
CHANGED
|
@@ -8,6 +8,9 @@ var getIsDragging = function getIsDragging() {
|
|
|
8
8
|
}
|
|
9
9
|
return document.documentElement.getAttribute(IS_SIDEBAR_DRAGGING) === 'true';
|
|
10
10
|
};
|
|
11
|
+
|
|
12
|
+
// TODO: I think this should be derived from the sidebar state,
|
|
13
|
+
// and not indirectly from observing an attribute change
|
|
11
14
|
var useIsSidebarDragging = function useIsSidebarDragging() {
|
|
12
15
|
var _useState = useState(getIsDragging),
|
|
13
16
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -4,8 +4,8 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
4
4
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
5
5
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
6
|
/** @jsx jsx */
|
|
7
|
-
import { useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
8
|
-
import { css, jsx } from '@emotion/react';
|
|
7
|
+
import { Fragment, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
|
+
import { css, Global, jsx } from '@emotion/react';
|
|
9
9
|
import { bindAll } from 'bind-event-listener';
|
|
10
10
|
import rafSchd from 'raf-schd';
|
|
11
11
|
import { COLLAPSED_LEFT_SIDEBAR_WIDTH, DEFAULT_LEFT_SIDEBAR_WIDTH, IS_SIDEBAR_DRAGGING, MIN_LEFT_SIDEBAR_DRAG_THRESHOLD, RESIZE_BUTTON_SELECTOR, RESIZE_CONTROL_SELECTOR, VAR_LEFT_SIDEBAR_WIDTH } from '../../common/constants';
|
|
@@ -27,6 +27,33 @@ var resizeControlStyles = css({
|
|
|
27
27
|
var showResizeButtonStyles = css({
|
|
28
28
|
'--ds--resize-button--opacity': 1
|
|
29
29
|
});
|
|
30
|
+
|
|
31
|
+
// @ts-expect-error adding `!important` to style rules is currently a type error
|
|
32
|
+
var globalResizingStyles = css({
|
|
33
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
34
|
+
'*': {
|
|
35
|
+
// Setting the cursor to be `ew-resize` on all elements so that even if the user
|
|
36
|
+
// pointer slips off the resize handle, the cursor will still be the resize cursor
|
|
37
|
+
cursor: 'ew-resize !important',
|
|
38
|
+
// Blocking selection while resizing
|
|
39
|
+
// Notes:
|
|
40
|
+
// - This prevents a user selection being caused by resizing
|
|
41
|
+
// - Safari + Firefox → all good
|
|
42
|
+
// - Chrome → This will undo the current selection while resizing (not ideal)
|
|
43
|
+
// - The current selection will resume after resizing
|
|
44
|
+
userSelect: 'none !important'
|
|
45
|
+
},
|
|
46
|
+
// eslint-disable-next-line @repo/internal/styles/no-nested-styles
|
|
47
|
+
iframe: {
|
|
48
|
+
// Disabling pointer events on iframes when resizing
|
|
49
|
+
// as iframes will swallower user events when the user is over them
|
|
50
|
+
pointerEvents: 'none !important'
|
|
51
|
+
}
|
|
52
|
+
// Note: We _could_ also disable `pointer-events` on all elements during resizing.
|
|
53
|
+
// However, to minimize risk we are just disabling `pointer-events` on iframes
|
|
54
|
+
// as that change is actually needed to fix resizing with iframes
|
|
55
|
+
});
|
|
56
|
+
|
|
30
57
|
var ResizeControl = function ResizeControl(_ref) {
|
|
31
58
|
var testId = _ref.testId,
|
|
32
59
|
overrides = _ref.overrides,
|
|
@@ -52,6 +79,13 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
52
79
|
isGrabAreaFocused = _useState2[0],
|
|
53
80
|
setIsGrabAreaFocused = _useState2[1];
|
|
54
81
|
var unbindEvents = useRef(null);
|
|
82
|
+
|
|
83
|
+
// Used in some cases to ensure function references don't have to change
|
|
84
|
+
// TODO: more functions could use `stableSidebarState` rather than `leftSidebarState`
|
|
85
|
+
var stableSidebarState = useRef(leftSidebarState);
|
|
86
|
+
useEffect(function () {
|
|
87
|
+
stableSidebarState.current = leftSidebarState;
|
|
88
|
+
}, [leftSidebarState]);
|
|
55
89
|
var toggleSideBar = function toggleSideBar(e) {
|
|
56
90
|
if (isResizing) {
|
|
57
91
|
return;
|
|
@@ -86,7 +120,11 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
86
120
|
offset.current = event.clientX - leftSidebarState[VAR_LEFT_SIDEBAR_WIDTH] - getLeftPanelWidth();
|
|
87
121
|
unbindEvents.current = bindAll(window, [{
|
|
88
122
|
type: 'mousemove',
|
|
89
|
-
listener:
|
|
123
|
+
listener: function listener(event) {
|
|
124
|
+
onUpdateResize({
|
|
125
|
+
clientX: event.clientX
|
|
126
|
+
});
|
|
127
|
+
}
|
|
90
128
|
}, {
|
|
91
129
|
type: 'mouseup',
|
|
92
130
|
listener: onFinishResizing
|
|
@@ -151,37 +189,45 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
151
189
|
offset.current = 0;
|
|
152
190
|
collapseLeftSidebar(undefined, true);
|
|
153
191
|
};
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
192
|
+
|
|
193
|
+
// It is important that `onUpdateResize` is a stable function reference, so that:
|
|
194
|
+
// 1. we ensure we are correctly throttling with `requestAnimationFrame`
|
|
195
|
+
// 2. that a `onUpdateResize` will cancel the one and only pending frame
|
|
196
|
+
// To help ensure `onUpdateResize` is stable, we are putting the last state into a ref
|
|
197
|
+
var _useState3 = useState(function () {
|
|
198
|
+
return rafSchd(function (_ref2) {
|
|
199
|
+
var clientX = _ref2.clientX;
|
|
200
|
+
// Allow the sidebar to be 50% of the available page width
|
|
201
|
+
var maxWidth = Math.round(window.innerWidth / 2);
|
|
202
|
+
var leftPanelWidth = getLeftPanelWidth();
|
|
203
|
+
var leftSidebarWidth = stableSidebarState.current.leftSidebarWidth;
|
|
204
|
+
var hasResizedOffLeftOfScreen = clientX < 0;
|
|
205
|
+
if (hasResizedOffLeftOfScreen) {
|
|
206
|
+
onResizeOffLeftOfScreen();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
var delta = Math.max(Math.min(clientX - leftSidebarWidth - leftPanelWidth, maxWidth - leftSidebarWidth - leftPanelWidth), COLLAPSED_LEFT_SIDEBAR_WIDTH - leftSidebarWidth - leftPanelWidth);
|
|
210
|
+
sidebarWidth.current = Math.max(leftSidebarWidth + delta - offset.current, COLLAPSED_LEFT_SIDEBAR_WIDTH);
|
|
211
|
+
document.documentElement.style.setProperty("--".concat(VAR_LEFT_SIDEBAR_WIDTH), "".concat(sidebarWidth.current, "px"));
|
|
212
|
+
});
|
|
213
|
+
}),
|
|
214
|
+
_useState4 = _slicedToArray(_useState3, 1),
|
|
215
|
+
onUpdateResize = _useState4[0];
|
|
176
216
|
var onFinishResizing = function onFinishResizing() {
|
|
217
|
+
var _unbindEvents$current2;
|
|
177
218
|
if (isLeftSidebarCollapsed) {
|
|
178
219
|
return;
|
|
179
220
|
}
|
|
180
221
|
document.documentElement.removeAttribute(IS_SIDEBAR_DRAGGING);
|
|
181
222
|
|
|
223
|
+
// TODO: the control flow is pretty strange as the first codepath which calls `collapseLeftSidebar()`
|
|
224
|
+
// does not return an updated state snapshot.
|
|
225
|
+
var updatedLeftSidebarState = null;
|
|
226
|
+
|
|
182
227
|
// If it is dragged to below the threshold,
|
|
183
228
|
// collapse the navigation
|
|
184
229
|
if (sidebarWidth.current < MIN_LEFT_SIDEBAR_DRAG_THRESHOLD) {
|
|
230
|
+
// TODO: for this codepath, `onCollapse` occurs before `onResizeEnd` which seems wrong
|
|
185
231
|
document.documentElement.style.setProperty("--".concat(VAR_LEFT_SIDEBAR_WIDTH), "".concat(COLLAPSED_LEFT_SIDEBAR_WIDTH, "px"));
|
|
186
232
|
collapseLeftSidebar(undefined, true);
|
|
187
233
|
}
|
|
@@ -203,11 +249,18 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
203
249
|
}, _defineProperty(_objectSpread3, VAR_LEFT_SIDEBAR_WIDTH, sidebarWidth.current), _defineProperty(_objectSpread3, "lastLeftSidebarWidth", sidebarWidth.current), _objectSpread3));
|
|
204
250
|
setLeftSidebarState(updatedLeftSidebarState);
|
|
205
251
|
}
|
|
252
|
+
(_unbindEvents$current2 = unbindEvents.current) === null || _unbindEvents$current2 === void 0 ? void 0 : _unbindEvents$current2.call(unbindEvents);
|
|
253
|
+
unbindEvents.current = null;
|
|
254
|
+
onUpdateResize.cancel();
|
|
255
|
+
sidebarWidth.current = 0;
|
|
256
|
+
offset.current = 0;
|
|
257
|
+
|
|
258
|
+
// TODO: no idea why this is in an animation frame
|
|
206
259
|
requestAnimationFrame(function () {
|
|
207
|
-
|
|
260
|
+
var _updatedLeftSidebarSt;
|
|
208
261
|
setIsGrabAreaFocused(false);
|
|
209
|
-
|
|
210
|
-
|
|
262
|
+
// Note: the `collapseSidebar` codepath does not return state, so we need to pull it from the ref
|
|
263
|
+
onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd((_updatedLeftSidebarSt = updatedLeftSidebarState) !== null && _updatedLeftSidebarSt !== void 0 ? _updatedLeftSidebarSt : stableSidebarState.current);
|
|
211
264
|
});
|
|
212
265
|
};
|
|
213
266
|
var onKeyDown = function onKeyDown(event) {
|
|
@@ -277,7 +330,7 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
277
330
|
var leftSidebarPercentageExpanded = getLeftSidebarPercentage(leftSidebarState.leftSidebarWidth, maxAriaWidth);
|
|
278
331
|
|
|
279
332
|
/* eslint-disable jsx-a11y/role-supports-aria-props */
|
|
280
|
-
return jsx("div", _extends({}, cssSelector, {
|
|
333
|
+
return jsx(Fragment, null, jsx("div", _extends({}, cssSelector, {
|
|
281
334
|
css: [resizeControlStyles, (isGrabAreaFocused || isLeftSidebarCollapsed) && showResizeButtonStyles]
|
|
282
335
|
}), jsx(Shadow, {
|
|
283
336
|
testId: testId && "".concat(testId, "-shadow")
|
|
@@ -300,7 +353,9 @@ var ResizeControl = function ResizeControl(_ref) {
|
|
|
300
353
|
label: resizeButtonLabel,
|
|
301
354
|
onClick: toggleSideBar,
|
|
302
355
|
testId: testId && "".concat(testId, "-resize-button")
|
|
303
|
-
}))
|
|
356
|
+
})), leftSidebarState.isResizing ? jsx(Global, {
|
|
357
|
+
styles: globalResizingStyles
|
|
358
|
+
}) : null);
|
|
304
359
|
/* eslint-enable jsx-a11y/role-supports-aria-props */
|
|
305
360
|
};
|
|
306
361
|
|
package/dist/esm/version.json
CHANGED