carbon-react 110.0.0 → 110.0.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.
@@ -43,7 +43,6 @@ const DateInput = ({
43
43
  const wrapperRef = useRef();
44
44
  const parentRef = useRef();
45
45
  const inputRef = useRef();
46
- const pickerRef = useRef();
47
46
  const alreadyFocused = useRef(false);
48
47
  const isBlurBlocked = useRef(false);
49
48
  const focusedViaPicker = useRef(false);
@@ -88,6 +87,19 @@ const DateInput = ({
88
87
  return ev;
89
88
  };
90
89
 
90
+ const handleClickAway = () => {
91
+ if (open) {
92
+ alreadyFocused.current = true;
93
+ inputRef.current.focus();
94
+ isBlurBlocked.current = false;
95
+ inputRef.current.blur();
96
+ setOpen(false);
97
+ alreadyFocused.current = false;
98
+ }
99
+ };
100
+
101
+ const handleClickInside = useClickAwayListener(handleClickAway, "mousedown");
102
+
91
103
  const handleChange = ev => {
92
104
  isInitialValue.current = false;
93
105
  onChange(buildCustomEvent(ev));
@@ -194,6 +206,8 @@ const DateInput = ({
194
206
  };
195
207
 
196
208
  const handleMouseDown = ev => {
209
+ handleClickInside(ev);
210
+
197
211
  if (disabled || readOnly) {
198
212
  return;
199
213
  }
@@ -215,8 +229,9 @@ const DateInput = ({
215
229
  handleMouseDown(e);
216
230
  };
217
231
 
218
- const handlePickerMouseDown = () => {
232
+ const handlePickerMouseDown = ev => {
219
233
  isBlurBlocked.current = true;
234
+ handleClickInside(ev);
220
235
  };
221
236
 
222
237
  const assignInput = input => {
@@ -266,18 +281,6 @@ const DateInput = ({
266
281
  return value;
267
282
  };
268
283
 
269
- const handleClickAway = () => {
270
- if (open) {
271
- alreadyFocused.current = true;
272
- inputRef.current.focus();
273
- isBlurBlocked.current = false;
274
- inputRef.current.blur();
275
- setOpen(false);
276
- alreadyFocused.current = false;
277
- }
278
- };
279
-
280
- useClickAwayListener([parentRef, pickerRef], handleClickAway, "mousedown");
281
284
  return /*#__PURE__*/React.createElement(StyledDateInput, _extends({
282
285
  ref: wrapperRef,
283
286
  role: "presentation",
@@ -315,7 +318,6 @@ const DateInput = ({
315
318
  onDayClick: handleDayClick,
316
319
  minDate: minDate,
317
320
  maxDate: maxDate,
318
- ref: pickerRef,
319
321
  pickerMouseDown: handlePickerMouseDown,
320
322
  open: open
321
323
  }));
@@ -39,7 +39,6 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
39
39
  const [submenuOpen, setSubmenuOpen] = useState(false);
40
40
  const [submenuFocusIndex, setSubmenuFocusIndex] = useState(undefined);
41
41
  const [characterString, setCharacterString] = useState("");
42
- const submenuRef = useRef();
43
42
  const formattedChildren = React.Children.map(children, child => {
44
43
  if (child.type === ScrollableBlock) {
45
44
  return [...child.props.children];
@@ -205,15 +204,15 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
205
204
  } // eslint-disable-next-line react-hooks/exhaustive-deps
206
205
 
207
206
  }, [characterString]);
208
- useClickAwayListener([submenuRef], handleClickAway);
207
+ const handleClickInside = useClickAwayListener(handleClickAway);
209
208
 
210
209
  if (inFullscreenView) {
211
210
  return /*#__PURE__*/React.createElement(StyledSubmenuWrapper, {
212
211
  "data-component": "submenu-wrapper",
213
- ref: submenuRef,
214
212
  inFullscreenView: inFullscreenView,
215
213
  menuType: menuContext.menuType,
216
- asPassiveItem: asPassiveItem
214
+ asPassiveItem: asPassiveItem,
215
+ onClick: handleClickInside
217
216
  }, /*#__PURE__*/React.createElement(StyledMenuItemWrapper, _extends({}, rest, {
218
217
  onClick: onClick,
219
218
  className: className,
@@ -243,8 +242,8 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
243
242
  "data-component": "submenu-wrapper",
244
243
  onMouseOver: !clickToOpen ? () => openSubmenu() : undefined,
245
244
  onMouseLeave: () => closeSubmenu(),
246
- ref: submenuRef,
247
- isSubmenuOpen: submenuOpen
245
+ isSubmenuOpen: submenuOpen,
246
+ onClick: handleClickInside
248
247
  }, /*#__PURE__*/React.createElement(StyledMenuItemWrapper, _extends({}, rest, {
249
248
  className: className,
250
249
  menuType: menuContext.menuType,
@@ -115,10 +115,11 @@ const MultiActionButton = ({
115
115
  onKeyDown: handleKeyDown
116
116
  }, childrenWithProps()));
117
117
 
118
- useClickAwayListener([ref], hideButtons);
118
+ const handleClick = useClickAwayListener(hideButtons);
119
119
  return /*#__PURE__*/React.createElement(StyledMultiActionButton, _extends({
120
120
  "aria-haspopup": "true",
121
121
  onMouseLeave: hideButtons,
122
+ onClick: handleClick,
122
123
  ref: ref,
123
124
  "data-component": "multi-action-button",
124
125
  "data-element": dataElement,
@@ -92,7 +92,6 @@ const PopoverContainer = ({
92
92
  }) => {
93
93
  const isControlled = open !== undefined;
94
94
  const [isOpenInternal, setIsOpenInternal] = useState(false);
95
- const ref = useRef(null);
96
95
  const closeButtonRef = useRef(null);
97
96
  const openButtonRef = useRef(null);
98
97
  const guid = useRef(createGuid());
@@ -143,12 +142,12 @@ const PopoverContainer = ({
143
142
  if (onClose) onClose(e);
144
143
  };
145
144
 
146
- useClickAwayListener([ref], handleClickAway, "mousedown");
145
+ const handleClick = useClickAwayListener(handleClickAway, "mousedown");
147
146
  return /*#__PURE__*/React.createElement(PopoverContainerWrapperStyle, {
148
147
  "data-component": "popover-container",
149
148
  role: "region",
150
149
  "aria-labelledby": popoverContainerId,
151
- ref: ref
150
+ onMouseDown: handleClick
152
151
  }, renderOpenComponent(renderOpenComponentProps), /*#__PURE__*/React.createElement(Transition, {
153
152
  in: isOpen,
154
153
  timeout: {
@@ -172,10 +172,11 @@ const SplitButton = ({
172
172
  }, childrenWithProps()));
173
173
  }
174
174
 
175
- useClickAwayListener([splitButtonNode], hideButtons);
175
+ const handleClick = useClickAwayListener(hideButtons);
176
176
  return /*#__PURE__*/React.createElement(StyledSplitButton, _extends({
177
177
  "aria-haspopup": "true",
178
178
  onMouseLeave: hideButtons,
179
+ onClick: handleClick,
179
180
  ref: splitButtonNode
180
181
  }, componentTags(), filterStyledSystemMarginProps(rest)), renderMainButton(), renderAdditionalButtons());
181
182
  };
@@ -1,3 +1,2 @@
1
- import React from "react";
2
- declare const _default: (targets: React.RefObject<HTMLElement>[], handleClickAway: (ev: Event) => void, eventTypeId?: "mousedown" | "click") => void;
1
+ declare const _default: (handleClickAway: (ev: Event) => void, eventTypeId?: "mousedown" | "click") => () => void;
3
2
  export default _default;
@@ -1,23 +1,25 @@
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
- });
1
+ import { useEffect, useRef, useCallback } from "react"; // Needs to also take Portals into account (so can't just check DOM containment), but ideally without using
2
+ // event.stopPropagation() which could have unexpected and frustrating consequences for consumers.
3
+ // Simple approach taken from https://github.com/facebook/react/issues/10962#issuecomment-444622208
12
4
 
13
- if (!(clickedElements !== null && clickedElements !== void 0 && clickedElements.length)) {
14
- handleClickAway(ev);
15
- }
16
- };
5
+ export default ((handleClickAway, eventTypeId = "click") => {
6
+ const clickIsInside = useRef(false);
7
+ const onDocumentClick = useCallback(ev => {
8
+ if (clickIsInside.current) {
9
+ clickIsInside.current = false;
10
+ return;
11
+ }
17
12
 
18
- document.addEventListener(eventTypeId, fnClickAway);
13
+ handleClickAway(ev);
14
+ }, [handleClickAway]);
15
+ const onInsideClick = useCallback(() => {
16
+ clickIsInside.current = true;
17
+ }, []);
18
+ useEffect(() => {
19
+ document.addEventListener(eventTypeId, onDocumentClick);
19
20
  return function cleanup() {
20
- document.removeEventListener(eventTypeId, fnClickAway);
21
+ document.removeEventListener(eventTypeId, onDocumentClick);
21
22
  };
22
- }, [handleClickAway, eventTypeId]);
23
+ }, [onDocumentClick, eventTypeId]);
24
+ return onInsideClick;
23
25
  });
@@ -69,7 +69,6 @@ const DateInput = ({
69
69
  const wrapperRef = (0, _react.useRef)();
70
70
  const parentRef = (0, _react.useRef)();
71
71
  const inputRef = (0, _react.useRef)();
72
- const pickerRef = (0, _react.useRef)();
73
72
  const alreadyFocused = (0, _react.useRef)(false);
74
73
  const isBlurBlocked = (0, _react.useRef)(false);
75
74
  const focusedViaPicker = (0, _react.useRef)(false);
@@ -114,6 +113,19 @@ const DateInput = ({
114
113
  return ev;
115
114
  };
116
115
 
116
+ const handleClickAway = () => {
117
+ if (open) {
118
+ alreadyFocused.current = true;
119
+ inputRef.current.focus();
120
+ isBlurBlocked.current = false;
121
+ inputRef.current.blur();
122
+ setOpen(false);
123
+ alreadyFocused.current = false;
124
+ }
125
+ };
126
+
127
+ const handleClickInside = (0, _useClickAwayListener.default)(handleClickAway, "mousedown");
128
+
117
129
  const handleChange = ev => {
118
130
  isInitialValue.current = false;
119
131
  onChange(buildCustomEvent(ev));
@@ -220,6 +232,8 @@ const DateInput = ({
220
232
  };
221
233
 
222
234
  const handleMouseDown = ev => {
235
+ handleClickInside(ev);
236
+
223
237
  if (disabled || readOnly) {
224
238
  return;
225
239
  }
@@ -241,8 +255,9 @@ const DateInput = ({
241
255
  handleMouseDown(e);
242
256
  };
243
257
 
244
- const handlePickerMouseDown = () => {
258
+ const handlePickerMouseDown = ev => {
245
259
  isBlurBlocked.current = true;
260
+ handleClickInside(ev);
246
261
  };
247
262
 
248
263
  const assignInput = input => {
@@ -292,18 +307,6 @@ const DateInput = ({
292
307
  return value;
293
308
  };
294
309
 
295
- const handleClickAway = () => {
296
- if (open) {
297
- alreadyFocused.current = true;
298
- inputRef.current.focus();
299
- isBlurBlocked.current = false;
300
- inputRef.current.blur();
301
- setOpen(false);
302
- alreadyFocused.current = false;
303
- }
304
- };
305
-
306
- (0, _useClickAwayListener.default)([parentRef, pickerRef], handleClickAway, "mousedown");
307
310
  return /*#__PURE__*/_react.default.createElement(_date.default, _extends({
308
311
  ref: wrapperRef,
309
312
  role: "presentation",
@@ -341,7 +344,6 @@ const DateInput = ({
341
344
  onDayClick: handleDayClick,
342
345
  minDate: minDate,
343
346
  maxDate: maxDate,
344
- ref: pickerRef,
345
347
  pickerMouseDown: handlePickerMouseDown,
346
348
  open: open
347
349
  }));
@@ -63,7 +63,6 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
63
63
  const [submenuOpen, setSubmenuOpen] = (0, _react.useState)(false);
64
64
  const [submenuFocusIndex, setSubmenuFocusIndex] = (0, _react.useState)(undefined);
65
65
  const [characterString, setCharacterString] = (0, _react.useState)("");
66
- const submenuRef = (0, _react.useRef)();
67
66
 
68
67
  const formattedChildren = _react.default.Children.map(children, child => {
69
68
  if (child.type === _scrollableBlock.default) {
@@ -232,15 +231,15 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
232
231
  } // eslint-disable-next-line react-hooks/exhaustive-deps
233
232
 
234
233
  }, [characterString]);
235
- (0, _useClickAwayListener.default)([submenuRef], handleClickAway);
234
+ const handleClickInside = (0, _useClickAwayListener.default)(handleClickAway);
236
235
 
237
236
  if (inFullscreenView) {
238
237
  return /*#__PURE__*/_react.default.createElement(_submenu.StyledSubmenuWrapper, {
239
238
  "data-component": "submenu-wrapper",
240
- ref: submenuRef,
241
239
  inFullscreenView: inFullscreenView,
242
240
  menuType: menuContext.menuType,
243
- asPassiveItem: asPassiveItem
241
+ asPassiveItem: asPassiveItem,
242
+ onClick: handleClickInside
244
243
  }, /*#__PURE__*/_react.default.createElement(_menuItem.default, _extends({}, rest, {
245
244
  onClick: onClick,
246
245
  className: className,
@@ -270,8 +269,8 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
270
269
  "data-component": "submenu-wrapper",
271
270
  onMouseOver: !clickToOpen ? () => openSubmenu() : undefined,
272
271
  onMouseLeave: () => closeSubmenu(),
273
- ref: submenuRef,
274
- isSubmenuOpen: submenuOpen
272
+ isSubmenuOpen: submenuOpen,
273
+ onClick: handleClickInside
275
274
  }, /*#__PURE__*/_react.default.createElement(_menuItem.default, _extends({}, rest, {
276
275
  className: className,
277
276
  menuType: menuContext.menuType,
@@ -136,10 +136,11 @@ const MultiActionButton = ({
136
136
  onKeyDown: handleKeyDown
137
137
  }, childrenWithProps()));
138
138
 
139
- (0, _useClickAwayListener.default)([ref], hideButtons);
139
+ const handleClick = (0, _useClickAwayListener.default)(hideButtons);
140
140
  return /*#__PURE__*/_react.default.createElement(_multiActionButton.StyledMultiActionButton, _extends({
141
141
  "aria-haspopup": "true",
142
142
  onMouseLeave: hideButtons,
143
+ onClick: handleClick,
143
144
  ref: ref,
144
145
  "data-component": "multi-action-button",
145
146
  "data-element": dataElement,
@@ -113,7 +113,6 @@ const PopoverContainer = ({
113
113
  }) => {
114
114
  const isControlled = open !== undefined;
115
115
  const [isOpenInternal, setIsOpenInternal] = (0, _react.useState)(false);
116
- const ref = (0, _react.useRef)(null);
117
116
  const closeButtonRef = (0, _react.useRef)(null);
118
117
  const openButtonRef = (0, _react.useRef)(null);
119
118
  const guid = (0, _react.useRef)((0, _guid.default)());
@@ -164,12 +163,12 @@ const PopoverContainer = ({
164
163
  if (onClose) onClose(e);
165
164
  };
166
165
 
167
- (0, _useClickAwayListener.default)([ref], handleClickAway, "mousedown");
166
+ const handleClick = (0, _useClickAwayListener.default)(handleClickAway, "mousedown");
168
167
  return /*#__PURE__*/_react.default.createElement(_popoverContainer.PopoverContainerWrapperStyle, {
169
168
  "data-component": "popover-container",
170
169
  role: "region",
171
170
  "aria-labelledby": popoverContainerId,
172
- ref: ref
171
+ onMouseDown: handleClick
173
172
  }, renderOpenComponent(renderOpenComponentProps), /*#__PURE__*/_react.default.createElement(_reactTransitionGroup.Transition, {
174
173
  in: isOpen,
175
174
  timeout: {
@@ -201,10 +201,11 @@ const SplitButton = ({
201
201
  }, childrenWithProps()));
202
202
  }
203
203
 
204
- (0, _useClickAwayListener.default)([splitButtonNode], hideButtons);
204
+ const handleClick = (0, _useClickAwayListener.default)(hideButtons);
205
205
  return /*#__PURE__*/_react.default.createElement(_splitButton.default, _extends({
206
206
  "aria-haspopup": "true",
207
207
  onMouseLeave: hideButtons,
208
+ onClick: handleClick,
208
209
  ref: splitButtonNode
209
210
  }, componentTags(), (0, _utils.filterStyledSystemMarginProps)(rest)), renderMainButton(), renderAdditionalButtons());
210
211
  };
@@ -1,3 +1,2 @@
1
- import React from "react";
2
- declare const _default: (targets: React.RefObject<HTMLElement>[], handleClickAway: (ev: Event) => void, eventTypeId?: "mousedown" | "click") => void;
1
+ declare const _default: (handleClickAway: (ev: Event) => void, eventTypeId?: "mousedown" | "click") => () => void;
3
2
  export default _default;
@@ -7,27 +7,29 @@ exports.default = void 0;
7
7
 
8
8
  var _react = require("react");
9
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
- });
10
+ // Needs to also take Portals into account (so can't just check DOM containment), but ideally without using
11
+ // event.stopPropagation() which could have unexpected and frustrating consequences for consumers.
12
+ // Simple approach taken from https://github.com/facebook/react/issues/10962#issuecomment-444622208
13
+ var _default = (handleClickAway, eventTypeId = "click") => {
14
+ const clickIsInside = (0, _react.useRef)(false);
15
+ const onDocumentClick = (0, _react.useCallback)(ev => {
16
+ if (clickIsInside.current) {
17
+ clickIsInside.current = false;
18
+ return;
19
+ }
20
20
 
21
- if (!(clickedElements !== null && clickedElements !== void 0 && clickedElements.length)) {
22
- handleClickAway(ev);
23
- }
24
- };
25
-
26
- document.addEventListener(eventTypeId, fnClickAway);
21
+ handleClickAway(ev);
22
+ }, [handleClickAway]);
23
+ const onInsideClick = (0, _react.useCallback)(() => {
24
+ clickIsInside.current = true;
25
+ }, []);
26
+ (0, _react.useEffect)(() => {
27
+ document.addEventListener(eventTypeId, onDocumentClick);
27
28
  return function cleanup() {
28
- document.removeEventListener(eventTypeId, fnClickAway);
29
+ document.removeEventListener(eventTypeId, onDocumentClick);
29
30
  };
30
- }, [handleClickAway, eventTypeId]);
31
+ }, [onDocumentClick, eventTypeId]);
32
+ return onInsideClick;
31
33
  };
32
34
 
33
35
  exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "110.0.0",
3
+ "version": "110.0.1",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "engineStrict": true,
6
6
  "engines": {