@rc-component/select 1.2.4 → 1.2.6

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.
@@ -5,7 +5,7 @@ import * as React from 'react';
5
5
  import { useAllowClear } from "../hooks/useAllowClear";
6
6
  import { BaseSelectContext } from "../hooks/useBaseProps";
7
7
  import useLock from "../hooks/useLock";
8
- import useSelectTriggerControl from "../hooks/useSelectTriggerControl";
8
+ import useSelectTriggerControl, { isInside } from "../hooks/useSelectTriggerControl";
9
9
  import SelectTrigger from "../SelectTrigger";
10
10
  import { getSeparatedContent, isValidCount } from "../utils/valueUtil";
11
11
  import Polite from "./Polite";
@@ -288,6 +288,12 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
288
288
  keyLockRef.current = false;
289
289
  };
290
290
 
291
+ // ========================== Focus / Blur ==========================
292
+ const getSelectElements = () => [getDOM(containerRef.current), triggerRef.current?.getPopupElement()];
293
+
294
+ // Close when click on non-select element
295
+ useSelectTriggerControl(getSelectElements, mergedOpen, triggerOpen, !!mergedComponents.root);
296
+
291
297
  // ========================== Focus / Blur ==========================
292
298
  /** Record real focus status */
293
299
  // const focusRef = React.useRef<boolean>(false);
@@ -302,6 +308,14 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
302
308
  onFocus?.(event);
303
309
  }
304
310
  };
311
+ const onRootBlur = () => {
312
+ // Delay close should check the activeElement
313
+ if (mergedOpen) {
314
+ triggerOpen(false, {
315
+ cancelFun: () => isInside(getSelectElements(), document.activeElement)
316
+ });
317
+ }
318
+ };
305
319
  const onInternalBlur = event => {
306
320
  setFocused(false);
307
321
  if (mergedSearchValue) {
@@ -317,11 +331,12 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
317
331
  });
318
332
  }
319
333
  }
334
+ onRootBlur();
320
335
  if (!disabled) {
321
336
  onBlur?.(event);
322
337
  }
323
338
  };
324
- const onInternalMouseDown = (event, ...restArgs) => {
339
+ const onRootMouseDown = (event, ...restArgs) => {
325
340
  const {
326
341
  target
327
342
  } = event;
@@ -330,9 +345,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
330
345
  // We should give focus back to selector if clicked item is not focusable
331
346
  if (popupElement?.contains(target) && triggerOpen) {
332
347
  // Tell `open` not to close since it's safe in the popup
333
- triggerOpen(true, {
334
- ignoreNext: true
335
- });
348
+ triggerOpen(true);
336
349
  }
337
350
  onMouseDown?.(event, ...restArgs);
338
351
  };
@@ -352,9 +365,6 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
352
365
  };
353
366
  }
354
367
 
355
- // Close when click on non-select element
356
- useSelectTriggerControl(() => [getDOM(containerRef.current), triggerRef.current?.getPopupElement()], mergedOpen, triggerOpen, !!mergedComponents.root);
357
-
358
368
  // ============================ Context =============================
359
369
  const baseSelectContext = React.useMemo(() => ({
360
370
  ...props,
@@ -463,7 +473,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
463
473
  tokenWithEnter: tokenWithEnter
464
474
  // Open
465
475
  ,
466
- onMouseDown: onInternalMouseDown
476
+ onMouseDown: onRootMouseDown
467
477
  // Components
468
478
  ,
469
479
  components: mergedComponents
@@ -488,7 +498,8 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
488
498
  empty: emptyOptions,
489
499
  onPopupVisibleChange: onTriggerVisibleChange,
490
500
  onPopupMouseEnter: onPopupMouseEnter,
491
- onPopupMouseDown: onInternalMouseDown
501
+ onPopupMouseDown: onRootMouseDown,
502
+ onPopupBlur: onRootBlur
492
503
  }, renderNode);
493
504
  return /*#__PURE__*/React.createElement(BaseSelectContext.Provider, {
494
505
  value: baseSelectContext
@@ -10,7 +10,6 @@ import { isValidateOpenKey } from "../utils/keyUtil";
10
10
  import { clsx } from 'clsx';
11
11
  import { getDOM } from "@rc-component/util/es/Dom/findDOMNode";
12
12
  import { composeRef } from "@rc-component/util/es/ref";
13
- import { macroTask } from "../hooks/useOpen";
14
13
  const DEFAULT_OMIT_PROPS = ['value', 'onChange', 'removeIcon', 'placeholder', 'maxTagCount', 'maxTagTextLength', 'maxTagPlaceholder', 'choiceTransitionName', 'onInputKeyDown', 'onPopupScroll', 'tabIndex', 'activeValue', 'onSelectorRemove', 'focused'];
15
14
  export default /*#__PURE__*/React.forwardRef(function SelectInput(props, ref) {
16
15
  const {
@@ -38,7 +37,6 @@ export default /*#__PURE__*/React.forwardRef(function SelectInput(props, ref) {
38
37
  autoFocus,
39
38
  // Events
40
39
  onMouseDown,
41
- onBlur,
42
40
  onClearMouseDown,
43
41
  onInputKeyDown,
44
42
  onSelectorRemove,
@@ -107,12 +105,13 @@ export default /*#__PURE__*/React.forwardRef(function SelectInput(props, ref) {
107
105
  // ====================== Open ======================
108
106
  const onInternalMouseDown = useEvent(event => {
109
107
  if (!disabled) {
108
+ const inputDOM = getDOM(inputRef.current);
109
+
110
110
  // https://github.com/ant-design/ant-design/issues/56002
111
111
  // Tell `useSelectTriggerControl` to ignore this event
112
112
  // When icon is dynamic render, the parentNode will miss
113
113
  // so we need to mark the event directly
114
- event.nativeEvent._ignore_global_close = true;
115
- const inputDOM = getDOM(inputRef.current);
114
+ event.nativeEvent._ori_target = inputDOM;
116
115
  if (inputDOM && event.target !== inputDOM && !inputDOM.contains(event.target)) {
117
116
  event.preventDefault();
118
117
  }
@@ -134,15 +133,6 @@ export default /*#__PURE__*/React.forwardRef(function SelectInput(props, ref) {
134
133
  }
135
134
  onMouseDown?.(event);
136
135
  });
137
- const onInternalBlur = event => {
138
- macroTask(() => {
139
- const inputNode = getDOM(inputRef.current);
140
- if (!inputNode || inputNode !== document.activeElement && !inputNode.contains(document.activeElement)) {
141
- toggleOpen(false);
142
- }
143
- });
144
- onBlur?.(event);
145
- };
146
136
 
147
137
  // =================== Components ===================
148
138
  const {
@@ -177,8 +167,7 @@ export default /*#__PURE__*/React.forwardRef(function SelectInput(props, ref) {
177
167
  style: style
178
168
  // Mouse Events
179
169
  ,
180
- onMouseDown: onInternalMouseDown,
181
- onBlur: onInternalBlur
170
+ onMouseDown: onInternalMouseDown
182
171
  }), /*#__PURE__*/React.createElement(Affix, {
183
172
  className: clsx(`${prefixCls}-prefix`, classNames?.prefix),
184
173
  style: styles?.prefix
@@ -25,6 +25,7 @@ export interface SelectTriggerProps {
25
25
  onPopupVisibleChange?: (visible: boolean) => void;
26
26
  onPopupMouseEnter: () => void;
27
27
  onPopupMouseDown: React.MouseEventHandler<HTMLDivElement>;
28
+ onPopupBlur?: React.FocusEventHandler<HTMLDivElement>;
28
29
  }
29
30
  declare const RefSelectTrigger: React.ForwardRefExoticComponent<SelectTriggerProps & React.RefAttributes<RefTriggerProps>>;
30
31
  export default RefSelectTrigger;
@@ -66,6 +66,7 @@ const SelectTrigger = (props, ref) => {
66
66
  onPopupVisibleChange,
67
67
  onPopupMouseEnter,
68
68
  onPopupMouseDown,
69
+ onPopupBlur,
69
70
  ...restProps
70
71
  } = props;
71
72
 
@@ -117,7 +118,8 @@ const SelectTrigger = (props, ref) => {
117
118
  },
118
119
  popup: /*#__PURE__*/React.createElement("div", {
119
120
  onMouseEnter: onPopupMouseEnter,
120
- onMouseDown: onPopupMouseDown
121
+ onMouseDown: onPopupMouseDown,
122
+ onBlur: onPopupBlur
121
123
  }, popupNode),
122
124
  ref: triggerPopupRef,
123
125
  stretch: stretch,
@@ -1,11 +1,10 @@
1
1
  export declare const macroTask: (fn: VoidFunction, times?: number) => void;
2
2
  /**
3
3
  * Trigger by latest open call, if nextOpen is undefined, means toggle.
4
- * ignoreNext will skip next call in the macro task queue.
4
+ * `weak` means this call can be ignored if previous call exists.
5
5
  */
6
6
  export type TriggerOpenType = (nextOpen?: boolean, config?: {
7
- ignoreNext?: boolean;
8
- lazy?: boolean;
7
+ cancelFun?: () => boolean;
9
8
  }) => void;
10
9
  /**
11
10
  * When `open` is controlled, follow the controlled value;
@@ -17,7 +17,7 @@ export const macroTask = (fn, times = 1) => {
17
17
 
18
18
  /**
19
19
  * Trigger by latest open call, if nextOpen is undefined, means toggle.
20
- * ignoreNext will skip next call in the macro task queue.
20
+ * `weak` means this call can be ignored if previous call exists.
21
21
  */
22
22
 
23
23
  /**
@@ -41,7 +41,6 @@ export default function useOpen(propOpen, onOpen, postOpen) {
41
41
  const ssrSafeOpen = rendered ? stateOpen : false;
42
42
  const mergedOpen = postOpen(ssrSafeOpen);
43
43
  const taskIdRef = useRef(0);
44
- const taskLockRef = useRef(false);
45
44
  const triggerEvent = useEvent(nextOpen => {
46
45
  if (onOpen && mergedOpen !== nextOpen) {
47
46
  onOpen(nextOpen);
@@ -50,32 +49,29 @@ export default function useOpen(propOpen, onOpen, postOpen) {
50
49
  });
51
50
  const toggleOpen = useEvent((nextOpen, config = {}) => {
52
51
  const {
53
- ignoreNext = false
52
+ cancelFun
54
53
  } = config;
55
54
  taskIdRef.current += 1;
56
55
  const id = taskIdRef.current;
57
56
  const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen;
58
-
59
- // Since `mergedOpen` is post-processed, we need to check if the value really changed
60
- if (nextOpenVal) {
61
- if (!taskLockRef.current) {
57
+ function triggerUpdate() {
58
+ if (
59
+ // Always check if id is match
60
+ id === taskIdRef.current &&
61
+ // Check if need to cancel
62
+ !cancelFun?.()) {
62
63
  triggerEvent(nextOpenVal);
63
-
64
- // Lock if needed
65
- if (ignoreNext) {
66
- taskLockRef.current = ignoreNext;
67
- macroTask(() => {
68
- taskLockRef.current = false;
69
- }, 2);
70
- }
71
64
  }
72
- return;
73
65
  }
74
- macroTask(() => {
75
- if (id === taskIdRef.current && !taskLockRef.current) {
76
- triggerEvent(nextOpenVal);
77
- }
78
- });
66
+
67
+ // Weak update can be ignored
68
+ if (nextOpenVal) {
69
+ triggerUpdate();
70
+ } else {
71
+ macroTask(() => {
72
+ triggerUpdate();
73
+ });
74
+ }
79
75
  });
80
76
  return [mergedOpen, toggleOpen];
81
77
  }
@@ -1 +1,3 @@
1
- export default function useSelectTriggerControl(elements: () => (HTMLElement | SVGElement | undefined)[], open: boolean, triggerOpen: (open: boolean) => void, customizedTrigger: boolean): void;
1
+ import type { TriggerOpenType } from './useOpen';
2
+ export declare function isInside(elements: (HTMLElement | SVGElement | undefined)[], target: HTMLElement): boolean;
3
+ export default function useSelectTriggerControl(elements: () => (HTMLElement | SVGElement | undefined)[], open: boolean, triggerOpen: TriggerOpenType, customizedTrigger: boolean): void;
@@ -1,5 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { useEvent } from '@rc-component/util';
3
+ export function isInside(elements, target) {
4
+ return elements.filter(element => element).some(element => element.contains(target) || element === target);
5
+ }
3
6
  export default function useSelectTriggerControl(elements, open, triggerOpen, customizedTrigger) {
4
7
  const onGlobalMouseDown = useEvent(event => {
5
8
  // If trigger is customized, Trigger will take control of popupVisible
@@ -10,9 +13,12 @@ export default function useSelectTriggerControl(elements, open, triggerOpen, cus
10
13
  if (target.shadowRoot && event.composed) {
11
14
  target = event.composedPath()[0] || target;
12
15
  }
16
+ if (event._ori_target) {
17
+ target = event._ori_target;
18
+ }
13
19
  if (open &&
14
20
  // Marked by SelectInput mouseDown event
15
- !event._ignore_global_close && elements().filter(element => element).every(element => !element.contains(target) && element !== target)) {
21
+ !isInside(elements(), target)) {
16
22
  // Should trigger close
17
23
  triggerOpen(false);
18
24
  }
@@ -10,7 +10,7 @@ var React = _interopRequireWildcard(require("react"));
10
10
  var _useAllowClear = require("../hooks/useAllowClear");
11
11
  var _useBaseProps = require("../hooks/useBaseProps");
12
12
  var _useLock = _interopRequireDefault(require("../hooks/useLock"));
13
- var _useSelectTriggerControl = _interopRequireDefault(require("../hooks/useSelectTriggerControl"));
13
+ var _useSelectTriggerControl = _interopRequireWildcard(require("../hooks/useSelectTriggerControl"));
14
14
  var _SelectTrigger = _interopRequireDefault(require("../SelectTrigger"));
15
15
  var _valueUtil = require("../utils/valueUtil");
16
16
  var _Polite = _interopRequireDefault(require("./Polite"));
@@ -297,6 +297,12 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
297
297
  keyLockRef.current = false;
298
298
  };
299
299
 
300
+ // ========================== Focus / Blur ==========================
301
+ const getSelectElements = () => [(0, _findDOMNode.getDOM)(containerRef.current), triggerRef.current?.getPopupElement()];
302
+
303
+ // Close when click on non-select element
304
+ (0, _useSelectTriggerControl.default)(getSelectElements, mergedOpen, triggerOpen, !!mergedComponents.root);
305
+
300
306
  // ========================== Focus / Blur ==========================
301
307
  /** Record real focus status */
302
308
  // const focusRef = React.useRef<boolean>(false);
@@ -311,6 +317,14 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
311
317
  onFocus?.(event);
312
318
  }
313
319
  };
320
+ const onRootBlur = () => {
321
+ // Delay close should check the activeElement
322
+ if (mergedOpen) {
323
+ triggerOpen(false, {
324
+ cancelFun: () => (0, _useSelectTriggerControl.isInside)(getSelectElements(), document.activeElement)
325
+ });
326
+ }
327
+ };
314
328
  const onInternalBlur = event => {
315
329
  setFocused(false);
316
330
  if (mergedSearchValue) {
@@ -326,11 +340,12 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
326
340
  });
327
341
  }
328
342
  }
343
+ onRootBlur();
329
344
  if (!disabled) {
330
345
  onBlur?.(event);
331
346
  }
332
347
  };
333
- const onInternalMouseDown = (event, ...restArgs) => {
348
+ const onRootMouseDown = (event, ...restArgs) => {
334
349
  const {
335
350
  target
336
351
  } = event;
@@ -339,9 +354,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
339
354
  // We should give focus back to selector if clicked item is not focusable
340
355
  if (popupElement?.contains(target) && triggerOpen) {
341
356
  // Tell `open` not to close since it's safe in the popup
342
- triggerOpen(true, {
343
- ignoreNext: true
344
- });
357
+ triggerOpen(true);
345
358
  }
346
359
  onMouseDown?.(event, ...restArgs);
347
360
  };
@@ -361,9 +374,6 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
361
374
  };
362
375
  }
363
376
 
364
- // Close when click on non-select element
365
- (0, _useSelectTriggerControl.default)(() => [(0, _findDOMNode.getDOM)(containerRef.current), triggerRef.current?.getPopupElement()], mergedOpen, triggerOpen, !!mergedComponents.root);
366
-
367
377
  // ============================ Context =============================
368
378
  const baseSelectContext = React.useMemo(() => ({
369
379
  ...props,
@@ -472,7 +482,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
472
482
  tokenWithEnter: tokenWithEnter
473
483
  // Open
474
484
  ,
475
- onMouseDown: onInternalMouseDown
485
+ onMouseDown: onRootMouseDown
476
486
  // Components
477
487
  ,
478
488
  components: mergedComponents
@@ -497,7 +507,8 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
497
507
  empty: emptyOptions,
498
508
  onPopupVisibleChange: onTriggerVisibleChange,
499
509
  onPopupMouseEnter: onPopupMouseEnter,
500
- onPopupMouseDown: onInternalMouseDown
510
+ onPopupMouseDown: onRootMouseDown,
511
+ onPopupBlur: onRootBlur
501
512
  }, renderNode);
502
513
  return /*#__PURE__*/React.createElement(_useBaseProps.BaseSelectContext.Provider, {
503
514
  value: baseSelectContext
@@ -15,7 +15,6 @@ var _keyUtil = require("../utils/keyUtil");
15
15
  var _clsx = require("clsx");
16
16
  var _findDOMNode = require("@rc-component/util/lib/Dom/findDOMNode");
17
17
  var _ref = require("@rc-component/util/lib/ref");
18
- var _useOpen = require("../hooks/useOpen");
19
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
19
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
21
20
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -47,7 +46,6 @@ var _default = exports.default = /*#__PURE__*/React.forwardRef(function SelectIn
47
46
  autoFocus,
48
47
  // Events
49
48
  onMouseDown,
50
- onBlur,
51
49
  onClearMouseDown,
52
50
  onInputKeyDown,
53
51
  onSelectorRemove,
@@ -116,12 +114,13 @@ var _default = exports.default = /*#__PURE__*/React.forwardRef(function SelectIn
116
114
  // ====================== Open ======================
117
115
  const onInternalMouseDown = (0, _util.useEvent)(event => {
118
116
  if (!disabled) {
117
+ const inputDOM = (0, _findDOMNode.getDOM)(inputRef.current);
118
+
119
119
  // https://github.com/ant-design/ant-design/issues/56002
120
120
  // Tell `useSelectTriggerControl` to ignore this event
121
121
  // When icon is dynamic render, the parentNode will miss
122
122
  // so we need to mark the event directly
123
- event.nativeEvent._ignore_global_close = true;
124
- const inputDOM = (0, _findDOMNode.getDOM)(inputRef.current);
123
+ event.nativeEvent._ori_target = inputDOM;
125
124
  if (inputDOM && event.target !== inputDOM && !inputDOM.contains(event.target)) {
126
125
  event.preventDefault();
127
126
  }
@@ -143,15 +142,6 @@ var _default = exports.default = /*#__PURE__*/React.forwardRef(function SelectIn
143
142
  }
144
143
  onMouseDown?.(event);
145
144
  });
146
- const onInternalBlur = event => {
147
- (0, _useOpen.macroTask)(() => {
148
- const inputNode = (0, _findDOMNode.getDOM)(inputRef.current);
149
- if (!inputNode || inputNode !== document.activeElement && !inputNode.contains(document.activeElement)) {
150
- toggleOpen(false);
151
- }
152
- });
153
- onBlur?.(event);
154
- };
155
145
 
156
146
  // =================== Components ===================
157
147
  const {
@@ -186,8 +176,7 @@ var _default = exports.default = /*#__PURE__*/React.forwardRef(function SelectIn
186
176
  style: style
187
177
  // Mouse Events
188
178
  ,
189
- onMouseDown: onInternalMouseDown,
190
- onBlur: onInternalBlur
179
+ onMouseDown: onInternalMouseDown
191
180
  }), /*#__PURE__*/React.createElement(_Affix.default, {
192
181
  className: (0, _clsx.clsx)(`${prefixCls}-prefix`, classNames?.prefix),
193
182
  style: styles?.prefix
@@ -25,6 +25,7 @@ export interface SelectTriggerProps {
25
25
  onPopupVisibleChange?: (visible: boolean) => void;
26
26
  onPopupMouseEnter: () => void;
27
27
  onPopupMouseDown: React.MouseEventHandler<HTMLDivElement>;
28
+ onPopupBlur?: React.FocusEventHandler<HTMLDivElement>;
28
29
  }
29
30
  declare const RefSelectTrigger: React.ForwardRefExoticComponent<SelectTriggerProps & React.RefAttributes<RefTriggerProps>>;
30
31
  export default RefSelectTrigger;
@@ -75,6 +75,7 @@ const SelectTrigger = (props, ref) => {
75
75
  onPopupVisibleChange,
76
76
  onPopupMouseEnter,
77
77
  onPopupMouseDown,
78
+ onPopupBlur,
78
79
  ...restProps
79
80
  } = props;
80
81
 
@@ -126,7 +127,8 @@ const SelectTrigger = (props, ref) => {
126
127
  },
127
128
  popup: /*#__PURE__*/React.createElement("div", {
128
129
  onMouseEnter: onPopupMouseEnter,
129
- onMouseDown: onPopupMouseDown
130
+ onMouseDown: onPopupMouseDown,
131
+ onBlur: onPopupBlur
130
132
  }, popupNode),
131
133
  ref: triggerPopupRef,
132
134
  stretch: stretch,
@@ -1,11 +1,10 @@
1
1
  export declare const macroTask: (fn: VoidFunction, times?: number) => void;
2
2
  /**
3
3
  * Trigger by latest open call, if nextOpen is undefined, means toggle.
4
- * ignoreNext will skip next call in the macro task queue.
4
+ * `weak` means this call can be ignored if previous call exists.
5
5
  */
6
6
  export type TriggerOpenType = (nextOpen?: boolean, config?: {
7
- ignoreNext?: boolean;
8
- lazy?: boolean;
7
+ cancelFun?: () => boolean;
9
8
  }) => void;
10
9
  /**
11
10
  * When `open` is controlled, follow the controlled value;
@@ -24,7 +24,7 @@ const macroTask = (fn, times = 1) => {
24
24
 
25
25
  /**
26
26
  * Trigger by latest open call, if nextOpen is undefined, means toggle.
27
- * ignoreNext will skip next call in the macro task queue.
27
+ * `weak` means this call can be ignored if previous call exists.
28
28
  */
29
29
  exports.macroTask = macroTask;
30
30
  /**
@@ -48,7 +48,6 @@ function useOpen(propOpen, onOpen, postOpen) {
48
48
  const ssrSafeOpen = rendered ? stateOpen : false;
49
49
  const mergedOpen = postOpen(ssrSafeOpen);
50
50
  const taskIdRef = (0, _react.useRef)(0);
51
- const taskLockRef = (0, _react.useRef)(false);
52
51
  const triggerEvent = (0, _util.useEvent)(nextOpen => {
53
52
  if (onOpen && mergedOpen !== nextOpen) {
54
53
  onOpen(nextOpen);
@@ -57,32 +56,29 @@ function useOpen(propOpen, onOpen, postOpen) {
57
56
  });
58
57
  const toggleOpen = (0, _util.useEvent)((nextOpen, config = {}) => {
59
58
  const {
60
- ignoreNext = false
59
+ cancelFun
61
60
  } = config;
62
61
  taskIdRef.current += 1;
63
62
  const id = taskIdRef.current;
64
63
  const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen;
65
-
66
- // Since `mergedOpen` is post-processed, we need to check if the value really changed
67
- if (nextOpenVal) {
68
- if (!taskLockRef.current) {
64
+ function triggerUpdate() {
65
+ if (
66
+ // Always check if id is match
67
+ id === taskIdRef.current &&
68
+ // Check if need to cancel
69
+ !cancelFun?.()) {
69
70
  triggerEvent(nextOpenVal);
70
-
71
- // Lock if needed
72
- if (ignoreNext) {
73
- taskLockRef.current = ignoreNext;
74
- macroTask(() => {
75
- taskLockRef.current = false;
76
- }, 2);
77
- }
78
71
  }
79
- return;
80
72
  }
81
- macroTask(() => {
82
- if (id === taskIdRef.current && !taskLockRef.current) {
83
- triggerEvent(nextOpenVal);
84
- }
85
- });
73
+
74
+ // Weak update can be ignored
75
+ if (nextOpenVal) {
76
+ triggerUpdate();
77
+ } else {
78
+ macroTask(() => {
79
+ triggerUpdate();
80
+ });
81
+ }
86
82
  });
87
83
  return [mergedOpen, toggleOpen];
88
84
  }
@@ -1 +1,3 @@
1
- export default function useSelectTriggerControl(elements: () => (HTMLElement | SVGElement | undefined)[], open: boolean, triggerOpen: (open: boolean) => void, customizedTrigger: boolean): void;
1
+ import type { TriggerOpenType } from './useOpen';
2
+ export declare function isInside(elements: (HTMLElement | SVGElement | undefined)[], target: HTMLElement): boolean;
3
+ export default function useSelectTriggerControl(elements: () => (HTMLElement | SVGElement | undefined)[], open: boolean, triggerOpen: TriggerOpenType, customizedTrigger: boolean): void;
@@ -4,10 +4,14 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = useSelectTriggerControl;
7
+ exports.isInside = isInside;
7
8
  var React = _interopRequireWildcard(require("react"));
8
9
  var _util = require("@rc-component/util");
9
10
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
10
11
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
12
+ function isInside(elements, target) {
13
+ return elements.filter(element => element).some(element => element.contains(target) || element === target);
14
+ }
11
15
  function useSelectTriggerControl(elements, open, triggerOpen, customizedTrigger) {
12
16
  const onGlobalMouseDown = (0, _util.useEvent)(event => {
13
17
  // If trigger is customized, Trigger will take control of popupVisible
@@ -18,9 +22,12 @@ function useSelectTriggerControl(elements, open, triggerOpen, customizedTrigger)
18
22
  if (target.shadowRoot && event.composed) {
19
23
  target = event.composedPath()[0] || target;
20
24
  }
25
+ if (event._ori_target) {
26
+ target = event._ori_target;
27
+ }
21
28
  if (open &&
22
29
  // Marked by SelectInput mouseDown event
23
- !event._ignore_global_close && elements().filter(element => element).every(element => !element.contains(target) && element !== target)) {
30
+ !isInside(elements(), target)) {
24
31
  // Should trigger close
25
32
  triggerOpen(false);
26
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rc-component/select",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "React Select",
5
5
  "engines": {
6
6
  "node": ">=8.x"