@apdesign/web-react 1.3.4 → 1.4.0

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.
@@ -2,12 +2,12 @@ import React from 'react';
2
2
  import Group from './group';
3
3
  import { ButtonProps } from './interface';
4
4
  declare const ButtonComponent: React.ForwardRefExoticComponent<Partial<{
5
- htmlType?: "button" | "submit" | "reset";
6
- } & import("./interface").BaseButtonProps & Omit<React.ButtonHTMLAttributes<any>, "className" | "type" | "onClick"> & {
5
+ htmlType?: "button" | "reset" | "submit";
6
+ } & import("./interface").BaseButtonProps & Omit<React.ButtonHTMLAttributes<any>, "className" | "onClick" | "type"> & {
7
7
  href: string;
8
8
  target?: string;
9
9
  anchorProps?: React.HTMLProps<HTMLAnchorElement>;
10
- } & Omit<React.AnchorHTMLAttributes<any>, "className" | "type" | "onClick">> & React.RefAttributes<unknown>> & {
10
+ } & Omit<React.AnchorHTMLAttributes<any>, "className" | "onClick" | "type">> & React.RefAttributes<unknown>> & {
11
11
  __BYTE_BUTTON: boolean;
12
12
  Group: typeof Group;
13
13
  };
@@ -1,6 +1,6 @@
1
1
  import { Dayjs } from 'dayjs';
2
2
  export declare function isTimeArrayChange(prevTime: Dayjs[], nextTime: Dayjs[]): boolean;
3
- export declare function getAvailableDayjsLength(value: any): 1 | 0 | 2;
3
+ export declare function getAvailableDayjsLength(value: any): 0 | 1 | 2;
4
4
  export declare function isDisabledDate(cellDate: any, disabledDate: any, mode: any): boolean;
5
5
  declare type WeekStartType = 0 | 1 | 2 | 3 | 4 | 5 | 6;
6
6
  export declare function getDefaultWeekStart(dayjsLocale: string): WeekStartType;
@@ -6,7 +6,7 @@ export declare type HotkeyInfo = {
6
6
  type: 'sibling' | 'generation' | 'enter';
7
7
  };
8
8
  export declare type ResetHotkeyInfo = (activeKey?: string) => void;
9
- declare const MenuContext: import("react").Context<Pick<MenuProps, "inDropdown" | "theme" | "mode" | "levelIndent" | "icons" | "collapse" | "autoScrollIntoView" | "selectedKeys" | "openKeys" | "scrollConfig" | "triggerProps" | "tooltipProps"> & {
9
+ declare const MenuContext: import("react").Context<Pick<MenuProps, "collapse" | "inDropdown" | "theme" | "mode" | "levelIndent" | "icons" | "autoScrollIntoView" | "selectedKeys" | "openKeys" | "scrollConfig" | "triggerProps" | "tooltipProps"> & {
10
10
  id?: string;
11
11
  prefixCls?: string;
12
12
  onClickMenuItem?: (key: string, event: any) => void;
@@ -52,7 +52,7 @@ import Trigger from '../Trigger';
52
52
  import OptGroup from './opt-group';
53
53
  import Option from './option';
54
54
  import ResizeObserver from '../_util/resizeObserver';
55
- import { isArray, isFunction, isObject } from '../_util/is';
55
+ import { isArray, isFunction, isNullOrUndefined, isObject } from '../_util/is';
56
56
  import getHotkeyHandler from '../_util/getHotkeyHandler';
57
57
  import warning from '../_util/warning';
58
58
  import SelectView from '../_class/select-view';
@@ -146,6 +146,8 @@ function Select(baseProps, ref) {
146
146
  var refPopupExiting = useRef(false);
147
147
  // Unique ID of this select instance
148
148
  var instancePopupID = useId(prefixCls + "-popup-");
149
+ // 添加一个 ref 来跟踪 props.value 的前一个值
150
+ var prevValueRef = useRef(props.value);
149
151
  var isNoOptionSelected = isEmptyValue(value, isMultipleMode);
150
152
  var valueActiveDefault = useMemo(function () {
151
153
  var _a, _b;
@@ -213,6 +215,20 @@ function Select(baseProps, ref) {
213
215
  setProxyValue(value.length === 0 ? undefined : value[0]);
214
216
  }
215
217
  }, [isMultipleMode, value]);
218
+ useEffect(function () {
219
+ if (isMultipleQuickSelectMode) {
220
+ // 判断 props.value 之前有值现在被手动设置为 undefined 或者 []
221
+ var hadValueBefore = !isNullOrUndefined(prevValueRef.current) &&
222
+ !(Array.isArray(prevValueRef.current) && prevValueRef.current.length === 0);
223
+ var isEmptyNow = isNullOrUndefined(props.value) || (Array.isArray(props.value) && props.value.length === 0);
224
+ if (hadValueBefore && isEmptyNow) {
225
+ setValue(getValidValue(props.value, isMultipleMode, labelInValue));
226
+ setProxyValue(getValidValue(props.value, isMultipleMode, labelInValue));
227
+ }
228
+ // 更新 ref 以保存当前值用于下次比较
229
+ prevValueRef.current = props.value;
230
+ }
231
+ }, [props.value, isMultipleQuickSelectMode]);
216
232
  // 选项下拉框显示/隐藏时的一些自动行为
217
233
  useEffect(function () {
218
234
  if (popupVisible) {
package/es/Tree/index.js CHANGED
@@ -106,6 +106,21 @@ import { ConfigContext } from '../ConfigProvider';
106
106
  import { getAllCheckedKeysByCheck, getCheckedKeysByInitKeys, getTreeDataFromTreeChildren, } from './util';
107
107
  import { TreeContext } from './context';
108
108
  import { pickDataAttributes } from '../_util/pick';
109
+ var style = document.createElement('style');
110
+ document.head.appendChild(style);
111
+ // 动态写入 hover 样式
112
+ var rules = [
113
+ ".arco-tree-node:hover .arco-tree-select-extra-QuickSingleSelect-button { display: block !important; }",
114
+ ];
115
+ rules.forEach(function (rule) {
116
+ try {
117
+ var styleSheet = style.sheet;
118
+ style.sheet.insertRule(rule, styleSheet.cssRules.length);
119
+ }
120
+ catch (e) {
121
+ console.error('插入 CSS 规则失败:', rule, e);
122
+ }
123
+ });
109
124
  var DefaultFieldNames = {
110
125
  key: 'key',
111
126
  title: 'title',
@@ -15,5 +15,5 @@ declare const useStateValue: (props: TreeSelectProps, key2nodeProps: KeyCacheTyp
15
15
  trigger?: NodeProps;
16
16
  checked?: boolean;
17
17
  selected?: boolean;
18
- }) => void];
18
+ }) => void, LabelValue[], () => void, () => void];
19
19
  export default useStateValue;
@@ -25,6 +25,15 @@ var __read = (this && this.__read) || function (o, n) {
25
25
  }
26
26
  return ar;
27
27
  };
28
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
29
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
30
+ if (ar || !(i in from)) {
31
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
32
+ ar[i] = from[i];
33
+ }
34
+ }
35
+ return to.concat(ar || Array.prototype.slice.call(from));
36
+ };
28
37
  import { useState, useRef, useCallback } from 'react';
29
38
  import isEqualWith from 'lodash/isEqualWith';
30
39
  import { normalizeValueToArray } from '../utils';
@@ -81,6 +90,8 @@ var getInitCheckKeys = function (keys, key2nodeProps, indeterminateKeys, props)
81
90
  return keys;
82
91
  };
83
92
  var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
93
+ var multiple = props.multiple || props.treeCheckable;
94
+ var isMultipleQuickSelectMode = multiple && props.isQuickSingleSelectMode;
84
95
  var valueCopy = useRef([]);
85
96
  var calcValue = function () {
86
97
  var propsValue = props.value || props.defaultValue || [];
@@ -93,10 +104,18 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
93
104
  return parseValue(propsValue, key2nodeProps);
94
105
  };
95
106
  var _a = __read(useState(calcValue), 2), value = _a[0], _setValue = _a[1];
107
+ // proxyValue 在isMultipleQuickSelectMode时候挡在真实value前面进行展示,真实的value只在确定时候更新。 proxyValue 必须和原有的value行为一致
108
+ var _b = __read(useState(value), 2), proxyValue = _b[0], _setProxyValue = _b[1];
109
+ var proxyValueCopy = useRef(value);
110
+ var stateValue = isMultipleQuickSelectMode ? proxyValue : value;
96
111
  var setValue = function (value) {
97
112
  valueCopy.current = value;
98
113
  _setValue(value);
99
114
  };
115
+ var setProxyValue = function (value) {
116
+ proxyValueCopy.current = value;
117
+ _setProxyValue(value);
118
+ };
100
119
  useUpdate(function () {
101
120
  var nextValue = calcValue();
102
121
  if ('value' in props) {
@@ -104,10 +123,12 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
104
123
  // 以外部传入为准,只比较value
105
124
  if (!isEqualWith(normalizeValueToArray(value), normalizeValueToArray(nextValue))) {
106
125
  setValue(nextValue);
126
+ setProxyValue(nextValue);
107
127
  }
108
128
  }
109
129
  else if (!isEqualWith(value, nextValue)) {
110
130
  setValue(nextValue);
131
+ setProxyValue(nextValue);
111
132
  }
112
133
  }
113
134
  }, [
@@ -117,10 +138,14 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
117
138
  props.value,
118
139
  key2nodeProps,
119
140
  ]);
141
+ var extra = useRef(null);
120
142
  var setStateValue = useCallback(function (newValue, extra) {
121
143
  var onChange = props.onChange, labelInValue = props.labelInValue;
122
144
  var multiple = props.multiple || props.treeCheckable;
123
- if (!('value' in props)) {
145
+ if (isMultipleQuickSelectMode) {
146
+ setProxyValue(newValue);
147
+ }
148
+ if (!('value' in props) && !isMultipleQuickSelectMode) {
124
149
  setValue(newValue);
125
150
  }
126
151
  var tmp;
@@ -132,8 +157,24 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
132
157
  else {
133
158
  tmp = labelInValue ? newValue[0] : newValue[0] && newValue[0].value;
134
159
  }
135
- onChange && onChange(tmp, extra);
160
+ if (isMultipleQuickSelectMode) {
161
+ extra.current = extra;
162
+ }
163
+ else {
164
+ onChange && onChange(tmp, extra);
165
+ }
136
166
  }, [props.onChange, props.labelInValue, props.multiple, props.treeCheckable, props.value]);
137
- return [value, setStateValue];
167
+ var confirmSetValue = function () {
168
+ var onChange = props.onChange, labelInValue = props.labelInValue;
169
+ setValue(__spreadArray([], __read(proxyValueCopy.current), false));
170
+ var tmp = proxyValueCopy.current.map(function (x) {
171
+ return labelInValue ? { label: x.label, value: x.value } : x.value;
172
+ });
173
+ onChange && onChange(tmp, extra.current);
174
+ };
175
+ var cancelSetValue = function () {
176
+ setProxyValue(value);
177
+ };
178
+ return [stateValue, setStateValue, value, confirmSetValue, cancelSetValue];
138
179
  };
139
180
  export default useStateValue;
@@ -19,6 +19,12 @@ export interface TreeSelectProps extends SelectViewCommonProps {
19
19
  * @en Whether to select multiple
20
20
  */
21
21
  multiple?: boolean;
22
+ /**
23
+ * @zh 是否开启快速单选模式。开启后,由于需要最后点击确定或者取消来选择,单个选项变化的事件将无效
24
+ * @en Whether to enable quick single selection mode.
25
+ * @defaultValue true
26
+ */
27
+ isQuickSingleSelectMode?: boolean;
22
28
  /**
23
29
  * @zh 选择框的默认值
24
30
  * @en The key of node selected by default
@@ -7,6 +7,7 @@ interface TreeListProps extends TreeSelectProps {
7
7
  filterNode: TreeProps['filterNode'];
8
8
  inputValue?: string;
9
9
  prefixCls?: string;
10
+ confirmCheck: () => void;
10
11
  }
11
12
  declare const _default: React.ForwardRefExoticComponent<TreeListProps & React.RefAttributes<unknown>>;
12
13
  export default _default;
@@ -34,13 +34,17 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
34
34
  }
35
35
  return to.concat(ar || Array.prototype.slice.call(from));
36
36
  };
37
- import React, { useRef, useCallback, useMemo, useImperativeHandle, forwardRef } from 'react';
37
+ import React, { useRef, useCallback, useMemo, useImperativeHandle, forwardRef, useContext, } from 'react';
38
38
  import Tree from '../Tree';
39
39
  import { isFunction, isString } from '../_util/is';
40
+ import { ConfigContext } from '../ConfigProvider';
40
41
  function TreeList(props, ref) {
41
- var value = props.value, multiple = props.multiple, loadMore = props.loadMore, treeCheckedStrategy = props.treeCheckedStrategy, treeCheckStrictly = props.treeCheckStrictly, treeData = props.treeData, treeProps = props.treeProps, prefixCls = props.prefixCls, treeCheckable = props.treeCheckable;
42
+ var value = props.value, multiple = props.multiple, isQuickSingleSelectMode = props.isQuickSingleSelectMode, loadMore = props.loadMore, treeCheckedStrategy = props.treeCheckedStrategy, treeCheckStrictly = props.treeCheckStrictly, treeData = props.treeData, treeProps = props.treeProps, prefixCls = props.prefixCls, treeCheckable = props.treeCheckable, confirmCheck = props.confirmCheck;
43
+ var locale = useContext(ConfigContext).locale;
42
44
  var propsRenderTitle = treeProps && treeProps.renderTitle;
45
+ var propsRenderExtra = treeProps && treeProps.renderExtra;
43
46
  var treeRef = useRef();
47
+ var isMultipleQuickSelectMode = multiple && isQuickSingleSelectMode;
44
48
  var handleCheck = useCallback(function (keys, _a) {
45
49
  var checkedNodes = _a.checkedNodes, checked = _a.checked, node = _a.node;
46
50
  var newValue = keys.map(function (key) {
@@ -120,6 +124,37 @@ function TreeList(props, ref) {
120
124
  }
121
125
  return title;
122
126
  }, [prefixCls, props.inputValue, propsRenderTitle]);
127
+ var renderExtra = useCallback(function (nodeProps) {
128
+ var _a;
129
+ if (isMultipleQuickSelectMode) {
130
+ if (propsRenderExtra) {
131
+ console.warn('renderExtra is not recommended for use in quick single select mode');
132
+ }
133
+ return (React.createElement(React.Fragment, null,
134
+ React.createElement("span", { className: prefixCls + "-extra-QuickSingleSelect-button", style: {
135
+ position: 'absolute',
136
+ right: 0,
137
+ display: 'none',
138
+ backgroundColor: 'rgb(var(--primary-6))',
139
+ cursor: 'pointer',
140
+ color: 'white',
141
+ padding: '6px',
142
+ fontSize: 12,
143
+ paddingLeft: '20px',
144
+ clipPath: 'polygon(12px 50%, 0% 0%, 100% 0%, 100% 100%, 0% 100%)',
145
+ whiteSpace: 'nowrap',
146
+ }, onClick: function () {
147
+ handleCheck([nodeProps._key], {
148
+ checkedNodes: [],
149
+ checked: true,
150
+ node: { props: nodeProps },
151
+ });
152
+ confirmCheck();
153
+ } }, (_a = locale.Select) === null || _a === void 0 ? void 0 : _a.filterThisItemOnly), propsRenderExtra === null || propsRenderExtra === void 0 ? void 0 :
154
+ propsRenderExtra(nodeProps)));
155
+ }
156
+ return propsRenderExtra === null || propsRenderExtra === void 0 ? void 0 : propsRenderExtra(nodeProps);
157
+ }, [propsRenderExtra, isMultipleQuickSelectMode]);
123
158
  var extraProps = useMemo(function () {
124
159
  return props.treeCheckable
125
160
  ? {
@@ -139,6 +174,6 @@ function TreeList(props, ref) {
139
174
  }, []);
140
175
  return (React.createElement(Tree, __assign({ ref: treeRef, size: props.size, blockNode: true, filterNode: props.filterNode }, treeProps, { checkable: treeCheckable, multiple: multiple, loadMore: props.loadMore ? handleLoadMore : undefined, checkedStrategy: treeCheckedStrategy, checkStrictly: treeCheckStrictly, onMouseDown: function (e) {
141
176
  e.preventDefault();
142
- } }, extraProps, { treeData: treeData, fieldNames: props.fieldNames, renderTitle: renderTitle, onSelect: onSelect, selectedKeys: selectedKeys })));
177
+ } }, extraProps, { treeData: treeData, fieldNames: props.fieldNames, renderTitle: renderTitle, renderExtra: renderExtra, onSelect: onSelect, selectedKeys: selectedKeys })));
143
178
  }
144
179
  export default forwardRef(TreeList);
@@ -89,6 +89,7 @@ import cs from '../_util/classNames';
89
89
  import useMergeProps from '../_util/hooks/useMergeProps';
90
90
  import useIsFirstRender from '../_util/hooks/useIsFirstRender';
91
91
  import useId from '../_util/hooks/useId';
92
+ import Button from '../Button';
92
93
  function isEmptyValue(value) {
93
94
  return (!value ||
94
95
  (isArray(value) && value.length === 0) ||
@@ -98,10 +99,11 @@ var defaultProps = {
98
99
  bordered: true,
99
100
  treeCheckedStrategy: Tree.SHOW_CHILD,
100
101
  fieldNames: DefaultFieldNames,
102
+ isQuickSingleSelectMode: true,
101
103
  };
102
104
  var triggerPopupAlign = { bottom: 4 };
103
105
  var TreeSelect = function (baseProps, ref) {
104
- var _a = useContext(ConfigContext), getPrefixCls = _a.getPrefixCls, renderEmpty = _a.renderEmpty, componentConfig = _a.componentConfig, rtl = _a.rtl;
106
+ var _a = useContext(ConfigContext), getPrefixCls = _a.getPrefixCls, renderEmpty = _a.renderEmpty, componentConfig = _a.componentConfig, rtl = _a.rtl, locale = _a.locale;
105
107
  var props = useMergeProps(baseProps, defaultProps, componentConfig === null || componentConfig === void 0 ? void 0 : componentConfig.TreeSelect);
106
108
  var refIsFirstRender = useIsFirstRender();
107
109
  var triggerRef = useRef();
@@ -123,8 +125,9 @@ var TreeSelect = function (baseProps, ref) {
123
125
  // 触发 onInputValueChange 回调的原因
124
126
  var refOnInputChangeCallbackReason = useRef(null);
125
127
  var onInputValueChange = props.onInputValueChange;
126
- var _f = __read(useStateValue(props, key2nodeProps, indeterminateKeys), 2), value = _f[0], setValue = _f[1];
127
128
  var multiple = props.multiple || props.treeCheckable;
129
+ var isMultipleQuickSelectMode = multiple && props.isQuickSingleSelectMode;
130
+ var _f = __read(useStateValue(props, key2nodeProps, indeterminateKeys), 5), value = _f[0], setValue = _f[1], realValue = _f[2], confirmSetValue = _f[3], cancelSetValue = _f[4];
128
131
  var prefixCls = getPrefixCls('tree-select');
129
132
  var isFilterNode = inputValue && !isFunction(props.onSearch);
130
133
  // Unique ID of this select instance
@@ -134,6 +137,9 @@ var TreeSelect = function (baseProps, ref) {
134
137
  if (visible !== popupVisible) {
135
138
  setPopupVisible(visible);
136
139
  (_a = props.onVisibleChange) === null || _a === void 0 ? void 0 : _a.call(props, visible);
140
+ if (isMultipleQuickSelectMode && !visible) {
141
+ cancelSetValue();
142
+ }
137
143
  }
138
144
  };
139
145
  // 尝试更新 inputValue,并触发 onInputValueChange
@@ -206,6 +212,13 @@ var TreeSelect = function (baseProps, ref) {
206
212
  tryUpdatePopupVisible(false);
207
213
  }
208
214
  }, [setValue, resetInputValue, popupVisible]);
215
+ var cancelCheck = function () {
216
+ tryUpdatePopupVisible(false);
217
+ };
218
+ var confirmCheck = function () {
219
+ confirmSetValue();
220
+ tryUpdatePopupVisible(false);
221
+ };
209
222
  var handleRemoveCheckedItem = function (item, index, e) {
210
223
  e.stopPropagation();
211
224
  if (item.disabled) {
@@ -213,21 +226,31 @@ var TreeSelect = function (baseProps, ref) {
213
226
  }
214
227
  var itemValue = isObject(item.value) ? item.value.value : item.value;
215
228
  if (!props.treeCheckable || props.treeCheckStrictly || !key2nodeProps[itemValue]) {
216
- var newValue = value.filter(function (_, i) { return i !== index; });
229
+ var newValue = realValue.filter(function (_, i) { return i !== index; });
217
230
  triggerChange(newValue, {
218
231
  trigger: key2nodeProps[itemValue] || item,
219
232
  checked: false,
220
233
  selected: false,
221
234
  });
235
+ if (isMultipleQuickSelectMode) {
236
+ setTimeout(function () {
237
+ confirmCheck();
238
+ }, 0);
239
+ }
222
240
  return;
223
241
  }
224
- var result = getAllCheckedKeysByCheck(itemValue, false, normalizeValueToArray(value), key2nodeProps, indeterminateKeys.current);
242
+ var result = getAllCheckedKeysByCheck(itemValue, false, normalizeValueToArray(realValue), key2nodeProps, indeterminateKeys.current);
225
243
  indeterminateKeys.current = result.indeterminateKeys;
226
- triggerChange(parseValue(result.checkedKeys, key2nodeProps, value), {
244
+ triggerChange(parseValue(result.checkedKeys, key2nodeProps, realValue), {
227
245
  trigger: key2nodeProps[itemValue],
228
246
  checked: false,
229
247
  selected: false,
230
248
  });
249
+ if (isMultipleQuickSelectMode) {
250
+ setTimeout(function () {
251
+ confirmCheck();
252
+ }, 0);
253
+ }
231
254
  };
232
255
  useEffect(function () {
233
256
  inputValue !== undefined && handleSearch(inputValue);
@@ -290,12 +313,35 @@ var TreeSelect = function (baseProps, ref) {
290
313
  var renderView = function (eleView) {
291
314
  return (React.createElement(Trigger, __assign({ autoAlignPopupWidth: false, autoAlignPopupMinWidth: true, ref: triggerRef, classNames: "slideDynamicOrigin", trigger: "click", position: "bl", getPopupContainer: props.getPopupContainer, popupAlign: triggerPopupAlign, unmountOnExit: props.unmountOnExit }, props.triggerProps, { className: cs(prefixCls + "-trigger", props.triggerProps && props.triggerProps.className), popup: function () {
292
315
  var _a;
293
- var _b, _c, _d;
316
+ var _b, _c, _d, _e, _f;
294
317
  var dropdownRender = props.dropdownRender;
295
- var dom = (isFilterNode && isEmptyValue(searchKeys)) || isEmptyValue(treeData) ? (props.notFoundContent || renderEmpty('TreeSelect')) : (React.createElement(TreeList, __assign({ prefixCls: prefixCls, ref: treeRef }, props, { inputValue: inputValue, filterNode: filterNode, value: value, onChange: triggerChange, multiple: multiple, treeData: treeData })));
296
- return (React.createElement("div", { id: instancePopupID, className: cs(prefixCls + "-popup", (_a = {}, _a[prefixCls + "-rtl-popup"] = rtl, _a)), style: __assign({ maxHeight: ((_b = props.treeProps) === null || _b === void 0 ? void 0 : _b.height) || ((_d = (_c = props.treeProps) === null || _c === void 0 ? void 0 : _c.virtualListProps) === null || _d === void 0 ? void 0 : _d.height)
318
+ var treeListDom = (React.createElement(TreeList, __assign({ prefixCls: prefixCls, ref: treeRef }, props, { inputValue: inputValue, filterNode: filterNode, value: value, onChange: triggerChange, multiple: multiple, treeData: treeData, confirmCheck: confirmCheck })));
319
+ var dom = (isFilterNode && isEmptyValue(searchKeys)) || isEmptyValue(treeData) ? (props.notFoundContent || renderEmpty('TreeSelect')) : isMultipleQuickSelectMode ? (React.createElement("div", { style: {
320
+ maxHeight: 188,
321
+ display: 'flex',
322
+ flexDirection: 'column',
323
+ } },
324
+ React.createElement("div", { style: { flex: 1, overflowY: 'auto' } }, treeListDom),
325
+ React.createElement("div", { style: {
326
+ flex: 'none',
327
+ display: 'flex',
328
+ justifyContent: 'flex-end',
329
+ gap: 12,
330
+ padding: '8px 16px 4px',
331
+ borderTop: '1px solid var(--color-fill-3)',
332
+ } },
333
+ React.createElement(Button, { size: "mini", onClick: cancelCheck }, (_b = locale.Select) === null || _b === void 0 ? void 0 : _b.cancelText),
334
+ React.createElement(Button, { type: "primary", size: "mini", onClick: function () {
335
+ confirmCheck();
336
+ } }, (_c = locale.Select) === null || _c === void 0 ? void 0 : _c.okText)))) : (treeListDom);
337
+ var wrapStyle = isMultipleQuickSelectMode
338
+ ? {
339
+ overflow: 'hidden',
340
+ }
341
+ : {};
342
+ return (React.createElement("div", { id: instancePopupID, className: cs(prefixCls + "-popup", (_a = {}, _a[prefixCls + "-rtl-popup"] = rtl, _a)), style: __assign(__assign({ maxHeight: ((_d = props.treeProps) === null || _d === void 0 ? void 0 : _d.height) || ((_f = (_e = props.treeProps) === null || _e === void 0 ? void 0 : _e.virtualListProps) === null || _f === void 0 ? void 0 : _f.height)
297
343
  ? 'unset'
298
- : '' }, props.dropdownMenuStyle) }, isFunction(dropdownRender) ? dropdownRender(dom) : dom));
344
+ : '' }, wrapStyle), props.dropdownMenuStyle) }, isFunction(dropdownRender) ? dropdownRender(dom) : dom));
299
345
  }, disabled: props.disabled, onVisibleChange: function (visible) {
300
346
  tryUpdatePopupVisible(visible);
301
347
  // props.onVisibleChange && props.onVisibleChange(visible);
@@ -316,9 +362,9 @@ var TreeSelect = function (baseProps, ref) {
316
362
  return props.triggerElement({ value: valueForCallback });
317
363
  })()
318
364
  : props.triggerElement;
319
- return !isNullOrUndefined(customTriggerElement) ? (renderView(customTriggerElement)) : (React.createElement(SelectView, __assign({ ref: refSelectView, rtl: rtl, ariaControls: instancePopupID }, props, { popupVisible: popupVisible, value: !multiple && isArray(value) ? value[0] : value, inputValue: inputValue,
365
+ return !isNullOrUndefined(customTriggerElement) ? (renderView(customTriggerElement)) : (React.createElement(SelectView, __assign({ ref: refSelectView, rtl: rtl, ariaControls: instancePopupID }, props, { popupVisible: popupVisible, value: !multiple && isArray(realValue) ? realValue[0] : realValue, inputValue: inputValue,
320
366
  // other
321
- isEmptyValue: isEmptyValue(value), prefixCls: prefixCls, isMultiple: multiple, renderText: renderText, onSort: tryUpdateSelectValue, onRemoveCheckedItem: handleRemoveCheckedItem, onClear: function (e) {
367
+ isEmptyValue: isEmptyValue(realValue), prefixCls: prefixCls, isMultiple: multiple, renderText: renderText, onSort: tryUpdateSelectValue, onRemoveCheckedItem: handleRemoveCheckedItem, onClear: function (e) {
322
368
  var _a;
323
369
  e.stopPropagation();
324
370
  triggerChange([], {});
package/es/index.d.ts CHANGED
@@ -139,4 +139,4 @@ export type { WatermarkProps } from './Watermark/interface';
139
139
  export { default as Watermark } from './Watermark';
140
140
  export type { ImageProps, ImagePreviewProps, ImagePreviewActionProps, ImagePreviewGroupProps } from './Image/interface';
141
141
  export { default as Image } from './Image';
142
- export declare const version = "1.3.4";
142
+ export declare const version = "1.4.0";
package/es/index.js CHANGED
@@ -69,4 +69,4 @@ export { default as Upload } from './Upload';
69
69
  export { default as Mentions } from './Mentions';
70
70
  export { default as Watermark } from './Watermark';
71
71
  export { default as Image } from './Image';
72
- export var version = '1.3.4';
72
+ export var version = '1.4.0';
@@ -170,6 +170,8 @@ function Select(baseProps, ref) {
170
170
  var refPopupExiting = (0, react_1.useRef)(false);
171
171
  // Unique ID of this select instance
172
172
  var instancePopupID = (0, useId_1.default)(prefixCls + "-popup-");
173
+ // 添加一个 ref 来跟踪 props.value 的前一个值
174
+ var prevValueRef = (0, react_1.useRef)(props.value);
173
175
  var isNoOptionSelected = (0, utils_1.isEmptyValue)(value, isMultipleMode);
174
176
  var valueActiveDefault = (0, react_1.useMemo)(function () {
175
177
  var _a, _b;
@@ -237,6 +239,20 @@ function Select(baseProps, ref) {
237
239
  setProxyValue(value.length === 0 ? undefined : value[0]);
238
240
  }
239
241
  }, [isMultipleMode, value]);
242
+ (0, react_1.useEffect)(function () {
243
+ if (isMultipleQuickSelectMode) {
244
+ // 判断 props.value 之前有值现在被手动设置为 undefined 或者 []
245
+ var hadValueBefore = !(0, is_1.isNullOrUndefined)(prevValueRef.current) &&
246
+ !(Array.isArray(prevValueRef.current) && prevValueRef.current.length === 0);
247
+ var isEmptyNow = (0, is_1.isNullOrUndefined)(props.value) || (Array.isArray(props.value) && props.value.length === 0);
248
+ if (hadValueBefore && isEmptyNow) {
249
+ setValue((0, utils_1.getValidValue)(props.value, isMultipleMode, labelInValue));
250
+ setProxyValue((0, utils_1.getValidValue)(props.value, isMultipleMode, labelInValue));
251
+ }
252
+ // 更新 ref 以保存当前值用于下次比较
253
+ prevValueRef.current = props.value;
254
+ }
255
+ }, [props.value, isMultipleQuickSelectMode]);
240
256
  // 选项下拉框显示/隐藏时的一些自动行为
241
257
  (0, react_1.useEffect)(function () {
242
258
  if (popupVisible) {
package/lib/Tree/index.js CHANGED
@@ -130,6 +130,21 @@ var ConfigProvider_1 = require("../ConfigProvider");
130
130
  var util_1 = require("./util");
131
131
  var context_1 = require("./context");
132
132
  var pick_1 = require("../_util/pick");
133
+ var style = document.createElement('style');
134
+ document.head.appendChild(style);
135
+ // 动态写入 hover 样式
136
+ var rules = [
137
+ ".arco-tree-node:hover .arco-tree-select-extra-QuickSingleSelect-button { display: block !important; }",
138
+ ];
139
+ rules.forEach(function (rule) {
140
+ try {
141
+ var styleSheet = style.sheet;
142
+ style.sheet.insertRule(rule, styleSheet.cssRules.length);
143
+ }
144
+ catch (e) {
145
+ console.error('插入 CSS 规则失败:', rule, e);
146
+ }
147
+ });
133
148
  var DefaultFieldNames = {
134
149
  key: 'key',
135
150
  title: 'title',
@@ -15,5 +15,5 @@ declare const useStateValue: (props: TreeSelectProps, key2nodeProps: KeyCacheTyp
15
15
  trigger?: NodeProps;
16
16
  checked?: boolean;
17
17
  selected?: boolean;
18
- }) => void];
18
+ }) => void, LabelValue[], () => void, () => void];
19
19
  export default useStateValue;
@@ -26,6 +26,15 @@ var __read = (this && this.__read) || function (o, n) {
26
26
  }
27
27
  return ar;
28
28
  };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
29
38
  var __importDefault = (this && this.__importDefault) || function (mod) {
30
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
31
40
  };
@@ -88,6 +97,8 @@ var getInitCheckKeys = function (keys, key2nodeProps, indeterminateKeys, props)
88
97
  return keys;
89
98
  };
90
99
  var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
100
+ var multiple = props.multiple || props.treeCheckable;
101
+ var isMultipleQuickSelectMode = multiple && props.isQuickSingleSelectMode;
91
102
  var valueCopy = (0, react_1.useRef)([]);
92
103
  var calcValue = function () {
93
104
  var propsValue = props.value || props.defaultValue || [];
@@ -100,10 +111,18 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
100
111
  return (0, exports.parseValue)(propsValue, key2nodeProps);
101
112
  };
102
113
  var _a = __read((0, react_1.useState)(calcValue), 2), value = _a[0], _setValue = _a[1];
114
+ // proxyValue 在isMultipleQuickSelectMode时候挡在真实value前面进行展示,真实的value只在确定时候更新。 proxyValue 必须和原有的value行为一致
115
+ var _b = __read((0, react_1.useState)(value), 2), proxyValue = _b[0], _setProxyValue = _b[1];
116
+ var proxyValueCopy = (0, react_1.useRef)(value);
117
+ var stateValue = isMultipleQuickSelectMode ? proxyValue : value;
103
118
  var setValue = function (value) {
104
119
  valueCopy.current = value;
105
120
  _setValue(value);
106
121
  };
122
+ var setProxyValue = function (value) {
123
+ proxyValueCopy.current = value;
124
+ _setProxyValue(value);
125
+ };
107
126
  (0, useUpdate_1.default)(function () {
108
127
  var nextValue = calcValue();
109
128
  if ('value' in props) {
@@ -111,10 +130,12 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
111
130
  // 以外部传入为准,只比较value
112
131
  if (!(0, isEqualWith_1.default)((0, utils_1.normalizeValueToArray)(value), (0, utils_1.normalizeValueToArray)(nextValue))) {
113
132
  setValue(nextValue);
133
+ setProxyValue(nextValue);
114
134
  }
115
135
  }
116
136
  else if (!(0, isEqualWith_1.default)(value, nextValue)) {
117
137
  setValue(nextValue);
138
+ setProxyValue(nextValue);
118
139
  }
119
140
  }
120
141
  }, [
@@ -124,10 +145,14 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
124
145
  props.value,
125
146
  key2nodeProps,
126
147
  ]);
148
+ var extra = (0, react_1.useRef)(null);
127
149
  var setStateValue = (0, react_1.useCallback)(function (newValue, extra) {
128
150
  var onChange = props.onChange, labelInValue = props.labelInValue;
129
151
  var multiple = props.multiple || props.treeCheckable;
130
- if (!('value' in props)) {
152
+ if (isMultipleQuickSelectMode) {
153
+ setProxyValue(newValue);
154
+ }
155
+ if (!('value' in props) && !isMultipleQuickSelectMode) {
131
156
  setValue(newValue);
132
157
  }
133
158
  var tmp;
@@ -139,8 +164,24 @@ var useStateValue = function (props, key2nodeProps, indeterminateKeys) {
139
164
  else {
140
165
  tmp = labelInValue ? newValue[0] : newValue[0] && newValue[0].value;
141
166
  }
142
- onChange && onChange(tmp, extra);
167
+ if (isMultipleQuickSelectMode) {
168
+ extra.current = extra;
169
+ }
170
+ else {
171
+ onChange && onChange(tmp, extra);
172
+ }
143
173
  }, [props.onChange, props.labelInValue, props.multiple, props.treeCheckable, props.value]);
144
- return [value, setStateValue];
174
+ var confirmSetValue = function () {
175
+ var onChange = props.onChange, labelInValue = props.labelInValue;
176
+ setValue(__spreadArray([], __read(proxyValueCopy.current), false));
177
+ var tmp = proxyValueCopy.current.map(function (x) {
178
+ return labelInValue ? { label: x.label, value: x.value } : x.value;
179
+ });
180
+ onChange && onChange(tmp, extra.current);
181
+ };
182
+ var cancelSetValue = function () {
183
+ setProxyValue(value);
184
+ };
185
+ return [stateValue, setStateValue, value, confirmSetValue, cancelSetValue];
145
186
  };
146
187
  exports.default = useStateValue;
@@ -19,6 +19,12 @@ export interface TreeSelectProps extends SelectViewCommonProps {
19
19
  * @en Whether to select multiple
20
20
  */
21
21
  multiple?: boolean;
22
+ /**
23
+ * @zh 是否开启快速单选模式。开启后,由于需要最后点击确定或者取消来选择,单个选项变化的事件将无效
24
+ * @en Whether to enable quick single selection mode.
25
+ * @defaultValue true
26
+ */
27
+ isQuickSingleSelectMode?: boolean;
22
28
  /**
23
29
  * @zh 选择框的默认值
24
30
  * @en The key of node selected by default
@@ -7,6 +7,7 @@ interface TreeListProps extends TreeSelectProps {
7
7
  filterNode: TreeProps['filterNode'];
8
8
  inputValue?: string;
9
9
  prefixCls?: string;
10
+ confirmCheck: () => void;
10
11
  }
11
12
  declare const _default: React.ForwardRefExoticComponent<TreeListProps & React.RefAttributes<unknown>>;
12
13
  export default _default;