carbon-react 109.1.0 → 109.1.1
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/esm/components/date/date.component.js +4 -7
- package/esm/components/menu/__internal__/submenu/submenu.component.js +4 -6
- package/esm/components/multi-action-button/multi-action-button.component.js +4 -13
- package/esm/components/popover-container/popover-container.component.d.ts +1 -1
- package/esm/components/popover-container/popover-container.component.js +5 -9
- package/esm/components/split-button/split-button.component.js +4 -11
- package/esm/hooks/__internal__/useClickAwayListener/index.d.ts +1 -0
- package/esm/hooks/__internal__/useClickAwayListener/index.js +1 -0
- package/esm/hooks/__internal__/useClickAwayListener/useClickAwayListener.d.ts +3 -0
- package/esm/hooks/__internal__/useClickAwayListener/useClickAwayListener.js +23 -0
- package/lib/components/date/date.component.js +4 -7
- package/lib/components/menu/__internal__/submenu/submenu.component.js +4 -6
- package/lib/components/multi-action-button/multi-action-button.component.js +5 -13
- package/lib/components/popover-container/popover-container.component.d.ts +1 -1
- package/lib/components/popover-container/popover-container.component.js +5 -9
- package/lib/components/split-button/split-button.component.js +5 -11
- package/lib/hooks/__internal__/useClickAwayListener/index.d.ts +1 -0
- package/lib/{__internal__/click-away-wrapper → hooks/__internal__/useClickAwayListener}/index.js +2 -2
- package/lib/hooks/__internal__/useClickAwayListener/package.json +6 -0
- package/lib/hooks/__internal__/useClickAwayListener/useClickAwayListener.d.ts +3 -0
- package/lib/hooks/__internal__/useClickAwayListener/useClickAwayListener.js +33 -0
- package/package.json +1 -1
- package/esm/__internal__/click-away-wrapper/click-away-wrapper.component.d.ts +0 -12
- package/esm/__internal__/click-away-wrapper/click-away-wrapper.component.js +0 -43
- package/esm/__internal__/click-away-wrapper/index.d.ts +0 -2
- package/esm/__internal__/click-away-wrapper/index.js +0 -1
- package/lib/__internal__/click-away-wrapper/click-away-wrapper.component.d.ts +0 -12
- package/lib/__internal__/click-away-wrapper/click-away-wrapper.component.js +0 -59
- package/lib/__internal__/click-away-wrapper/index.d.ts +0 -2
- package/lib/__internal__/click-away-wrapper/package.json +0 -6
|
@@ -12,7 +12,7 @@ import StyledDateInput from "./date.style";
|
|
|
12
12
|
import Textbox from "../textbox";
|
|
13
13
|
import DatePicker from "./__internal__/date-picker";
|
|
14
14
|
import DateRangeContext from "../date-range/date-range.context";
|
|
15
|
-
import
|
|
15
|
+
import useClickAwayListener from "../../hooks/__internal__/useClickAwayListener";
|
|
16
16
|
const marginPropTypes = filterStyledSystemMarginProps(styledSystemPropTypes.space);
|
|
17
17
|
|
|
18
18
|
const DateInput = ({
|
|
@@ -277,11 +277,8 @@ const DateInput = ({
|
|
|
277
277
|
}
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
eventTypeId: "mousedown",
|
|
283
|
-
targets: [parentRef, pickerRef]
|
|
284
|
-
}, /*#__PURE__*/React.createElement(StyledDateInput, _extends({
|
|
280
|
+
useClickAwayListener([parentRef, pickerRef], handleClickAway, "mousedown");
|
|
281
|
+
return /*#__PURE__*/React.createElement(StyledDateInput, _extends({
|
|
285
282
|
ref: wrapperRef,
|
|
286
283
|
role: "presentation",
|
|
287
284
|
size: size,
|
|
@@ -321,7 +318,7 @@ const DateInput = ({
|
|
|
321
318
|
ref: pickerRef,
|
|
322
319
|
pickerMouseDown: handlePickerMouseDown,
|
|
323
320
|
open: open
|
|
324
|
-
}))
|
|
321
|
+
}));
|
|
325
322
|
};
|
|
326
323
|
|
|
327
324
|
DateInput.propTypes = { ...Textbox.propTypes,
|
|
@@ -12,7 +12,7 @@ import MenuItem from "../../menu-item";
|
|
|
12
12
|
import { characterNavigation } from "../keyboard-navigation";
|
|
13
13
|
import ScrollableBlock from "../../scrollable-block";
|
|
14
14
|
import SubmenuContext from "./submenu.context";
|
|
15
|
-
import
|
|
15
|
+
import useClickAwayListener from "../../../../hooks/__internal__/useClickAwayListener";
|
|
16
16
|
const Submenu = /*#__PURE__*/React.forwardRef(({
|
|
17
17
|
children,
|
|
18
18
|
className,
|
|
@@ -205,6 +205,7 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
|
|
|
205
205
|
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
206
206
|
|
|
207
207
|
}, [characterString]);
|
|
208
|
+
useClickAwayListener([submenuRef], handleClickAway);
|
|
208
209
|
|
|
209
210
|
if (inFullscreenView) {
|
|
210
211
|
return /*#__PURE__*/React.createElement(StyledSubmenuWrapper, {
|
|
@@ -238,10 +239,7 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
|
|
|
238
239
|
}, child))));
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
return /*#__PURE__*/React.createElement(
|
|
242
|
-
handleClickAway: handleClickAway,
|
|
243
|
-
targets: [submenuRef]
|
|
244
|
-
}, /*#__PURE__*/React.createElement(StyledSubmenuWrapper, {
|
|
242
|
+
return /*#__PURE__*/React.createElement(StyledSubmenuWrapper, {
|
|
245
243
|
"data-component": "submenu-wrapper",
|
|
246
244
|
onMouseOver: !clickToOpen ? () => openSubmenu() : undefined,
|
|
247
245
|
onMouseLeave: () => closeSubmenu(),
|
|
@@ -279,7 +277,7 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
|
|
|
279
277
|
updateFocusIndex: setSubmenuFocusIndex,
|
|
280
278
|
itemIndex: child.type === MenuItem ? index : undefined
|
|
281
279
|
}
|
|
282
|
-
}, child))))
|
|
280
|
+
}, child))));
|
|
283
281
|
});
|
|
284
282
|
Submenu.propTypes = {
|
|
285
283
|
/** Children elements */
|
|
@@ -2,6 +2,7 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
|
|
|
2
2
|
|
|
3
3
|
import React, { useCallback, useEffect, useState, useRef, useMemo } from "react";
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
|
+
import useClickAwayListener from "../../hooks/__internal__/useClickAwayListener";
|
|
5
6
|
import { StyledMultiActionButton, StyledButtonChildrenContainer } from "./multi-action-button.style";
|
|
6
7
|
import Button, { ButtonWithForwardRef } from "../button";
|
|
7
8
|
import Events from "../../__internal__/utils/helpers/events";
|
|
@@ -105,31 +106,20 @@ const MultiActionButton = ({
|
|
|
105
106
|
(_additionalButtons$cu = additionalButtons.current[nextIndex].current) === null || _additionalButtons$cu === void 0 ? void 0 : _additionalButtons$cu.focus();
|
|
106
107
|
}
|
|
107
108
|
}, [buttonChildren, hideButtons]);
|
|
108
|
-
const handleClickOutside = useCallback(({
|
|
109
|
-
target
|
|
110
|
-
}) => {
|
|
111
|
-
var _ref$current, _buttonContainer$curr;
|
|
112
|
-
|
|
113
|
-
if (!((_ref$current = ref.current) !== null && _ref$current !== void 0 && _ref$current.contains(target)) && !((_buttonContainer$curr = buttonContainer.current) !== null && _buttonContainer$curr !== void 0 && _buttonContainer$curr.contains(target))) {
|
|
114
|
-
hideButtons();
|
|
115
|
-
}
|
|
116
|
-
}, [hideButtons]);
|
|
117
109
|
const addListeners = useCallback(() => {
|
|
118
110
|
/* istanbul ignore else */
|
|
119
111
|
if (!listening.current) {
|
|
120
|
-
document.addEventListener("click", handleClickOutside);
|
|
121
112
|
document.addEventListener("keydown", handleKeyDown);
|
|
122
113
|
listening.current = true;
|
|
123
114
|
}
|
|
124
|
-
}, [handleKeyDown
|
|
115
|
+
}, [handleKeyDown]);
|
|
125
116
|
const removeListeners = useCallback(() => {
|
|
126
117
|
/* istanbul ignore else */
|
|
127
118
|
if (listening.current) {
|
|
128
|
-
document.removeEventListener("click", handleClickOutside);
|
|
129
119
|
document.removeEventListener("keydown", handleKeyDown);
|
|
130
120
|
listening.current = false;
|
|
131
121
|
}
|
|
132
|
-
}, [handleKeyDown
|
|
122
|
+
}, [handleKeyDown]);
|
|
133
123
|
useEffect(() => {
|
|
134
124
|
if (showAdditionalButtons) {
|
|
135
125
|
addListeners();
|
|
@@ -200,6 +190,7 @@ const MultiActionButton = ({
|
|
|
200
190
|
ref: buttonContainer
|
|
201
191
|
}, childrenWithProps()));
|
|
202
192
|
|
|
193
|
+
useClickAwayListener([ref], hideButtons);
|
|
203
194
|
return /*#__PURE__*/React.createElement(StyledMultiActionButton, _extends({
|
|
204
195
|
"aria-haspopup": "true",
|
|
205
196
|
onMouseLeave: hideButtons,
|
|
@@ -36,7 +36,7 @@ export interface PopoverContainerProps extends PaddingProps {
|
|
|
36
36
|
/** Sets the popover container dialog header name */
|
|
37
37
|
title?: string;
|
|
38
38
|
/** Callback fires when close icon clicked */
|
|
39
|
-
onClose?: (ev: React.MouseEvent<HTMLElement>) => void;
|
|
39
|
+
onClose?: (ev: React.MouseEvent<HTMLElement> | Event) => void;
|
|
40
40
|
/** if `true` the popover-container is open */
|
|
41
41
|
open?: boolean;
|
|
42
42
|
/** Callback fires when open component is clicked */
|
|
@@ -7,7 +7,7 @@ import { PopoverContainerWrapperStyle, PopoverContainerHeaderStyle, PopoverConta
|
|
|
7
7
|
import Icon from "../icon";
|
|
8
8
|
import createGuid from "../../__internal__/utils/helpers/guid";
|
|
9
9
|
import { filterStyledSystemPaddingProps } from "../../style/utils";
|
|
10
|
-
import
|
|
10
|
+
import useClickAwayListener from "../../hooks/__internal__/useClickAwayListener";
|
|
11
11
|
|
|
12
12
|
const renderOpen = ({
|
|
13
13
|
tabIndex,
|
|
@@ -118,19 +118,15 @@ const PopoverContainer = ({
|
|
|
118
118
|
onClick: handleCloseButtonClick,
|
|
119
119
|
ref: closeButtonRef,
|
|
120
120
|
"aria-label": closeButtonAriaLabel
|
|
121
|
-
};
|
|
122
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
121
|
+
};
|
|
123
122
|
|
|
124
123
|
const handleClickAway = e => {
|
|
125
124
|
if (!isControlled) setIsOpenInternal(false);
|
|
126
125
|
if (onClose) onClose(e);
|
|
127
126
|
};
|
|
128
127
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
handleClickAway: handleClickAway,
|
|
132
|
-
eventTypeId: "mousedown"
|
|
133
|
-
}, /*#__PURE__*/React.createElement(PopoverContainerWrapperStyle, {
|
|
128
|
+
useClickAwayListener([ref], handleClickAway, "mousedown");
|
|
129
|
+
return /*#__PURE__*/React.createElement(PopoverContainerWrapperStyle, {
|
|
134
130
|
"data-component": "popover-container",
|
|
135
131
|
role: "region",
|
|
136
132
|
"aria-labelledby": popoverContainerId,
|
|
@@ -158,7 +154,7 @@ const PopoverContainer = ({
|
|
|
158
154
|
}, filterStyledSystemPaddingProps(rest)), /*#__PURE__*/React.createElement(PopoverContainerHeaderStyle, null, /*#__PURE__*/React.createElement(PopoverContainerTitleStyle, {
|
|
159
155
|
id: popoverContainerId,
|
|
160
156
|
"data-element": "popover-container-title"
|
|
161
|
-
}, title), renderCloseComponent(renderCloseComponentProps)), children)))
|
|
157
|
+
}, title), renderCloseComponent(renderCloseComponentProps)), children)));
|
|
162
158
|
};
|
|
163
159
|
|
|
164
160
|
PopoverContainer.propTypes = {
|
|
@@ -4,6 +4,7 @@ import React, { useRef, useState, useContext, useCallback, useEffect } from "rea
|
|
|
4
4
|
import { ThemeContext } from "styled-components";
|
|
5
5
|
import PropTypes from "prop-types";
|
|
6
6
|
import styledSystemPropTypes from "@styled-system/prop-types";
|
|
7
|
+
import useClickAwayListener from "../../hooks/__internal__/useClickAwayListener";
|
|
7
8
|
import Icon from "../icon";
|
|
8
9
|
import Button, { ButtonWithForwardRef } from "../button";
|
|
9
10
|
import StyledSplitButton from "./split-button.style";
|
|
@@ -49,13 +50,6 @@ const SplitButton = ({
|
|
|
49
50
|
if (isToggleButtonFocused.current) return;
|
|
50
51
|
setShowAdditionalButtons(false);
|
|
51
52
|
}, []);
|
|
52
|
-
const handleClickOutside = useCallback(({
|
|
53
|
-
target
|
|
54
|
-
}) => {
|
|
55
|
-
if (!splitButtonNode.current.contains(target) && buttonContainer.current && !buttonContainer.current.contains(target)) {
|
|
56
|
-
hideButtons();
|
|
57
|
-
}
|
|
58
|
-
}, [hideButtons]);
|
|
59
53
|
const handleKeyDown = useCallback(ev => {
|
|
60
54
|
const numOfChildren = children.length - 1;
|
|
61
55
|
const currentIndex = additionalButtons.current.findIndex(node => node.current === document.activeElement);
|
|
@@ -88,19 +82,17 @@ const SplitButton = ({
|
|
|
88
82
|
const addListeners = useCallback(() => {
|
|
89
83
|
/* istanbul ignore else */
|
|
90
84
|
if (!listening.current) {
|
|
91
|
-
document.addEventListener("click", handleClickOutside);
|
|
92
85
|
document.addEventListener("keydown", handleKeyDown);
|
|
93
86
|
listening.current = true;
|
|
94
87
|
}
|
|
95
|
-
}, [handleKeyDown
|
|
88
|
+
}, [handleKeyDown]);
|
|
96
89
|
const removeListeners = useCallback(() => {
|
|
97
90
|
/* istanbul ignore else */
|
|
98
91
|
if (listening.current) {
|
|
99
|
-
document.removeEventListener("click", handleClickOutside);
|
|
100
92
|
document.removeEventListener("keydown", handleKeyDown);
|
|
101
93
|
listening.current = false;
|
|
102
94
|
}
|
|
103
|
-
}, [handleKeyDown
|
|
95
|
+
}, [handleKeyDown]);
|
|
104
96
|
useEffect(() => {
|
|
105
97
|
if (showAdditionalButtons) {
|
|
106
98
|
addListeners();
|
|
@@ -260,6 +252,7 @@ const SplitButton = ({
|
|
|
260
252
|
}, childrenWithProps()));
|
|
261
253
|
}
|
|
262
254
|
|
|
255
|
+
useClickAwayListener([splitButtonNode], hideButtons);
|
|
263
256
|
return /*#__PURE__*/React.createElement(StyledSplitButton, _extends({
|
|
264
257
|
"aria-haspopup": "true",
|
|
265
258
|
onMouseLeave: hideButtons,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./useClickAwayListener";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./useClickAwayListener";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
export default ((targets, handleClickAway, eventTypeId = "click") => {
|
|
3
|
+
const targetsRef = useRef(targets);
|
|
4
|
+
targetsRef.current = targets;
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const fnClickAway = ev => {
|
|
7
|
+
const clickedElements = targetsRef.current.filter(targetRef => {
|
|
8
|
+
var _targetRef$current;
|
|
9
|
+
|
|
10
|
+
return (_targetRef$current = targetRef.current) === null || _targetRef$current === void 0 ? void 0 : _targetRef$current.contains(ev === null || ev === void 0 ? void 0 : ev.target);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (!(clickedElements !== null && clickedElements !== void 0 && clickedElements.length)) {
|
|
14
|
+
handleClickAway(ev);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
document.addEventListener(eventTypeId, fnClickAway);
|
|
19
|
+
return function cleanup() {
|
|
20
|
+
document.removeEventListener(eventTypeId, fnClickAway);
|
|
21
|
+
};
|
|
22
|
+
}, [handleClickAway, eventTypeId]);
|
|
23
|
+
});
|
|
@@ -29,7 +29,7 @@ var _datePicker = _interopRequireDefault(require("./__internal__/date-picker"));
|
|
|
29
29
|
|
|
30
30
|
var _dateRange = _interopRequireDefault(require("../date-range/date-range.context"));
|
|
31
31
|
|
|
32
|
-
var
|
|
32
|
+
var _useClickAwayListener = _interopRequireDefault(require("../../hooks/__internal__/useClickAwayListener"));
|
|
33
33
|
|
|
34
34
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
35
35
|
|
|
@@ -303,11 +303,8 @@ const DateInput = ({
|
|
|
303
303
|
}
|
|
304
304
|
};
|
|
305
305
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
eventTypeId: "mousedown",
|
|
309
|
-
targets: [parentRef, pickerRef]
|
|
310
|
-
}, /*#__PURE__*/_react.default.createElement(_date.default, _extends({
|
|
306
|
+
(0, _useClickAwayListener.default)([parentRef, pickerRef], handleClickAway, "mousedown");
|
|
307
|
+
return /*#__PURE__*/_react.default.createElement(_date.default, _extends({
|
|
311
308
|
ref: wrapperRef,
|
|
312
309
|
role: "presentation",
|
|
313
310
|
size: size,
|
|
@@ -347,7 +344,7 @@ const DateInput = ({
|
|
|
347
344
|
ref: pickerRef,
|
|
348
345
|
pickerMouseDown: handlePickerMouseDown,
|
|
349
346
|
open: open
|
|
350
|
-
}))
|
|
347
|
+
}));
|
|
351
348
|
};
|
|
352
349
|
|
|
353
350
|
DateInput.propTypes = { ..._textbox.default.propTypes,
|
|
@@ -27,7 +27,7 @@ var _scrollableBlock = _interopRequireDefault(require("../../scrollable-block"))
|
|
|
27
27
|
|
|
28
28
|
var _submenu2 = _interopRequireDefault(require("./submenu.context"));
|
|
29
29
|
|
|
30
|
-
var
|
|
30
|
+
var _useClickAwayListener = _interopRequireDefault(require("../../../../hooks/__internal__/useClickAwayListener"));
|
|
31
31
|
|
|
32
32
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
33
33
|
|
|
@@ -232,6 +232,7 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
232
232
|
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
233
233
|
|
|
234
234
|
}, [characterString]);
|
|
235
|
+
(0, _useClickAwayListener.default)([submenuRef], handleClickAway);
|
|
235
236
|
|
|
236
237
|
if (inFullscreenView) {
|
|
237
238
|
return /*#__PURE__*/_react.default.createElement(_submenu.StyledSubmenuWrapper, {
|
|
@@ -265,10 +266,7 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
265
266
|
}, child))));
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
return /*#__PURE__*/_react.default.createElement(
|
|
269
|
-
handleClickAway: handleClickAway,
|
|
270
|
-
targets: [submenuRef]
|
|
271
|
-
}, /*#__PURE__*/_react.default.createElement(_submenu.StyledSubmenuWrapper, {
|
|
269
|
+
return /*#__PURE__*/_react.default.createElement(_submenu.StyledSubmenuWrapper, {
|
|
272
270
|
"data-component": "submenu-wrapper",
|
|
273
271
|
onMouseOver: !clickToOpen ? () => openSubmenu() : undefined,
|
|
274
272
|
onMouseLeave: () => closeSubmenu(),
|
|
@@ -306,7 +304,7 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
306
304
|
updateFocusIndex: setSubmenuFocusIndex,
|
|
307
305
|
itemIndex: child.type === _menuItem2.default ? index : undefined
|
|
308
306
|
}
|
|
309
|
-
}, child))))
|
|
307
|
+
}, child))));
|
|
310
308
|
});
|
|
311
309
|
|
|
312
310
|
Submenu.propTypes = {
|
|
@@ -9,6 +9,8 @@ var _react = _interopRequireWildcard(require("react"));
|
|
|
9
9
|
|
|
10
10
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
11
|
|
|
12
|
+
var _useClickAwayListener = _interopRequireDefault(require("../../hooks/__internal__/useClickAwayListener"));
|
|
13
|
+
|
|
12
14
|
var _multiActionButton = require("./multi-action-button.style");
|
|
13
15
|
|
|
14
16
|
var _button = _interopRequireWildcard(require("../button"));
|
|
@@ -125,31 +127,20 @@ const MultiActionButton = ({
|
|
|
125
127
|
(_additionalButtons$cu = additionalButtons.current[nextIndex].current) === null || _additionalButtons$cu === void 0 ? void 0 : _additionalButtons$cu.focus();
|
|
126
128
|
}
|
|
127
129
|
}, [buttonChildren, hideButtons]);
|
|
128
|
-
const handleClickOutside = (0, _react.useCallback)(({
|
|
129
|
-
target
|
|
130
|
-
}) => {
|
|
131
|
-
var _ref$current, _buttonContainer$curr;
|
|
132
|
-
|
|
133
|
-
if (!((_ref$current = ref.current) !== null && _ref$current !== void 0 && _ref$current.contains(target)) && !((_buttonContainer$curr = buttonContainer.current) !== null && _buttonContainer$curr !== void 0 && _buttonContainer$curr.contains(target))) {
|
|
134
|
-
hideButtons();
|
|
135
|
-
}
|
|
136
|
-
}, [hideButtons]);
|
|
137
130
|
const addListeners = (0, _react.useCallback)(() => {
|
|
138
131
|
/* istanbul ignore else */
|
|
139
132
|
if (!listening.current) {
|
|
140
|
-
document.addEventListener("click", handleClickOutside);
|
|
141
133
|
document.addEventListener("keydown", handleKeyDown);
|
|
142
134
|
listening.current = true;
|
|
143
135
|
}
|
|
144
|
-
}, [handleKeyDown
|
|
136
|
+
}, [handleKeyDown]);
|
|
145
137
|
const removeListeners = (0, _react.useCallback)(() => {
|
|
146
138
|
/* istanbul ignore else */
|
|
147
139
|
if (listening.current) {
|
|
148
|
-
document.removeEventListener("click", handleClickOutside);
|
|
149
140
|
document.removeEventListener("keydown", handleKeyDown);
|
|
150
141
|
listening.current = false;
|
|
151
142
|
}
|
|
152
|
-
}, [handleKeyDown
|
|
143
|
+
}, [handleKeyDown]);
|
|
153
144
|
(0, _react.useEffect)(() => {
|
|
154
145
|
if (showAdditionalButtons) {
|
|
155
146
|
addListeners();
|
|
@@ -220,6 +211,7 @@ const MultiActionButton = ({
|
|
|
220
211
|
ref: buttonContainer
|
|
221
212
|
}, childrenWithProps()));
|
|
222
213
|
|
|
214
|
+
(0, _useClickAwayListener.default)([ref], hideButtons);
|
|
223
215
|
return /*#__PURE__*/_react.default.createElement(_multiActionButton.StyledMultiActionButton, _extends({
|
|
224
216
|
"aria-haspopup": "true",
|
|
225
217
|
onMouseLeave: hideButtons,
|
|
@@ -36,7 +36,7 @@ export interface PopoverContainerProps extends PaddingProps {
|
|
|
36
36
|
/** Sets the popover container dialog header name */
|
|
37
37
|
title?: string;
|
|
38
38
|
/** Callback fires when close icon clicked */
|
|
39
|
-
onClose?: (ev: React.MouseEvent<HTMLElement>) => void;
|
|
39
|
+
onClose?: (ev: React.MouseEvent<HTMLElement> | Event) => void;
|
|
40
40
|
/** if `true` the popover-container is open */
|
|
41
41
|
open?: boolean;
|
|
42
42
|
/** Callback fires when open component is clicked */
|
|
@@ -19,7 +19,7 @@ var _guid = _interopRequireDefault(require("../../__internal__/utils/helpers/gui
|
|
|
19
19
|
|
|
20
20
|
var _utils = require("../../style/utils");
|
|
21
21
|
|
|
22
|
-
var
|
|
22
|
+
var _useClickAwayListener = _interopRequireDefault(require("../../hooks/__internal__/useClickAwayListener"));
|
|
23
23
|
|
|
24
24
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
25
|
|
|
@@ -138,19 +138,15 @@ const PopoverContainer = ({
|
|
|
138
138
|
onClick: handleCloseButtonClick,
|
|
139
139
|
ref: closeButtonRef,
|
|
140
140
|
"aria-label": closeButtonAriaLabel
|
|
141
|
-
};
|
|
142
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
141
|
+
};
|
|
143
142
|
|
|
144
143
|
const handleClickAway = e => {
|
|
145
144
|
if (!isControlled) setIsOpenInternal(false);
|
|
146
145
|
if (onClose) onClose(e);
|
|
147
146
|
};
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
handleClickAway: handleClickAway,
|
|
152
|
-
eventTypeId: "mousedown"
|
|
153
|
-
}, /*#__PURE__*/_react.default.createElement(_popoverContainer.PopoverContainerWrapperStyle, {
|
|
148
|
+
(0, _useClickAwayListener.default)([ref], handleClickAway, "mousedown");
|
|
149
|
+
return /*#__PURE__*/_react.default.createElement(_popoverContainer.PopoverContainerWrapperStyle, {
|
|
154
150
|
"data-component": "popover-container",
|
|
155
151
|
role: "region",
|
|
156
152
|
"aria-labelledby": popoverContainerId,
|
|
@@ -178,7 +174,7 @@ const PopoverContainer = ({
|
|
|
178
174
|
}, (0, _utils.filterStyledSystemPaddingProps)(rest)), /*#__PURE__*/_react.default.createElement(_popoverContainer.PopoverContainerHeaderStyle, null, /*#__PURE__*/_react.default.createElement(_popoverContainer.PopoverContainerTitleStyle, {
|
|
179
175
|
id: popoverContainerId,
|
|
180
176
|
"data-element": "popover-container-title"
|
|
181
|
-
}, title), renderCloseComponent(renderCloseComponentProps)), children)))
|
|
177
|
+
}, title), renderCloseComponent(renderCloseComponentProps)), children)));
|
|
182
178
|
};
|
|
183
179
|
|
|
184
180
|
exports.PopoverContainer = PopoverContainer;
|
|
@@ -13,6 +13,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
13
13
|
|
|
14
14
|
var _propTypes2 = _interopRequireDefault(require("@styled-system/prop-types"));
|
|
15
15
|
|
|
16
|
+
var _useClickAwayListener = _interopRequireDefault(require("../../hooks/__internal__/useClickAwayListener"));
|
|
17
|
+
|
|
16
18
|
var _icon = _interopRequireDefault(require("../icon"));
|
|
17
19
|
|
|
18
20
|
var _button = _interopRequireWildcard(require("../button"));
|
|
@@ -80,13 +82,6 @@ const SplitButton = ({
|
|
|
80
82
|
if (isToggleButtonFocused.current) return;
|
|
81
83
|
setShowAdditionalButtons(false);
|
|
82
84
|
}, []);
|
|
83
|
-
const handleClickOutside = (0, _react.useCallback)(({
|
|
84
|
-
target
|
|
85
|
-
}) => {
|
|
86
|
-
if (!splitButtonNode.current.contains(target) && buttonContainer.current && !buttonContainer.current.contains(target)) {
|
|
87
|
-
hideButtons();
|
|
88
|
-
}
|
|
89
|
-
}, [hideButtons]);
|
|
90
85
|
const handleKeyDown = (0, _react.useCallback)(ev => {
|
|
91
86
|
const numOfChildren = children.length - 1;
|
|
92
87
|
const currentIndex = additionalButtons.current.findIndex(node => node.current === document.activeElement);
|
|
@@ -119,19 +114,17 @@ const SplitButton = ({
|
|
|
119
114
|
const addListeners = (0, _react.useCallback)(() => {
|
|
120
115
|
/* istanbul ignore else */
|
|
121
116
|
if (!listening.current) {
|
|
122
|
-
document.addEventListener("click", handleClickOutside);
|
|
123
117
|
document.addEventListener("keydown", handleKeyDown);
|
|
124
118
|
listening.current = true;
|
|
125
119
|
}
|
|
126
|
-
}, [handleKeyDown
|
|
120
|
+
}, [handleKeyDown]);
|
|
127
121
|
const removeListeners = (0, _react.useCallback)(() => {
|
|
128
122
|
/* istanbul ignore else */
|
|
129
123
|
if (listening.current) {
|
|
130
|
-
document.removeEventListener("click", handleClickOutside);
|
|
131
124
|
document.removeEventListener("keydown", handleKeyDown);
|
|
132
125
|
listening.current = false;
|
|
133
126
|
}
|
|
134
|
-
}, [handleKeyDown
|
|
127
|
+
}, [handleKeyDown]);
|
|
135
128
|
(0, _react.useEffect)(() => {
|
|
136
129
|
if (showAdditionalButtons) {
|
|
137
130
|
addListeners();
|
|
@@ -291,6 +284,7 @@ const SplitButton = ({
|
|
|
291
284
|
}, childrenWithProps()));
|
|
292
285
|
}
|
|
293
286
|
|
|
287
|
+
(0, _useClickAwayListener.default)([splitButtonNode], hideButtons);
|
|
294
288
|
return /*#__PURE__*/_react.default.createElement(_splitButton.default, _extends({
|
|
295
289
|
"aria-haspopup": "true",
|
|
296
290
|
onMouseLeave: hideButtons,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./useClickAwayListener";
|
package/lib/{__internal__/click-away-wrapper → hooks/__internal__/useClickAwayListener}/index.js
RENAMED
|
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
Object.defineProperty(exports, "default", {
|
|
7
7
|
enumerable: true,
|
|
8
8
|
get: function () {
|
|
9
|
-
return
|
|
9
|
+
return _useClickAwayListener.default;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var _useClickAwayListener = _interopRequireDefault(require("./useClickAwayListener"));
|
|
14
14
|
|
|
15
15
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
|
|
10
|
+
var _default = (targets, handleClickAway, eventTypeId = "click") => {
|
|
11
|
+
const targetsRef = (0, _react.useRef)(targets);
|
|
12
|
+
targetsRef.current = targets;
|
|
13
|
+
(0, _react.useEffect)(() => {
|
|
14
|
+
const fnClickAway = ev => {
|
|
15
|
+
const clickedElements = targetsRef.current.filter(targetRef => {
|
|
16
|
+
var _targetRef$current;
|
|
17
|
+
|
|
18
|
+
return (_targetRef$current = targetRef.current) === null || _targetRef$current === void 0 ? void 0 : _targetRef$current.contains(ev === null || ev === void 0 ? void 0 : ev.target);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (!(clickedElements !== null && clickedElements !== void 0 && clickedElements.length)) {
|
|
22
|
+
handleClickAway(ev);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
document.addEventListener(eventTypeId, fnClickAway);
|
|
27
|
+
return function cleanup() {
|
|
28
|
+
document.removeEventListener(eventTypeId, fnClickAway);
|
|
29
|
+
};
|
|
30
|
+
}, [handleClickAway, eventTypeId]);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface ClickAwayWrapperProps {
|
|
3
|
-
children: React.ReactNode;
|
|
4
|
-
handleClickAway: (ev: CustomEvent) => void;
|
|
5
|
-
eventTypeId?: "mousedown" | "click";
|
|
6
|
-
targets: React.RefObject<HTMLElement>[];
|
|
7
|
-
}
|
|
8
|
-
declare const ClickAwayWrapper: {
|
|
9
|
-
({ children, handleClickAway, eventTypeId, targets, }: ClickAwayWrapperProps): JSX.Element;
|
|
10
|
-
displayName: string;
|
|
11
|
-
};
|
|
12
|
-
export default ClickAwayWrapper;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
import Events from "../utils/helpers/events";
|
|
4
|
-
|
|
5
|
-
const ClickAwayWrapper = ({
|
|
6
|
-
children,
|
|
7
|
-
handleClickAway,
|
|
8
|
-
eventTypeId = "click",
|
|
9
|
-
targets
|
|
10
|
-
}) => {
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
const fnClickAway = ev => {
|
|
13
|
-
const clickedElements = targets.filter(ref => (ref === null || ref === void 0 ? void 0 : ref.current) && Events.composedPath(ev).includes(ref.current));
|
|
14
|
-
|
|
15
|
-
if (!clickedElements || !clickedElements.length) {
|
|
16
|
-
handleClickAway(ev);
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
document.addEventListener(eventTypeId, fnClickAway);
|
|
21
|
-
return function cleanup() {
|
|
22
|
-
document.removeEventListener(eventTypeId, fnClickAway);
|
|
23
|
-
};
|
|
24
|
-
}, [handleClickAway, targets, eventTypeId]);
|
|
25
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
ClickAwayWrapper.propTypes = {
|
|
29
|
-
"children": PropTypes.node,
|
|
30
|
-
"eventTypeId": PropTypes.oneOf(["click", "mousedown"]),
|
|
31
|
-
"handleClickAway": PropTypes.func.isRequired,
|
|
32
|
-
"targets": PropTypes.arrayOf(PropTypes.shape({
|
|
33
|
-
"current": PropTypes.oneOfType([PropTypes.oneOf([null]), function (props, propName) {
|
|
34
|
-
if (props[propName] == null) {
|
|
35
|
-
return new Error("Prop '" + propName + "' is required but wasn't specified");
|
|
36
|
-
} else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
|
|
37
|
-
return new Error("Expected prop '" + propName + "' to be of type Element");
|
|
38
|
-
}
|
|
39
|
-
}]).isRequired
|
|
40
|
-
})).isRequired
|
|
41
|
-
};
|
|
42
|
-
ClickAwayWrapper.displayName = "ClickAwayWrapper";
|
|
43
|
-
export default ClickAwayWrapper;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "./click-away-wrapper.component";
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface ClickAwayWrapperProps {
|
|
3
|
-
children: React.ReactNode;
|
|
4
|
-
handleClickAway: (ev: CustomEvent) => void;
|
|
5
|
-
eventTypeId?: "mousedown" | "click";
|
|
6
|
-
targets: React.RefObject<HTMLElement>[];
|
|
7
|
-
}
|
|
8
|
-
declare const ClickAwayWrapper: {
|
|
9
|
-
({ children, handleClickAway, eventTypeId, targets, }: ClickAwayWrapperProps): JSX.Element;
|
|
10
|
-
displayName: string;
|
|
11
|
-
};
|
|
12
|
-
export default ClickAwayWrapper;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
|
|
10
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
-
|
|
12
|
-
var _events = _interopRequireDefault(require("../utils/helpers/events"));
|
|
13
|
-
|
|
14
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
|
-
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
17
|
-
|
|
18
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
19
|
-
|
|
20
|
-
const ClickAwayWrapper = ({
|
|
21
|
-
children,
|
|
22
|
-
handleClickAway,
|
|
23
|
-
eventTypeId = "click",
|
|
24
|
-
targets
|
|
25
|
-
}) => {
|
|
26
|
-
(0, _react.useEffect)(() => {
|
|
27
|
-
const fnClickAway = ev => {
|
|
28
|
-
const clickedElements = targets.filter(ref => (ref === null || ref === void 0 ? void 0 : ref.current) && _events.default.composedPath(ev).includes(ref.current));
|
|
29
|
-
|
|
30
|
-
if (!clickedElements || !clickedElements.length) {
|
|
31
|
-
handleClickAway(ev);
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
document.addEventListener(eventTypeId, fnClickAway);
|
|
36
|
-
return function cleanup() {
|
|
37
|
-
document.removeEventListener(eventTypeId, fnClickAway);
|
|
38
|
-
};
|
|
39
|
-
}, [handleClickAway, targets, eventTypeId]);
|
|
40
|
-
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
ClickAwayWrapper.propTypes = {
|
|
44
|
-
"children": _propTypes.default.node,
|
|
45
|
-
"eventTypeId": _propTypes.default.oneOf(["click", "mousedown"]),
|
|
46
|
-
"handleClickAway": _propTypes.default.func.isRequired,
|
|
47
|
-
"targets": _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
48
|
-
"current": _propTypes.default.oneOfType([_propTypes.default.oneOf([null]), function (props, propName) {
|
|
49
|
-
if (props[propName] == null) {
|
|
50
|
-
return new Error("Prop '" + propName + "' is required but wasn't specified");
|
|
51
|
-
} else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
|
|
52
|
-
return new Error("Expected prop '" + propName + "' to be of type Element");
|
|
53
|
-
}
|
|
54
|
-
}]).isRequired
|
|
55
|
-
})).isRequired
|
|
56
|
-
};
|
|
57
|
-
ClickAwayWrapper.displayName = "ClickAwayWrapper";
|
|
58
|
-
var _default = ClickAwayWrapper;
|
|
59
|
-
exports.default = _default;
|