@douyinfe/semi-ui 2.1.4-alpha.0 → 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 (162) hide show
  1. package/_base/_story/a11y.jsx +1302 -0
  2. package/_base/_story/a11y.scss +49 -0
  3. package/_base/_story/index.scss +1 -0
  4. package/_base/_story/index.stories.js +3 -1
  5. package/_utils/index.ts +2 -1
  6. package/button/Button.tsx +1 -0
  7. package/button/__test__/button.test.js +15 -0
  8. package/button/_story/button.stories.js +13 -0
  9. package/button/buttonGroup.tsx +6 -4
  10. package/cascader/__test__/cascader.test.js +221 -0
  11. package/cascader/_story/cascader.stories.js +138 -0
  12. package/cascader/index.tsx +37 -21
  13. package/cascader/item.tsx +7 -2
  14. package/checkbox/__test__/checkboxGroup.test.js +37 -5
  15. package/checkbox/_story/checkbox.stories.js +78 -6
  16. package/checkbox/checkbox.tsx +3 -0
  17. package/checkbox/checkboxGroup.tsx +3 -2
  18. package/datePicker/__test__/datePicker.test.js +67 -2
  19. package/datePicker/_story/datePicker.stories.js +3 -1
  20. package/datePicker/_story/v2/YearButton.jsx +17 -0
  21. package/datePicker/_story/v2/index.js +1 -0
  22. package/datePicker/monthsGrid.tsx +12 -1
  23. package/datePicker/navigation.tsx +55 -29
  24. package/descriptions/__test__/descriptions.test.js +27 -1
  25. package/descriptions/_story/descriptions.stories.js +52 -2
  26. package/descriptions/item.tsx +1 -1
  27. package/dist/css/semi.css +105 -32
  28. package/dist/css/semi.min.css +1 -1
  29. package/dist/umd/semi-ui.js +801 -227
  30. package/dist/umd/semi-ui.js.map +1 -1
  31. package/dist/umd/semi-ui.min.js +1 -1
  32. package/dist/umd/semi-ui.min.js.map +1 -1
  33. package/form/_story/form.stories.js +0 -67
  34. package/form/_story/form.stories.tsx +2 -2
  35. package/form/hoc/withField.tsx +2 -2
  36. package/lib/cjs/_base/base.css +2 -2
  37. package/lib/cjs/_utils/index.d.ts +1 -0
  38. package/lib/cjs/_utils/index.js +3 -2
  39. package/lib/cjs/button/Button.d.ts +1 -0
  40. package/lib/cjs/button/buttonGroup.js +11 -3
  41. package/lib/cjs/cascader/index.d.ts +7 -0
  42. package/lib/cjs/cascader/index.js +35 -22
  43. package/lib/cjs/cascader/item.d.ts +2 -0
  44. package/lib/cjs/cascader/item.js +9 -2
  45. package/lib/cjs/checkbox/checkbox.js +4 -1
  46. package/lib/cjs/checkbox/checkboxGroup.d.ts +1 -0
  47. package/lib/cjs/checkbox/checkboxGroup.js +3 -1
  48. package/lib/cjs/datePicker/dateInput.d.ts +1 -1
  49. package/lib/cjs/datePicker/datePicker.d.ts +1 -1
  50. package/lib/cjs/datePicker/monthsGrid.d.ts +2 -1
  51. package/lib/cjs/datePicker/monthsGrid.js +6 -0
  52. package/lib/cjs/datePicker/navigation.js +47 -7
  53. package/lib/cjs/descriptions/item.js +1 -1
  54. package/lib/cjs/form/baseForm.d.ts +6 -0
  55. package/lib/cjs/form/field.d.ts +6 -0
  56. package/lib/cjs/form/hoc/withField.js +3 -1
  57. package/lib/cjs/locale/source/es.d.ts +7 -0
  58. package/lib/cjs/locale/source/es.js +168 -0
  59. package/lib/cjs/modal/Modal.d.ts +8 -8
  60. package/lib/cjs/modal/Modal.js +4 -4
  61. package/lib/cjs/modal/confirm.d.ts +10 -10
  62. package/lib/cjs/navigation/index.d.ts +2 -2
  63. package/lib/cjs/pagination/index.js +9 -4
  64. package/lib/cjs/radio/radio.d.ts +1 -1
  65. package/lib/cjs/radio/radio.js +1 -0
  66. package/lib/cjs/radio/radioGroup.d.ts +1 -1
  67. package/lib/cjs/rating/item.js +3 -2
  68. package/lib/cjs/select/index.d.ts +10 -0
  69. package/lib/cjs/select/index.js +15 -9
  70. package/lib/cjs/table/Table.d.ts +1 -1
  71. package/lib/cjs/timePicker/TimePicker.d.ts +2 -2
  72. package/lib/cjs/timePicker/TimeShape.d.ts +1 -1
  73. package/lib/cjs/timePicker/index.d.ts +2 -2
  74. package/lib/cjs/timeline/item.d.ts +5 -2
  75. package/lib/cjs/timeline/item.js +13 -7
  76. package/lib/cjs/tree/treeNode.js +0 -2
  77. package/lib/cjs/treeSelect/index.js +1 -0
  78. package/lib/cjs/typography/title.d.ts +1 -1
  79. package/lib/cjs/upload/fileCard.d.ts +2 -0
  80. package/lib/cjs/upload/fileCard.js +70 -45
  81. package/lib/cjs/upload/index.d.ts +34 -4
  82. package/lib/cjs/upload/index.js +141 -25
  83. package/lib/cjs/upload/interface.d.ts +3 -0
  84. package/lib/es/_base/base.css +2 -2
  85. package/lib/es/_utils/index.d.ts +1 -0
  86. package/lib/es/_utils/index.js +3 -2
  87. package/lib/es/button/Button.d.ts +1 -0
  88. package/lib/es/button/buttonGroup.js +3 -3
  89. package/lib/es/cascader/index.d.ts +7 -0
  90. package/lib/es/cascader/index.js +34 -25
  91. package/lib/es/cascader/item.d.ts +2 -0
  92. package/lib/es/cascader/item.js +9 -2
  93. package/lib/es/checkbox/checkbox.js +4 -1
  94. package/lib/es/checkbox/checkboxGroup.d.ts +1 -0
  95. package/lib/es/checkbox/checkboxGroup.js +3 -1
  96. package/lib/es/datePicker/dateInput.d.ts +1 -1
  97. package/lib/es/datePicker/datePicker.d.ts +1 -1
  98. package/lib/es/datePicker/monthsGrid.d.ts +2 -1
  99. package/lib/es/datePicker/monthsGrid.js +6 -0
  100. package/lib/es/datePicker/navigation.js +48 -8
  101. package/lib/es/descriptions/item.js +1 -1
  102. package/lib/es/form/baseForm.d.ts +6 -0
  103. package/lib/es/form/field.d.ts +6 -0
  104. package/lib/es/form/hoc/withField.js +3 -1
  105. package/lib/es/locale/source/es.d.ts +7 -0
  106. package/lib/es/locale/source/es.js +157 -0
  107. package/lib/es/modal/Modal.d.ts +8 -8
  108. package/lib/es/modal/Modal.js +4 -4
  109. package/lib/es/modal/confirm.d.ts +10 -10
  110. package/lib/es/navigation/index.d.ts +2 -2
  111. package/lib/es/pagination/index.js +8 -4
  112. package/lib/es/radio/radio.d.ts +1 -1
  113. package/lib/es/radio/radio.js +1 -0
  114. package/lib/es/radio/radioGroup.d.ts +1 -1
  115. package/lib/es/rating/item.js +3 -2
  116. package/lib/es/select/index.d.ts +10 -0
  117. package/lib/es/select/index.js +19 -9
  118. package/lib/es/table/Table.d.ts +1 -1
  119. package/lib/es/timePicker/TimePicker.d.ts +2 -2
  120. package/lib/es/timePicker/TimeShape.d.ts +1 -1
  121. package/lib/es/timePicker/index.d.ts +2 -2
  122. package/lib/es/timeline/item.d.ts +5 -2
  123. package/lib/es/timeline/item.js +12 -7
  124. package/lib/es/tree/treeNode.js +0 -2
  125. package/lib/es/treeSelect/index.js +1 -0
  126. package/lib/es/typography/title.d.ts +1 -1
  127. package/lib/es/upload/fileCard.d.ts +2 -0
  128. package/lib/es/upload/fileCard.js +69 -44
  129. package/lib/es/upload/index.d.ts +34 -4
  130. package/lib/es/upload/index.js +141 -24
  131. package/lib/es/upload/interface.d.ts +3 -0
  132. package/locale/source/es.ts +160 -0
  133. package/modal/Modal.tsx +6 -6
  134. package/navigation/__test__/navigation.test.js +4 -4
  135. package/navigation/_story/AutoOpen/index.js +1 -1
  136. package/navigation/_story/WithChildren/index.js +1 -1
  137. package/navigation/_story/navigation.stories.js +1 -1
  138. package/navigation/_story/navigation.stories.tsx +4 -4
  139. package/navigation/index.tsx +2 -2
  140. package/package.json +16 -8
  141. package/pagination/_story/pagination.stories.js +11 -0
  142. package/pagination/index.tsx +9 -4
  143. package/popover/Arrow.tsx +1 -1
  144. package/radio/__test__/radioGroup.test.jsx +41 -6
  145. package/radio/_story/radio.stories.js +22 -11
  146. package/radio/radio.tsx +1 -0
  147. package/rating/item.tsx +2 -1
  148. package/select/_story/select.stories.js +39 -14
  149. package/select/index.tsx +21 -7
  150. package/table/_story/DynamicFilters/index.js +13 -16
  151. package/timeline/__test__/timeline.test.js +17 -1
  152. package/timeline/_story/timeline.stories.js +70 -6
  153. package/timeline/item.tsx +11 -6
  154. package/tooltip/_story/tooltip.stories.js +1 -1
  155. package/tree/_story/tree.stories.js +2 -2
  156. package/tree/treeNode.tsx +0 -2
  157. package/treeSelect/index.tsx +3 -2
  158. package/tsconfig.json +2 -1
  159. package/upload/__test__/upload.test.js +50 -1
  160. package/upload/fileCard.tsx +110 -95
  161. package/upload/index.tsx +155 -54
  162. package/upload/interface.ts +3 -0
@@ -14,10 +14,10 @@ import CascaderFoundation, {
14
14
  } from '@douyinfe/semi-foundation/cascader/foundation';
15
15
  import { cssClasses, strings } from '@douyinfe/semi-foundation/cascader/constants';
16
16
  import { numbers as popoverNumbers } from '@douyinfe/semi-foundation/popover/constants';
17
- import { isEqual, isString, isEmpty, isFunction, isNumber, noop } from 'lodash';
17
+ import { isEqual, isString, isEmpty, isFunction, isNumber, noop, flatten } from 'lodash';
18
18
  import '@douyinfe/semi-foundation/cascader/cascader.scss';
19
19
  import { IconClear, IconChevronDown } from '@douyinfe/semi-icons';
20
- import { findKeysForValues, convertDataToEntities } from '@douyinfe/semi-foundation/cascader/util';
20
+ import { findKeysForValues, convertDataToEntities, calcMergeType } from '@douyinfe/semi-foundation/cascader/util';
21
21
  import { calcCheckedKeys, normalizeKeyList, calcDisabledKeys } from '@douyinfe/semi-foundation/tree/treeUtil';
22
22
  import ConfigContext from '../configProvider/context';
23
23
  import BaseComponent, { ValidateStatus } from '../_base/baseComponent';
@@ -143,15 +143,19 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
143
143
  showRestTagsPopover: PropTypes.bool,
144
144
  restTagsPopoverProps: PropTypes.object,
145
145
  max: PropTypes.number,
146
+ separator: PropTypes.string,
146
147
  onExceed: PropTypes.func,
147
148
  onClear: PropTypes.func,
148
149
  loadData: PropTypes.func,
149
150
  onLoad: PropTypes.func,
150
151
  loadedKeys: PropTypes.array,
151
152
  disableStrictly: PropTypes.bool,
153
+ leafOnly: PropTypes.bool,
154
+ enableLeafClick: PropTypes.bool,
152
155
  };
153
156
 
154
157
  static defaultProps = {
158
+ leafOnly: false,
155
159
  arrowIcon: <IconChevronDown />,
156
160
  stopPropagation: true,
157
161
  motion: true,
@@ -168,6 +172,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
168
172
  filterLeafOnly: true,
169
173
  showRestTagsPopover: false,
170
174
  restTagsPopoverProps: {},
175
+ separator: ' / ',
171
176
  size: 'default' as const,
172
177
  treeNodeFilterProp: 'label' as const,
173
178
  displayProp: 'label' as const,
@@ -177,6 +182,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
177
182
  onClear: noop,
178
183
  onDropdownVisibleChange: noop,
179
184
  onListScroll: noop,
185
+ enableLeafClick: false,
180
186
  };
181
187
 
182
188
  options: any;
@@ -185,6 +191,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
185
191
  triggerRef: React.RefObject<HTMLDivElement>;
186
192
  optionsRef: React.RefObject<any>;
187
193
  clickOutsideHandler: any;
194
+ mergeType: string;
188
195
 
189
196
  constructor(props: CascaderProps) {
190
197
  super(props);
@@ -215,8 +222,8 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
215
222
  checkedKeys: new Set([]),
216
223
  /* Key of half checked node, when multiple */
217
224
  halfCheckedKeys: new Set([]),
218
- /* Auto merged checkedKeys, when multiple */
219
- mergedCheckedKeys: new Set([]),
225
+ /* Auto merged checkedKeys or leaf checkedKeys, when multiple */
226
+ resolvedCheckedKeys: new Set([]),
220
227
  /* Keys of loaded item */
221
228
  loadedKeys: new Set(),
222
229
  /* Keys of loading item */
@@ -226,6 +233,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
226
233
  };
227
234
  this.options = {};
228
235
  this.isEmpty = false;
236
+ this.mergeType = calcMergeType(props.autoMergeValue, props.leafOnly);
229
237
  this.inputRef = React.createRef();
230
238
  this.triggerRef = React.createRef();
231
239
  this.optionsRef = React.createRef();
@@ -346,7 +354,9 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
346
354
  multiple,
347
355
  value,
348
356
  defaultValue,
349
- onChangeWithObject
357
+ onChangeWithObject,
358
+ leafOnly,
359
+ autoMergeValue,
350
360
  } = props;
351
361
  const { prevProps } = prevState;
352
362
  let keyEntities = prevState.keyEntities || {};
@@ -402,21 +412,18 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
402
412
  });
403
413
  realKeys = formatKeys;
404
414
  }
405
- let checkedKeys = new Set([]);
406
- let halfCheckedKeys = new Set([]);
407
- realKeys.forEach(v => {
408
- const calRes = calcCheckedKeys(v, keyEntities);
409
- checkedKeys = new Set([...checkedKeys, ...calRes.checkedKeys]);
410
- halfCheckedKeys = new Set([...halfCheckedKeys, ...calRes.halfCheckedKeys]);
411
- });
415
+ const calRes = calcCheckedKeys(flatten(realKeys as string[]), keyEntities);
416
+ const checkedKeys = new Set(calRes.checkedKeys);
417
+ const halfCheckedKeys = new Set(calRes.halfCheckedKeys);
412
418
  // disableStrictly
413
419
  if (props.disableStrictly) {
414
420
  newState.disabledKeys = calcDisabledKeys(keyEntities);
415
421
  }
422
+ const isLeafOnlyMerge = calcMergeType(autoMergeValue, leafOnly) === strings.LEAF_ONLY_MERGE_TYPE;
416
423
  newState.prevProps = props;
417
424
  newState.checkedKeys = checkedKeys;
418
425
  newState.halfCheckedKeys = halfCheckedKeys;
419
- newState.mergedCheckedKeys = new Set(normalizeKeyList(checkedKeys, keyEntities));
426
+ newState.resolvedCheckedKeys = new Set(normalizeKeyList(checkedKeys, keyEntities, isLeafOnlyMerge));
420
427
  }
421
428
  }
422
429
  return newState;
@@ -493,7 +500,6 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
493
500
  const {
494
501
  size,
495
502
  disabled,
496
- autoMergeValue,
497
503
  placeholder,
498
504
  maxTagCount,
499
505
  showRestTagsPopover,
@@ -503,11 +509,13 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
503
509
  inputValue,
504
510
  checkedKeys,
505
511
  keyEntities,
506
- mergedCheckedKeys
512
+ resolvedCheckedKeys
507
513
  } = this.state;
508
514
  const tagInputcls = cls(`${prefixcls}-tagInput-wrapper`);
509
515
  const tagValue: Array<Array<string>> = [];
510
- const realKeys = autoMergeValue ? mergedCheckedKeys : checkedKeys;
516
+ const realKeys = this.mergeType === strings.NONE_MERGE_TYPE
517
+ ? checkedKeys
518
+ : resolvedCheckedKeys;
511
519
  [...realKeys].forEach(checkedKey => {
512
520
  if (!isEmpty(keyEntities[checkedKey])) {
513
521
  tagValue.push(keyEntities[checkedKey].valuePath);
@@ -592,6 +600,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
592
600
  dropdownStyle,
593
601
  loadData,
594
602
  emptyContent,
603
+ separator,
595
604
  topSlot,
596
605
  bottomSlot,
597
606
  showNext,
@@ -606,6 +615,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
606
615
  <Item
607
616
  activeKeys={activeKeys}
608
617
  selectedKeys={selectedKeys}
618
+ separator={separator}
609
619
  loadedKeys={loadedKeys}
610
620
  loadingKeys={loadingKeys}
611
621
  onItemClick={this.handleItemClick}
@@ -658,8 +668,10 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
658
668
 
659
669
  renderMultipleTags = () => {
660
670
  const { autoMergeValue, maxTagCount } = this.props;
661
- const { checkedKeys, mergedCheckedKeys } = this.state;
662
- const realKeys = autoMergeValue ? mergedCheckedKeys : checkedKeys;
671
+ const { checkedKeys, resolvedCheckedKeys } = this.state;
672
+ const realKeys = this.mergeType === strings.NONE_MERGE_TYPE
673
+ ? checkedKeys
674
+ : resolvedCheckedKeys;
663
675
  const displayTag: Array<ReactNode> = [];
664
676
  const hiddenTag: Array<ReactNode> = [];
665
677
  [...realKeys].forEach((checkedKey, idx) => {
@@ -729,11 +741,15 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
729
741
  };
730
742
 
731
743
  renderCustomTrigger = () => {
732
- const { disabled, triggerRender, multiple, autoMergeValue } = this.props;
733
- const { selectedKeys, inputValue, inputPlaceHolder, mergedCheckedKeys, checkedKeys } = this.state;
744
+ const { disabled, triggerRender, multiple } = this.props;
745
+ const { selectedKeys, inputValue, inputPlaceHolder, resolvedCheckedKeys, checkedKeys } = this.state;
734
746
  let realValue;
735
747
  if (multiple) {
736
- realValue = autoMergeValue ? mergedCheckedKeys : checkedKeys;
748
+ if (this.mergeType === strings.NONE_MERGE_TYPE) {
749
+ realValue = checkedKeys;
750
+ } else {
751
+ realValue = resolvedCheckedKeys;
752
+ }
737
753
  } else {
738
754
  realValue = [...selectedKeys][0];
739
755
  }
package/cascader/item.tsx CHANGED
@@ -54,6 +54,7 @@ export interface CascaderItemProps {
54
54
  emptyContent: React.ReactNode;
55
55
  loadData: (selectOptions: CascaderData[]) => Promise<void>;
56
56
  data: Array<Data | Entity>;
57
+ separator: string;
57
58
  multiple: boolean;
58
59
  checkedKeys: Set<string>;
59
60
  halfCheckedKeys: Set<string>;
@@ -75,6 +76,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
75
76
  checkedKeys: PropTypes.object,
76
77
  halfCheckedKeys: PropTypes.object,
77
78
  onItemCheckboxClick: PropTypes.func,
79
+ separator: PropTypes.string,
78
80
  keyword: PropTypes.string
79
81
  };
80
82
 
@@ -104,6 +106,9 @@ export default class Item extends PureComponent<CascaderItemProps> {
104
106
  const { onItemCheckboxClick } = this.props;
105
107
  // Prevent Checkbox's click event bubbling to trigger the li click event
106
108
  e.stopPropagation();
109
+ if (e.nativeEvent && typeof e.nativeEvent.stopImmediatePropagation === 'function') {
110
+ e.nativeEvent.stopImmediatePropagation();
111
+ }
107
112
  onItemCheckboxClick(item);
108
113
  };
109
114
 
@@ -139,7 +144,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
139
144
 
140
145
  highlight = (searchText: React.ReactNode[]) => {
141
146
  const content: React.ReactNode[] = [];
142
- const { keyword } = this.props;
147
+ const { keyword, separator } = this.props;
143
148
  searchText.forEach((item, idx) => {
144
149
  if (typeof item === 'string' && includes(item, keyword)) {
145
150
  item.split(keyword).forEach((node, index) => {
@@ -156,7 +161,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
156
161
  content.push(item);
157
162
  }
158
163
  if (idx !== searchText.length - 1) {
159
- content.push(' / ');
164
+ content.push(separator);
160
165
  }
161
166
  });
162
167
  return content;
@@ -136,13 +136,45 @@ describe('CheckboxGroup', () => {
136
136
  });
137
137
 
138
138
  it('checkboxGroup card style', () => {
139
- const checkbox = getCG({ type: 'card' });
140
- expect(checkbox.exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)).toEqual(true);
139
+ const checkboxGroup = getCG({ type: 'card' });
140
+ expect(checkboxGroup.exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)).toEqual(true);
141
+ checkboxGroup.unmount();
142
+
143
+ const disabledCheckboxGroup = getCG({ type: 'card', disabled: true, defaultValue: 'abc' });
144
+ expect(
145
+ disabledCheckboxGroup
146
+ .find(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)
147
+ .at(0)
148
+ .exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType_checked_disabled`)
149
+ ).toEqual(true);
150
+ expect(
151
+ disabledCheckboxGroup
152
+ .find(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)
153
+ .at(1)
154
+ .exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType_checked_disabled`)
155
+ ).toEqual(false);
156
+ disabledCheckboxGroup.unmount();
141
157
  });
142
158
 
143
159
  it('checkboxGroup pure card style', () => {
144
- const checkbox = getCG({ type: 'pureCard' });
145
- expect(checkbox.exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)).toEqual(true);
146
- expect(checkbox.exists(`.${BASE_CLASS_PREFIX}-checkbox-inner-pureCardType`)).toEqual(true);
160
+ const checkboxGroup = getCG({ type: 'pureCard' });
161
+ expect(checkboxGroup.exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)).toEqual(true);
162
+ expect(checkboxGroup.exists(`.${BASE_CLASS_PREFIX}-checkbox-inner-pureCardType`)).toEqual(true);
163
+ checkboxGroup.unmount();
164
+
165
+ const disabledCheckboxGroup = getCG({ type: 'pureCard', disabled: true, defaultValue: 'abc' });
166
+ expect(
167
+ disabledCheckboxGroup
168
+ .find(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)
169
+ .at(0)
170
+ .exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType_checked_disabled`)
171
+ ).toEqual(true);
172
+ expect(
173
+ disabledCheckboxGroup
174
+ .find(`.${BASE_CLASS_PREFIX}-checkbox-cardType`)
175
+ .at(1)
176
+ .exists(`.${BASE_CLASS_PREFIX}-checkbox-cardType_checked_disabled`)
177
+ ).toEqual(false);
178
+ disabledCheckboxGroup.unmount();
147
179
  });
148
180
  });
@@ -1,6 +1,8 @@
1
1
  import React, { useCallback, useMemo, useState } from 'react';
2
2
  import Button from '../../button';
3
3
  import Popover from '../../popover';
4
+ import Tag from '../../tag';
5
+ import Cascader from '../../cascader';
4
6
  import Checkbox from '../index';
5
7
  import CheckboxGroup from '../checkboxGroup';
6
8
  import { Col, Input, Row } from '../../index';
@@ -572,12 +574,12 @@ export const CheckboxGroupCardStyle = () => (
572
574
  </CheckboxGroup>
573
575
  <br />
574
576
  <br />
575
- <div>radio disabled</div>
577
+ <div>Checkbox disabled</div>
576
578
  <CheckboxGroup type="card" direction="horizontal" defaultValue={['1']}>
577
- <Checkbox value="1" disabled extra="Semi Design" style={{ width: 280 }}>
579
+ <Checkbox value="1" disabled extra="disabled+checked" style={{ width: 280 }}>
578
580
  多选框标题
579
581
  </Checkbox>
580
- <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
582
+ <Checkbox value="2" disabled extra="disabled+unchecked" style={{ width: 280 }}>
581
583
  多选框标题
582
584
  </Checkbox>
583
585
  <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
@@ -765,12 +767,12 @@ export const CheckboxGroupPureCardStyle = () => (
765
767
  </CheckboxGroup>
766
768
  <br />
767
769
  <br />
768
- <div>radio disabled</div>
770
+ <div>Checkbox disabled</div>
769
771
  <CheckboxGroup type="pureCard" defaultValue={['1']}>
770
- <Checkbox value="1" disabled extra="Semi Design" style={{ width: 280 }}>
772
+ <Checkbox value="1" disabled extra="disabled+checked" style={{ width: 280 }}>
771
773
  多选框标题
772
774
  </Checkbox>
773
- <Checkbox value="2" extra="Semi Design" style={{ width: 280 }}>
775
+ <Checkbox value="2" disabled extra="disabled+unchecked" style={{ width: 280 }}>
774
776
  多选框标题
775
777
  </Checkbox>
776
778
  <Checkbox value="3" extra="Semi Design" style={{ width: 280 }}>
@@ -941,3 +943,73 @@ export const CheckboxGroupPureCardStyle = () => (
941
943
  </CheckboxGroup>
942
944
  </>
943
945
  );
946
+
947
+ export const CheckboxOnChangeEvent = () => (
948
+ <div style={{marginLeft: 100}}>
949
+ <div>查看 onChange 入参</div>
950
+ <Checkbox onChange={e => console.log(e)}>
951
+ Apple
952
+ </Checkbox>
953
+ <div style={{marginTop: 30}}>Popover 内套 Popover, 且 content 为 checkbox</div>
954
+ <Popover
955
+ trigger={'click'}
956
+ onClickOutSide={e => console.log('onClickOutSide')}
957
+ content={
958
+ <Popover
959
+ trigger='click'
960
+ content={
961
+ <Checkbox
962
+ onChange={e => {
963
+ console.log('checkbox onChange', e);
964
+ e.stopPropagation();
965
+ e.nativeEvent && e.nativeEvent.stopImmediatePropagation();
966
+ }}
967
+ >
968
+ Semi Design
969
+ </Checkbox>
970
+ }
971
+ >
972
+ trigger
973
+ </Popover>
974
+ }
975
+ >
976
+ <Tag>点击此处</Tag>
977
+ </Popover>
978
+ <div style={{marginTop: 30}}>Popover 内套 Cascader 多选</div>
979
+ <Popover
980
+ trigger={'click'}
981
+ content={
982
+ <Cascader
983
+ defaultValue={['zhejiang', 'ningbo', 'jiangbei']}
984
+ style={{ width: 300 }}
985
+ treeData={[
986
+ {
987
+ label: '浙江省',
988
+ value: 'zhejiang',
989
+ children: [
990
+ {
991
+ label: '杭州市',
992
+ value: 'hangzhou',
993
+ children: [
994
+ {
995
+ label: '西湖区',
996
+ value: 'xihu',
997
+ },
998
+ ],
999
+ },
1000
+ ],
1001
+ }
1002
+ ]}
1003
+ placeholder="请选择所在地区"
1004
+ multiple
1005
+ />
1006
+ }
1007
+ >
1008
+ <Tag>点击此处</Tag>
1009
+ </Popover>
1010
+ </div>
1011
+ );
1012
+
1013
+ CheckboxOnChangeEvent.story = {
1014
+ name: 'checkbox onChange event',
1015
+ };
@@ -123,6 +123,7 @@ class Checkbox extends BaseComponent<CheckboxProps, CheckboxState> {
123
123
  onMouseLeave,
124
124
  extra,
125
125
  value,
126
+ id,
126
127
  } = this.props;
127
128
  const { checked } = this.state;
128
129
  const props: Record<string, any> = {
@@ -154,6 +155,7 @@ class Checkbox extends BaseComponent<CheckboxProps, CheckboxState> {
154
155
  [`${prefix}-cardType_disabled`]: props.disabled && props.isCardType,
155
156
  [`${prefix}-cardType_unDisabled`]: !(props.disabled && props.isCardType),
156
157
  [`${prefix}-cardType_checked`]: props.isCardType && props.checked && !props.disabled,
158
+ [`${prefix}-cardType_checked_disabled`]: props.isCardType && props.checked && props.disabled,
157
159
  [className]: Boolean(className),
158
160
  });
159
161
 
@@ -173,6 +175,7 @@ class Checkbox extends BaseComponent<CheckboxProps, CheckboxState> {
173
175
  <span
174
176
  style={style}
175
177
  className={wrapper}
178
+ id={id}
176
179
  onMouseEnter={onMouseEnter}
177
180
  onMouseLeave={onMouseLeave}
178
181
  onClick={this.handleChange}
@@ -25,6 +25,7 @@ export type CheckboxGroupProps = {
25
25
  style?: React.CSSProperties;
26
26
  className?: string;
27
27
  type?: CheckboxType;
28
+ id?: string;
28
29
  };
29
30
 
30
31
  export type CheckboxGroupState = {
@@ -96,7 +97,7 @@ class CheckboxGroup extends BaseComponent<CheckboxGroupProps, CheckboxGroupState
96
97
  }
97
98
 
98
99
  render() {
99
- const { children, options, prefixCls, direction, className, style, type } = this.props;
100
+ const { children, options, prefixCls, direction, className, id, style, type } = this.props;
100
101
 
101
102
  const isPureCardType = type === strings.TYPE_PURECARD;
102
103
  const isCardType = type === strings.TYPE_CARD || isPureCardType;
@@ -148,7 +149,7 @@ class CheckboxGroup extends BaseComponent<CheckboxGroupProps, CheckboxGroupState
148
149
  }
149
150
 
150
151
  return (
151
- <div className={prefixClsDisplay} style={style}>
152
+ <div className={prefixClsDisplay} style={style} id={id}>
152
153
  <Context.Provider
153
154
  value={{
154
155
  checkboxGroup: {
@@ -280,10 +280,12 @@ describe(`DatePicker`, () => {
280
280
  const rightPanel = document.querySelector(`.${BASE_CLASS_PREFIX}-datepicker-month-grid-right`);
281
281
  const rightNavBtns = rightPanel.querySelectorAll(`.${BASE_CLASS_PREFIX}-datepicker-navigation .${BASE_CLASS_PREFIX}-button`);
282
282
 
283
- _.get(rightNavBtns, 1).click();
283
+ // 点击右边面板下一月
284
+ _.get(rightNavBtns, 2).click();
284
285
  await sleep();
285
286
 
286
- _.times(leftPrevClickTimes).forEach(() => _.first(leftNavBtns).click());
287
+ // 点击左边面板上一月
288
+ _.times(leftPrevClickTimes).forEach(() => _.get(leftNavBtns, 1).click());
287
289
 
288
290
  const leftSecondWeek = leftPanel.querySelectorAll(`.${BASE_CLASS_PREFIX}-datepicker-week`)[1];
289
291
  const leftSecondWeekDays = leftSecondWeek.querySelectorAll(`.${BASE_CLASS_PREFIX}-datepicker-day`);
@@ -870,4 +872,67 @@ describe(`DatePicker`, () => {
870
872
  expect(allSeparators[0].textContent.trim()).toBe(rangeSeparator);
871
873
  expect(allSeparators[1].textContent.trim()).toBe(rangeSeparator);
872
874
  });
875
+
876
+ it('test click next/prev year buttons', () => {
877
+ let props = {
878
+ type: 'dateRange',
879
+ motion: false,
880
+ style: { width: 300 },
881
+ defaultPickerValue: new Date('2021-12-01'),
882
+ defaultOpen: true,
883
+ };
884
+ const elem = mount(<DatePicker {...props} />);
885
+
886
+ const leftPanel = document.querySelector(`.semi-datepicker-month-grid-left`);
887
+ const leftNavBtns = leftPanel.querySelector(`.semi-datepicker-navigation`).children;
888
+ const rightPanel = document.querySelector(`.semi-datepicker-month-grid-right`);
889
+ const rightNavBtns = rightPanel.querySelector(`.semi-datepicker-navigation`).children;
890
+
891
+ // 点击左边面板上一年
892
+ _.get(leftNavBtns, 0).click();
893
+ expect(document.querySelector(`.semi-datepicker-month-grid-left .semi-datepicker-navigation-month`).textContent).toBe('2020年 12月');
894
+ // 点击左边面板下一年
895
+ _.get(leftNavBtns, 4).click();
896
+ expect(document.querySelector(`.semi-datepicker-month-grid-left .semi-datepicker-navigation-month`).textContent).toBe('2021年 12月');
897
+
898
+ // 点击右边面板下一年
899
+ _.get(rightNavBtns, 4).click();
900
+ expect(document.querySelector(`.semi-datepicker-month-grid-right .semi-datepicker-navigation-month`).textContent).toBe('2023年 1月');
901
+ // 点击右边面板上一年
902
+ _.get(rightNavBtns, 0).click();
903
+ expect(document.querySelector(`.semi-datepicker-month-grid-right .semi-datepicker-navigation-month`).textContent).toBe('2022年 1月');
904
+ });
905
+
906
+ const testMonthSyncChange = type => {
907
+ let props = {
908
+ type,
909
+ motion: false,
910
+ style: { width: 300 },
911
+ defaultPickerValue: new Date('2021-12-01'),
912
+ defaultOpen: true,
913
+ };
914
+ const elem = mount(<DatePicker {...props} />);
915
+
916
+ const leftPanel = document.querySelector(`.semi-datepicker-month-grid-left`);
917
+ const leftNavBtns = leftPanel.querySelector(`.semi-datepicker-navigation`).children;
918
+ const rightPanel = document.querySelector(`.semi-datepicker-month-grid-right`);
919
+ const rightNavBtns = rightPanel.querySelector(`.semi-datepicker-navigation`).children;
920
+
921
+ // 点击左边面板下一月,自动切换右面板
922
+ _.get(leftNavBtns, 3).click();
923
+ expect(document.querySelector(`.semi-datepicker-month-grid-left .semi-datepicker-navigation-month`).textContent).toBe('2022年 1月');
924
+ expect(document.querySelector(`.semi-datepicker-month-grid-right .semi-datepicker-navigation-month`).textContent).toBe('2022年 2月');
925
+ // 点击右边面板上一月,自动切换左面板
926
+ _.get(rightNavBtns, 1).click();
927
+ expect(document.querySelector(`.semi-datepicker-month-grid-left .semi-datepicker-navigation-month`).textContent).toBe('2021年 12月');
928
+ expect(document.querySelector(`.semi-datepicker-month-grid-right .semi-datepicker-navigation-month`).textContent).toBe('2022年 1月');
929
+
930
+ // 点击左边面板上一月,不需要自动切换右面板
931
+ _.get(leftNavBtns, 1).click();
932
+ expect(document.querySelector(`.semi-datepicker-month-grid-left .semi-datepicker-navigation-month`).textContent).toBe('2021年 11月');
933
+ elem.unmount();
934
+ }
935
+
936
+ it('test month sync change dateRange type', () => { testMonthSyncChange('dateRange') });
937
+ it('test month sync change dateTimeRange type', () => { testMonthSyncChange('dateTimeRange')});
873
938
  });
@@ -36,6 +36,7 @@ import DatePickerSlot from './DatePickerSlot';
36
36
  import DatePickerTimeZone from './DatePickerTimeZone';
37
37
  import BetterRangePicker from './BetterRangePicker';
38
38
  import SyncSwitchMonth from './SyncSwitchMonth';
39
+ import { YearButton } from './v2';
39
40
 
40
41
  export default {
41
42
  title: 'DatePicker',
@@ -65,7 +66,8 @@ export {
65
66
  DatePickerSlot,
66
67
  DatePickerTimeZone,
67
68
  BetterRangePicker,
68
- SyncSwitchMonth
69
+ SyncSwitchMonth,
70
+ YearButton
69
71
  }
70
72
 
71
73
  const demoDiv = {
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { DatePicker } from '../../../index';
3
+
4
+ export default function App() {
5
+ return (
6
+ <div>
7
+ <h4>type=date</h4>
8
+ <DatePicker />
9
+ <h4>type=dateRange</h4>
10
+ <DatePicker type="dateRange" defaultPickerValue="2021-12" />
11
+ <h4>type=dateTimeRange</h4>
12
+ <DatePicker type="dateTimeRange" />
13
+ <h4>type=dateRange + compact</h4>
14
+ <DatePicker type="dateRange" density="compact" />
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1 @@
1
+ export { default as YearButton } from './YearButton';
@@ -446,6 +446,10 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
446
446
  });
447
447
  };
448
448
 
449
+ getYAMOpenType = () => {
450
+ return this.foundation.getYAMOpenType();
451
+ }
452
+
449
453
  renderTimePicker(panelType: PanelType, panelDetail: MonthInfo) {
450
454
  const { type, locale, format, hideDisabledOptions, timePickerOpts, dateFnsLocale } = this.props;
451
455
  const { pickerDate } = panelDetail;
@@ -606,8 +610,15 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
606
610
  } else if (type === 'year' || type === 'month') {
607
611
  content = 'year month';
608
612
  }
613
+ const yearOpenType = this.getYAMOpenType();
614
+
609
615
  return (
610
- <div className={monthGridCls} x-type={type} ref={current => this.cacheRefCurrent('monthGrid', current)}>
616
+ <div
617
+ className={monthGridCls}
618
+ x-type={type}
619
+ x-panel-yearandmonth-open-type={yearOpenType}
620
+ ref={current => this.cacheRefCurrent('monthGrid', current)}
621
+ >
611
622
  {content}
612
623
  </div>
613
624
  );