@rc-component/select 1.5.0 → 1.5.2

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.
@@ -135,7 +135,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
135
135
  // ============================== Open ==============================
136
136
  // Not trigger `open` when `notFoundContent` is empty
137
137
  const emptyListContent = !notFoundContent && emptyOptions;
138
- const [mergedOpen, triggerOpen] = useOpen(defaultOpen || false, open, onPopupVisibleChange, nextOpen => disabled || emptyListContent ? false : nextOpen);
138
+ const [mergedOpen, triggerOpen, lockOptions] = useOpen(defaultOpen || false, open, onPopupVisibleChange, nextOpen => disabled || emptyListContent ? false : nextOpen);
139
139
 
140
140
  // ============================= Search =============================
141
141
  const tokenWithEnter = React.useMemo(() => (tokenSeparators || []).some(tokenSeparator => ['\n', '\r\n'].includes(tokenSeparator)), [tokenSeparators]);
@@ -379,8 +379,9 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
379
379
  toggleOpen: triggerOpen,
380
380
  showScrollBar,
381
381
  styles,
382
- classNames
383
- }), [props, notFoundContent, triggerOpen, id, showSearch, multiple, mergedOpen, showScrollBar, styles, classNames]);
382
+ classNames,
383
+ lockOptions
384
+ }), [props, notFoundContent, triggerOpen, id, showSearch, multiple, mergedOpen, showScrollBar, styles, classNames, lockOptions]);
384
385
 
385
386
  // ==================================================================
386
387
  // == Render ==
package/es/OptionList.js CHANGED
@@ -34,7 +34,8 @@ const OptionList = (_, ref) => {
34
34
  toggleOpen,
35
35
  notFoundContent,
36
36
  onPopupScroll,
37
- showScrollBar
37
+ showScrollBar,
38
+ lockOptions
38
39
  } = useBaseProps();
39
40
  const {
40
41
  maxCount,
@@ -54,7 +55,7 @@ const OptionList = (_, ref) => {
54
55
  styles: contextStyles
55
56
  } = React.useContext(SelectContext);
56
57
  const itemPrefixCls = `${prefixCls}-item`;
57
- const memoFlattenOptions = useMemo(() => flattenOptions, [open, flattenOptions], (prev, next) => next[0] && prev[1] !== next[1]);
58
+ const memoFlattenOptions = useMemo(() => flattenOptions, [open, lockOptions], (prev, next) => next[0] && !next[1]);
58
59
 
59
60
  // =========================== List ===========================
60
61
  const listRef = React.useRef(null);
@@ -138,7 +138,7 @@ export default /*#__PURE__*/React.forwardRef(function MultipleContent({
138
138
  prefixCls: `${prefixCls}-content`,
139
139
  className: classNames?.content,
140
140
  style: styles?.content,
141
- prefix: !displayValues.length && (!searchValue || !triggerOpen) ? /*#__PURE__*/React.createElement(Placeholder, null) : null,
141
+ prefix: !displayValues.length && !inputValue && /*#__PURE__*/React.createElement(Placeholder, null),
142
142
  data: displayValues,
143
143
  renderItem: renderItem,
144
144
  renderRest: renderRest,
@@ -42,9 +42,9 @@ const SingleContent = /*#__PURE__*/React.forwardRef(({
42
42
  const optionProps = React.useMemo(() => {
43
43
  const restProps = {
44
44
  className: `${prefixCls}-content-value`,
45
- style: {
46
- visibility: mergedSearchValue ? 'hidden' : 'visible'
47
- }
45
+ style: mergedSearchValue ? {
46
+ visibility: 'hidden'
47
+ } : {}
48
48
  };
49
49
  if (displayValue && selectContext?.flattenOptions) {
50
50
  const option = selectContext.flattenOptions.find(opt => opt.value === displayValue.value);
@@ -8,6 +8,7 @@ export interface BaseSelectContextProps extends BaseSelectProps {
8
8
  triggerOpen: boolean;
9
9
  multiple: boolean;
10
10
  toggleOpen: (open?: boolean) => void;
11
+ lockOptions: boolean;
11
12
  }
12
13
  export declare const BaseSelectContext: React.Context<BaseSelectContextProps>;
13
14
  export default function useBaseProps(): BaseSelectContextProps;
@@ -15,4 +15,4 @@ export type TriggerOpenType = (nextOpen?: boolean, config?: {
15
15
  * SSR handling: During SSR, `open` is always false to avoid Portal issues.
16
16
  * On client-side hydration, it syncs with the actual open state.
17
17
  */
18
- export default function useOpen(defaultOpen: boolean, propOpen: boolean, onOpen: (nextOpen: boolean) => void, postOpen: (nextOpen: boolean) => boolean): [boolean, TriggerOpenType];
18
+ export default function useOpen(defaultOpen: boolean, propOpen: boolean, onOpen: (nextOpen: boolean) => void, postOpen: (nextOpen: boolean) => boolean): [open: boolean, toggleOpen: TriggerOpenType, lockOptions: boolean];
@@ -37,6 +37,9 @@ export default function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
37
37
  }, []);
38
38
  const [stateOpen, internalSetOpen] = useControlledState(defaultOpen, propOpen);
39
39
 
40
+ // Lock for options update
41
+ const [lock, setLock] = useState(false);
42
+
40
43
  // During SSR, always return false for open state
41
44
  const ssrSafeOpen = rendered ? stateOpen : false;
42
45
  const mergedOpen = postOpen(ssrSafeOpen);
@@ -54,6 +57,7 @@ export default function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
54
57
  taskIdRef.current += 1;
55
58
  const id = taskIdRef.current;
56
59
  const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen;
60
+ setLock(!nextOpenVal);
57
61
  function triggerUpdate() {
58
62
  if (
59
63
  // Always check if id is match
@@ -61,6 +65,7 @@ export default function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
61
65
  // Check if need to cancel
62
66
  !cancelFun?.()) {
63
67
  triggerEvent(nextOpenVal);
68
+ setLock(false);
64
69
  }
65
70
  }
66
71
 
@@ -73,5 +78,5 @@ export default function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
73
78
  });
74
79
  }
75
80
  });
76
- return [mergedOpen, toggleOpen];
81
+ return [mergedOpen, toggleOpen, lock];
77
82
  }
@@ -144,7 +144,7 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
144
144
  // ============================== Open ==============================
145
145
  // Not trigger `open` when `notFoundContent` is empty
146
146
  const emptyListContent = !notFoundContent && emptyOptions;
147
- const [mergedOpen, triggerOpen] = (0, _useOpen.default)(defaultOpen || false, open, onPopupVisibleChange, nextOpen => disabled || emptyListContent ? false : nextOpen);
147
+ const [mergedOpen, triggerOpen, lockOptions] = (0, _useOpen.default)(defaultOpen || false, open, onPopupVisibleChange, nextOpen => disabled || emptyListContent ? false : nextOpen);
148
148
 
149
149
  // ============================= Search =============================
150
150
  const tokenWithEnter = React.useMemo(() => (tokenSeparators || []).some(tokenSeparator => ['\n', '\r\n'].includes(tokenSeparator)), [tokenSeparators]);
@@ -388,8 +388,9 @@ const BaseSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
388
388
  toggleOpen: triggerOpen,
389
389
  showScrollBar,
390
390
  styles,
391
- classNames
392
- }), [props, notFoundContent, triggerOpen, id, showSearch, multiple, mergedOpen, showScrollBar, styles, classNames]);
391
+ classNames,
392
+ lockOptions
393
+ }), [props, notFoundContent, triggerOpen, id, showSearch, multiple, mergedOpen, showScrollBar, styles, classNames, lockOptions]);
393
394
 
394
395
  // ==================================================================
395
396
  // == Render ==
package/lib/OptionList.js CHANGED
@@ -42,7 +42,8 @@ const OptionList = (_, ref) => {
42
42
  toggleOpen,
43
43
  notFoundContent,
44
44
  onPopupScroll,
45
- showScrollBar
45
+ showScrollBar,
46
+ lockOptions
46
47
  } = (0, _useBaseProps.default)();
47
48
  const {
48
49
  maxCount,
@@ -62,7 +63,7 @@ const OptionList = (_, ref) => {
62
63
  styles: contextStyles
63
64
  } = React.useContext(_SelectContext.default);
64
65
  const itemPrefixCls = `${prefixCls}-item`;
65
- const memoFlattenOptions = (0, _useMemo.default)(() => flattenOptions, [open, flattenOptions], (prev, next) => next[0] && prev[1] !== next[1]);
66
+ const memoFlattenOptions = (0, _useMemo.default)(() => flattenOptions, [open, lockOptions], (prev, next) => next[0] && !next[1]);
66
67
 
67
68
  // =========================== List ===========================
68
69
  const listRef = React.useRef(null);
@@ -147,7 +147,7 @@ var _default = exports.default = /*#__PURE__*/React.forwardRef(function Multiple
147
147
  prefixCls: `${prefixCls}-content`,
148
148
  className: classNames?.content,
149
149
  style: styles?.content,
150
- prefix: !displayValues.length && (!searchValue || !triggerOpen) ? /*#__PURE__*/React.createElement(_Placeholder.default, null) : null,
150
+ prefix: !displayValues.length && !inputValue && /*#__PURE__*/React.createElement(_Placeholder.default, null),
151
151
  data: displayValues,
152
152
  renderItem: renderItem,
153
153
  renderRest: renderRest,
@@ -51,9 +51,9 @@ const SingleContent = /*#__PURE__*/React.forwardRef(({
51
51
  const optionProps = React.useMemo(() => {
52
52
  const restProps = {
53
53
  className: `${prefixCls}-content-value`,
54
- style: {
55
- visibility: mergedSearchValue ? 'hidden' : 'visible'
56
- }
54
+ style: mergedSearchValue ? {
55
+ visibility: 'hidden'
56
+ } : {}
57
57
  };
58
58
  if (displayValue && selectContext?.flattenOptions) {
59
59
  const option = selectContext.flattenOptions.find(opt => opt.value === displayValue.value);
@@ -8,6 +8,7 @@ export interface BaseSelectContextProps extends BaseSelectProps {
8
8
  triggerOpen: boolean;
9
9
  multiple: boolean;
10
10
  toggleOpen: (open?: boolean) => void;
11
+ lockOptions: boolean;
11
12
  }
12
13
  export declare const BaseSelectContext: React.Context<BaseSelectContextProps>;
13
14
  export default function useBaseProps(): BaseSelectContextProps;
@@ -15,4 +15,4 @@ export type TriggerOpenType = (nextOpen?: boolean, config?: {
15
15
  * SSR handling: During SSR, `open` is always false to avoid Portal issues.
16
16
  * On client-side hydration, it syncs with the actual open state.
17
17
  */
18
- export default function useOpen(defaultOpen: boolean, propOpen: boolean, onOpen: (nextOpen: boolean) => void, postOpen: (nextOpen: boolean) => boolean): [boolean, TriggerOpenType];
18
+ export default function useOpen(defaultOpen: boolean, propOpen: boolean, onOpen: (nextOpen: boolean) => void, postOpen: (nextOpen: boolean) => boolean): [open: boolean, toggleOpen: TriggerOpenType, lockOptions: boolean];
@@ -44,6 +44,9 @@ function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
44
44
  }, []);
45
45
  const [stateOpen, internalSetOpen] = (0, _util.useControlledState)(defaultOpen, propOpen);
46
46
 
47
+ // Lock for options update
48
+ const [lock, setLock] = (0, _react.useState)(false);
49
+
47
50
  // During SSR, always return false for open state
48
51
  const ssrSafeOpen = rendered ? stateOpen : false;
49
52
  const mergedOpen = postOpen(ssrSafeOpen);
@@ -61,6 +64,7 @@ function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
61
64
  taskIdRef.current += 1;
62
65
  const id = taskIdRef.current;
63
66
  const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen;
67
+ setLock(!nextOpenVal);
64
68
  function triggerUpdate() {
65
69
  if (
66
70
  // Always check if id is match
@@ -68,6 +72,7 @@ function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
68
72
  // Check if need to cancel
69
73
  !cancelFun?.()) {
70
74
  triggerEvent(nextOpenVal);
75
+ setLock(false);
71
76
  }
72
77
  }
73
78
 
@@ -80,5 +85,5 @@ function useOpen(defaultOpen, propOpen, onOpen, postOpen) {
80
85
  });
81
86
  }
82
87
  });
83
- return [mergedOpen, toggleOpen];
88
+ return [mergedOpen, toggleOpen, lock];
84
89
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rc-component/select",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "React Select",
5
5
  "engines": {
6
6
  "node": ">=8.x"