@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.
@@ -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
- else {
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,
@@ -61,7 +61,6 @@ exports.style = (0, utils_1.defineCss)(({ spacing, text, easing }) => (0, react_
61
61
  white-space: nowrap;
62
62
  text-overflow: ellipsis;
63
63
  overflow: hidden;
64
- direction: rtl;
65
64
  }
66
65
  }
67
66
  }
@@ -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 optionsMap = (0, react_1.useMemo)(() => {
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, context.optionsMap]);
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 selectionStatus = (0, react_1.useMemo)(() => {
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, context.selectionStatus]);
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 toggleSelected = (0, react_1.useCallback)((value) => {
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
- }, [context.inSelection]);
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
- else {
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,
@@ -58,7 +58,6 @@ export const style = defineCss(({ spacing, text, easing }) => css `
58
58
  white-space: nowrap;
59
59
  text-overflow: ellipsis;
60
60
  overflow: hidden;
61
- direction: rtl;
62
61
  }
63
62
  }
64
63
  }
@@ -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 optionsMap = useMemo(() => {
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, context.optionsMap]);
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 selectionStatus = useMemo(() => {
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, context.selectionStatus]);
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 toggleSelected = useCallback((value) => {
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
- }, [context.inSelection]);
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canlooks/can-ui",
3
- "version": "0.0.199",
3
+ "version": "0.0.201",
4
4
  "author": "C.CanLiang <canlooks@gmail.com>",
5
5
  "description": "My ui framework",
6
6
  "license": "MIT",