@douyinfe/semi-foundation 2.31.2 → 2.32.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 (67) hide show
  1. package/cascader/foundation.ts +8 -1
  2. package/datePicker/_utils/getDefaultFormatToken.ts +1 -0
  3. package/datePicker/_utils/getInsetInputFormatToken.ts +1 -0
  4. package/datePicker/_utils/getInsetInputValueFromInsetInputStr.ts +1 -0
  5. package/datePicker/constants.ts +1 -1
  6. package/datePicker/datePicker.scss +33 -6
  7. package/datePicker/foundation.ts +132 -74
  8. package/datePicker/inputFoundation.ts +8 -2
  9. package/datePicker/variables.scss +6 -4
  10. package/datePicker/yearAndMonthFoundation.ts +65 -18
  11. package/lib/cjs/cascader/foundation.d.ts +2 -0
  12. package/lib/cjs/datePicker/_utils/getDefaultFormatToken.d.ts +1 -0
  13. package/lib/cjs/datePicker/_utils/getDefaultFormatToken.js +2 -1
  14. package/lib/cjs/datePicker/_utils/getInsetInputFormatToken.js +1 -0
  15. package/lib/cjs/datePicker/_utils/getInsetInputValueFromInsetInputStr.js +1 -0
  16. package/lib/cjs/datePicker/constants.d.ts +1 -1
  17. package/lib/cjs/datePicker/constants.js +1 -1
  18. package/lib/cjs/datePicker/datePicker.css +29 -11
  19. package/lib/cjs/datePicker/datePicker.scss +33 -6
  20. package/lib/cjs/datePicker/foundation.d.ts +34 -6
  21. package/lib/cjs/datePicker/foundation.js +145 -69
  22. package/lib/cjs/datePicker/inputFoundation.d.ts +1 -1
  23. package/lib/cjs/datePicker/inputFoundation.js +13 -1
  24. package/lib/cjs/datePicker/variables.scss +6 -4
  25. package/lib/cjs/datePicker/yearAndMonthFoundation.d.ts +66 -13
  26. package/lib/cjs/datePicker/yearAndMonthFoundation.js +55 -14
  27. package/lib/cjs/modal/modal.css +1 -0
  28. package/lib/cjs/modal/modal.scss +1 -0
  29. package/lib/cjs/modal/variables.scss +1 -0
  30. package/lib/cjs/sideSheet/sideSheet.css +10 -0
  31. package/lib/cjs/sideSheet/sideSheet.scss +15 -0
  32. package/lib/cjs/sideSheet/variables.scss +6 -0
  33. package/lib/cjs/switch/foundation.js +0 -3
  34. package/lib/cjs/treeSelect/foundation.d.ts +3 -0
  35. package/lib/cjs/treeSelect/foundation.js +3 -2
  36. package/lib/es/cascader/foundation.d.ts +2 -0
  37. package/lib/es/datePicker/_utils/getDefaultFormatToken.d.ts +1 -0
  38. package/lib/es/datePicker/_utils/getDefaultFormatToken.js +2 -1
  39. package/lib/es/datePicker/_utils/getInsetInputFormatToken.js +1 -0
  40. package/lib/es/datePicker/_utils/getInsetInputValueFromInsetInputStr.js +1 -0
  41. package/lib/es/datePicker/constants.d.ts +1 -1
  42. package/lib/es/datePicker/constants.js +1 -1
  43. package/lib/es/datePicker/datePicker.css +29 -11
  44. package/lib/es/datePicker/datePicker.scss +33 -6
  45. package/lib/es/datePicker/foundation.d.ts +34 -6
  46. package/lib/es/datePicker/foundation.js +145 -69
  47. package/lib/es/datePicker/inputFoundation.d.ts +1 -1
  48. package/lib/es/datePicker/inputFoundation.js +13 -1
  49. package/lib/es/datePicker/variables.scss +6 -4
  50. package/lib/es/datePicker/yearAndMonthFoundation.d.ts +66 -13
  51. package/lib/es/datePicker/yearAndMonthFoundation.js +58 -14
  52. package/lib/es/modal/modal.css +1 -0
  53. package/lib/es/modal/modal.scss +1 -0
  54. package/lib/es/modal/variables.scss +1 -0
  55. package/lib/es/sideSheet/sideSheet.css +10 -0
  56. package/lib/es/sideSheet/sideSheet.scss +15 -0
  57. package/lib/es/sideSheet/variables.scss +6 -0
  58. package/lib/es/switch/foundation.js +0 -3
  59. package/lib/es/treeSelect/foundation.d.ts +3 -0
  60. package/lib/es/treeSelect/foundation.js +3 -2
  61. package/modal/modal.scss +1 -0
  62. package/modal/variables.scss +1 -0
  63. package/package.json +2 -2
  64. package/sideSheet/sideSheet.scss +15 -0
  65. package/sideSheet/variables.scss +6 -0
  66. package/switch/foundation.ts +2 -3
  67. package/treeSelect/foundation.ts +6 -3
@@ -91,9 +91,16 @@ export interface BasicTriggerRenderProps {
91
91
  * should call this function when the value of the Input component
92
92
  * customized by triggerRender is updated to synchronize the state
93
93
  * with Cascader. */
94
+ onSearch: (inputValue: string) => void;
95
+ /* This function is the same as onSearch (supported since v2.32.0),
96
+ * because this function was used before, and to align with TreeSelect,
97
+ * use onSearch instead of onChange is more suitable,
98
+ * onChange needs to be deleted in the next Major
99
+ */
94
100
  onChange: (inputValue: string) => void;
95
101
  /* Function to clear the value */
96
- onClear: (e: any) => void
102
+ onClear: (e: any) => void;
103
+ onRemove: (key: string) => void
97
104
  }
98
105
 
99
106
  export interface BasicScrollPanelProps {
@@ -6,6 +6,7 @@ const defaultFormatTokens = {
6
6
  dateRange: strings.FORMAT_FULL_DATE,
7
7
  dateTimeRange: strings.FORMAT_DATE_TIME,
8
8
  month: strings.FORMAT_YEAR_MONTH,
9
+ monthRange: strings.FORMAT_YEAR_MONTH,
9
10
  } as const;
10
11
 
11
12
  const getDefaultFormatToken = (type: string) => defaultFormatTokens;
@@ -31,6 +31,7 @@ export default function getInsetInputFormatToken(options: { format: string; type
31
31
  break;
32
32
  case 'date':
33
33
  case 'month':
34
+ case 'monthRange':
34
35
  case 'dateRange':
35
36
  default:
36
37
  const dateResult = dateReg.exec(format);
@@ -34,6 +34,7 @@ export default function getInsetInputValueFromInsetInputStr(options: { inputValu
34
34
  switch (type) {
35
35
  case 'date':
36
36
  case 'month':
37
+ case 'monthRange':
37
38
  insetInputValue.monthLeft.dateInput = inputValue;
38
39
  break;
39
40
  case 'dateRange':
@@ -46,7 +46,7 @@ const strings = {
46
46
  DEFAULT_SEPARATOR_MULTIPLE: ',',
47
47
  DEFAULT_SEPARATOR_RANGE: ' ~ ',
48
48
  SIZE_SET: ['small', 'default', 'large'],
49
- TYPE_SET: ['date', 'dateRange', 'year', 'month', 'dateTime', 'dateTimeRange'],
49
+ TYPE_SET: ['date', 'dateRange', 'year', 'month', 'monthRange', 'dateTime', 'dateTimeRange'],
50
50
  PRESET_POSITION_SET: ['left', 'right', 'top', 'bottom'],
51
51
  DENSITY_SET: ['default', 'compact'],
52
52
  PANEL_TYPE_LEFT: 'left',
@@ -169,11 +169,23 @@ $module-list: #{$prefix}-scrolllist;
169
169
  }
170
170
 
171
171
  // 年月选择器
172
-
173
172
  &-panel-yam {
174
173
  // add left or right preset panel to panel yam, max-width will be bigger
175
174
  max-width: $width-datepicker_monthPanel_max + $width-datepicker_presetPanel_left_and_right;
176
175
 
176
+ &[x-type="monthRange"] {
177
+ max-width: $width-datepicker_monthRangePanel_max + $width-datepicker_presetPanel_left_and_right;
178
+ }
179
+
180
+ .#{$module}-yearmonth-body {
181
+ display: flex;
182
+
183
+ .#{$prefix}-scrolllist:nth-child(2) {
184
+ border-left: 1px solid var(--semi-color-border);
185
+
186
+ }
187
+ }
188
+
177
189
  .#{$prefix}-scrolllist {
178
190
  box-shadow: none;
179
191
  height: $height-datepicker_panel_yam_scrolllist;
@@ -196,13 +208,14 @@ $module-list: #{$prefix}-scrolllist;
196
208
  padding: 0;
197
209
  overflow: hidden;
198
210
 
199
- .#{$prefix}-scrolllist-item-wheel {
211
+ .#{$prefix}-scrolllist-item-wheel:not(#neverExistElement) {
212
+ // equal to #{$prefix}-scrolllist-item-wheel, add [:not] selector only to increase selector priority
200
213
  border: none;
201
214
  }
202
215
 
203
- .#{$prefix}-scrolllist-item {
204
- border: none;
205
- }
216
+ // .#{$prefix}-scrolllist-item {
217
+ // border: none;
218
+ // }
206
219
  }
207
220
  }
208
221
  }
@@ -832,6 +845,9 @@ $module-list: #{$prefix}-scrolllist;
832
845
  &[x-type=month] {
833
846
  width: $width-datepicker_insetInput_month_type_wrapper;
834
847
  }
848
+ &[x-type=monthRange] {
849
+ width: $width-datepicker_insetInput_month_range_type_wrapper;
850
+ }
835
851
 
836
852
  .#{$prefix}-input-wrapper {
837
853
  flex: 1;
@@ -869,7 +885,9 @@ $module-list: #{$prefix}-scrolllist;
869
885
  border-color: $color-datepicker_range_trigger-border-active ;
870
886
  }
871
887
 
872
-
888
+ .#{$module}-monthRange-input {
889
+ background-color: transparent;
890
+ }
873
891
 
874
892
  &-wrapper {
875
893
  box-sizing: border-box;
@@ -1108,6 +1126,15 @@ $module-list: #{$prefix}-scrolllist;
1108
1126
  padding: $spacing-datepicker_yam_panel_header_compact-padding;
1109
1127
  }
1110
1128
 
1129
+ .#{$module}-yearmonth-body {
1130
+ display: flex;
1131
+
1132
+ .#{$prefix}-scrolllist:nth-child(2){
1133
+ border: 1px solid var(--semi-color-border);
1134
+
1135
+ }
1136
+ }
1137
+
1111
1138
  .#{$prefix}-scrolllist {
1112
1139
  @include font-size-small;
1113
1140
  line-height: $lineHeight-datepicker_compact;
@@ -109,13 +109,11 @@ export interface EventHandlerProps {
109
109
  onPanelChange?: OnPanelChangeType;
110
110
  onConfirm?: OnConfirmType;
111
111
  // properties below need overwrite
112
- // onBlur?: React.MouseEventHandler<HTMLInputElement>;
113
112
  onBlur?: (e: any) => void;
114
- // onClear?: React.MouseEventHandler<HTMLDivElement>;
115
113
  onClear?: (e: any) => void;
116
- // onFocus?: React.MouseEventHandler<HTMLInputElement>;
117
114
  onFocus?: (e: any, rangType: RangeType) => void;
118
- onPresetClick?: OnPresetClickType
115
+ onPresetClick?: OnPresetClickType;
116
+ onClickOutSide?: () => void
119
117
  }
120
118
 
121
119
  export interface DatePickerFoundationProps extends ElementProps, RenderProps, EventHandlerProps {
@@ -190,7 +188,7 @@ export interface DatePickerFoundationState {
190
188
  export { Type, DateInputFoundationProps };
191
189
 
192
190
  export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationProps, DatePickerFoundationState> {
193
- togglePanel: (panelShow: boolean) => void;
191
+ togglePanel: (panelShow: boolean, cb?: () => void) => void;
194
192
  registerClickOutSide: () => void;
195
193
  unregisterClickOutSide: () => void;
196
194
  notifyBlur: DatePickerFoundationProps['onBlur'];
@@ -212,7 +210,10 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
212
210
  isEventTarget: (e: any) => boolean;
213
211
  updateInsetInputValue: (insetInputValue: InsetInputValue) => void;
214
212
  setInsetInputFocus: () => void;
215
- setTriggerDisabled: (disabled: boolean) => void
213
+ setTriggerDisabled: (disabled: boolean) => void;
214
+ setInputFocus: () => void;
215
+ setInputBlur: () => void;
216
+ setRangeInputBlur: () => void
216
217
  }
217
218
 
218
219
 
@@ -223,6 +224,7 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
223
224
  */
224
225
  export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapter> {
225
226
 
227
+ clickConfirmButton: boolean;
226
228
  constructor(adapter: DatePickerAdapter) {
227
229
  super({ ...adapter });
228
230
  }
@@ -251,8 +253,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
251
253
  const result = this.parseWithTimezone(_value, timeZone, prevTimeZone);
252
254
  this._adapter.updatePrevTimezone(prevTimeZone);
253
255
  // reset input value when value update
254
- this._adapter.updateInputValue(null);
255
- this._adapter.updateInsetInputValue(null);
256
+ this.clearInputValue();
256
257
  this._adapter.updateValue(result);
257
258
  this.resetCachedSelectedValue(result);
258
259
  this.initRangeInputFocus(result);
@@ -327,7 +328,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
327
328
 
328
329
  destroy() {
329
330
  // Ensure that event listeners will be uninstalled and users may not trigger closePanel
330
- // this._adapter.togglePanel(false);
331
+ this._adapter.togglePanel(false);
331
332
  this._adapter.unregisterClickOutSide();
332
333
  }
333
334
 
@@ -344,45 +345,46 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
344
345
  openPanel() {
345
346
  if (!this.getProp('disabled')) {
346
347
  if (!this._isControlledComponent('open')) {
347
- this._adapter.togglePanel(true);
348
- this._adapter.registerClickOutSide();
348
+ this.open();
349
349
  }
350
350
  this._adapter.notifyOpenChange(true);
351
351
  }
352
352
  }
353
353
 
354
354
  /**
355
+ * @deprecated
355
356
  * do these side effects when type is dateRange or dateTimeRange
356
357
  * 1. trigger input blur, if input value is invalid, set input value and state value to previous status
357
358
  * 2. set cachedSelectedValue using given dates(in needConfirm mode)
358
359
  * - directly closePanel without click confirm will set cachedSelectedValue to state value
359
360
  * - select one date(which means that the selection value is incomplete) and click confirm also set cachedSelectedValue to state value
360
361
  */
361
- rangeTypeSideEffectsWhenClosePanel(inputValue: string, willUpdateDates: Date[]) {
362
- if (this._isRangeType()) {
363
- this._adapter.setRangeInputFocus(false);
364
- /**
365
- * inputValue is string when it is not disabled or can't parsed
366
- * when inputValue is null, picker value will back to last selected value
367
- */
368
- this.handleInputBlur(inputValue);
369
- this.resetCachedSelectedValue(willUpdateDates);
370
- }
371
- }
362
+ // rangeTypeSideEffectsWhenClosePanel(inputValue: string, willUpdateDates: Date[]) {
363
+ // if (this._isRangeType()) {
364
+ // this._adapter.setRangeInputFocus(false);
365
+ // /**
366
+ // * inputValue is string when it is not disabled or can't parsed
367
+ // * when inputValue is null, picker value will back to last selected value
368
+ // */
369
+ // this.handleInputBlur(inputValue);
370
+ // this.resetCachedSelectedValue(willUpdateDates);
371
+ // }
372
+ // }
372
373
 
373
374
  /**
375
+ * @deprecated
374
376
  * clear input value when selected date is not confirmed
375
377
  */
376
- needConfirmSideEffectsWhenClosePanel(willUpdateDates: Date[] | null | undefined) {
377
- if (this._adapter.needConfirm() && !this._isRangeType()) {
378
- /**
379
- * if `null` input element will show `cachedSelectedValue` formatted value(format in DateInput render)
380
- * if `` input element will show `` directly
381
- */
382
- this._adapter.updateInputValue(null);
383
- this.resetCachedSelectedValue(willUpdateDates);
384
- }
385
- }
378
+ // needConfirmSideEffectsWhenClosePanel(willUpdateDates: Date[] | null | undefined) {
379
+ // if (this._adapter.needConfirm() && !this._isRangeType()) {
380
+ // /**
381
+ // * if `null` input element will show `cachedSelectedValue` formatted value(format in DateInput render)
382
+ // * if `` input element will show `` directly
383
+ // */
384
+ // this._adapter.updateInputValue(null);
385
+ // this.resetCachedSelectedValue(willUpdateDates);
386
+ // }
387
+ // }
386
388
 
387
389
  /**
388
390
  * clear inset input value when close panel
@@ -421,17 +423,92 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
421
423
  const { value } = this._adapter.getStates();
422
424
  const willUpdateDates = isNullOrUndefined(dates) ? value : dates;
423
425
  if (!this._isControlledComponent('open')) {
424
- this._adapter.togglePanel(false);
425
- this._adapter.unregisterClickOutSide();
426
+ this.close();
427
+ } else {
428
+ this.resetInnerSelectedStates(willUpdateDates);
426
429
  }
427
- // range type picker, closing panel requires the following side effects
428
- this.rangeTypeSideEffectsWhenClosePanel(inputValue, willUpdateDates as Date[]);
429
- this.needConfirmSideEffectsWhenClosePanel(willUpdateDates as Date[]);
430
- this.clearInsetInputValue();
431
430
  this._adapter.notifyOpenChange(false);
431
+ }
432
+
433
+ open() {
434
+ this._adapter.togglePanel(true);
435
+ this._adapter.registerClickOutSide();
436
+ }
437
+
438
+ close() {
439
+ this._adapter.togglePanel(false, () => this.resetInnerSelectedStates());
440
+ this._adapter.unregisterClickOutSide();
441
+ }
442
+
443
+ focus(focusType?: Exclude<RangeType, false>) {
444
+ if (this._isRangeType()) {
445
+ const rangeInputFocus = focusType ?? 'rangeStart';
446
+ this._adapter.setRangeInputFocus(rangeInputFocus);
447
+ } else {
448
+ this._adapter.setInputFocus();
449
+ }
450
+ }
451
+
452
+ blur() {
453
+ if (this._isRangeType()) {
454
+ this._adapter.setRangeInputBlur();
455
+ } else {
456
+ this._adapter.setInputBlur();
457
+ }
458
+ }
459
+
460
+ /**
461
+ * reset cachedSelectedValue, inputValue when close panel
462
+ */
463
+ resetInnerSelectedStates(willUpdateDates?: Date[]) {
464
+ const { value } = this._adapter.getStates();
465
+ const needResetCachedSelectedValue = !this.isCachedSelectedValueValid(willUpdateDates) || this._adapter.needConfirm() && !this.clickConfirmButton;
466
+ if (needResetCachedSelectedValue) {
467
+ this.resetCachedSelectedValue(value);
468
+ }
469
+ this.resetFocus();
470
+ this.clearInputValue();
471
+ this.clickConfirmButton = false;
472
+ }
473
+
474
+ resetFocus(e?: any) {
475
+ this._adapter.setRangeInputFocus(false);
432
476
  this._adapter.notifyBlur(e);
433
477
  }
434
478
 
479
+ /**
480
+ * cachedSelectedValue can be `(Date|null)[]` or `null`
481
+ */
482
+ isCachedSelectedValueValid(dates: Date[]) {
483
+ const cachedSelectedValue = dates || this._adapter.getState('cachedSelectedValue');
484
+ const { type } = this._adapter.getProps();
485
+ let isValid = true;
486
+ switch (true) {
487
+ case type === 'dateRange':
488
+ case type === 'dateTimeRange':
489
+ if (!this._isRangeValueComplete(cachedSelectedValue)) {
490
+ isValid = false;
491
+ }
492
+ break;
493
+ default:
494
+ const value = cachedSelectedValue?.filter(item => item);
495
+ if (!(Array.isArray(value) && value.length)) {
496
+ isValid = false;
497
+ }
498
+ break;
499
+ }
500
+ return isValid;
501
+ }
502
+
503
+ /**
504
+ * 将输入框内容置空
505
+ */
506
+ clearInputValue() {
507
+ this._adapter.updateInputValue(null);
508
+ this._adapter.updateInsetInputValue(null);
509
+ }
510
+
511
+
435
512
  /**
436
513
  * clear range input focus when open is controlled
437
514
  * fixed github 1375
@@ -519,38 +596,8 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
519
596
  * @param {String} input
520
597
  * @param {Event} e
521
598
  */
599
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
522
600
  handleInputBlur(input = '', e?: any) {
523
- const parsedResult = input ?
524
- this._isMultiple() ?
525
- this.parseMultipleInput(input, ',', true) :
526
- this.parseInput(input) :
527
- [];
528
-
529
- const stateValue = this.getState('value');
530
-
531
- // console.log(input, parsedResult);
532
-
533
- if (parsedResult && parsedResult.length) {
534
- this._updateValueAndInput(parsedResult, input === '');
535
- } else if (input === '') {
536
- // if clear input, set input to `''`
537
- this._updateValueAndInput('' as any, true, '');
538
- } else {
539
- this._updateValueAndInput(stateValue);
540
- }
541
-
542
- /**
543
- * 当不是范围类型且不需要确认时,使用 stateValue 重置 cachedSelectedValue
544
- * 这样做的目的是,在输入非法值时,使用上次选中的值作为已选值
545
- * needConfirm 或者 range type 时,我们在 close panel 时调用 resetCachedSelectedValue,这里不用重复调用
546
- *
547
- * Use stateValue to reset cachedSelectedValue when it is not a range type and does not require confirmation
548
- * The purpose of this is to use the last selected value as the selected value when an invalid value is entered
549
- * When needConfirm or range type, we call resetCachedSelectedValue when close panel, no need to call repeatedly here
550
- */
551
- if (!this._adapter.needConfirm() && !this._isRangeType()) {
552
- this.resetCachedSelectedValue(stateValue);
553
- }
554
601
  }
555
602
 
556
603
  /**
@@ -666,6 +713,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
666
713
  break;
667
714
  case 'dateRange':
668
715
  case 'dateTimeRange':
716
+ case 'monthRange':
669
717
  const separator = rangeSeparator;
670
718
  const values = input.split(separator);
671
719
  parsedResult =
@@ -859,6 +907,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
859
907
 
860
908
  case 'dateRange':
861
909
  case 'dateTimeRange':
910
+ case 'monthRange':
862
911
  const startIsTruthy = !isNullOrUndefined(dates[0]);
863
912
  const endIsTruthy = !isNullOrUndefined(dates[1]);
864
913
  if (startIsTruthy && endIsTruthy) {
@@ -898,6 +947,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
898
947
  break;
899
948
  case 'dateRange':
900
949
  case 'dateTimeRange':
950
+ case 'monthRange':
901
951
  for (let i = 0; i < dates.length; i += 2) {
902
952
  strs.push(this.formatDates(dates.slice(i, i + 2), customFormat));
903
953
  }
@@ -1007,22 +1057,29 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
1007
1057
  }
1008
1058
 
1009
1059
  /**
1010
- * when changing the year and month through the panel when the type is year or month
1060
+ * when changing the year and month through the panel when the type is year or month or monthRange
1011
1061
  * @param {*} item
1012
1062
  */
1013
- handleYMSelectedChange(item: { currentMonth?: number; currentYear?: number } = {}) {
1063
+ handleYMSelectedChange(item: { currentMonth?: { left: number; right: number }; currentYear?: { left: number; right: number } } = {}) {
1014
1064
  // console.log(item);
1015
1065
  const { currentMonth, currentYear } = item;
1066
+ const { type } = this.getProps();
1016
1067
 
1017
- if (typeof currentMonth === 'number' && typeof currentYear === 'number') {
1018
- // Strings with only dates (e.g. "1970-01-01") will be treated as UTC instead of local time #1460
1019
- const date = new Date(currentYear, currentMonth - 1);
1068
+ if (type === 'month') {
1069
+ const date = new Date(currentYear['left'], currentMonth['left'] - 1);
1020
1070
 
1021
1071
  this.handleSelectedChange([date]);
1072
+ } else {
1073
+ const dateLeft = new Date(currentYear['left'], currentMonth['left'] - 1);
1074
+ const dateRight = new Date(currentYear['right'], currentMonth['right'] - 1);
1075
+
1076
+ this.handleSelectedChange([dateLeft, dateRight]);
1077
+
1022
1078
  }
1023
1079
  }
1024
1080
 
1025
1081
  handleConfirm() {
1082
+ this.clickConfirmButton = true;
1026
1083
  const { cachedSelectedValue, value } = this._adapter.getStates();
1027
1084
  const isRangeValueComplete = this._isRangeValueComplete(cachedSelectedValue);
1028
1085
  const newValue = isRangeValueComplete ? cachedSelectedValue : value;
@@ -1122,6 +1179,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
1122
1179
  break;
1123
1180
  case 'dateRange':
1124
1181
  case 'dateTimeRange':
1182
+ case 'monthRange':
1125
1183
  notifyValue = _value.map(v => v && this.localeFormat(v, formatToken));
1126
1184
  notifyDate = [..._value];
1127
1185
  break;
@@ -17,7 +17,7 @@ const KEY_CODE_ENTER = 'Enter';
17
17
  const KEY_CODE_TAB = 'Tab';
18
18
 
19
19
 
20
- export type Type = 'date' | 'dateRange' | 'year' | 'month' | 'dateTime' | 'dateTimeRange';
20
+ export type Type = 'date' | 'dateRange' | 'year' | 'month' | 'dateTime' | 'dateTimeRange' | 'monthRange';
21
21
  export type RangeType = 'rangeStart' | 'rangeEnd';
22
22
  export type PanelType = 'left' | 'right';
23
23
 
@@ -180,6 +180,9 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
180
180
  case 'month':
181
181
  text = formatDateValues(value, formatToken, undefined, dateFnsLocale);
182
182
  break;
183
+ case 'monthRange':
184
+ text = formatDateValues(value, formatToken, { groupSize: 2, groupInnerSeparator: rangeSeparator }, dateFnsLocale);
185
+ break;
183
186
  default:
184
187
  break;
185
188
  }
@@ -244,7 +247,7 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
244
247
  * Otherwise the default format will be used as placeholder
245
248
  */
246
249
  getInsetInputPlaceholder() {
247
- const { type, format } = this._adapter.getProps();
250
+ const { type, format, rangeSeparator } = this._adapter.getProps();
248
251
  const insetInputFormat = getInsetInputFormatToken({ type, format });
249
252
  let datePlaceholder, timePlaceholder;
250
253
 
@@ -257,6 +260,8 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
257
260
  case 'dateTime':
258
261
  case 'dateTimeRange':
259
262
  [datePlaceholder, timePlaceholder] = insetInputFormat.split(' ');
263
+ case 'monthRange':
264
+ datePlaceholder = insetInputFormat + rangeSeparator + insetInputFormat;
260
265
  break;
261
266
  }
262
267
 
@@ -302,6 +307,7 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
302
307
  switch (type) {
303
308
  case 'date':
304
309
  case 'month':
310
+ case 'monthRange':
305
311
  inputValue = insetInputValue.monthLeft.dateInput;
306
312
  break;
307
313
  case 'dateRange':
@@ -9,6 +9,7 @@ $height-datepicker_timeType_tpk: calc(100% - 54px); // 时间面板高度
9
9
  $height-datepicker_panel_yam_scrolllist: 266px; // 时间滚动内容高度
10
10
 
11
11
  $width-datepicker_monthPanel_max: 284px; // 年月选择器最大宽度
12
+ $width-datepicker_monthRangePanel_max: 384px; // 年月选择器最大宽度
12
13
  $height-datepicker_timepicker_header_min: 24px; // 年月选择 header 最小高度
13
14
  $width-datepicker_navigation_button_min: 32px; // header 按钮最小宽度
14
15
  $height-datepicker_yamShowing_min: 378px; // 日期时间选择器菜单最小高度
@@ -30,7 +31,8 @@ $height-datepicker_timeType_insetInput_yam: 100%; // 时间面板高度 - 内嵌
30
31
  $height-datepicker_timeType_insetInput_tpk: 100%; // 时间面板高度 - 内嵌输入框
31
32
  $width-datepicker_insetInput_date_type_wrapper: 284px; // 日期类型内嵌输入框宽度
32
33
  $width-datepicker_insetInput_date_range_type_wrapper: $width-datepicker_insetInput_date_type_wrapper * 2; // 范围选择内嵌输入框宽度
33
- $width-datepicker_insetInput_month_type_wrapper: 204px; // 月份类型内嵌输入框宽度
34
+ $width-datepicker_insetInput_month_type_wrapper: 165px; // 月份类型内嵌输入框宽度
35
+ $width-datepicker_insetInput_month_range_type_wrapper: 331px; // 年月范围类型内嵌输入框宽度
34
36
  $height-datepicker_insetInput_separator: 32px;
35
37
  $height-datepicker_month_grid_yearType_insetInput: 317px;
36
38
  $height-datepicker_month_grid_timeType_insetInput: 317px;
@@ -222,7 +224,7 @@ $transition-datepicker_range_input: background-color .16s ease-in-out;
222
224
  $width-datepicker_presetPanel_left_and_right_content: $width-datepicker_presetPanel_left_and_right - $spacing-datepicker_quick_control_content-paddingX * 2; // 左右方位快捷选择面板,内容宽度
223
225
  $width-datepicker_presetPanel_top_and_bottom_content_date: $width-datepicker_day * 7 + $spacing-datepicker_month-padding * 2 - $spacing-datepicker_quick_control_top_and_bottom_content-paddingX * 2; // date/dateTime下, 上下方位快捷选择面板内容宽度, 默认(284 - 40)px
224
226
  $width-datepicker_presetPanel_top_and_bottom_content_range: ($width-datepicker_day * 7 + $spacing-datepicker_month-padding * 2) * 2 - $spacing-datepicker_quick_control_top_and_bottom_content-paddingX * 2; // dateRange/dateTimeRange下, 上下方位快捷选择内容面板宽度,默认528px
225
- $width-datepicker_presetPanel_top_and_bottom_content_month: 194px - $spacing-datepicker_quick_control_top_and_bottom_content-paddingX * 2; // month下,上下方位快捷选择内容面板宽度, 默认154px
227
+ $width-datepicker_presetPanel_top_and_bottom_content_month: 165px - $spacing-datepicker_quick_control_top_and_bottom_content-paddingX * 2; // month下,上下方位快捷选择内容面板宽度, 默认154px
226
228
 
227
229
  $height-datepicker_month_max: $width-datepicker_day * 7 + 1px; // 年月面板最大高度, 最多6 + 1行,再加上一个border宽度, 默认253px
228
230
  $height-datepicker_month_max_compact: $width-datepicker_day_compact * 7 + $spacing-datepicker_weeks_compact-paddingTop + $spacing-datepicker_weeks_compact-padding + $spacing-datepicker_weekday_compact-paddingBottom; // 年月面板最大高度, 最多6 + 1行,再加上padding,默认220px
@@ -233,7 +235,7 @@ $height-datepicker_presetPanel_left_and_right_except_content: 20px + $spacing-da
233
235
  // compact
234
236
  $width-datepicker_presetPanel_top_and_bottom_content_date_compact: $width-datepicker_day_compact * 7 + $spacing-datepicker_weeks_compact-padding * 2 - $spacing-datepicker_quick_control_top_and_bottom_content_compact-paddingX * 2; // date/dateTime下, 上下方位快捷选择面板内容宽度, 默认(216 - 20)px
235
237
  $width-datepicker_presetPanel_top_and_bottom_content_range_compact: ($width-datepicker_day_compact * 7 + $spacing-datepicker_weeks_compact-padding * 2) * 2 - $spacing-datepicker_quick_control_top_and_bottom_content_compact-paddingX * 2; // dateRange/dateTimeRange下, 上下方位快捷选择内容面板宽度,默认412px
236
- $width-datepicker_presetPanel_top_and_bottom_content_month_compact: 194px - $spacing-datepicker_quick_control_top_and_bottom_content_compact-paddingX * 2; // month下,上下方位快捷选择内容面板宽度, 默认174px
238
+ $width-datepicker_presetPanel_top_and_bottom_content_month_compact: 165px - $spacing-datepicker_quick_control_top_and_bottom_content_compact-paddingX * 2; // month下,上下方位快捷选择内容面板宽度, 默认174px
237
239
 
238
240
  $height-datepicker_date_panel_compact: $height-datepicker_month_max_compact + $width-datepicker_nav_compact + $spacing-datepicker_nav_compact-padding; // compact,date/dateRange,面板渲染最大高度,默认256px
239
241
  $height-datepicker_date_time_panel_compact: $height-datepicker_date_panel_compact + $height-datepicker_switch_compact; // compact,dateTime/dateTImeRange,面板渲染最大高度,默认288px
@@ -242,7 +244,7 @@ $height-datepicker_presetPanel_left_and_right_except_content_compact: 20px + $sp
242
244
  $width-datepicker_presetPanel_left_and_right_two_col_button: ($width-datepicker_presetPanel_left_and_right_content - $spacing-datepicker_quick_control_item-margin) * 0.5; // 左右方位快捷选择面板,固定两列,按钮宽度
243
245
  $width-datepicker_presetPanel_top_and_bottom_three_col_button: ($width-datepicker_presetPanel_top_and_bottom_content_date - $spacing-datepicker_quick_control_item-margin * 2) * 0.333; // 上下方位快捷选择面板,固定三列,按钮宽度
244
246
  $width-datepicker_presetPanel_top_and_bottom_five_col_button: ($width-datepicker_presetPanel_top_and_bottom_content_range - $spacing-datepicker_quick_control_item-margin * 4) * 0.2; // 上下方位快捷选择面板,固定五列,按钮宽度
245
- $width-datepicker_presetPanel_top_and_bottom_two_col_button:($width-datepicker_presetPanel_top_and_bottom_content_month - $spacing-datepicker_quick_control_item-margin) * 0.5; // 上下方位快捷选择面板,固定两列,按钮宽度
247
+ $width-datepicker_presetPanel_top_and_bottom_two_col_button: ($width-datepicker_presetPanel_top_and_bottom_content_month - $spacing-datepicker_quick_control_item-margin) * 0.5; // 上下方位快捷选择面板,固定两列,按钮宽度
246
248
 
247
249
  // compact
248
250
  $width-datepicker_presetPanel_top_and_bottom_three_col_button_compact: ($width-datepicker_presetPanel_top_and_bottom_content_date_compact - $spacing-datepicker_quick_control_item-margin * 2) * 0.333; // 上下方位快捷选择面板,固定三列,按钮宽度