@douyinfe/semi-foundation 2.1.3 → 2.2.0-beta.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 (106) hide show
  1. package/cascader/cascader.scss +1 -1
  2. package/cascader/constants.ts +4 -0
  3. package/cascader/foundation.ts +29 -15
  4. package/cascader/util.ts +13 -0
  5. package/checkbox/checkbox.scss +25 -1
  6. package/checkbox/checkboxFoundation.ts +15 -4
  7. package/checkbox/variables.scss +6 -1
  8. package/datePicker/datePicker.scss +18 -0
  9. package/datePicker/monthsGridFoundation.ts +101 -8
  10. package/lib/cjs/cascader/cascader.css +2 -2
  11. package/lib/cjs/cascader/cascader.scss +1 -1
  12. package/lib/cjs/cascader/constants.d.ts +3 -0
  13. package/lib/cjs/cascader/constants.js +6 -1
  14. package/lib/cjs/cascader/foundation.d.ts +4 -1
  15. package/lib/cjs/cascader/foundation.js +24 -11
  16. package/lib/cjs/cascader/util.d.ts +1 -0
  17. package/lib/cjs/cascader/util.js +17 -0
  18. package/lib/cjs/checkbox/checkbox.css +21 -2
  19. package/lib/cjs/checkbox/checkbox.scss +25 -1
  20. package/lib/cjs/checkbox/checkboxFoundation.d.ts +11 -4
  21. package/lib/cjs/checkbox/checkboxFoundation.js +7 -0
  22. package/lib/cjs/checkbox/variables.scss +6 -1
  23. package/lib/cjs/datePicker/datePicker.css +6 -0
  24. package/lib/cjs/datePicker/datePicker.scss +18 -0
  25. package/lib/cjs/datePicker/monthsGridFoundation.d.ts +35 -3
  26. package/lib/cjs/datePicker/monthsGridFoundation.js +139 -6
  27. package/lib/cjs/modal/modal.css +1 -1
  28. package/lib/cjs/modal/modalFoundation.d.ts +2 -2
  29. package/lib/cjs/modal/variables.scss +1 -1
  30. package/lib/cjs/radio/radio.css +33 -2
  31. package/lib/cjs/radio/radio.scss +44 -1
  32. package/lib/cjs/radio/variables.scss +12 -2
  33. package/lib/cjs/rating/rating.css +3 -0
  34. package/lib/cjs/rating/rating.scss +4 -0
  35. package/lib/cjs/select/select.scss +1 -1
  36. package/lib/cjs/sideSheet/sideSheet.css +1 -1
  37. package/lib/cjs/sideSheet/variables.scss +1 -1
  38. package/lib/cjs/table/table.css +2 -2
  39. package/lib/cjs/table/table.scss +2 -2
  40. package/lib/cjs/table/variables.scss +3 -0
  41. package/lib/cjs/timeline/timeline.css +3 -0
  42. package/lib/cjs/timeline/timeline.scss +5 -1
  43. package/lib/cjs/tree/treeUtil.js +14 -14
  44. package/lib/cjs/upload/foundation.d.ts +1 -0
  45. package/lib/cjs/upload/foundation.js +106 -0
  46. package/lib/cjs/upload/rtl.scss +0 -4
  47. package/lib/cjs/upload/upload.css +31 -19
  48. package/lib/cjs/upload/upload.scss +31 -8
  49. package/lib/cjs/upload/variables.scss +6 -2
  50. package/lib/es/cascader/cascader.css +2 -2
  51. package/lib/es/cascader/cascader.scss +1 -1
  52. package/lib/es/cascader/constants.d.ts +3 -0
  53. package/lib/es/cascader/constants.js +6 -1
  54. package/lib/es/cascader/foundation.d.ts +4 -1
  55. package/lib/es/cascader/foundation.js +24 -12
  56. package/lib/es/cascader/util.d.ts +1 -0
  57. package/lib/es/cascader/util.js +14 -0
  58. package/lib/es/checkbox/checkbox.css +21 -2
  59. package/lib/es/checkbox/checkbox.scss +25 -1
  60. package/lib/es/checkbox/checkboxFoundation.d.ts +11 -4
  61. package/lib/es/checkbox/checkboxFoundation.js +7 -0
  62. package/lib/es/checkbox/variables.scss +6 -1
  63. package/lib/es/datePicker/datePicker.css +6 -0
  64. package/lib/es/datePicker/datePicker.scss +18 -0
  65. package/lib/es/datePicker/monthsGridFoundation.d.ts +35 -3
  66. package/lib/es/datePicker/monthsGridFoundation.js +139 -6
  67. package/lib/es/modal/modal.css +1 -1
  68. package/lib/es/modal/modalFoundation.d.ts +2 -2
  69. package/lib/es/modal/variables.scss +1 -1
  70. package/lib/es/radio/radio.css +33 -2
  71. package/lib/es/radio/radio.scss +44 -1
  72. package/lib/es/radio/variables.scss +12 -2
  73. package/lib/es/rating/rating.css +3 -0
  74. package/lib/es/rating/rating.scss +4 -0
  75. package/lib/es/select/select.scss +1 -1
  76. package/lib/es/sideSheet/sideSheet.css +1 -1
  77. package/lib/es/sideSheet/variables.scss +1 -1
  78. package/lib/es/table/table.css +2 -2
  79. package/lib/es/table/table.scss +2 -2
  80. package/lib/es/table/variables.scss +3 -0
  81. package/lib/es/timeline/timeline.css +3 -0
  82. package/lib/es/timeline/timeline.scss +5 -1
  83. package/lib/es/tree/treeUtil.js +13 -12
  84. package/lib/es/upload/foundation.d.ts +1 -0
  85. package/lib/es/upload/foundation.js +107 -0
  86. package/lib/es/upload/rtl.scss +0 -4
  87. package/lib/es/upload/upload.css +31 -19
  88. package/lib/es/upload/upload.scss +31 -8
  89. package/lib/es/upload/variables.scss +6 -2
  90. package/modal/modalFoundation.ts +2 -2
  91. package/modal/variables.scss +1 -1
  92. package/package.json +3 -3
  93. package/radio/radio.scss +44 -1
  94. package/radio/variables.scss +12 -2
  95. package/rating/rating.scss +4 -0
  96. package/select/select.scss +1 -1
  97. package/sideSheet/variables.scss +1 -1
  98. package/table/table.scss +2 -2
  99. package/table/variables.scss +3 -0
  100. package/timeline/timeline.scss +5 -1
  101. package/tree/treeUtil.ts +6 -2
  102. package/tsconfig.json +2 -1
  103. package/upload/foundation.ts +81 -0
  104. package/upload/rtl.scss +0 -4
  105. package/upload/upload.scss +31 -8
  106. package/upload/variables.scss +6 -2
@@ -116,7 +116,7 @@ $module: #{$prefix}-cascader;
116
116
  margin-left: 0;
117
117
  }
118
118
 
119
- &-disabled {
119
+ &-disabled.#{$prefix}-tag {
120
120
  color: $color-cascader_input_disabled-text-default;
121
121
  cursor: not-allowed;
122
122
 
@@ -12,6 +12,10 @@ const strings = {
12
12
  IS_VALUE: 'isValue',
13
13
  SHOW_NEXT_BY_CLICK: 'click',
14
14
  SHOW_NEXT_BY_HOVER: 'hover',
15
+ /* Merge Type */
16
+ LEAF_ONLY_MERGE_TYPE: 'leafOnly',
17
+ AUTO_MERGE_VALUE_MERGE_TYPE: 'autoMergeValue',
18
+ NONE_MERGE_TYPE: 'none',
15
19
  } as const;
16
20
 
17
21
  const numbers = {};
@@ -14,8 +14,11 @@ import {
14
14
  convertDataToEntities,
15
15
  findKeysForValues,
16
16
  normalizedArr,
17
- isValid
17
+ isValid,
18
+ calcMergeType
18
19
  } from './util';
20
+ import { strings } from './constants';
21
+
19
22
  export interface BasicData {
20
23
  data: BasicCascaderData;
21
24
  disabled: boolean;
@@ -99,6 +102,7 @@ export interface BasicScrollPanelProps {
99
102
  export interface BasicCascaderProps {
100
103
  mouseEnterDelay?: number;
101
104
  mouseLeaveDelay?: number;
105
+ separator?: string;
102
106
  arrowIcon?: any;
103
107
  changeOnSelect?: boolean;
104
108
  multiple?: boolean;
@@ -138,6 +142,8 @@ export interface BasicCascaderProps {
138
142
  topSlot?: any;
139
143
  showNext?: ShowNextType;
140
144
  disableStrictly?: boolean;
145
+ leafOnly?: boolean;
146
+ enableLeafClick?: boolean;
141
147
  onClear?: () => void;
142
148
  triggerRender?: (props: BasicTriggerRenderProps) => any;
143
149
  onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
@@ -168,7 +174,7 @@ export interface BasicCascaderInnerData {
168
174
  isHovering: boolean;
169
175
  checkedKeys: Set<string>;
170
176
  halfCheckedKeys: Set<string>;
171
- mergedCheckedKeys: Set<string>;
177
+ resolvedCheckedKeys: Set<string>;
172
178
  loadedKeys: Set<string>;
173
179
  loadingKeys: Set<string>;
174
180
  loading: boolean;
@@ -601,10 +607,11 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
601
607
  }
602
608
 
603
609
  _defaultRenderText(path: any[], displayRender?: BasicCascaderProps['displayRender']) {
610
+ const separator = this.getProp('separator');
604
611
  if (displayRender && typeof displayRender === 'function') {
605
612
  return displayRender(path);
606
613
  } else {
607
- return path.join(' / ');
614
+ return path.join(separator);
608
615
  }
609
616
  }
610
617
 
@@ -649,7 +656,7 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
649
656
  }
650
657
 
651
658
  handleSingleSelect(e: any, item: BasicEntity | BasicData) {
652
- const { changeOnSelect: allowChange, filterLeafOnly, multiple } = this.getProps();
659
+ const { changeOnSelect: allowChange, filterLeafOnly, multiple, enableLeafClick } = this.getProps();
653
660
  const { keyEntities, selectedKeys, isSearching } = this.getStates();
654
661
  const filterable = this._isFilterable();
655
662
  const { data, key } = item;
@@ -667,6 +674,9 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
667
674
  }
668
675
  if (multiple) {
669
676
  this._adapter.updateStates({ activeKeys: new Set(activeKeys) });
677
+ if (isLeaf && enableLeafClick) {
678
+ this.onItemCheckboxClick(item);
679
+ }
670
680
  } else {
671
681
  this._adapter.notifySelect(data.value);
672
682
  if (hasChanged) {
@@ -703,8 +713,8 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
703
713
 
704
714
  _handleMultipleSelect(item: BasicEntity | BasicData) {
705
715
  const { key } = item;
706
- const { checkedKeys, keyEntities, mergedCheckedKeys } = this.getStates();
707
- const { autoMergeValue, max, disableStrictly } = this.getProps();
716
+ const { checkedKeys, keyEntities, resolvedCheckedKeys } = this.getStates();
717
+ const { autoMergeValue, max, disableStrictly, leafOnly } = this.getProps();
708
718
  // prev checked status
709
719
  const prevCheckedStatus = checkedKeys.has(key);
710
720
  // next checked status
@@ -719,18 +729,22 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
719
729
  this.calcNonDisabedCheckedKeys(key, curCheckedStatus) :
720
730
  this.calcCheckedKeys(key, curCheckedStatus);
721
731
 
722
- const curMergedCheckedKeys = new Set(normalizeKeyList(curCheckedKeys, keyEntities));
732
+ const mergeType = calcMergeType(autoMergeValue, leafOnly);
733
+ const isLeafOnlyMerge = mergeType === strings.LEAF_ONLY_MERGE_TYPE;
734
+ const isNoneMerge = mergeType === strings.NONE_MERGE_TYPE;
735
+
736
+ const curResolvedCheckedKeys = new Set(normalizeKeyList(curCheckedKeys, keyEntities, isLeafOnlyMerge));
723
737
 
724
- const curRealCheckedKeys = autoMergeValue ?
725
- curMergedCheckedKeys :
726
- curCheckedKeys;
738
+ const curRealCheckedKeys = isNoneMerge
739
+ ? curCheckedKeys
740
+ : curResolvedCheckedKeys;
727
741
 
728
742
  if (isNumber(max)) {
729
- if (autoMergeValue) {
743
+ if (!isNoneMerge) {
730
744
  // When it exceeds max, the quantity is allowed to be reduced, and no further increase is allowed
731
- if (mergedCheckedKeys.size < curMergedCheckedKeys.size && curMergedCheckedKeys.size > max) {
745
+ if (resolvedCheckedKeys.size < curResolvedCheckedKeys.size && curResolvedCheckedKeys.size > max) {
732
746
  const checkedEntities: BasicEntity[] = [];
733
- curMergedCheckedKeys.forEach(itemKey => {
747
+ curResolvedCheckedKeys.forEach(itemKey => {
734
748
  checkedEntities.push(keyEntities[itemKey]);
735
749
  });
736
750
  this._adapter.notifyOnExceed(checkedEntities);
@@ -752,7 +766,7 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
752
766
  this._adapter.updateStates({
753
767
  checkedKeys: curCheckedKeys,
754
768
  halfCheckedKeys: curHalfCheckedKeys,
755
- mergedCheckedKeys: curMergedCheckedKeys
769
+ resolvedCheckedKeys: curResolvedCheckedKeys
756
770
  });
757
771
  }
758
772
 
@@ -868,7 +882,7 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
868
882
  newState.halfCheckedKeys = new Set([]);
869
883
  newState.selectedKeys = new Set([]);
870
884
  newState.activeKeys = new Set([]);
871
- newState.mergedCheckedKeys = new Set([]);
885
+ newState.resolvedCheckedKeys = new Set([]);
872
886
  this._adapter.notifyChange([]);
873
887
  } else {
874
888
  // if click clearBtn when not searching, clear selected and active values as well
package/cascader/util.ts CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  isUndefined,
4
4
  isEqual
5
5
  } from 'lodash';
6
+ import { strings } from './constants';
6
7
 
7
8
  function getPosition(level: any, index: any) {
8
9
  return `${level}-${index}`;
@@ -79,4 +80,16 @@ export function findKeysForValues(value: any, keyEntities: any) {
79
80
  .filter((item: any) => isEqual(item.valuePath, valuePath))
80
81
  .map((item: any) => item.key);
81
82
  return res;
83
+ }
84
+
85
+ export function calcMergeType(autoMergeValue: boolean, leafOnly: boolean): string {
86
+ let mergeType: string;
87
+ if (leafOnly) {
88
+ mergeType = strings.LEAF_ONLY_MERGE_TYPE;
89
+ } else if (autoMergeValue) {
90
+ mergeType = strings.AUTO_MERGE_VALUE_MERGE_TYPE;
91
+ } else {
92
+ mergeType = strings.NONE_MERGE_TYPE;
93
+ }
94
+ return mergeType;
82
95
  }
@@ -44,6 +44,7 @@ $module: #{$prefix}-checkbox;
44
44
  .#{$module}-inner-checked {
45
45
  .#{$module}-inner-display {
46
46
  background: $color-checkbox_checked-bg-hover;
47
+ box-shadow: none;
47
48
  }
48
49
  }
49
50
  }
@@ -56,6 +57,7 @@ $module: #{$prefix}-checkbox;
56
57
  .#{$module}-inner-checked {
57
58
  .#{$module}-inner-display {
58
59
  background: $color-checkbox_checked-bg-active;
60
+ box-shadow: none;
59
61
  }
60
62
  }
61
63
  }
@@ -70,6 +72,7 @@ $module: #{$prefix}-checkbox;
70
72
  .#{$module}-inner-checked {
71
73
  .#{$module}-inner-display {
72
74
  background: $color-checkbox_checked-bg-disabled;
75
+ box-shadow: none;
73
76
  }
74
77
  }
75
78
  }
@@ -125,7 +128,7 @@ $module: #{$prefix}-checkbox;
125
128
 
126
129
  &.#{$module}-indeterminate .#{$module}-inner-display {
127
130
  background: $color-checkbox_checked-bg-hover;
128
- box-shadow: inset 0 0 0 $size-checkbox_inner-shadow $color-checkbox_default-border-hover;
131
+ box-shadow: none;
129
132
  color: $color-checkbox_checked-icon-hover;
130
133
  }
131
134
 
@@ -153,6 +156,7 @@ $module: #{$prefix}-checkbox;
153
156
  background: $color-checkbox_checked-bg-active;
154
157
  border-color: $color-checkbox_checked-border-active;
155
158
  color: $color-checkbox_checked-icon-active;
159
+ box-shadow: none;
156
160
  }
157
161
 
158
162
  .#{$module}-inner-checked {
@@ -222,6 +226,15 @@ $module: #{$prefix}-checkbox;
222
226
 
223
227
  &:hover {
224
228
  background: $color-checkbox_cardType_checked-bg;
229
+ border-color: $color-checkbox_cardType_checked_border-hover;
230
+ .#{$module}-inner-checked .#{$module}-inner-display {
231
+ box-shadow: none;
232
+ }
233
+ }
234
+
235
+ &:active {
236
+ background: $color-checkbox_cardType_checked-bg;
237
+ border-color: $color-checkbox_cardType_checked_border-active;
225
238
  }
226
239
  }
227
240
 
@@ -233,6 +246,17 @@ $module: #{$prefix}-checkbox;
233
246
  background: transparent;
234
247
  }
235
248
  }
249
+
250
+ &_checked_disabled.#{$module}-cardType {
251
+ background: $color-checkbox_cardType_checked_disabled-bg;
252
+ border: $width-checkbox_cardType_checked_disabled-border solid $color-checkbox_cardType_checked_disabled_border-default;
253
+
254
+ &:hover {
255
+ .#{$module}-inner-checked .#{$module}-inner-display {
256
+ box-shadow: none;
257
+ }
258
+ }
259
+ }
236
260
  }
237
261
 
238
262
  &-indeterminate,
@@ -8,6 +8,9 @@ export interface BasicCheckboxEvent {
8
8
  target: BasicTargetObject;
9
9
  stopPropagation: () => void;
10
10
  preventDefault: () => void;
11
+ nativeEvent: {
12
+ stopImmediatePropagation: () => void;
13
+ }
11
14
  }
12
15
  export interface CheckboxAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
13
16
  getIsInGroup: () => boolean;
@@ -28,7 +31,7 @@ class CheckboxFoundation<P = Record<string, any>, S = Record<string, any>> exten
28
31
  // eslint-disable-next-line @typescript-eslint/no-empty-function
29
32
  init() {}
30
33
 
31
- getEvent(checked: boolean, e: MouseEvent) {
34
+ getEvent(checked: boolean, e: any) {
32
35
  const props = this.getProps();
33
36
  const cbValue = {
34
37
  target: {
@@ -41,16 +44,23 @@ class CheckboxFoundation<P = Record<string, any>, S = Record<string, any>> exten
41
44
  preventDefault: () => {
42
45
  e.preventDefault();
43
46
  },
47
+ nativeEvent: {
48
+ stopImmediatePropagation: () => {
49
+ if (e.nativeEvent && typeof e.nativeEvent.stopImmediatePropagation === 'function') {
50
+ e.nativeEvent.stopImmediatePropagation();
51
+ }
52
+ }
53
+ },
44
54
  };
45
55
  return cbValue;
46
56
  }
47
57
 
48
- notifyChange(checked: boolean, e: MouseEvent) {
58
+ notifyChange(checked: boolean, e: any) {
49
59
  const cbValue = this.getEvent(checked, e);
50
60
  this._adapter.notifyChange(cbValue);
51
61
  }
52
62
 
53
- handleChange(e: MouseEvent) {
63
+ handleChange(e: any) {
54
64
  const disabled = this.getProp('disabled');
55
65
 
56
66
  if (disabled) {
@@ -78,7 +88,7 @@ class CheckboxFoundation<P = Record<string, any>, S = Record<string, any>> exten
78
88
  }
79
89
  }
80
90
 
81
- handleChangeInGroup(e: MouseEvent) {
91
+ handleChangeInGroup(e: any) {
82
92
  const { value } = this.getProps();
83
93
  const groupValue = this._adapter.getGroupValue();
84
94
  const checked = groupValue.includes(value);
@@ -97,6 +107,7 @@ class CheckboxFoundation<P = Record<string, any>, S = Record<string, any>> exten
97
107
  }
98
108
 
99
109
  export interface BaseCheckboxProps {
110
+ id?: string;
100
111
  autoFocus?: boolean;
101
112
  checked?: boolean;
102
113
  defaultChecked?: boolean;
@@ -19,9 +19,13 @@ $color-checkbox_checked-border-default: var(--semi-color-primary); // 选框选
19
19
  $color-checkbox_checked-border-hover: var(--semi-color-primary-hover); // 选框选中态描边颜色 - 悬浮
20
20
  $color-checkbox_checked-border-active: var(--semi-color-primary-active); // 选框选中态描边颜色 - 按下
21
21
  $color-checkbox_cardType_checked-bg: var(--semi-color-primary-light-default); // 卡片类型复选框选中时的背景颜色 - 默认
22
+ $color-checkbox_cardType_checked_disabled-bg: var(--semi-color-primary-light-default); // 卡片类型复选框选中且禁用时的背景颜色 - 默认
22
23
  $color-checkbox_cardType-bg-hover: var(--semi-color-fill-0); // 卡片类型复选框选中时的背景颜色 - 悬浮
23
24
  $color-checkbox_cardType-bg-active: var(--semi-color-fill-1); // 卡片类型复选框选中时的背景颜色 - 按下
24
- $color-checkbox_cardType_checked_border-default: var(--semi-color-focus-border); //卡片类型复选框选中时的边框颜色 - 默认
25
+ $color-checkbox_cardType_checked_border-default: var(--semi-color-primary); //卡片类型复选框选中时的边框颜色 - 默认
26
+ $color-checkbox_cardType_checked_border-hover: var(--semi-color-primary-hover); //卡片类型复选框选中时的边框颜色 - 悬浮
27
+ $color-checkbox_cardType_checked_border-active: var(--semi-color-primary-active); //卡片类型复选框选中时的边框颜色 - 按下
28
+ $color-checkbox_cardType_checked_disabled_border-default: var(--semi-color-primary-disabled); //卡片类型复选框选中且禁用时的边框颜色 - 默认
25
29
  $color-checkbox_cardType_addon-text-default: var(--semi-color-text-0); // 卡片类型复选框 addon 的文字颜色 - 默认
26
30
  $color-checkbox_cardType_extra-text-default: var(--semi-color-text-2); // 卡片类型复选框 extra 的文字颜色 - 默认
27
31
  $color-checkbox_cardType_inner-bg-hover: var(--semi-color-white); // 卡片类型复选框 inner 的背景颜色 - 悬浮
@@ -37,6 +41,7 @@ $size-checkbox_inner-shadow: $border-thickness-control; // 选框内描边宽度
37
41
  $width-checkbox_inner: $width-icon-medium; // 选框对勾 icon 宽度
38
42
  $height-checkbox_inner: 20px; // 选框对勾 icon 高度
39
43
  $width-checkbox_cardType_checked-border: 1px; // 卡片类型复选框的边框宽度
44
+ $width-checkbox_cardType_checked_disabled-border: 1px; // 卡片类型复选框选中且禁用的边框宽度
40
45
 
41
46
  $radius-checkbox_cardType: 3px; // 卡片类型复选框的圆角大小
42
47
  $radius-checkbox_inner: var(--semi-border-radius-extra-small); // 选框圆角
@@ -94,6 +94,15 @@ $module: #{$prefix}-datepicker;
94
94
  min-height: $height-datepicker_timepicker_header_min;
95
95
  }
96
96
  }
97
+
98
+ // 为了防止 scrollList 因为 weeks 变化高度发生变化导致年月可能发生滚动
99
+ // In order to prevent scrollList from scrolling due to changes in the height of weeks, the year and month may be scrolled
100
+ &[x-panel-yearandmonth-open-type="left"],
101
+ &[x-panel-yearandmonth-open-type="right"] {
102
+ .#{$module}-weeks {
103
+ min-height: 6 * $width-datepicker_day;
104
+ }
105
+ }
97
106
  }
98
107
 
99
108
  // 年月选择器
@@ -833,6 +842,15 @@ $module: #{$prefix}-datepicker;
833
842
  }
834
843
  }
835
844
  }
845
+
846
+ // 为了防止 scrollList 因为 weeks 变化高度发生变化导致年月可能发生滚动
847
+ // In order to prevent scrollList from scrolling due to changes in the height of weeks, the year and month may be scrolled
848
+ &[x-panel-yearandmonth-open-type="left"],
849
+ &[x-panel-yearandmonth-open-type="right"] {
850
+ .#{$module}-weeks {
851
+ min-height: 6 * $width-datepicker_day_compact;
852
+ }
853
+ }
836
854
  }
837
855
 
838
856
  // 年月选择器
@@ -47,6 +47,7 @@ interface MonthsGridElementProps {
47
47
  }
48
48
 
49
49
  export type PanelType = 'left' | 'right';
50
+ export type YearMonthChangeType = 'prevMonth' | 'nextMonth' | 'prevYear' | 'nextYear';
50
51
 
51
52
  export interface MonthsGridFoundationProps extends MonthsGridElementProps {
52
53
  type?: Type;
@@ -268,9 +269,65 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
268
269
  // eslint-disable-next-line @typescript-eslint/no-empty-function
269
270
  destroy() { }
270
271
 
272
+ /**
273
+ * sync change another panel month when change months from the else yam panel
274
+ * call it when
275
+ * - current change panel targe date month is same with another panel date
276
+ *
277
+ * @example
278
+ * - panelType=right, target=new Date('2022-09-01') and left panel is in '2022-09' => call it, left panel minus one month to '2022-08'
279
+ * - panelType=left, target=new Date('2021-12-01') and right panel is in '2021-12' => call it, right panel add one month to '2021-01'
280
+ */
281
+ handleSyncChangeMonths(options: { panelType: PanelType, target: Date }) {
282
+ const { panelType, target } = options;
283
+ const { type } = this._adapter.getProps();
284
+ const { monthLeft, monthRight } = this._adapter.getStates();
285
+ if (this.isRangeType(type)) {
286
+ if (panelType === 'right' && differenceInCalendarMonths(target, monthLeft.pickerDate) === 0) {
287
+ this.handleYearOrMonthChange('prevMonth', 'left', 1, true);
288
+ } else if (panelType === 'left' && differenceInCalendarMonths(monthRight.pickerDate, target) === 0) {
289
+ this.handleYearOrMonthChange('nextMonth', 'right', 1, true);
290
+ }
291
+ }
292
+ }
293
+
294
+ /**
295
+ * Get the target date based on the panel type and switch type
296
+ */
297
+ getTargetChangeDate(options: { panelType: PanelType, switchType: YearMonthChangeType }) {
298
+ const { panelType, switchType } = options;
299
+ const { monthRight, monthLeft } = this._adapter.getStates();
300
+ const currentDate = panelType === 'left' ? monthLeft.pickerDate : monthRight.pickerDate;
301
+ let target: Date;
302
+
303
+ switch (switchType) {
304
+ case 'prevMonth':
305
+ target = addMonths(currentDate, -1);
306
+ break;
307
+ case 'nextMonth':
308
+ target = addMonths(currentDate, 1);
309
+ break;
310
+ case 'prevYear':
311
+ target = addYears(currentDate, -1);
312
+ break;
313
+ case 'nextYear':
314
+ target = addYears(currentDate, 1);
315
+ break;
316
+ }
317
+ return target;
318
+ }
319
+
320
+ /**
321
+ * Change month by yam panel
322
+ */
271
323
  toMonth(panelType: PanelType, target: Date) {
324
+ const { type } = this._adapter.getProps();
272
325
  const diff = this._getDiff('month', target, panelType);
273
326
  this.handleYearOrMonthChange(diff < 0 ? 'prevMonth' : 'nextMonth', panelType, Math.abs(diff), false);
327
+
328
+ if (this.isRangeType(type)) {
329
+ this.handleSyncChangeMonths({ panelType, target });
330
+ }
274
331
  }
275
332
 
276
333
  toYear(panelType: PanelType, target: Date) {
@@ -289,30 +346,43 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
289
346
  return typeof realType === 'string' && /range/i.test(realType);
290
347
  }
291
348
 
292
- handleSwitchMonth(switchType: 'prevMonth' | 'nextMonth', panelType: PanelType) {
349
+ handleSwitchMonthOrYear(switchType: YearMonthChangeType, panelType: PanelType) {
293
350
  const { type, syncSwitchMonth } = this.getProps();
294
- if (this.isRangeType(type) && syncSwitchMonth) {
351
+ const rangeType = this.isRangeType(type);
352
+
353
+ // range type and syncSwitchMonth, we should change panels at same time
354
+ if (rangeType && syncSwitchMonth) {
295
355
  this.handleYearOrMonthChange(switchType, 'left', 1, true);
296
356
  this.handleYearOrMonthChange(switchType, 'right', 1, true);
297
357
  } else {
298
358
  this.handleYearOrMonthChange(switchType, panelType);
359
+
360
+ /**
361
+ * default behavior (v2.2.0)
362
+ * In order to prevent the two panels from being the same month, this will confuse the user when selecting the range
363
+ * https://github.com/DouyinFE/semi-design/issues/260
364
+ */
365
+ if (rangeType) {
366
+ const target = this.getTargetChangeDate({ panelType, switchType });
367
+ this.handleSyncChangeMonths({ panelType, target });
368
+ }
299
369
  }
300
370
  }
301
371
 
302
372
  prevMonth(panelType: PanelType) {
303
- this.handleSwitchMonth('prevMonth', panelType);
373
+ this.handleSwitchMonthOrYear('prevMonth', panelType);
304
374
  }
305
375
 
306
376
  nextMonth(panelType: PanelType) {
307
- this.handleSwitchMonth('nextMonth', panelType);
377
+ this.handleSwitchMonthOrYear('nextMonth', panelType);
308
378
  }
309
379
 
310
380
  prevYear(panelType: PanelType) {
311
- this.handleYearOrMonthChange('prevYear', panelType);
381
+ this.handleSwitchMonthOrYear('prevYear', panelType);
312
382
  }
313
383
 
314
384
  nextYear(panelType: PanelType) {
315
- this.handleYearOrMonthChange('nextYear', panelType);
385
+ this.handleSwitchMonthOrYear('nextYear', panelType);
316
386
  }
317
387
 
318
388
  /**
@@ -414,7 +484,7 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
414
484
  }
415
485
 
416
486
  handleYearOrMonthChange(
417
- type: 'prevMonth' | 'nextMonth' | 'prevYear' | 'nextYear',
487
+ type: YearMonthChangeType,
418
488
  panelType: PanelType = strings.PANEL_TYPE_LEFT,
419
489
  step = 1,
420
490
  notSeparateInRange = false
@@ -458,7 +528,7 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
458
528
  * @param {*} targetDate
459
529
  */
460
530
  updateDateAfterChangeYM(
461
- type: 'prevMonth' | 'nextMonth' | 'prevYear' | 'nextYear',
531
+ type: YearMonthChangeType,
462
532
  targetDate: Date
463
533
  ) {
464
534
  const { multiple, disabledDate } = this.getProps();
@@ -839,4 +909,27 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
839
909
  showDatePanel(panelType: PanelType) {
840
910
  this._updatePanelDetail(panelType, { isTimePickerOpen: false, isYearPickerOpen: false });
841
911
  }
912
+
913
+ /**
914
+ * Get year and month panel open type
915
+ *
916
+ * It is useful info to set minHeight of weeks.
917
+ * - When yam open type is 'left' or 'right', weeks minHeight should be set
918
+ * If the minHeight is not set, the change of the number of weeks will cause the scrollList to be unstable
919
+ */
920
+ getYAMOpenType() {
921
+ const { monthLeft, monthRight } = this._adapter.getStates();
922
+ const leftYearPickerOpen = monthLeft.isYearPickerOpen;
923
+ const rightYearPickerOpen = monthRight.isYearPickerOpen;
924
+
925
+ if (leftYearPickerOpen && rightYearPickerOpen) {
926
+ return 'both';
927
+ } else if (leftYearPickerOpen) {
928
+ return 'left';
929
+ } else if (rightYearPickerOpen) {
930
+ return 'right';
931
+ } else {
932
+ return 'none';
933
+ }
934
+ }
842
935
  }
@@ -99,11 +99,11 @@
99
99
  .semi-cascader-selection-tag:first-child {
100
100
  margin-left: 0;
101
101
  }
102
- .semi-cascader-selection-tag-disabled {
102
+ .semi-cascader-selection-tag-disabled.semi-tag {
103
103
  color: var(--semi-color-disabled-text);
104
104
  cursor: not-allowed;
105
105
  }
106
- .semi-cascader-selection-tag-disabled .semi-tag-close {
106
+ .semi-cascader-selection-tag-disabled.semi-tag .semi-tag-close {
107
107
  color: var(--semi-color-disabled-text);
108
108
  cursor: not-allowed;
109
109
  pointer-events: none;
@@ -116,7 +116,7 @@ $module: #{$prefix}-cascader;
116
116
  margin-left: 0;
117
117
  }
118
118
 
119
- &-disabled {
119
+ &-disabled.#{$prefix}-tag {
120
120
  color: $color-cascader_input_disabled-text-default;
121
121
  cursor: not-allowed;
122
122
 
@@ -9,6 +9,9 @@ declare const strings: {
9
9
  readonly IS_VALUE: "isValue";
10
10
  readonly SHOW_NEXT_BY_CLICK: "click";
11
11
  readonly SHOW_NEXT_BY_HOVER: "hover";
12
+ readonly LEAF_ONLY_MERGE_TYPE: "leafOnly";
13
+ readonly AUTO_MERGE_VALUE_MERGE_TYPE: "autoMergeValue";
14
+ readonly NONE_MERGE_TYPE: "none";
12
15
  };
13
16
  declare const numbers: {};
14
17
  export { cssClasses, strings, numbers };
@@ -21,7 +21,12 @@ const strings = {
21
21
  IS_KEY: 'isKey',
22
22
  IS_VALUE: 'isValue',
23
23
  SHOW_NEXT_BY_CLICK: 'click',
24
- SHOW_NEXT_BY_HOVER: 'hover'
24
+ SHOW_NEXT_BY_HOVER: 'hover',
25
+
26
+ /* Merge Type */
27
+ LEAF_ONLY_MERGE_TYPE: 'leafOnly',
28
+ AUTO_MERGE_VALUE_MERGE_TYPE: 'autoMergeValue',
29
+ NONE_MERGE_TYPE: 'none'
25
30
  };
26
31
  exports.strings = strings;
27
32
  const numbers = {};
@@ -57,6 +57,7 @@ export interface BasicScrollPanelProps {
57
57
  export interface BasicCascaderProps {
58
58
  mouseEnterDelay?: number;
59
59
  mouseLeaveDelay?: number;
60
+ separator?: string;
60
61
  arrowIcon?: any;
61
62
  changeOnSelect?: boolean;
62
63
  multiple?: boolean;
@@ -96,6 +97,8 @@ export interface BasicCascaderProps {
96
97
  topSlot?: any;
97
98
  showNext?: ShowNextType;
98
99
  disableStrictly?: boolean;
100
+ leafOnly?: boolean;
101
+ enableLeafClick?: boolean;
99
102
  onClear?: () => void;
100
103
  triggerRender?: (props: BasicTriggerRenderProps) => any;
101
104
  onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
@@ -125,7 +128,7 @@ export interface BasicCascaderInnerData {
125
128
  isHovering: boolean;
126
129
  checkedKeys: Set<string>;
127
130
  halfCheckedKeys: Set<string>;
128
- mergedCheckedKeys: Set<string>;
131
+ resolvedCheckedKeys: Set<string>;
129
132
  loadedKeys: Set<string>;
130
133
  loadingKeys: Set<string>;
131
134
  loading: boolean;