@canlooks/can-ui 0.0.199 → 0.0.201
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/dist/cjs/components/cascade/cascade.js +57 -54
- package/dist/cjs/components/cascade/cascade.style.js +0 -1
- package/dist/cjs/components/cascade/cascadePanel.js +1 -1
- package/dist/cjs/components/selectionContext/selectionContext.d.ts +2 -0
- package/dist/cjs/components/selectionContext/selectionHook.js +10 -17
- package/dist/cjs/components/treeSelect/treeSelect.js +1 -0
- package/dist/esm/components/cascade/cascade.js +57 -54
- package/dist/esm/components/cascade/cascade.style.js +0 -1
- package/dist/esm/components/cascade/cascadePanel.js +1 -1
- package/dist/esm/components/selectionContext/selectionContext.d.ts +2 -0
- package/dist/esm/components/selectionContext/selectionHook.js +10 -17
- package/dist/esm/components/treeSelect/treeSelect.js +1 -0
- package/package.json +1 -1
|
@@ -32,6 +32,36 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
32
32
|
(0, react_1.useEffect)(() => {
|
|
33
33
|
loadOptions && searchable && deferredSearchValue && innerLoadOptions();
|
|
34
34
|
}, [deferredSearchValue]);
|
|
35
|
+
/**
|
|
36
|
+
* --------------------------------------------------------------------
|
|
37
|
+
* 控制选中状态
|
|
38
|
+
*/
|
|
39
|
+
const [pathifiedValue, setPathifiedValue] = (0, utils_1.useControlled)(defaultValue || [], value, onChange);
|
|
40
|
+
// 路径转单一键
|
|
41
|
+
const toStandardValue = (path) => {
|
|
42
|
+
if (!path) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (multiple) {
|
|
46
|
+
return path.map(path => path[path.length - 1]);
|
|
47
|
+
}
|
|
48
|
+
return path[path.length - 1];
|
|
49
|
+
};
|
|
50
|
+
// 单一键转路径
|
|
51
|
+
const toPathifiedValue = (value) => {
|
|
52
|
+
if (!value) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const findParent = (v, path = []) => {
|
|
56
|
+
const node = optionsMap.get(v);
|
|
57
|
+
if (node) {
|
|
58
|
+
path.unshift(v);
|
|
59
|
+
node._parentId && findParent(node._parentId, path);
|
|
60
|
+
}
|
|
61
|
+
return path;
|
|
62
|
+
};
|
|
63
|
+
return multiple ? value.map(v => findParent(v)) : findParent(value);
|
|
64
|
+
};
|
|
35
65
|
/**
|
|
36
66
|
* --------------------------------------------------------------------
|
|
37
67
|
* 打开的弹框与面板
|
|
@@ -41,7 +71,13 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
41
71
|
// 关闭动画结束后清空搜索框
|
|
42
72
|
searchable && !open && setInnerSearchValue('');
|
|
43
73
|
};
|
|
44
|
-
const [openedPanels, setOpenedPanels] = (0, react_1.useState)(
|
|
74
|
+
const [openedPanels, setOpenedPanels] = (0, react_1.useState)(() => {
|
|
75
|
+
const value = multiple ? pathifiedValue.current?.[0] : pathifiedValue.current;
|
|
76
|
+
if ((0, utils_1.isNoValue)(value)) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
return value.slice(0, -1);
|
|
80
|
+
});
|
|
45
81
|
const toggleOpenedPanels = (value, index) => {
|
|
46
82
|
setOpenedPanels(o => {
|
|
47
83
|
const newOpened = o.slice(0, index);
|
|
@@ -69,55 +105,17 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
69
105
|
// 打开下拉框时请求数据
|
|
70
106
|
loadOptions && innerOpen.current && innerLoadOptions(innerSearchValue.current);
|
|
71
107
|
}, [innerOpen.current]);
|
|
72
|
-
const actualOptions = innerOptions || options;
|
|
73
|
-
/**
|
|
74
|
-
* --------------------------------------------------------------------
|
|
75
|
-
* 控制选中状态
|
|
76
|
-
*/
|
|
77
|
-
const [pathifiedValue, setPathifiedValue] = (0, utils_1.useControlled)(defaultValue || [], value, onChange);
|
|
78
|
-
// 路径转单一键
|
|
79
|
-
const toStandardValue = (path) => {
|
|
80
|
-
if (!path) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
if (multiple) {
|
|
84
|
-
return path.map(path => path[path.length - 1]);
|
|
85
|
-
}
|
|
86
|
-
return path[path.length - 1];
|
|
87
|
-
};
|
|
88
|
-
// 单一键转路径
|
|
89
|
-
const toPathifiedValue = (value) => {
|
|
90
|
-
if (!value) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const findParent = (v, path = []) => {
|
|
94
|
-
const node = optionsMap.get(v);
|
|
95
|
-
if (node) {
|
|
96
|
-
path.unshift(v);
|
|
97
|
-
node._parentId && findParent(node._parentId, path);
|
|
98
|
-
}
|
|
99
|
-
return path;
|
|
100
|
-
};
|
|
101
|
-
return multiple ? value.map(v => findParent(v)) : findParent(value);
|
|
102
|
-
};
|
|
103
|
-
const { value: innerValue, setValue: setInnerValue, toggleSelected, selectionStatus, optionsMap } = (0, selectionContext_1.useSelection)({
|
|
104
|
-
options: actualOptions,
|
|
105
|
-
multiple,
|
|
106
|
-
value: toStandardValue(pathifiedValue.current),
|
|
107
|
-
onChange(value) {
|
|
108
|
-
setPathifiedValue(toPathifiedValue(value));
|
|
109
|
-
},
|
|
110
|
-
primaryKey,
|
|
111
|
-
childrenKey,
|
|
112
|
-
clearable,
|
|
113
|
-
integration
|
|
114
|
-
});
|
|
115
108
|
const onClear = () => {
|
|
116
109
|
setInnerValue([]);
|
|
117
110
|
setOpenedPanels([]);
|
|
118
111
|
};
|
|
119
112
|
const onOptionClick = async (option, index) => {
|
|
120
113
|
const optVal = option[primaryKey];
|
|
114
|
+
if (!option.children?.length) {
|
|
115
|
+
toggleSelected(option[primaryKey]);
|
|
116
|
+
!multiple && setInnerOpen(false);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
121
119
|
const opened = openedPanels[index] === optVal;
|
|
122
120
|
if (!opened) {
|
|
123
121
|
loadOptions && await innerLoadOptions(innerSearchValue.current, option);
|
|
@@ -131,6 +129,20 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
131
129
|
toggleSelected(option[primaryKey]);
|
|
132
130
|
onOptionClick(option, index);
|
|
133
131
|
};
|
|
132
|
+
const actualOptions = innerOptions || options;
|
|
133
|
+
const { value: innerValue, setValue: setInnerValue, toggleSelected, selectionStatus, optionsMap } = (0, selectionContext_1.useSelection)({
|
|
134
|
+
standalone: true,
|
|
135
|
+
options: actualOptions,
|
|
136
|
+
multiple,
|
|
137
|
+
value: toStandardValue(pathifiedValue.current),
|
|
138
|
+
onChange(value) {
|
|
139
|
+
setPathifiedValue(toPathifiedValue(value));
|
|
140
|
+
},
|
|
141
|
+
primaryKey,
|
|
142
|
+
childrenKey,
|
|
143
|
+
clearable,
|
|
144
|
+
integration
|
|
145
|
+
});
|
|
134
146
|
/**
|
|
135
147
|
* --------------------------------------------------------------------
|
|
136
148
|
* 键盘控制
|
|
@@ -156,13 +168,6 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
156
168
|
setOpen: setInnerOpen,
|
|
157
169
|
onEnter(info) {
|
|
158
170
|
keyboardPressHandler(info);
|
|
159
|
-
},
|
|
160
|
-
onKeyDown(info, e) {
|
|
161
|
-
if (e.key === 'ArrowRight' && info.horizontalIndex === info.horizontalCount - 1) {
|
|
162
|
-
// 在最后一个面板按右箭头,相当于按回车
|
|
163
|
-
e.preventDefault();
|
|
164
|
-
keyboardPressHandler(info);
|
|
165
|
-
}
|
|
166
171
|
}
|
|
167
172
|
});
|
|
168
173
|
const keyboardPressHandler = ({ verticalIndex, horizontalIndex }) => {
|
|
@@ -185,9 +190,7 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
185
190
|
if (multiple) {
|
|
186
191
|
return pathifiedValue.current?.map(path => (0, jsx_runtime_1.jsx)(tag_1.Tag, { closable: true, onClose: () => toggleSelected(path[path.length - 1]), children: (0, utils_1.joinNodes)(path, v => optionsMap.get(v)?.[labelKey] ?? v.toString()) }, path[path.length - 1]));
|
|
187
192
|
}
|
|
188
|
-
|
|
189
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: cascade_style_1.classes.backfillWrap, children: (0, utils_1.joinNodes)(pathifiedValue.current, v => optionsMap.get(v)?.[labelKey] ?? v.toString()) }));
|
|
190
|
-
}
|
|
193
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: cascade_style_1.classes.backfillWrap, children: (0, utils_1.joinNodes)(pathifiedValue.current, v => optionsMap.get(v)?.[labelKey] ?? v.toString()) }));
|
|
191
194
|
};
|
|
192
195
|
return ((0, jsx_runtime_1.jsx)(popper_1.Popper, { ...(0, utils_1.mergeComponentProps)({
|
|
193
196
|
css: cascade_style_1.cascadePopperStyle,
|
|
@@ -35,7 +35,7 @@ function CascadePanel({ options, index = 0 }) {
|
|
|
35
35
|
if (!option || typeof option !== 'object') {
|
|
36
36
|
return option;
|
|
37
37
|
}
|
|
38
|
-
const { _parentId, ...opt } = option;
|
|
38
|
+
const { _parentId, _isLast, ...opt } = option;
|
|
39
39
|
const optVal = opt[primaryKey];
|
|
40
40
|
const status = selectionStatus?.get(optVal);
|
|
41
41
|
const opened = openedPanels[index] === optVal;
|
|
@@ -32,6 +32,8 @@ export type SelectionContextBaseProps<O extends OptionType<V>, V extends Id = Id
|
|
|
32
32
|
disabled?: boolean;
|
|
33
33
|
onToggle?(checked: boolean, value: V, option?: O): void;
|
|
34
34
|
children?: ReactNode;
|
|
35
|
+
/** 若设为true,则该Context不受父级Context影响,默认为`false` */
|
|
36
|
+
standalone?: boolean;
|
|
35
37
|
};
|
|
36
38
|
export type ISelectionContext<O extends OptionType<V>, V extends Id = Id> = {
|
|
37
39
|
inSelection: true;
|
|
@@ -19,15 +19,12 @@ function useSelection({ ...props }) {
|
|
|
19
19
|
* 若嵌套在另个一SelectionContext内,取最外层数据
|
|
20
20
|
*/
|
|
21
21
|
const context = (0, selectionContext_1.useSelectionContext)();
|
|
22
|
-
if (context.inSelection) {
|
|
22
|
+
if (!props.standalone && context.inSelection) {
|
|
23
23
|
innerValue.current = context.value;
|
|
24
24
|
setInnerValue = context.setValue;
|
|
25
25
|
innerOptions.current = context.options;
|
|
26
26
|
}
|
|
27
|
-
const
|
|
28
|
-
if (context.inSelection) {
|
|
29
|
-
return context.optionsMap;
|
|
30
|
-
}
|
|
27
|
+
const _optionsMap = (0, react_1.useMemo)(() => {
|
|
31
28
|
const map = new Map();
|
|
32
29
|
const fn = (arr, parentId) => {
|
|
33
30
|
// 有时arr可能不为数组,需要判断,如DataGrid组件的row.children
|
|
@@ -41,7 +38,8 @@ function useSelection({ ...props }) {
|
|
|
41
38
|
};
|
|
42
39
|
fn(innerOptions.current);
|
|
43
40
|
return map;
|
|
44
|
-
}, [innerOptions.current, props.primaryKey, props.childrenKey
|
|
41
|
+
}, [innerOptions.current, props.primaryKey, props.childrenKey]);
|
|
42
|
+
const optionsMap = !props.standalone && context.inSelection ? context.optionsMap : _optionsMap;
|
|
45
43
|
const syncOptionsMap = (0, utils_1.useSync)(optionsMap);
|
|
46
44
|
const syncProps = (0, utils_1.useSync)(props);
|
|
47
45
|
const calSelectionStatus = (selectedSet = new Set((0, utils_1.toArray)(innerValue.current))) => {
|
|
@@ -84,21 +82,15 @@ function useSelection({ ...props }) {
|
|
|
84
82
|
return map;
|
|
85
83
|
};
|
|
86
84
|
const preCalSelectionStatus = (0, react_1.useRef)(void 0);
|
|
87
|
-
const
|
|
88
|
-
if (context.inSelection) {
|
|
89
|
-
return context.selectionStatus;
|
|
90
|
-
}
|
|
85
|
+
const _selectionStatus = (0, react_1.useMemo)(() => {
|
|
91
86
|
// 调用toggleSelected()方法后可能会预先计算selectionStatus
|
|
92
87
|
const ret = preCalSelectionStatus.current || calSelectionStatus();
|
|
93
88
|
preCalSelectionStatus.current = void 0;
|
|
94
89
|
return ret;
|
|
95
|
-
}, [innerValue.current, optionsMap, props.multiple, props.relation
|
|
90
|
+
}, [innerValue.current, optionsMap, props.multiple, props.relation]);
|
|
91
|
+
const selectionStatus = !props.standalone && context.inSelection ? context.selectionStatus : _selectionStatus;
|
|
96
92
|
const syncSelectionStatus = (0, utils_1.useSync)(selectionStatus);
|
|
97
|
-
const
|
|
98
|
-
if (context.inSelection) {
|
|
99
|
-
context.toggleSelected(value);
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
93
|
+
const _toggleSelected = (0, react_1.useCallback)((value) => {
|
|
102
94
|
if (syncProps.current.disabled) {
|
|
103
95
|
return;
|
|
104
96
|
}
|
|
@@ -190,7 +182,8 @@ function useSelection({ ...props }) {
|
|
|
190
182
|
children && loopOptions(callback, children, ret);
|
|
191
183
|
});
|
|
192
184
|
}
|
|
193
|
-
}, [
|
|
185
|
+
}, []);
|
|
186
|
+
const toggleSelected = !props.standalone && context.inSelection ? context.toggleSelected : _toggleSelected;
|
|
194
187
|
return {
|
|
195
188
|
inSelection: true,
|
|
196
189
|
multiple: props.multiple,
|
|
@@ -39,6 +39,7 @@ value, onChange, renderBackfill, ...props }) => {
|
|
|
39
39
|
return fn(react_1.Children.toArray(children));
|
|
40
40
|
}, [options, nodes, children]);
|
|
41
41
|
const { value: innerValue, setValue: setInnerValue, toggleSelected, optionsMap } = (0, selectionContext_1.useSelection)({
|
|
42
|
+
standalone: true,
|
|
42
43
|
options: actualOptions,
|
|
43
44
|
primaryKey,
|
|
44
45
|
childrenKey,
|
|
@@ -28,6 +28,36 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
28
28
|
useEffect(() => {
|
|
29
29
|
loadOptions && searchable && deferredSearchValue && innerLoadOptions();
|
|
30
30
|
}, [deferredSearchValue]);
|
|
31
|
+
/**
|
|
32
|
+
* --------------------------------------------------------------------
|
|
33
|
+
* 控制选中状态
|
|
34
|
+
*/
|
|
35
|
+
const [pathifiedValue, setPathifiedValue] = useControlled(defaultValue || [], value, onChange);
|
|
36
|
+
// 路径转单一键
|
|
37
|
+
const toStandardValue = (path) => {
|
|
38
|
+
if (!path) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (multiple) {
|
|
42
|
+
return path.map(path => path[path.length - 1]);
|
|
43
|
+
}
|
|
44
|
+
return path[path.length - 1];
|
|
45
|
+
};
|
|
46
|
+
// 单一键转路径
|
|
47
|
+
const toPathifiedValue = (value) => {
|
|
48
|
+
if (!value) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const findParent = (v, path = []) => {
|
|
52
|
+
const node = optionsMap.get(v);
|
|
53
|
+
if (node) {
|
|
54
|
+
path.unshift(v);
|
|
55
|
+
node._parentId && findParent(node._parentId, path);
|
|
56
|
+
}
|
|
57
|
+
return path;
|
|
58
|
+
};
|
|
59
|
+
return multiple ? value.map(v => findParent(v)) : findParent(value);
|
|
60
|
+
};
|
|
31
61
|
/**
|
|
32
62
|
* --------------------------------------------------------------------
|
|
33
63
|
* 打开的弹框与面板
|
|
@@ -37,7 +67,13 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
37
67
|
// 关闭动画结束后清空搜索框
|
|
38
68
|
searchable && !open && setInnerSearchValue('');
|
|
39
69
|
};
|
|
40
|
-
const [openedPanels, setOpenedPanels] = useState(
|
|
70
|
+
const [openedPanels, setOpenedPanels] = useState(() => {
|
|
71
|
+
const value = multiple ? pathifiedValue.current?.[0] : pathifiedValue.current;
|
|
72
|
+
if (isNoValue(value)) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
return value.slice(0, -1);
|
|
76
|
+
});
|
|
41
77
|
const toggleOpenedPanels = (value, index) => {
|
|
42
78
|
setOpenedPanels(o => {
|
|
43
79
|
const newOpened = o.slice(0, index);
|
|
@@ -65,55 +101,17 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
65
101
|
// 打开下拉框时请求数据
|
|
66
102
|
loadOptions && innerOpen.current && innerLoadOptions(innerSearchValue.current);
|
|
67
103
|
}, [innerOpen.current]);
|
|
68
|
-
const actualOptions = innerOptions || options;
|
|
69
|
-
/**
|
|
70
|
-
* --------------------------------------------------------------------
|
|
71
|
-
* 控制选中状态
|
|
72
|
-
*/
|
|
73
|
-
const [pathifiedValue, setPathifiedValue] = useControlled(defaultValue || [], value, onChange);
|
|
74
|
-
// 路径转单一键
|
|
75
|
-
const toStandardValue = (path) => {
|
|
76
|
-
if (!path) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (multiple) {
|
|
80
|
-
return path.map(path => path[path.length - 1]);
|
|
81
|
-
}
|
|
82
|
-
return path[path.length - 1];
|
|
83
|
-
};
|
|
84
|
-
// 单一键转路径
|
|
85
|
-
const toPathifiedValue = (value) => {
|
|
86
|
-
if (!value) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const findParent = (v, path = []) => {
|
|
90
|
-
const node = optionsMap.get(v);
|
|
91
|
-
if (node) {
|
|
92
|
-
path.unshift(v);
|
|
93
|
-
node._parentId && findParent(node._parentId, path);
|
|
94
|
-
}
|
|
95
|
-
return path;
|
|
96
|
-
};
|
|
97
|
-
return multiple ? value.map(v => findParent(v)) : findParent(value);
|
|
98
|
-
};
|
|
99
|
-
const { value: innerValue, setValue: setInnerValue, toggleSelected, selectionStatus, optionsMap } = useSelection({
|
|
100
|
-
options: actualOptions,
|
|
101
|
-
multiple,
|
|
102
|
-
value: toStandardValue(pathifiedValue.current),
|
|
103
|
-
onChange(value) {
|
|
104
|
-
setPathifiedValue(toPathifiedValue(value));
|
|
105
|
-
},
|
|
106
|
-
primaryKey,
|
|
107
|
-
childrenKey,
|
|
108
|
-
clearable,
|
|
109
|
-
integration
|
|
110
|
-
});
|
|
111
104
|
const onClear = () => {
|
|
112
105
|
setInnerValue([]);
|
|
113
106
|
setOpenedPanels([]);
|
|
114
107
|
};
|
|
115
108
|
const onOptionClick = async (option, index) => {
|
|
116
109
|
const optVal = option[primaryKey];
|
|
110
|
+
if (!option.children?.length) {
|
|
111
|
+
toggleSelected(option[primaryKey]);
|
|
112
|
+
!multiple && setInnerOpen(false);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
117
115
|
const opened = openedPanels[index] === optVal;
|
|
118
116
|
if (!opened) {
|
|
119
117
|
loadOptions && await innerLoadOptions(innerSearchValue.current, option);
|
|
@@ -127,6 +125,20 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
127
125
|
toggleSelected(option[primaryKey]);
|
|
128
126
|
onOptionClick(option, index);
|
|
129
127
|
};
|
|
128
|
+
const actualOptions = innerOptions || options;
|
|
129
|
+
const { value: innerValue, setValue: setInnerValue, toggleSelected, selectionStatus, optionsMap } = useSelection({
|
|
130
|
+
standalone: true,
|
|
131
|
+
options: actualOptions,
|
|
132
|
+
multiple,
|
|
133
|
+
value: toStandardValue(pathifiedValue.current),
|
|
134
|
+
onChange(value) {
|
|
135
|
+
setPathifiedValue(toPathifiedValue(value));
|
|
136
|
+
},
|
|
137
|
+
primaryKey,
|
|
138
|
+
childrenKey,
|
|
139
|
+
clearable,
|
|
140
|
+
integration
|
|
141
|
+
});
|
|
130
142
|
/**
|
|
131
143
|
* --------------------------------------------------------------------
|
|
132
144
|
* 键盘控制
|
|
@@ -152,13 +164,6 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
152
164
|
setOpen: setInnerOpen,
|
|
153
165
|
onEnter(info) {
|
|
154
166
|
keyboardPressHandler(info);
|
|
155
|
-
},
|
|
156
|
-
onKeyDown(info, e) {
|
|
157
|
-
if (e.key === 'ArrowRight' && info.horizontalIndex === info.horizontalCount - 1) {
|
|
158
|
-
// 在最后一个面板按右箭头,相当于按回车
|
|
159
|
-
e.preventDefault();
|
|
160
|
-
keyboardPressHandler(info);
|
|
161
|
-
}
|
|
162
167
|
}
|
|
163
168
|
});
|
|
164
169
|
const keyboardPressHandler = ({ verticalIndex, horizontalIndex }) => {
|
|
@@ -181,9 +186,7 @@ loading, options, labelKey = 'label', primaryKey = 'value', childrenKey = 'child
|
|
|
181
186
|
if (multiple) {
|
|
182
187
|
return pathifiedValue.current?.map(path => _jsx(Tag, { closable: true, onClose: () => toggleSelected(path[path.length - 1]), children: joinNodes(path, v => optionsMap.get(v)?.[labelKey] ?? v.toString()) }, path[path.length - 1]));
|
|
183
188
|
}
|
|
184
|
-
|
|
185
|
-
return (_jsx("div", { className: classes.backfillWrap, children: joinNodes(pathifiedValue.current, v => optionsMap.get(v)?.[labelKey] ?? v.toString()) }));
|
|
186
|
-
}
|
|
189
|
+
return (_jsx("div", { className: classes.backfillWrap, children: joinNodes(pathifiedValue.current, v => optionsMap.get(v)?.[labelKey] ?? v.toString()) }));
|
|
187
190
|
};
|
|
188
191
|
return (_jsx(Popper, { ...mergeComponentProps({
|
|
189
192
|
css: cascadePopperStyle,
|
|
@@ -32,7 +32,7 @@ export function CascadePanel({ options, index = 0 }) {
|
|
|
32
32
|
if (!option || typeof option !== 'object') {
|
|
33
33
|
return option;
|
|
34
34
|
}
|
|
35
|
-
const { _parentId, ...opt } = option;
|
|
35
|
+
const { _parentId, _isLast, ...opt } = option;
|
|
36
36
|
const optVal = opt[primaryKey];
|
|
37
37
|
const status = selectionStatus?.get(optVal);
|
|
38
38
|
const opened = openedPanels[index] === optVal;
|
|
@@ -32,6 +32,8 @@ export type SelectionContextBaseProps<O extends OptionType<V>, V extends Id = Id
|
|
|
32
32
|
disabled?: boolean;
|
|
33
33
|
onToggle?(checked: boolean, value: V, option?: O): void;
|
|
34
34
|
children?: ReactNode;
|
|
35
|
+
/** 若设为true,则该Context不受父级Context影响,默认为`false` */
|
|
36
|
+
standalone?: boolean;
|
|
35
37
|
};
|
|
36
38
|
export type ISelectionContext<O extends OptionType<V>, V extends Id = Id> = {
|
|
37
39
|
inSelection: true;
|
|
@@ -15,15 +15,12 @@ export function useSelection({ ...props }) {
|
|
|
15
15
|
* 若嵌套在另个一SelectionContext内,取最外层数据
|
|
16
16
|
*/
|
|
17
17
|
const context = useSelectionContext();
|
|
18
|
-
if (context.inSelection) {
|
|
18
|
+
if (!props.standalone && context.inSelection) {
|
|
19
19
|
innerValue.current = context.value;
|
|
20
20
|
setInnerValue = context.setValue;
|
|
21
21
|
innerOptions.current = context.options;
|
|
22
22
|
}
|
|
23
|
-
const
|
|
24
|
-
if (context.inSelection) {
|
|
25
|
-
return context.optionsMap;
|
|
26
|
-
}
|
|
23
|
+
const _optionsMap = useMemo(() => {
|
|
27
24
|
const map = new Map();
|
|
28
25
|
const fn = (arr, parentId) => {
|
|
29
26
|
// 有时arr可能不为数组,需要判断,如DataGrid组件的row.children
|
|
@@ -37,7 +34,8 @@ export function useSelection({ ...props }) {
|
|
|
37
34
|
};
|
|
38
35
|
fn(innerOptions.current);
|
|
39
36
|
return map;
|
|
40
|
-
}, [innerOptions.current, props.primaryKey, props.childrenKey
|
|
37
|
+
}, [innerOptions.current, props.primaryKey, props.childrenKey]);
|
|
38
|
+
const optionsMap = !props.standalone && context.inSelection ? context.optionsMap : _optionsMap;
|
|
41
39
|
const syncOptionsMap = useSync(optionsMap);
|
|
42
40
|
const syncProps = useSync(props);
|
|
43
41
|
const calSelectionStatus = (selectedSet = new Set(toArray(innerValue.current))) => {
|
|
@@ -80,21 +78,15 @@ export function useSelection({ ...props }) {
|
|
|
80
78
|
return map;
|
|
81
79
|
};
|
|
82
80
|
const preCalSelectionStatus = useRef(void 0);
|
|
83
|
-
const
|
|
84
|
-
if (context.inSelection) {
|
|
85
|
-
return context.selectionStatus;
|
|
86
|
-
}
|
|
81
|
+
const _selectionStatus = useMemo(() => {
|
|
87
82
|
// 调用toggleSelected()方法后可能会预先计算selectionStatus
|
|
88
83
|
const ret = preCalSelectionStatus.current || calSelectionStatus();
|
|
89
84
|
preCalSelectionStatus.current = void 0;
|
|
90
85
|
return ret;
|
|
91
|
-
}, [innerValue.current, optionsMap, props.multiple, props.relation
|
|
86
|
+
}, [innerValue.current, optionsMap, props.multiple, props.relation]);
|
|
87
|
+
const selectionStatus = !props.standalone && context.inSelection ? context.selectionStatus : _selectionStatus;
|
|
92
88
|
const syncSelectionStatus = useSync(selectionStatus);
|
|
93
|
-
const
|
|
94
|
-
if (context.inSelection) {
|
|
95
|
-
context.toggleSelected(value);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
89
|
+
const _toggleSelected = useCallback((value) => {
|
|
98
90
|
if (syncProps.current.disabled) {
|
|
99
91
|
return;
|
|
100
92
|
}
|
|
@@ -186,7 +178,8 @@ export function useSelection({ ...props }) {
|
|
|
186
178
|
children && loopOptions(callback, children, ret);
|
|
187
179
|
});
|
|
188
180
|
}
|
|
189
|
-
}, [
|
|
181
|
+
}, []);
|
|
182
|
+
const toggleSelected = !props.standalone && context.inSelection ? context.toggleSelected : _toggleSelected;
|
|
190
183
|
return {
|
|
191
184
|
inSelection: true,
|
|
192
185
|
multiple: props.multiple,
|
|
@@ -36,6 +36,7 @@ value, onChange, renderBackfill, ...props }) => {
|
|
|
36
36
|
return fn(Children.toArray(children));
|
|
37
37
|
}, [options, nodes, children]);
|
|
38
38
|
const { value: innerValue, setValue: setInnerValue, toggleSelected, optionsMap } = useSelection({
|
|
39
|
+
standalone: true,
|
|
39
40
|
options: actualOptions,
|
|
40
41
|
primaryKey,
|
|
41
42
|
childrenKey,
|