@douyinfe/semi-foundation 2.52.0-beta.1 → 2.52.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.
Files changed (39) hide show
  1. package/cascader/foundation.ts +17 -10
  2. package/cascader/util.ts +43 -0
  3. package/datePicker/foundation.ts +3 -0
  4. package/dropdown/dropdown.scss +1 -0
  5. package/image/previewInnerFoundation.ts +4 -0
  6. package/lib/cjs/cascader/foundation.d.ts +4 -11
  7. package/lib/cjs/cascader/foundation.js +25 -16
  8. package/lib/cjs/cascader/util.d.ts +6 -0
  9. package/lib/cjs/cascader/util.js +42 -0
  10. package/lib/cjs/datePicker/foundation.js +3 -0
  11. package/lib/cjs/dropdown/dropdown.css +1 -0
  12. package/lib/cjs/dropdown/dropdown.scss +1 -0
  13. package/lib/cjs/image/previewInnerFoundation.js +3 -0
  14. package/lib/cjs/select/foundation.js +2 -0
  15. package/lib/cjs/select/select.scss +3 -4
  16. package/lib/cjs/select/variables.scss +7 -6
  17. package/lib/cjs/tooltip/foundation.js +11 -0
  18. package/lib/cjs/tree/treeUtil.d.ts +1 -2
  19. package/lib/cjs/tree/treeUtil.js +2 -3
  20. package/lib/es/cascader/foundation.d.ts +4 -11
  21. package/lib/es/cascader/foundation.js +27 -18
  22. package/lib/es/cascader/util.d.ts +6 -0
  23. package/lib/es/cascader/util.js +40 -0
  24. package/lib/es/datePicker/foundation.js +3 -0
  25. package/lib/es/dropdown/dropdown.css +1 -0
  26. package/lib/es/dropdown/dropdown.scss +1 -0
  27. package/lib/es/image/previewInnerFoundation.js +3 -0
  28. package/lib/es/select/foundation.js +2 -0
  29. package/lib/es/select/select.scss +3 -4
  30. package/lib/es/select/variables.scss +7 -6
  31. package/lib/es/tooltip/foundation.js +11 -0
  32. package/lib/es/tree/treeUtil.d.ts +1 -2
  33. package/lib/es/tree/treeUtil.js +2 -3
  34. package/package.json +3 -3
  35. package/select/foundation.ts +2 -0
  36. package/select/select.scss +3 -4
  37. package/select/variables.scss +7 -6
  38. package/tooltip/foundation.ts +12 -2
  39. package/tree/treeUtil.ts +2 -3
@@ -1,7 +1,6 @@
1
1
  import { isEqual, get, difference, isUndefined, assign, cloneDeep, isEmpty, isNumber, includes, isFunction, isObject } from 'lodash';
2
2
  import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
3
  import {
4
- filter,
5
4
  findAncestorKeys,
6
5
  calcCheckedKeysForUnchecked,
7
6
  calcCheckedKeysForChecked,
@@ -11,11 +10,13 @@ import {
11
10
  } from '../tree/treeUtil';
12
11
  import { Motion } from '../utils/type';
13
12
  import {
13
+ filter,
14
14
  convertDataToEntities,
15
15
  normalizedArr,
16
16
  isValid,
17
17
  calcMergeType,
18
- getKeysByValuePath
18
+ getKeysByValuePath,
19
+ getKeyByPos
19
20
  } from './util';
20
21
  import { strings } from './constants';
21
22
  import isEnterPress from '../utils/isEnterPress';
@@ -56,6 +57,8 @@ export interface BasicEntity {
56
57
  parentKey?: string;
57
58
  /* key path */
58
59
  path: Array<string>;
60
+ /* pos in treeData */
61
+ pos: string;
59
62
  /* value path */
60
63
  valuePath: Array<string>
61
64
  }
@@ -908,8 +911,8 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
908
911
  if (_notExist) {
909
912
  return false;
910
913
  }
911
- const filteredPath = this.getItemPropPath(key, treeNodeFilterProp).join();
912
- return filter(sugInput, data, filterTreeNode, false, filteredPath);
914
+ const filteredPath = this.getItemPropPath(key, treeNodeFilterProp);
915
+ return filter(sugInput, data, filterTreeNode, filteredPath);
913
916
  })
914
917
  .filter(
915
918
  item => (filterTreeNode && !filterLeafOnly) ||
@@ -932,6 +935,7 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
932
935
  const isControlled = this._isControlledComponent();
933
936
  const newState: Partial<BasicCascaderInnerData> = {};
934
937
  if (multiple) {
938
+ newState.isSearching = false;
935
939
  this._adapter.updateInputValue('');
936
940
  this._adapter.notifyOnSearch('');
937
941
  newState.checkedKeys = new Set([]);
@@ -1026,17 +1030,20 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
1026
1030
  this._adapter.notifyListScroll(e, { panelIndex: ind, activeNode: data });
1027
1031
  }
1028
1032
 
1029
- handleTagRemove(e: any, tagValuePath: string[]) {
1033
+ handleTagRemoveByKey = (key: string) => {
1030
1034
  const { keyEntities } = this.getStates();
1031
1035
  const { disabled } = this.getProps();
1032
1036
  if (disabled) {
1033
1037
  /* istanbul ignore next */
1034
1038
  return;
1035
1039
  }
1036
- const removedItem = (Object.values(keyEntities) as BasicEntity[])
1037
- .filter(item => isEqual(item.valuePath, tagValuePath))[0];
1038
- !isEmpty(removedItem) &&
1039
- !removedItem.data.disabled &&
1040
- this._handleMultipleSelect(removedItem);
1040
+ const removedItem = keyEntities[key] ?? {};
1041
+ !removedItem?.data?.disable && this._handleMultipleSelect(removedItem);
1042
+ }
1043
+
1044
+ handleTagRemoveInTrigger = (pos: string) => {
1045
+ const { treeData } = this.getStates();
1046
+ const key = getKeyByPos(pos, treeData);
1047
+ this.handleTagRemoveByKey(key);
1041
1048
  }
1042
1049
  }
package/cascader/util.ts CHANGED
@@ -21,6 +21,36 @@ export function normalizedArr(val: any) {
21
21
  }
22
22
  }
23
23
 
24
+ /**
25
+ * @returns whether option includes sugInput.
26
+ * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
27
+ */
28
+ export function filter(sugInput: string, option: any, filterTreeNode: any, filteredPath?: string[]) {
29
+ if (!filterTreeNode) {
30
+ return true;
31
+ }
32
+ let filterFn = filterTreeNode;
33
+ let target: string;
34
+ if (typeof filterTreeNode === 'boolean') {
35
+ filterFn = (targetVal: string, val: string) => {
36
+ const input = targetVal.toLowerCase();
37
+ return val
38
+ .toLowerCase()
39
+ .includes(input);
40
+ };
41
+ // 当 filterTreeNode 是 bool 类型时,由 Cascader 内部判断是否符合筛选条件,使用 join('') 修复搜索英文逗号导致所有数据被匹配问题
42
+ // When the type of of filterTreeNode is bool, Cascader internally determines whether it meets the filtering conditions.
43
+ // Use join('') to fix the problem that searching for English commas causes all data to be matched.
44
+ target = filteredPath.join('');
45
+ } else {
46
+ // 当 filterTreeNode 为函数类型时,由用户判断是否符合筛选条件,使用 join(), 和原来保持一致
47
+ // When the type of of filterTreeNode is function, the user determines whether it meets the filtering conditions,
48
+ // uses join() to be consistent with the previous version.
49
+ target = filteredPath.join();
50
+ }
51
+ return filterFn(sugInput, target, option);
52
+ }
53
+
24
54
  /**
25
55
  * Traverse all the data by `treeData`.
26
56
  */
@@ -31,10 +61,12 @@ function traverseDataNodes(treeNodes: any, callback: any) {
31
61
  // Process node if is not root
32
62
  if (node) {
33
63
  const key = parent ? `${parent.key}${VALUE_SPLIT}${node.value}` : node.value;
64
+ const pos = parent ? getPosition(parent.pos, ind) : `${ind}`;
34
65
  item = {
35
66
  data: { ...node },
36
67
  ind,
37
68
  key,
69
+ pos,
38
70
  level: parent ? parent.level + 1 : 0,
39
71
  parentKey: parent ? parent.key : null,
40
72
  path: parent ? [...parent.path, key] : [key],
@@ -74,6 +106,17 @@ export function getValuePathByKey(key: string) {
74
106
  return key.split(VALUE_SPLIT);
75
107
  }
76
108
 
109
+ export function getKeyByPos(pos: string, treeData: any) {
110
+ const posArr = pos.split('-').map(item => Number(item));
111
+ let resultData = treeData;
112
+ let valuePath = [];
113
+ posArr.forEach((item, index) => {
114
+ resultData = index === 0 ? resultData[item] : resultData?.children?.[item];
115
+ valuePath.push(resultData?.value);
116
+ });
117
+ return getKeyByValuePath(valuePath);
118
+ }
119
+
77
120
  export function convertDataToEntities(dataNodes: any) {
78
121
  const keyEntities: any = {};
79
122
 
@@ -18,6 +18,7 @@ import type { Type, DateInputFoundationProps, InsetInputValue } from './inputFou
18
18
  import type { MonthsGridFoundationProps } from './monthsGridFoundation';
19
19
  import type { WeekStartNumber } from './_utils/getMonthTable';
20
20
  import isValidTimeZone from './_utils/isValidTimeZone';
21
+ import warning from '../utils/warning';
21
22
 
22
23
  export type ValidateStatus = ArrayElement<typeof strings.STATUS>;
23
24
  export type InputSize = ArrayElement<typeof strings.SIZE_SET>;
@@ -292,6 +293,8 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
292
293
  parsedV = zonedTimeToUtc(parsedV, prevTimeZone);
293
294
  }
294
295
  result.push(isValidTimeZone(timeZone) ? utcToZonedTime(parsedV, timeZone) : parsedV);
296
+ } else {
297
+ warning(true, `[Semi DatePicker] value cannot be parsed, value: ${String(v)}`);
295
298
  }
296
299
  }
297
300
  }
@@ -7,6 +7,7 @@ $module: #{$prefix}-dropdown;
7
7
  .#{$module} {
8
8
  @include font-size-regular;
9
9
  &-wrapper {
10
+ overflow-y:auto; // prevent flow out of the radius limit area
10
11
  @include shadow-elevated;
11
12
  position: relative;
12
13
  z-index: $z-dropdown;
@@ -226,6 +226,10 @@ export default class PreviewInnerFoundation<P = Record<string, any>, S = Record<
226
226
  }
227
227
 
228
228
  const preloadImages = getPreloadImagArr(imgSrc, currentIndex, preLoadGap, infinite);
229
+ if (preloadImages.length === 0) {
230
+ return;
231
+ }
232
+
229
233
  const Img = new Image();
230
234
  let index = 0;
231
235
  function callback(e: any) {
@@ -24,6 +24,7 @@ export interface BasicEntity {
24
24
  parent?: BasicEntity;
25
25
  parentKey?: string;
26
26
  path: Array<string>;
27
+ pos: string;
27
28
  valuePath: Array<string>;
28
29
  }
29
30
  export interface BasicCascaderData {
@@ -239,16 +240,7 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
239
240
  * @param {boolean} curCheckedStatus checked status of node
240
241
  */
241
242
  calcCheckedKeys(key: string, curCheckedStatus: boolean): {
242
- checkedKeys: Set<string>; /**
243
- * If selectedKeys does not meet the update conditions,
244
- * and state.selectedKeys is the same as selectedKeys
245
- * at this time, state.selectedKeys should be cleared.
246
- * A typical scenario is:
247
- * The originally selected node is the leaf node, but
248
- * after props.treeData is dynamically updated, the node
249
- * is a non-leaf node. At this point, selectedKeys should
250
- * be cleared.
251
- */
243
+ checkedKeys: Set<string>;
252
244
  halfCheckedKeys: Set<string>;
253
245
  };
254
246
  handleInputChange(sugInput: string): void;
@@ -260,5 +252,6 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
260
252
  getRenderData(): BasicEntity[] | BasicData[];
261
253
  getFilteredData(): BasicData[];
262
254
  handleListScroll(e: any, ind: number): void;
263
- handleTagRemove(e: any, tagValuePath: string[]): void;
255
+ handleTagRemoveByKey: (key: string) => void;
256
+ handleTagRemoveInTrigger: (pos: string) => void;
264
257
  }
@@ -29,6 +29,28 @@ class CascaderFoundation extends _foundation.default {
29
29
  isSearching: false
30
30
  });
31
31
  };
32
+ this.handleTagRemoveByKey = key => {
33
+ var _a, _b;
34
+ const {
35
+ keyEntities
36
+ } = this.getStates();
37
+ const {
38
+ disabled
39
+ } = this.getProps();
40
+ if (disabled) {
41
+ /* istanbul ignore next */
42
+ return;
43
+ }
44
+ const removedItem = (_a = keyEntities[key]) !== null && _a !== void 0 ? _a : {};
45
+ !((_b = removedItem === null || removedItem === void 0 ? void 0 : removedItem.data) === null || _b === void 0 ? void 0 : _b.disable) && this._handleMultipleSelect(removedItem);
46
+ };
47
+ this.handleTagRemoveInTrigger = pos => {
48
+ const {
49
+ treeData
50
+ } = this.getStates();
51
+ const key = (0, _util.getKeyByPos)(pos, treeData);
52
+ this.handleTagRemoveByKey(key);
53
+ };
32
54
  }
33
55
  init() {
34
56
  const isOpen = this.getProp('open') || this.getProp('defaultOpen');
@@ -737,8 +759,8 @@ class CascaderFoundation extends _foundation.default {
737
759
  if (_notExist) {
738
760
  return false;
739
761
  }
740
- const filteredPath = this.getItemPropPath(key, treeNodeFilterProp).join();
741
- return (0, _treeUtil.filter)(sugInput, data, filterTreeNode, false, filteredPath);
762
+ const filteredPath = this.getItemPropPath(key, treeNodeFilterProp);
763
+ return (0, _util.filter)(sugInput, data, filterTreeNode, filteredPath);
742
764
  }).filter(item => filterTreeNode && !filterLeafOnly || this._isLeaf(item)).map(item => item.key);
743
765
  }
744
766
  this._adapter.updateStates({
@@ -760,6 +782,7 @@ class CascaderFoundation extends _foundation.default {
760
782
  const isControlled = this._isControlledComponent();
761
783
  const newState = {};
762
784
  if (multiple) {
785
+ newState.isSearching = false;
763
786
  this._adapter.updateInputValue('');
764
787
  this._adapter.notifyOnSearch('');
765
788
  newState.checkedKeys = new Set([]);
@@ -862,19 +885,5 @@ class CascaderFoundation extends _foundation.default {
862
885
  activeNode: data
863
886
  });
864
887
  }
865
- handleTagRemove(e, tagValuePath) {
866
- const {
867
- keyEntities
868
- } = this.getStates();
869
- const {
870
- disabled
871
- } = this.getProps();
872
- if (disabled) {
873
- /* istanbul ignore next */
874
- return;
875
- }
876
- const removedItem = Object.values(keyEntities).filter(item => (0, _isEqual2.default)(item.valuePath, tagValuePath))[0];
877
- !(0, _isEmpty2.default)(removedItem) && !removedItem.data.disabled && this._handleMultipleSelect(removedItem);
878
- }
879
888
  }
880
889
  exports.default = CascaderFoundation;
@@ -1,7 +1,13 @@
1
1
  export declare function isValid(val: any): boolean;
2
2
  export declare function normalizedArr(val: any): any[];
3
+ /**
4
+ * @returns whether option includes sugInput.
5
+ * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
6
+ */
7
+ export declare function filter(sugInput: string, option: any, filterTreeNode: any, filteredPath?: string[]): any;
3
8
  export declare function getKeysByValuePath(valuePath: (string | number)[][] | (string | number)[]): string[];
4
9
  export declare function getKeyByValuePath(valuePath: (string | number)[]): string;
5
10
  export declare function getValuePathByKey(key: string): string[];
11
+ export declare function getKeyByPos(pos: string, treeData: any): string;
6
12
  export declare function convertDataToEntities(dataNodes: any): any;
7
13
  export declare function calcMergeType(autoMergeValue: boolean, leafOnly: boolean): string;
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.calcMergeType = calcMergeType;
7
7
  exports.convertDataToEntities = convertDataToEntities;
8
+ exports.filter = filter;
9
+ exports.getKeyByPos = getKeyByPos;
8
10
  exports.getKeyByValuePath = getKeyByValuePath;
9
11
  exports.getKeysByValuePath = getKeysByValuePath;
10
12
  exports.getValuePathByKey = getValuePathByKey;
@@ -27,6 +29,33 @@ function normalizedArr(val) {
27
29
  return val;
28
30
  }
29
31
  }
32
+ /**
33
+ * @returns whether option includes sugInput.
34
+ * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
35
+ */
36
+ function filter(sugInput, option, filterTreeNode, filteredPath) {
37
+ if (!filterTreeNode) {
38
+ return true;
39
+ }
40
+ let filterFn = filterTreeNode;
41
+ let target;
42
+ if (typeof filterTreeNode === 'boolean') {
43
+ filterFn = (targetVal, val) => {
44
+ const input = targetVal.toLowerCase();
45
+ return val.toLowerCase().includes(input);
46
+ };
47
+ // 当 filterTreeNode 是 bool 类型时,由 Cascader 内部判断是否符合筛选条件,使用 join('') 修复搜索英文逗号导致所有数据被匹配问题
48
+ // When the type of of filterTreeNode is bool, Cascader internally determines whether it meets the filtering conditions.
49
+ // Use join('') to fix the problem that searching for English commas causes all data to be matched.
50
+ target = filteredPath.join('');
51
+ } else {
52
+ // 当 filterTreeNode 为函数类型时,由用户判断是否符合筛选条件,使用 join(), 和原来保持一致
53
+ // When the type of of filterTreeNode is function, the user determines whether it meets the filtering conditions,
54
+ // uses join() to be consistent with the previous version.
55
+ target = filteredPath.join();
56
+ }
57
+ return filterFn(sugInput, target, option);
58
+ }
30
59
  /**
31
60
  * Traverse all the data by `treeData`.
32
61
  */
@@ -37,10 +66,12 @@ function traverseDataNodes(treeNodes, callback) {
37
66
  // Process node if is not root
38
67
  if (node) {
39
68
  const key = parent ? `${parent.key}${_constants.VALUE_SPLIT}${node.value}` : node.value;
69
+ const pos = parent ? getPosition(parent.pos, ind) : `${ind}`;
40
70
  item = {
41
71
  data: Object.assign({}, node),
42
72
  ind,
43
73
  key,
74
+ pos,
44
75
  level: parent ? parent.level + 1 : 0,
45
76
  parentKey: parent ? parent.key : null,
46
77
  path: parent ? [...parent.path, key] : [key],
@@ -73,6 +104,17 @@ function getKeyByValuePath(valuePath) {
73
104
  function getValuePathByKey(key) {
74
105
  return key.split(_constants.VALUE_SPLIT);
75
106
  }
107
+ function getKeyByPos(pos, treeData) {
108
+ const posArr = pos.split('-').map(item => Number(item));
109
+ let resultData = treeData;
110
+ let valuePath = [];
111
+ posArr.forEach((item, index) => {
112
+ var _a;
113
+ resultData = index === 0 ? resultData[item] : (_a = resultData === null || resultData === void 0 ? void 0 : resultData.children) === null || _a === void 0 ? void 0 : _a[item];
114
+ valuePath.push(resultData === null || resultData === void 0 ? void 0 : resultData.value);
115
+ });
116
+ return getKeyByValuePath(valuePath);
117
+ }
76
118
  function convertDataToEntities(dataNodes) {
77
119
  const keyEntities = {};
78
120
  traverseDataNodes(dataNodes, data => {
@@ -21,6 +21,7 @@ var _constants2 = require("../input/constants");
21
21
  var _getInsetInputFormatToken = _interopRequireDefault(require("./_utils/getInsetInputFormatToken"));
22
22
  var _getInsetInputValueFromInsetInputStr = _interopRequireDefault(require("./_utils/getInsetInputValueFromInsetInputStr"));
23
23
  var _isValidTimeZone = _interopRequireDefault(require("./_utils/isValidTimeZone"));
24
+ var _warning = _interopRequireDefault(require("../utils/warning"));
24
25
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26
  /**
26
27
  * The datePicker foundation.js is responsible for maintaining the date value and the input box value, as well as the callback of both
@@ -125,6 +126,8 @@ class DatePickerFoundation extends _foundation.default {
125
126
  parsedV = (0, _dateFnsExtra.zonedTimeToUtc)(parsedV, prevTimeZone);
126
127
  }
127
128
  result.push((0, _isValidTimeZone.default)(timeZone) ? (0, _dateFnsExtra.utcToZonedTime)(parsedV, timeZone) : parsedV);
129
+ } else {
130
+ (0, _warning.default)(true, `[Semi DatePicker] value cannot be parsed, value: ${String(v)}`);
128
131
  }
129
132
  }
130
133
  }
@@ -7,6 +7,7 @@
7
7
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
8
8
  }
9
9
  .semi-dropdown-wrapper {
10
+ overflow-y: auto;
10
11
  box-shadow: var(--semi-shadow-elevated);
11
12
  position: relative;
12
13
  z-index: 1050;
@@ -7,6 +7,7 @@ $module: #{$prefix}-dropdown;
7
7
  .#{$module} {
8
8
  @include font-size-regular;
9
9
  &-wrapper {
10
+ overflow-y:auto; // prevent flow out of the radius limit area
10
11
  @include shadow-elevated;
11
12
  position: relative;
12
13
  z-index: $z-dropdown;
@@ -231,6 +231,9 @@ class PreviewInnerFoundation extends _foundation.default {
231
231
  return;
232
232
  }
233
233
  const preloadImages = (0, _utils.getPreloadImagArr)(imgSrc, currentIndex, preLoadGap, infinite);
234
+ if (preloadImages.length === 0) {
235
+ return;
236
+ }
234
237
  const Img = new Image();
235
238
  let index = 0;
236
239
  function callback(e) {
@@ -1017,6 +1017,8 @@ class SelectFoundation extends _foundation.default {
1017
1017
  if (filter) {
1018
1018
  this.clearInput(e);
1019
1019
  }
1020
+ // after click showClear button, the select need to be focused
1021
+ this.focus();
1020
1022
  this.clearSelected();
1021
1023
  // prevent this click open dropdown
1022
1024
  e.stopPropagation();
@@ -59,12 +59,12 @@ $overflowList: #{$prefix}-overflow-list;
59
59
 
60
60
  &-open,
61
61
  &-focus {
62
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
62
+ border: $width-select-border-focus solid $color-select_default-border-focus;
63
63
  outline: 0;
64
64
 
65
65
  &:hover {
66
66
  background-color: $color-select-bg-default;
67
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
67
+ border: $width-select-border-hover solid $color-select_default-border-focus;
68
68
  }
69
69
 
70
70
  // when click the trigger, trigger get the focus state, active style should take effect
@@ -124,9 +124,8 @@ $overflowList: #{$prefix}-overflow-list;
124
124
  }
125
125
 
126
126
  &:focus {
127
- // border: $border-thickness-control-focus solid $color-select_default-border-focus;
128
127
  // when select is disabled, the border should not have active color
129
- border: $border-thickness-control-focus solid transparent;
128
+ border: $width-select-border-focus solid transparent;
130
129
  }
131
130
 
132
131
  .#{$module}-selection,
@@ -6,7 +6,8 @@ $color-select-bg-focus: var(--semi-color-fill-0); // 选择器输入框背景色
6
6
  $color-select-border-default: transparent; // 选择器输入框描边颜色
7
7
  $color-select-border-hover: $color-select-border-default; // 选择器输入框描边颜色 - 悬浮
8
8
  $color-select-border-active: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 按下态
9
- $color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 悬停态
9
+ $color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 选中态
10
+
10
11
  $color-select_warning-bg-default: var(--semi-color-warning-light-default); // 警示选择器输入框背景色 - 默认态
11
12
  $color-select_warning-border-default: var(--semi-color-warning-light-default); // 警示选择器输入框描边颜色 - 默认态
12
13
  $color-select_warning-bg-hover: var(--semi-color-warning-light-hover); // 警示选择器输入框背景色 - 悬停态
@@ -15,6 +16,7 @@ $color-select_warning-bg-focus: var(--semi-color-warning-light-default); // 警
15
16
  $color-select_warning-border-focus: var(--semi-color-warning); // 警示选择器输入框描边颜色 - 选中态
16
17
  $color-select_warning-bg-active: var(--semi-color-warning-light-active); // 警示选择器输入框背景色 - 按下态
17
18
  $color-select_warning-border-active: var(--semi-color-warning-light-active); // 警示选择器输入框描边颜色 - 按下态
19
+
18
20
  $color-select_danger-bg-default: var(--semi-color-danger-light-default); // 报错选择器输入框背景色 - 默认态
19
21
  $color-select_danger-border-default: var(--semi-color-danger-light-default); // 报错选择器输入框描边颜色 - 默认态
20
22
  $color-select_danger-bg-hover: var(--semi-color-danger-light-hover); // 报错选择器输入框背景色 - 悬停态
@@ -23,7 +25,9 @@ $color-select_danger-bg-focus: var(--semi-color-danger-light-default); // 报错
23
25
  $color-select_danger-border-focus: var(--semi-color-danger); // 报错选择器输入框描边颜色 - 选中态
24
26
  $color-select_danger-bg-active: var(--semi-color-danger-light-active); // 报错选择器输入框背景色 - 按下态
25
27
  $color-select_danger-border-active: var(--semi-color-danger-light-active); // 报错选择器输入框描边颜色 - 按下态
26
- $color-select_default-border-focus: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 选中态
28
+
29
+ $color-select_default-border-focus: var(--semi-color-focus-border); // 默认选择器输入框描边颜色 - 选中态
30
+
27
31
  $color-select_main-text-default: var(--semi-color-text-0); // 选择器输入框回填内容文本颜色
28
32
  $color-select-icon-default: var(--semi-color-text-2); // 选择器输入框图标颜色
29
33
  $color-select_clearBtn-text-default: var(--semi-color-text-2); // 选择器输入框清空按钮颜色 - 默认态
@@ -34,6 +38,7 @@ $color-select_input_disabled-border: var(--semi-color-border); // 禁用选择
34
38
  $color-select_input_disabled-text: var(--semi-color-disabled-text); // 禁用选择器输入框回填内容文字颜色
35
39
  $color-select_input_disabled-bg-hover: var(--semi-color-disabled-fill); // 选择器输入框回填内容文字颜色 - 悬停态
36
40
  $color-select_input_placeholder-text: var(--semi-color-text-2); // 选择器输入框占位文本文字颜色
41
+
37
42
  $color-select_option_main-text: var(--semi-color-text-0); // 选择器菜单选项文本颜色
38
43
  $color-select_option_keyword-text: var(--semi-color-primary); // 选择器菜单选项匹配搜索结果文本颜色
39
44
  $color-select_option-bg-default: transparent; // 选择器菜单选项背景颜色 - 默认态
@@ -88,10 +93,6 @@ $spacing-select_option-paddingTop: $spacing-tight; // 选择器菜单项顶部
88
93
  $spacing-select_option-paddingBottom: $spacing-tight; // 选择器菜单项底部内边距
89
94
 
90
95
 
91
- // $spacing-select_option_first-marginTop: $spacing-extra-tight; // 选择器第一个菜单项顶部外边距
92
- // $spacing-select_option_last-marginBottom: $spacing-extra-tight; // 选择器最后一个菜单项顶部外边距
93
-
94
-
95
96
  $spacing-select_tag-marginTop: $spacing-super-tight - 1px; // 多项选择器标签顶部外边距
96
97
  $spacing-select_tag-marginRight: $spacing-extra-tight; // 多项选择器标签右侧外边距
97
98
  $spacing-select_tag-marginBottom: $spacing-super-tight - 1px; // 多项选择器标签底部外边距
@@ -427,6 +427,7 @@ class Tooltip extends _foundation.default {
427
427
  return null;
428
428
  }
429
429
  calcPosStyle(props) {
430
+ var _a;
430
431
  const {
431
432
  spacing,
432
433
  isOverFlow
@@ -477,6 +478,10 @@ class Tooltip extends _foundation.default {
477
478
  const isTriggerNearLeft = middleX - containerRect.left < containerRect.right - middleX;
478
479
  const isTriggerNearTop = middleY - containerRect.top < containerRect.bottom - middleY;
479
480
  const isWrapperWidthOverflow = wrapperRect.width > innerWidth;
481
+ const scaled = Math.abs((wrapperRect === null || wrapperRect === void 0 ? void 0 : wrapperRect.width) - ((_a = this._adapter.getContainer()) === null || _a === void 0 ? void 0 : _a.clientWidth)) > 1;
482
+ if (scaled) {
483
+ SPACING = SPACING * wrapperRect.width / this._adapter.getContainer().clientWidth;
484
+ }
480
485
  switch (position) {
481
486
  case 'top':
482
487
  // left = middleX;
@@ -593,6 +598,12 @@ class Tooltip extends _foundation.default {
593
598
  // Calculate container positioning relative to window
594
599
  left = left - containerRect.left;
595
600
  top = top - containerRect.top;
601
+ if (scaled) {
602
+ left /= wrapperRect.width / this._adapter.getContainer().clientWidth;
603
+ }
604
+ if (scaled) {
605
+ top /= wrapperRect.height / this._adapter.getContainer().clientHeight;
606
+ }
596
607
  /**
597
608
  * container为body时,如果position不为relative或absolute,这时trigger计算出的top/left会根据html定位(initial containing block)
598
609
  * 此时如果body有margin,则计算出的位置相对于body会有问题 fix issue #1368
@@ -60,9 +60,8 @@ export declare function calcMotionKeys(oldKeySet: Set<string>, newKeySet: Set<st
60
60
  /**
61
61
  * @returns whether option includes sugInput.
62
62
  * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
63
- * The filteredPath parameter will only be passed in when the Cascader calls the filter function
64
63
  */
65
- export declare function filter(sugInput: string, option: any, filterTreeNode: any, filterProps: any, filteredPath?: string): any;
64
+ export declare function filter(sugInput: string, option: any, filterTreeNode: any, filterProps: any): any;
66
65
  export declare function normalizedArr(val: any): any[];
67
66
  export declare function normalizeKeyList(keyList: any, keyEntities: KeyEntities, leafOnly?: boolean, flag?: boolean): string[];
68
67
  export declare function getMotionKeys(eventKey: string, expandedKeys: Set<string>, keyEntities: KeyEntities): any[];
@@ -423,14 +423,13 @@ function calcMotionKeys(oldKeySet, newKeySet, keyEntities) {
423
423
  /**
424
424
  * @returns whether option includes sugInput.
425
425
  * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
426
- * The filteredPath parameter will only be passed in when the Cascader calls the filter function
427
426
  */
428
- function filter(sugInput, option, filterTreeNode, filterProps, filteredPath) {
427
+ function filter(sugInput, option, filterTreeNode, filterProps) {
429
428
  if (!filterTreeNode) {
430
429
  return true;
431
430
  }
432
431
  let filterFn = filterTreeNode;
433
- let target = filteredPath !== null && filteredPath !== void 0 ? filteredPath : option;
432
+ let target = option;
434
433
  if (typeof filterTreeNode === 'boolean') {
435
434
  filterFn = (targetVal, val) => {
436
435
  const input = targetVal.toLowerCase();
@@ -24,6 +24,7 @@ export interface BasicEntity {
24
24
  parent?: BasicEntity;
25
25
  parentKey?: string;
26
26
  path: Array<string>;
27
+ pos: string;
27
28
  valuePath: Array<string>;
28
29
  }
29
30
  export interface BasicCascaderData {
@@ -239,16 +240,7 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
239
240
  * @param {boolean} curCheckedStatus checked status of node
240
241
  */
241
242
  calcCheckedKeys(key: string, curCheckedStatus: boolean): {
242
- checkedKeys: Set<string>; /**
243
- * If selectedKeys does not meet the update conditions,
244
- * and state.selectedKeys is the same as selectedKeys
245
- * at this time, state.selectedKeys should be cleared.
246
- * A typical scenario is:
247
- * The originally selected node is the leaf node, but
248
- * after props.treeData is dynamically updated, the node
249
- * is a non-leaf node. At this point, selectedKeys should
250
- * be cleared.
251
- */
243
+ checkedKeys: Set<string>;
252
244
  halfCheckedKeys: Set<string>;
253
245
  };
254
246
  handleInputChange(sugInput: string): void;
@@ -260,5 +252,6 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
260
252
  getRenderData(): BasicEntity[] | BasicData[];
261
253
  getFilteredData(): BasicData[];
262
254
  handleListScroll(e: any, ind: number): void;
263
- handleTagRemove(e: any, tagValuePath: string[]): void;
255
+ handleTagRemoveByKey: (key: string) => void;
256
+ handleTagRemoveInTrigger: (pos: string) => void;
264
257
  }
@@ -10,8 +10,8 @@ import _difference from "lodash/difference";
10
10
  import _get from "lodash/get";
11
11
  import _isEqual from "lodash/isEqual";
12
12
  import BaseFoundation from '../base/foundation';
13
- import { filter, findAncestorKeys, calcCheckedKeysForUnchecked, calcCheckedKeysForChecked, calcCheckedKeys, findDescendantKeys, normalizeKeyList } from '../tree/treeUtil';
14
- import { convertDataToEntities, normalizedArr, isValid, calcMergeType, getKeysByValuePath } from './util';
13
+ import { findAncestorKeys, calcCheckedKeysForUnchecked, calcCheckedKeysForChecked, calcCheckedKeys, findDescendantKeys, normalizeKeyList } from '../tree/treeUtil';
14
+ import { filter, convertDataToEntities, normalizedArr, isValid, calcMergeType, getKeysByValuePath, getKeyByPos } from './util';
15
15
  import { strings } from './constants';
16
16
  import isEnterPress from '../utils/isEnterPress';
17
17
  export default class CascaderFoundation extends BaseFoundation {
@@ -22,6 +22,28 @@ export default class CascaderFoundation extends BaseFoundation {
22
22
  isSearching: false
23
23
  });
24
24
  };
25
+ this.handleTagRemoveByKey = key => {
26
+ var _a, _b;
27
+ const {
28
+ keyEntities
29
+ } = this.getStates();
30
+ const {
31
+ disabled
32
+ } = this.getProps();
33
+ if (disabled) {
34
+ /* istanbul ignore next */
35
+ return;
36
+ }
37
+ const removedItem = (_a = keyEntities[key]) !== null && _a !== void 0 ? _a : {};
38
+ !((_b = removedItem === null || removedItem === void 0 ? void 0 : removedItem.data) === null || _b === void 0 ? void 0 : _b.disable) && this._handleMultipleSelect(removedItem);
39
+ };
40
+ this.handleTagRemoveInTrigger = pos => {
41
+ const {
42
+ treeData
43
+ } = this.getStates();
44
+ const key = getKeyByPos(pos, treeData);
45
+ this.handleTagRemoveByKey(key);
46
+ };
25
47
  }
26
48
  init() {
27
49
  const isOpen = this.getProp('open') || this.getProp('defaultOpen');
@@ -730,8 +752,8 @@ export default class CascaderFoundation extends BaseFoundation {
730
752
  if (_notExist) {
731
753
  return false;
732
754
  }
733
- const filteredPath = this.getItemPropPath(key, treeNodeFilterProp).join();
734
- return filter(sugInput, data, filterTreeNode, false, filteredPath);
755
+ const filteredPath = this.getItemPropPath(key, treeNodeFilterProp);
756
+ return filter(sugInput, data, filterTreeNode, filteredPath);
735
757
  }).filter(item => filterTreeNode && !filterLeafOnly || this._isLeaf(item)).map(item => item.key);
736
758
  }
737
759
  this._adapter.updateStates({
@@ -753,6 +775,7 @@ export default class CascaderFoundation extends BaseFoundation {
753
775
  const isControlled = this._isControlledComponent();
754
776
  const newState = {};
755
777
  if (multiple) {
778
+ newState.isSearching = false;
756
779
  this._adapter.updateInputValue('');
757
780
  this._adapter.notifyOnSearch('');
758
781
  newState.checkedKeys = new Set([]);
@@ -855,18 +878,4 @@ export default class CascaderFoundation extends BaseFoundation {
855
878
  activeNode: data
856
879
  });
857
880
  }
858
- handleTagRemove(e, tagValuePath) {
859
- const {
860
- keyEntities
861
- } = this.getStates();
862
- const {
863
- disabled
864
- } = this.getProps();
865
- if (disabled) {
866
- /* istanbul ignore next */
867
- return;
868
- }
869
- const removedItem = Object.values(keyEntities).filter(item => _isEqual(item.valuePath, tagValuePath))[0];
870
- !_isEmpty(removedItem) && !removedItem.data.disabled && this._handleMultipleSelect(removedItem);
871
- }
872
881
  }
@@ -1,7 +1,13 @@
1
1
  export declare function isValid(val: any): boolean;
2
2
  export declare function normalizedArr(val: any): any[];
3
+ /**
4
+ * @returns whether option includes sugInput.
5
+ * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
6
+ */
7
+ export declare function filter(sugInput: string, option: any, filterTreeNode: any, filteredPath?: string[]): any;
3
8
  export declare function getKeysByValuePath(valuePath: (string | number)[][] | (string | number)[]): string[];
4
9
  export declare function getKeyByValuePath(valuePath: (string | number)[]): string;
5
10
  export declare function getValuePathByKey(key: string): string[];
11
+ export declare function getKeyByPos(pos: string, treeData: any): string;
6
12
  export declare function convertDataToEntities(dataNodes: any): any;
7
13
  export declare function calcMergeType(autoMergeValue: boolean, leafOnly: boolean): string;
@@ -14,6 +14,33 @@ export function normalizedArr(val) {
14
14
  return val;
15
15
  }
16
16
  }
17
+ /**
18
+ * @returns whether option includes sugInput.
19
+ * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
20
+ */
21
+ export function filter(sugInput, option, filterTreeNode, filteredPath) {
22
+ if (!filterTreeNode) {
23
+ return true;
24
+ }
25
+ let filterFn = filterTreeNode;
26
+ let target;
27
+ if (typeof filterTreeNode === 'boolean') {
28
+ filterFn = (targetVal, val) => {
29
+ const input = targetVal.toLowerCase();
30
+ return val.toLowerCase().includes(input);
31
+ };
32
+ // 当 filterTreeNode 是 bool 类型时,由 Cascader 内部判断是否符合筛选条件,使用 join('') 修复搜索英文逗号导致所有数据被匹配问题
33
+ // When the type of of filterTreeNode is bool, Cascader internally determines whether it meets the filtering conditions.
34
+ // Use join('') to fix the problem that searching for English commas causes all data to be matched.
35
+ target = filteredPath.join('');
36
+ } else {
37
+ // 当 filterTreeNode 为函数类型时,由用户判断是否符合筛选条件,使用 join(), 和原来保持一致
38
+ // When the type of of filterTreeNode is function, the user determines whether it meets the filtering conditions,
39
+ // uses join() to be consistent with the previous version.
40
+ target = filteredPath.join();
41
+ }
42
+ return filterFn(sugInput, target, option);
43
+ }
17
44
  /**
18
45
  * Traverse all the data by `treeData`.
19
46
  */
@@ -24,10 +51,12 @@ function traverseDataNodes(treeNodes, callback) {
24
51
  // Process node if is not root
25
52
  if (node) {
26
53
  const key = parent ? `${parent.key}${VALUE_SPLIT}${node.value}` : node.value;
54
+ const pos = parent ? getPosition(parent.pos, ind) : `${ind}`;
27
55
  item = {
28
56
  data: Object.assign({}, node),
29
57
  ind,
30
58
  key,
59
+ pos,
31
60
  level: parent ? parent.level + 1 : 0,
32
61
  parentKey: parent ? parent.key : null,
33
62
  path: parent ? [...parent.path, key] : [key],
@@ -60,6 +89,17 @@ export function getKeyByValuePath(valuePath) {
60
89
  export function getValuePathByKey(key) {
61
90
  return key.split(VALUE_SPLIT);
62
91
  }
92
+ export function getKeyByPos(pos, treeData) {
93
+ const posArr = pos.split('-').map(item => Number(item));
94
+ let resultData = treeData;
95
+ let valuePath = [];
96
+ posArr.forEach((item, index) => {
97
+ var _a;
98
+ resultData = index === 0 ? resultData[item] : (_a = resultData === null || resultData === void 0 ? void 0 : resultData.children) === null || _a === void 0 ? void 0 : _a[item];
99
+ valuePath.push(resultData === null || resultData === void 0 ? void 0 : resultData.value);
100
+ });
101
+ return getKeyByValuePath(valuePath);
102
+ }
63
103
  export function convertDataToEntities(dataNodes) {
64
104
  const keyEntities = {};
65
105
  traverseDataNodes(dataNodes, data => {
@@ -15,6 +15,7 @@ import { strings as inputStrings } from '../input/constants';
15
15
  import getInsetInputFormatToken from './_utils/getInsetInputFormatToken';
16
16
  import getInsetInputValueFromInsetInputStr from './_utils/getInsetInputValueFromInsetInputStr';
17
17
  import isValidTimeZone from './_utils/isValidTimeZone';
18
+ import warning from '../utils/warning';
18
19
  /**
19
20
  * The datePicker foundation.js is responsible for maintaining the date value and the input box value, as well as the callback of both
20
21
  * task 1. Accept the selected date change, update the date value, and update the input box value according to the date = > Notify the change
@@ -118,6 +119,8 @@ export default class DatePickerFoundation extends BaseFoundation {
118
119
  parsedV = zonedTimeToUtc(parsedV, prevTimeZone);
119
120
  }
120
121
  result.push(isValidTimeZone(timeZone) ? utcToZonedTime(parsedV, timeZone) : parsedV);
122
+ } else {
123
+ warning(true, `[Semi DatePicker] value cannot be parsed, value: ${String(v)}`);
121
124
  }
122
125
  }
123
126
  }
@@ -7,6 +7,7 @@
7
7
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
8
8
  }
9
9
  .semi-dropdown-wrapper {
10
+ overflow-y: auto;
10
11
  box-shadow: var(--semi-shadow-elevated);
11
12
  position: relative;
12
13
  z-index: 1050;
@@ -7,6 +7,7 @@ $module: #{$prefix}-dropdown;
7
7
  .#{$module} {
8
8
  @include font-size-regular;
9
9
  &-wrapper {
10
+ overflow-y:auto; // prevent flow out of the radius limit area
10
11
  @include shadow-elevated;
11
12
  position: relative;
12
13
  z-index: $z-dropdown;
@@ -224,6 +224,9 @@ export default class PreviewInnerFoundation extends BaseFoundation {
224
224
  return;
225
225
  }
226
226
  const preloadImages = getPreloadImagArr(imgSrc, currentIndex, preLoadGap, infinite);
227
+ if (preloadImages.length === 0) {
228
+ return;
229
+ }
227
230
  const Img = new Image();
228
231
  let index = 0;
229
232
  function callback(e) {
@@ -1008,6 +1008,8 @@ export default class SelectFoundation extends BaseFoundation {
1008
1008
  if (filter) {
1009
1009
  this.clearInput(e);
1010
1010
  }
1011
+ // after click showClear button, the select need to be focused
1012
+ this.focus();
1011
1013
  this.clearSelected();
1012
1014
  // prevent this click open dropdown
1013
1015
  e.stopPropagation();
@@ -59,12 +59,12 @@ $overflowList: #{$prefix}-overflow-list;
59
59
 
60
60
  &-open,
61
61
  &-focus {
62
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
62
+ border: $width-select-border-focus solid $color-select_default-border-focus;
63
63
  outline: 0;
64
64
 
65
65
  &:hover {
66
66
  background-color: $color-select-bg-default;
67
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
67
+ border: $width-select-border-hover solid $color-select_default-border-focus;
68
68
  }
69
69
 
70
70
  // when click the trigger, trigger get the focus state, active style should take effect
@@ -124,9 +124,8 @@ $overflowList: #{$prefix}-overflow-list;
124
124
  }
125
125
 
126
126
  &:focus {
127
- // border: $border-thickness-control-focus solid $color-select_default-border-focus;
128
127
  // when select is disabled, the border should not have active color
129
- border: $border-thickness-control-focus solid transparent;
128
+ border: $width-select-border-focus solid transparent;
130
129
  }
131
130
 
132
131
  .#{$module}-selection,
@@ -6,7 +6,8 @@ $color-select-bg-focus: var(--semi-color-fill-0); // 选择器输入框背景色
6
6
  $color-select-border-default: transparent; // 选择器输入框描边颜色
7
7
  $color-select-border-hover: $color-select-border-default; // 选择器输入框描边颜色 - 悬浮
8
8
  $color-select-border-active: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 按下态
9
- $color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 悬停态
9
+ $color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 选中态
10
+
10
11
  $color-select_warning-bg-default: var(--semi-color-warning-light-default); // 警示选择器输入框背景色 - 默认态
11
12
  $color-select_warning-border-default: var(--semi-color-warning-light-default); // 警示选择器输入框描边颜色 - 默认态
12
13
  $color-select_warning-bg-hover: var(--semi-color-warning-light-hover); // 警示选择器输入框背景色 - 悬停态
@@ -15,6 +16,7 @@ $color-select_warning-bg-focus: var(--semi-color-warning-light-default); // 警
15
16
  $color-select_warning-border-focus: var(--semi-color-warning); // 警示选择器输入框描边颜色 - 选中态
16
17
  $color-select_warning-bg-active: var(--semi-color-warning-light-active); // 警示选择器输入框背景色 - 按下态
17
18
  $color-select_warning-border-active: var(--semi-color-warning-light-active); // 警示选择器输入框描边颜色 - 按下态
19
+
18
20
  $color-select_danger-bg-default: var(--semi-color-danger-light-default); // 报错选择器输入框背景色 - 默认态
19
21
  $color-select_danger-border-default: var(--semi-color-danger-light-default); // 报错选择器输入框描边颜色 - 默认态
20
22
  $color-select_danger-bg-hover: var(--semi-color-danger-light-hover); // 报错选择器输入框背景色 - 悬停态
@@ -23,7 +25,9 @@ $color-select_danger-bg-focus: var(--semi-color-danger-light-default); // 报错
23
25
  $color-select_danger-border-focus: var(--semi-color-danger); // 报错选择器输入框描边颜色 - 选中态
24
26
  $color-select_danger-bg-active: var(--semi-color-danger-light-active); // 报错选择器输入框背景色 - 按下态
25
27
  $color-select_danger-border-active: var(--semi-color-danger-light-active); // 报错选择器输入框描边颜色 - 按下态
26
- $color-select_default-border-focus: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 选中态
28
+
29
+ $color-select_default-border-focus: var(--semi-color-focus-border); // 默认选择器输入框描边颜色 - 选中态
30
+
27
31
  $color-select_main-text-default: var(--semi-color-text-0); // 选择器输入框回填内容文本颜色
28
32
  $color-select-icon-default: var(--semi-color-text-2); // 选择器输入框图标颜色
29
33
  $color-select_clearBtn-text-default: var(--semi-color-text-2); // 选择器输入框清空按钮颜色 - 默认态
@@ -34,6 +38,7 @@ $color-select_input_disabled-border: var(--semi-color-border); // 禁用选择
34
38
  $color-select_input_disabled-text: var(--semi-color-disabled-text); // 禁用选择器输入框回填内容文字颜色
35
39
  $color-select_input_disabled-bg-hover: var(--semi-color-disabled-fill); // 选择器输入框回填内容文字颜色 - 悬停态
36
40
  $color-select_input_placeholder-text: var(--semi-color-text-2); // 选择器输入框占位文本文字颜色
41
+
37
42
  $color-select_option_main-text: var(--semi-color-text-0); // 选择器菜单选项文本颜色
38
43
  $color-select_option_keyword-text: var(--semi-color-primary); // 选择器菜单选项匹配搜索结果文本颜色
39
44
  $color-select_option-bg-default: transparent; // 选择器菜单选项背景颜色 - 默认态
@@ -88,10 +93,6 @@ $spacing-select_option-paddingTop: $spacing-tight; // 选择器菜单项顶部
88
93
  $spacing-select_option-paddingBottom: $spacing-tight; // 选择器菜单项底部内边距
89
94
 
90
95
 
91
- // $spacing-select_option_first-marginTop: $spacing-extra-tight; // 选择器第一个菜单项顶部外边距
92
- // $spacing-select_option_last-marginBottom: $spacing-extra-tight; // 选择器最后一个菜单项顶部外边距
93
-
94
-
95
96
  $spacing-select_tag-marginTop: $spacing-super-tight - 1px; // 多项选择器标签顶部外边距
96
97
  $spacing-select_tag-marginRight: $spacing-extra-tight; // 多项选择器标签右侧外边距
97
98
  $spacing-select_tag-marginBottom: $spacing-super-tight - 1px; // 多项选择器标签底部外边距
@@ -420,6 +420,7 @@ export default class Tooltip extends BaseFoundation {
420
420
  return null;
421
421
  }
422
422
  calcPosStyle(props) {
423
+ var _a;
423
424
  const {
424
425
  spacing,
425
426
  isOverFlow
@@ -470,6 +471,10 @@ export default class Tooltip extends BaseFoundation {
470
471
  const isTriggerNearLeft = middleX - containerRect.left < containerRect.right - middleX;
471
472
  const isTriggerNearTop = middleY - containerRect.top < containerRect.bottom - middleY;
472
473
  const isWrapperWidthOverflow = wrapperRect.width > innerWidth;
474
+ const scaled = Math.abs((wrapperRect === null || wrapperRect === void 0 ? void 0 : wrapperRect.width) - ((_a = this._adapter.getContainer()) === null || _a === void 0 ? void 0 : _a.clientWidth)) > 1;
475
+ if (scaled) {
476
+ SPACING = SPACING * wrapperRect.width / this._adapter.getContainer().clientWidth;
477
+ }
473
478
  switch (position) {
474
479
  case 'top':
475
480
  // left = middleX;
@@ -586,6 +591,12 @@ export default class Tooltip extends BaseFoundation {
586
591
  // Calculate container positioning relative to window
587
592
  left = left - containerRect.left;
588
593
  top = top - containerRect.top;
594
+ if (scaled) {
595
+ left /= wrapperRect.width / this._adapter.getContainer().clientWidth;
596
+ }
597
+ if (scaled) {
598
+ top /= wrapperRect.height / this._adapter.getContainer().clientHeight;
599
+ }
589
600
  /**
590
601
  * container为body时,如果position不为relative或absolute,这时trigger计算出的top/left会根据html定位(initial containing block)
591
602
  * 此时如果body有margin,则计算出的位置相对于body会有问题 fix issue #1368
@@ -60,9 +60,8 @@ export declare function calcMotionKeys(oldKeySet: Set<string>, newKeySet: Set<st
60
60
  /**
61
61
  * @returns whether option includes sugInput.
62
62
  * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
63
- * The filteredPath parameter will only be passed in when the Cascader calls the filter function
64
63
  */
65
- export declare function filter(sugInput: string, option: any, filterTreeNode: any, filterProps: any, filteredPath?: string): any;
64
+ export declare function filter(sugInput: string, option: any, filterTreeNode: any, filterProps: any): any;
66
65
  export declare function normalizedArr(val: any): any[];
67
66
  export declare function normalizeKeyList(keyList: any, keyEntities: KeyEntities, leafOnly?: boolean, flag?: boolean): string[];
68
67
  export declare function getMotionKeys(eventKey: string, expandedKeys: Set<string>, keyEntities: KeyEntities): any[];
@@ -388,14 +388,13 @@ export function calcMotionKeys(oldKeySet, newKeySet, keyEntities) {
388
388
  /**
389
389
  * @returns whether option includes sugInput.
390
390
  * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
391
- * The filteredPath parameter will only be passed in when the Cascader calls the filter function
392
391
  */
393
- export function filter(sugInput, option, filterTreeNode, filterProps, filteredPath) {
392
+ export function filter(sugInput, option, filterTreeNode, filterProps) {
394
393
  if (!filterTreeNode) {
395
394
  return true;
396
395
  }
397
396
  let filterFn = filterTreeNode;
398
- let target = filteredPath !== null && filteredPath !== void 0 ? filteredPath : option;
397
+ let target = option;
399
398
  if (typeof filterTreeNode === 'boolean') {
400
399
  filterFn = (targetVal, val) => {
401
400
  const input = targetVal.toLowerCase();
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-foundation",
3
- "version": "2.52.0-beta.1",
3
+ "version": "2.52.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build:lib": "node ./scripts/compileLib.js",
7
7
  "prepublishOnly": "npm run build:lib"
8
8
  },
9
9
  "dependencies": {
10
- "@douyinfe/semi-animation": "2.52.0-beta.1",
10
+ "@douyinfe/semi-animation": "2.52.0",
11
11
  "async-validator": "^3.5.0",
12
12
  "classnames": "^2.2.6",
13
13
  "date-fns": "^2.29.3",
@@ -23,7 +23,7 @@
23
23
  "*.scss",
24
24
  "*.css"
25
25
  ],
26
- "gitHead": "f06aca5797fda6a3f03a003ddd24591da9a4e6d4",
26
+ "gitHead": "3520c78b985bdeb81c5ce745ebc2f2e11511f8dd",
27
27
  "devDependencies": {
28
28
  "@babel/plugin-transform-runtime": "^7.15.8",
29
29
  "@babel/preset-env": "^7.15.8",
@@ -1022,6 +1022,8 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
1022
1022
  if (filter) {
1023
1023
  this.clearInput(e);
1024
1024
  }
1025
+ // after click showClear button, the select need to be focused
1026
+ this.focus();
1025
1027
  this.clearSelected();
1026
1028
  // prevent this click open dropdown
1027
1029
  e.stopPropagation();
@@ -59,12 +59,12 @@ $overflowList: #{$prefix}-overflow-list;
59
59
 
60
60
  &-open,
61
61
  &-focus {
62
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
62
+ border: $width-select-border-focus solid $color-select_default-border-focus;
63
63
  outline: 0;
64
64
 
65
65
  &:hover {
66
66
  background-color: $color-select-bg-default;
67
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
67
+ border: $width-select-border-hover solid $color-select_default-border-focus;
68
68
  }
69
69
 
70
70
  // when click the trigger, trigger get the focus state, active style should take effect
@@ -124,9 +124,8 @@ $overflowList: #{$prefix}-overflow-list;
124
124
  }
125
125
 
126
126
  &:focus {
127
- // border: $border-thickness-control-focus solid $color-select_default-border-focus;
128
127
  // when select is disabled, the border should not have active color
129
- border: $border-thickness-control-focus solid transparent;
128
+ border: $width-select-border-focus solid transparent;
130
129
  }
131
130
 
132
131
  .#{$module}-selection,
@@ -6,7 +6,8 @@ $color-select-bg-focus: var(--semi-color-fill-0); // 选择器输入框背景色
6
6
  $color-select-border-default: transparent; // 选择器输入框描边颜色
7
7
  $color-select-border-hover: $color-select-border-default; // 选择器输入框描边颜色 - 悬浮
8
8
  $color-select-border-active: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 按下态
9
- $color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 悬停态
9
+ $color-select-border-focus: $color-select-border-active;// 选择器输入框描边颜色 - 选中态
10
+
10
11
  $color-select_warning-bg-default: var(--semi-color-warning-light-default); // 警示选择器输入框背景色 - 默认态
11
12
  $color-select_warning-border-default: var(--semi-color-warning-light-default); // 警示选择器输入框描边颜色 - 默认态
12
13
  $color-select_warning-bg-hover: var(--semi-color-warning-light-hover); // 警示选择器输入框背景色 - 悬停态
@@ -15,6 +16,7 @@ $color-select_warning-bg-focus: var(--semi-color-warning-light-default); // 警
15
16
  $color-select_warning-border-focus: var(--semi-color-warning); // 警示选择器输入框描边颜色 - 选中态
16
17
  $color-select_warning-bg-active: var(--semi-color-warning-light-active); // 警示选择器输入框背景色 - 按下态
17
18
  $color-select_warning-border-active: var(--semi-color-warning-light-active); // 警示选择器输入框描边颜色 - 按下态
19
+
18
20
  $color-select_danger-bg-default: var(--semi-color-danger-light-default); // 报错选择器输入框背景色 - 默认态
19
21
  $color-select_danger-border-default: var(--semi-color-danger-light-default); // 报错选择器输入框描边颜色 - 默认态
20
22
  $color-select_danger-bg-hover: var(--semi-color-danger-light-hover); // 报错选择器输入框背景色 - 悬停态
@@ -23,7 +25,9 @@ $color-select_danger-bg-focus: var(--semi-color-danger-light-default); // 报错
23
25
  $color-select_danger-border-focus: var(--semi-color-danger); // 报错选择器输入框描边颜色 - 选中态
24
26
  $color-select_danger-bg-active: var(--semi-color-danger-light-active); // 报错选择器输入框背景色 - 按下态
25
27
  $color-select_danger-border-active: var(--semi-color-danger-light-active); // 报错选择器输入框描边颜色 - 按下态
26
- $color-select_default-border-focus: var(--semi-color-focus-border); // 选择器输入框描边颜色 - 选中态
28
+
29
+ $color-select_default-border-focus: var(--semi-color-focus-border); // 默认选择器输入框描边颜色 - 选中态
30
+
27
31
  $color-select_main-text-default: var(--semi-color-text-0); // 选择器输入框回填内容文本颜色
28
32
  $color-select-icon-default: var(--semi-color-text-2); // 选择器输入框图标颜色
29
33
  $color-select_clearBtn-text-default: var(--semi-color-text-2); // 选择器输入框清空按钮颜色 - 默认态
@@ -34,6 +38,7 @@ $color-select_input_disabled-border: var(--semi-color-border); // 禁用选择
34
38
  $color-select_input_disabled-text: var(--semi-color-disabled-text); // 禁用选择器输入框回填内容文字颜色
35
39
  $color-select_input_disabled-bg-hover: var(--semi-color-disabled-fill); // 选择器输入框回填内容文字颜色 - 悬停态
36
40
  $color-select_input_placeholder-text: var(--semi-color-text-2); // 选择器输入框占位文本文字颜色
41
+
37
42
  $color-select_option_main-text: var(--semi-color-text-0); // 选择器菜单选项文本颜色
38
43
  $color-select_option_keyword-text: var(--semi-color-primary); // 选择器菜单选项匹配搜索结果文本颜色
39
44
  $color-select_option-bg-default: transparent; // 选择器菜单选项背景颜色 - 默认态
@@ -88,10 +93,6 @@ $spacing-select_option-paddingTop: $spacing-tight; // 选择器菜单项顶部
88
93
  $spacing-select_option-paddingBottom: $spacing-tight; // 选择器菜单项底部内边距
89
94
 
90
95
 
91
- // $spacing-select_option_first-marginTop: $spacing-extra-tight; // 选择器第一个菜单项顶部外边距
92
- // $spacing-select_option_last-marginBottom: $spacing-extra-tight; // 选择器最后一个菜单项顶部外边距
93
-
94
-
95
96
  $spacing-select_tag-marginTop: $spacing-super-tight - 1px; // 多项选择器标签顶部外边距
96
97
  $spacing-select_tag-marginRight: $spacing-extra-tight; // 多项选择器标签右侧外边距
97
98
  $spacing-select_tag-marginBottom: $spacing-super-tight - 1px; // 多项选择器标签底部外边距
@@ -450,7 +450,10 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
450
450
  const isTriggerNearTop = middleY - containerRect.top < containerRect.bottom - middleY;
451
451
 
452
452
  const isWrapperWidthOverflow = wrapperRect.width > innerWidth;
453
-
453
+ const scaled = Math.abs(wrapperRect?.width - this._adapter.getContainer()?.clientWidth) > 1;
454
+ if (scaled) {
455
+ SPACING = SPACING * wrapperRect.width/this._adapter.getContainer().clientWidth;
456
+ }
454
457
  switch (position) {
455
458
  case 'top':
456
459
  // left = middleX;
@@ -570,6 +573,14 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
570
573
  left = left - containerRect.left;
571
574
  top = top - containerRect.top;
572
575
 
576
+ if (scaled) {
577
+ left /= wrapperRect.width/this._adapter.getContainer().clientWidth;
578
+ }
579
+
580
+ if (scaled) {
581
+ top /= wrapperRect.height/this._adapter.getContainer().clientHeight;
582
+ }
583
+
573
584
  /**
574
585
  * container为body时,如果position不为relative或absolute,这时trigger计算出的top/left会根据html定位(initial containing block)
575
586
  * 此时如果body有margin,则计算出的位置相对于body会有问题 fix issue #1368
@@ -828,7 +839,6 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
828
839
 
829
840
  const halfHeight = triggerRect.height / 2;
830
841
  const halfWidth = triggerRect.width / 2;
831
-
832
842
  // 视口, 原空间与反向空间是否都不足判断
833
843
  // Viewport, whether the original space and the reverse space are insufficient to judge
834
844
  const isViewYOverFlow = this.isOverFlow(clientTop - marginTop, restClientBottom - marginBottom, wrapperRect.height + spacing);
package/tree/treeUtil.ts CHANGED
@@ -422,14 +422,13 @@ export function calcMotionKeys(oldKeySet: Set<string>, newKeySet: Set<string>, k
422
422
  /**
423
423
  * @returns whether option includes sugInput.
424
424
  * When filterTreeNode is a function,returns the result of filterTreeNode which called with (sugInput, target, option).
425
- * The filteredPath parameter will only be passed in when the Cascader calls the filter function
426
425
  */
427
- export function filter(sugInput: string, option: any, filterTreeNode: any, filterProps: any, filteredPath?: string) {
426
+ export function filter(sugInput: string, option: any, filterTreeNode: any, filterProps: any) {
428
427
  if (!filterTreeNode) {
429
428
  return true;
430
429
  }
431
430
  let filterFn = filterTreeNode;
432
- let target = filteredPath ?? option;
431
+ let target = option;
433
432
  if (typeof filterTreeNode === 'boolean') {
434
433
  filterFn = (targetVal: string, val: any) => {
435
434
  const input = targetVal.toLowerCase();