@douyinfe/semi-foundation 2.31.4 → 2.32.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 (97) hide show
  1. package/autoComplete/autoComplete.scss +2 -0
  2. package/cascader/foundation.ts +8 -1
  3. package/datePicker/_utils/getDefaultFormatToken.ts +1 -0
  4. package/datePicker/_utils/getInsetInputFormatToken.ts +1 -0
  5. package/datePicker/_utils/getInsetInputValueFromInsetInputStr.ts +1 -0
  6. package/datePicker/constants.ts +1 -1
  7. package/datePicker/datePicker.scss +33 -6
  8. package/datePicker/foundation.ts +132 -74
  9. package/datePicker/inputFoundation.ts +9 -3
  10. package/datePicker/variables.scss +6 -4
  11. package/datePicker/yearAndMonthFoundation.ts +65 -18
  12. package/lib/cjs/autoComplete/autoComplete.css +1 -0
  13. package/lib/cjs/autoComplete/autoComplete.scss +2 -0
  14. package/lib/cjs/cascader/foundation.d.ts +2 -0
  15. package/lib/cjs/datePicker/_utils/getDefaultFormatToken.d.ts +1 -0
  16. package/lib/cjs/datePicker/_utils/getDefaultFormatToken.js +2 -1
  17. package/lib/cjs/datePicker/_utils/getInsetInputFormatToken.js +1 -0
  18. package/lib/cjs/datePicker/_utils/getInsetInputValueFromInsetInputStr.js +1 -0
  19. package/lib/cjs/datePicker/constants.d.ts +1 -1
  20. package/lib/cjs/datePicker/constants.js +1 -1
  21. package/lib/cjs/datePicker/datePicker.css +29 -11
  22. package/lib/cjs/datePicker/datePicker.scss +33 -6
  23. package/lib/cjs/datePicker/foundation.d.ts +34 -6
  24. package/lib/cjs/datePicker/foundation.js +145 -69
  25. package/lib/cjs/datePicker/inputFoundation.d.ts +1 -1
  26. package/lib/cjs/datePicker/inputFoundation.js +13 -1
  27. package/lib/cjs/datePicker/variables.scss +6 -4
  28. package/lib/cjs/datePicker/yearAndMonthFoundation.d.ts +66 -13
  29. package/lib/cjs/datePicker/yearAndMonthFoundation.js +55 -14
  30. package/lib/cjs/modal/modal.css +1 -0
  31. package/lib/cjs/modal/modal.scss +1 -0
  32. package/lib/cjs/modal/variables.scss +1 -0
  33. package/lib/cjs/sideSheet/sideSheet.css +10 -0
  34. package/lib/cjs/sideSheet/sideSheet.scss +15 -0
  35. package/lib/cjs/sideSheet/variables.scss +6 -0
  36. package/lib/cjs/spin/spin.css +1 -0
  37. package/lib/cjs/spin/spin.scss +1 -0
  38. package/lib/cjs/table/table.css +4 -3
  39. package/lib/cjs/table/table.scss +6 -3
  40. package/lib/cjs/table/utils.d.ts +52 -3
  41. package/lib/cjs/table/utils.js +1 -48
  42. package/lib/cjs/table/variables.scss +2 -0
  43. package/lib/cjs/tree/tree.css +1 -0
  44. package/lib/cjs/tree/tree.scss +1 -0
  45. package/lib/cjs/treeSelect/foundation.d.ts +3 -0
  46. package/lib/cjs/treeSelect/foundation.js +3 -2
  47. package/lib/cjs/upload/upload.css +3 -0
  48. package/lib/cjs/upload/upload.scss +1 -0
  49. package/lib/es/autoComplete/autoComplete.css +1 -0
  50. package/lib/es/autoComplete/autoComplete.scss +2 -0
  51. package/lib/es/cascader/foundation.d.ts +2 -0
  52. package/lib/es/datePicker/_utils/getDefaultFormatToken.d.ts +1 -0
  53. package/lib/es/datePicker/_utils/getDefaultFormatToken.js +2 -1
  54. package/lib/es/datePicker/_utils/getInsetInputFormatToken.js +1 -0
  55. package/lib/es/datePicker/_utils/getInsetInputValueFromInsetInputStr.js +1 -0
  56. package/lib/es/datePicker/constants.d.ts +1 -1
  57. package/lib/es/datePicker/constants.js +1 -1
  58. package/lib/es/datePicker/datePicker.css +29 -11
  59. package/lib/es/datePicker/datePicker.scss +33 -6
  60. package/lib/es/datePicker/foundation.d.ts +34 -6
  61. package/lib/es/datePicker/foundation.js +145 -69
  62. package/lib/es/datePicker/inputFoundation.d.ts +1 -1
  63. package/lib/es/datePicker/inputFoundation.js +13 -1
  64. package/lib/es/datePicker/variables.scss +6 -4
  65. package/lib/es/datePicker/yearAndMonthFoundation.d.ts +66 -13
  66. package/lib/es/datePicker/yearAndMonthFoundation.js +58 -14
  67. package/lib/es/modal/modal.css +1 -0
  68. package/lib/es/modal/modal.scss +1 -0
  69. package/lib/es/modal/variables.scss +1 -0
  70. package/lib/es/sideSheet/sideSheet.css +10 -0
  71. package/lib/es/sideSheet/sideSheet.scss +15 -0
  72. package/lib/es/sideSheet/variables.scss +6 -0
  73. package/lib/es/spin/spin.css +1 -0
  74. package/lib/es/spin/spin.scss +1 -0
  75. package/lib/es/table/table.css +4 -3
  76. package/lib/es/table/table.scss +6 -3
  77. package/lib/es/table/utils.d.ts +52 -3
  78. package/lib/es/table/utils.js +1 -43
  79. package/lib/es/table/variables.scss +2 -0
  80. package/lib/es/tree/tree.css +1 -0
  81. package/lib/es/tree/tree.scss +1 -0
  82. package/lib/es/treeSelect/foundation.d.ts +3 -0
  83. package/lib/es/treeSelect/foundation.js +3 -2
  84. package/lib/es/upload/upload.css +3 -0
  85. package/lib/es/upload/upload.scss +1 -0
  86. package/modal/modal.scss +1 -0
  87. package/modal/variables.scss +1 -0
  88. package/package.json +2 -2
  89. package/sideSheet/sideSheet.scss +15 -0
  90. package/sideSheet/variables.scss +6 -0
  91. package/spin/spin.scss +1 -0
  92. package/table/table.scss +6 -3
  93. package/table/utils.ts +1 -43
  94. package/table/variables.scss +2 -0
  95. package/tree/tree.scss +1 -0
  96. package/treeSelect/foundation.ts +6 -3
  97. package/upload/upload.scss +1 -0
@@ -27,6 +27,8 @@ $module: #{$prefix}-autocomplete;
27
27
  padding-top: $spacing-autoComplete_loading_wrapper-paddingTop;
28
28
  padding-bottom: $spacing-autoComplete_loading_wrapper-paddingBottom;
29
29
  cursor: not-allowed;
30
+ // make sure that spin align vertical, no need to make 20px as a spacing token here
31
+ height: 20px;
30
32
  // height: $spacing-extra-loose;
31
33
  // @include all-center;
32
34
  .#{$prefix}-spin {
@@ -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;
@@ -110,13 +110,11 @@ export interface EventHandlerProps {
110
110
  onPanelChange?: OnPanelChangeType;
111
111
  onConfirm?: OnConfirmType;
112
112
  // properties below need overwrite
113
- // onBlur?: React.MouseEventHandler<HTMLInputElement>;
114
113
  onBlur?: (e: any) => void;
115
- // onClear?: React.MouseEventHandler<HTMLDivElement>;
116
114
  onClear?: (e: any) => void;
117
- // onFocus?: React.MouseEventHandler<HTMLInputElement>;
118
115
  onFocus?: (e: any, rangType: RangeType) => void;
119
- onPresetClick?: OnPresetClickType
116
+ onPresetClick?: OnPresetClickType;
117
+ onClickOutSide?: () => void
120
118
  }
121
119
 
122
120
  export interface DatePickerFoundationProps extends ElementProps, RenderProps, EventHandlerProps {
@@ -191,7 +189,7 @@ export interface DatePickerFoundationState {
191
189
  export { Type, DateInputFoundationProps };
192
190
 
193
191
  export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationProps, DatePickerFoundationState> {
194
- togglePanel: (panelShow: boolean) => void;
192
+ togglePanel: (panelShow: boolean, cb?: () => void) => void;
195
193
  registerClickOutSide: () => void;
196
194
  unregisterClickOutSide: () => void;
197
195
  notifyBlur: DatePickerFoundationProps['onBlur'];
@@ -213,7 +211,10 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
213
211
  isEventTarget: (e: any) => boolean;
214
212
  updateInsetInputValue: (insetInputValue: InsetInputValue) => void;
215
213
  setInsetInputFocus: () => void;
216
- setTriggerDisabled: (disabled: boolean) => void
214
+ setTriggerDisabled: (disabled: boolean) => void;
215
+ setInputFocus: () => void;
216
+ setInputBlur: () => void;
217
+ setRangeInputBlur: () => void
217
218
  }
218
219
 
219
220
 
@@ -224,6 +225,7 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
224
225
  */
225
226
  export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapter> {
226
227
 
228
+ clickConfirmButton: boolean;
227
229
  constructor(adapter: DatePickerAdapter) {
228
230
  super({ ...adapter });
229
231
  }
@@ -245,8 +247,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
245
247
  const result = this.parseWithTimezone(_value, timeZone, prevTimeZone);
246
248
  this._adapter.updatePrevTimezone(prevTimeZone);
247
249
  // reset input value when value update
248
- this._adapter.updateInputValue(null);
249
- this._adapter.updateInsetInputValue(null);
250
+ this.clearInputValue();
250
251
  this._adapter.updateValue(result);
251
252
  this.resetCachedSelectedValue(result);
252
253
  this.initRangeInputFocus(result);
@@ -332,7 +333,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
332
333
 
333
334
  destroy() {
334
335
  // Ensure that event listeners will be uninstalled and users may not trigger closePanel
335
- // this._adapter.togglePanel(false);
336
+ this._adapter.togglePanel(false);
336
337
  this._adapter.unregisterClickOutSide();
337
338
  }
338
339
 
@@ -349,45 +350,46 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
349
350
  openPanel() {
350
351
  if (!this.getProp('disabled')) {
351
352
  if (!this._isControlledComponent('open')) {
352
- this._adapter.togglePanel(true);
353
- this._adapter.registerClickOutSide();
353
+ this.open();
354
354
  }
355
355
  this._adapter.notifyOpenChange(true);
356
356
  }
357
357
  }
358
358
 
359
359
  /**
360
+ * @deprecated
360
361
  * do these side effects when type is dateRange or dateTimeRange
361
362
  * 1. trigger input blur, if input value is invalid, set input value and state value to previous status
362
363
  * 2. set cachedSelectedValue using given dates(in needConfirm mode)
363
364
  * - directly closePanel without click confirm will set cachedSelectedValue to state value
364
365
  * - select one date(which means that the selection value is incomplete) and click confirm also set cachedSelectedValue to state value
365
366
  */
366
- rangeTypeSideEffectsWhenClosePanel(inputValue: string, willUpdateDates: Date[]) {
367
- if (this._isRangeType()) {
368
- this._adapter.setRangeInputFocus(false);
369
- /**
370
- * inputValue is string when it is not disabled or can't parsed
371
- * when inputValue is null, picker value will back to last selected value
372
- */
373
- this.handleInputBlur(inputValue);
374
- this.resetCachedSelectedValue(willUpdateDates);
375
- }
376
- }
367
+ // rangeTypeSideEffectsWhenClosePanel(inputValue: string, willUpdateDates: Date[]) {
368
+ // if (this._isRangeType()) {
369
+ // this._adapter.setRangeInputFocus(false);
370
+ // /**
371
+ // * inputValue is string when it is not disabled or can't parsed
372
+ // * when inputValue is null, picker value will back to last selected value
373
+ // */
374
+ // this.handleInputBlur(inputValue);
375
+ // this.resetCachedSelectedValue(willUpdateDates);
376
+ // }
377
+ // }
377
378
 
378
379
  /**
380
+ * @deprecated
379
381
  * clear input value when selected date is not confirmed
380
382
  */
381
- needConfirmSideEffectsWhenClosePanel(willUpdateDates: Date[] | null | undefined) {
382
- if (this._adapter.needConfirm() && !this._isRangeType()) {
383
- /**
384
- * if `null` input element will show `cachedSelectedValue` formatted value(format in DateInput render)
385
- * if `` input element will show `` directly
386
- */
387
- this._adapter.updateInputValue(null);
388
- this.resetCachedSelectedValue(willUpdateDates);
389
- }
390
- }
383
+ // needConfirmSideEffectsWhenClosePanel(willUpdateDates: Date[] | null | undefined) {
384
+ // if (this._adapter.needConfirm() && !this._isRangeType()) {
385
+ // /**
386
+ // * if `null` input element will show `cachedSelectedValue` formatted value(format in DateInput render)
387
+ // * if `` input element will show `` directly
388
+ // */
389
+ // this._adapter.updateInputValue(null);
390
+ // this.resetCachedSelectedValue(willUpdateDates);
391
+ // }
392
+ // }
391
393
 
392
394
  /**
393
395
  * clear inset input value when close panel
@@ -426,17 +428,92 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
426
428
  const { value } = this._adapter.getStates();
427
429
  const willUpdateDates = isNullOrUndefined(dates) ? value : dates;
428
430
  if (!this._isControlledComponent('open')) {
429
- this._adapter.togglePanel(false);
430
- this._adapter.unregisterClickOutSide();
431
+ this.close();
432
+ } else {
433
+ this.resetInnerSelectedStates(willUpdateDates);
431
434
  }
432
- // range type picker, closing panel requires the following side effects
433
- this.rangeTypeSideEffectsWhenClosePanel(inputValue, willUpdateDates as Date[]);
434
- this.needConfirmSideEffectsWhenClosePanel(willUpdateDates as Date[]);
435
- this.clearInsetInputValue();
436
435
  this._adapter.notifyOpenChange(false);
436
+ }
437
+
438
+ open() {
439
+ this._adapter.togglePanel(true);
440
+ this._adapter.registerClickOutSide();
441
+ }
442
+
443
+ close() {
444
+ this._adapter.togglePanel(false, () => this.resetInnerSelectedStates());
445
+ this._adapter.unregisterClickOutSide();
446
+ }
447
+
448
+ focus(focusType?: Exclude<RangeType, false>) {
449
+ if (this._isRangeType()) {
450
+ const rangeInputFocus = focusType ?? 'rangeStart';
451
+ this._adapter.setRangeInputFocus(rangeInputFocus);
452
+ } else {
453
+ this._adapter.setInputFocus();
454
+ }
455
+ }
456
+
457
+ blur() {
458
+ if (this._isRangeType()) {
459
+ this._adapter.setRangeInputBlur();
460
+ } else {
461
+ this._adapter.setInputBlur();
462
+ }
463
+ }
464
+
465
+ /**
466
+ * reset cachedSelectedValue, inputValue when close panel
467
+ */
468
+ resetInnerSelectedStates(willUpdateDates?: Date[]) {
469
+ const { value } = this._adapter.getStates();
470
+ const needResetCachedSelectedValue = !this.isCachedSelectedValueValid(willUpdateDates) || this._adapter.needConfirm() && !this.clickConfirmButton;
471
+ if (needResetCachedSelectedValue) {
472
+ this.resetCachedSelectedValue(value);
473
+ }
474
+ this.resetFocus();
475
+ this.clearInputValue();
476
+ this.clickConfirmButton = false;
477
+ }
478
+
479
+ resetFocus(e?: any) {
480
+ this._adapter.setRangeInputFocus(false);
437
481
  this._adapter.notifyBlur(e);
438
482
  }
439
483
 
484
+ /**
485
+ * cachedSelectedValue can be `(Date|null)[]` or `null`
486
+ */
487
+ isCachedSelectedValueValid(dates: Date[]) {
488
+ const cachedSelectedValue = dates || this._adapter.getState('cachedSelectedValue');
489
+ const { type } = this._adapter.getProps();
490
+ let isValid = true;
491
+ switch (true) {
492
+ case type === 'dateRange':
493
+ case type === 'dateTimeRange':
494
+ if (!this._isRangeValueComplete(cachedSelectedValue)) {
495
+ isValid = false;
496
+ }
497
+ break;
498
+ default:
499
+ const value = cachedSelectedValue?.filter(item => item);
500
+ if (!(Array.isArray(value) && value.length)) {
501
+ isValid = false;
502
+ }
503
+ break;
504
+ }
505
+ return isValid;
506
+ }
507
+
508
+ /**
509
+ * 将输入框内容置空
510
+ */
511
+ clearInputValue() {
512
+ this._adapter.updateInputValue(null);
513
+ this._adapter.updateInsetInputValue(null);
514
+ }
515
+
516
+
440
517
  /**
441
518
  * clear range input focus when open is controlled
442
519
  * fixed github 1375
@@ -524,38 +601,8 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
524
601
  * @param {String} input
525
602
  * @param {Event} e
526
603
  */
604
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
527
605
  handleInputBlur(input = '', e?: any) {
528
- const parsedResult = input ?
529
- this._isMultiple() ?
530
- this.parseMultipleInput(input, ',', true) :
531
- this.parseInput(input) :
532
- [];
533
-
534
- const stateValue = this.getState('value');
535
-
536
- // console.log(input, parsedResult);
537
-
538
- if (parsedResult && parsedResult.length) {
539
- this._updateValueAndInput(parsedResult, input === '');
540
- } else if (input === '') {
541
- // if clear input, set input to `''`
542
- this._updateValueAndInput('' as any, true, '');
543
- } else {
544
- this._updateValueAndInput(stateValue);
545
- }
546
-
547
- /**
548
- * 当不是范围类型且不需要确认时,使用 stateValue 重置 cachedSelectedValue
549
- * 这样做的目的是,在输入非法值时,使用上次选中的值作为已选值
550
- * needConfirm 或者 range type 时,我们在 close panel 时调用 resetCachedSelectedValue,这里不用重复调用
551
- *
552
- * Use stateValue to reset cachedSelectedValue when it is not a range type and does not require confirmation
553
- * The purpose of this is to use the last selected value as the selected value when an invalid value is entered
554
- * When needConfirm or range type, we call resetCachedSelectedValue when close panel, no need to call repeatedly here
555
- */
556
- if (!this._adapter.needConfirm() && !this._isRangeType()) {
557
- this.resetCachedSelectedValue(stateValue);
558
- }
559
606
  }
560
607
 
561
608
  /**
@@ -671,6 +718,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
671
718
  break;
672
719
  case 'dateRange':
673
720
  case 'dateTimeRange':
721
+ case 'monthRange':
674
722
  const separator = rangeSeparator;
675
723
  const values = input.split(separator);
676
724
  parsedResult =
@@ -864,6 +912,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
864
912
 
865
913
  case 'dateRange':
866
914
  case 'dateTimeRange':
915
+ case 'monthRange':
867
916
  const startIsTruthy = !isNullOrUndefined(dates[0]);
868
917
  const endIsTruthy = !isNullOrUndefined(dates[1]);
869
918
  if (startIsTruthy && endIsTruthy) {
@@ -903,6 +952,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
903
952
  break;
904
953
  case 'dateRange':
905
954
  case 'dateTimeRange':
955
+ case 'monthRange':
906
956
  for (let i = 0; i < dates.length; i += 2) {
907
957
  strs.push(this.formatDates(dates.slice(i, i + 2), customFormat));
908
958
  }
@@ -1012,22 +1062,29 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
1012
1062
  }
1013
1063
 
1014
1064
  /**
1015
- * when changing the year and month through the panel when the type is year or month
1065
+ * when changing the year and month through the panel when the type is year or month or monthRange
1016
1066
  * @param {*} item
1017
1067
  */
1018
- handleYMSelectedChange(item: { currentMonth?: number; currentYear?: number } = {}) {
1068
+ handleYMSelectedChange(item: { currentMonth?: { left: number; right: number }; currentYear?: { left: number; right: number } } = {}) {
1019
1069
  // console.log(item);
1020
1070
  const { currentMonth, currentYear } = item;
1071
+ const { type } = this.getProps();
1021
1072
 
1022
- if (typeof currentMonth === 'number' && typeof currentYear === 'number') {
1023
- // Strings with only dates (e.g. "1970-01-01") will be treated as UTC instead of local time #1460
1024
- const date = new Date(currentYear, currentMonth - 1);
1073
+ if (type === 'month') {
1074
+ const date = new Date(currentYear['left'], currentMonth['left'] - 1);
1025
1075
 
1026
1076
  this.handleSelectedChange([date]);
1077
+ } else {
1078
+ const dateLeft = new Date(currentYear['left'], currentMonth['left'] - 1);
1079
+ const dateRight = new Date(currentYear['right'], currentMonth['right'] - 1);
1080
+
1081
+ this.handleSelectedChange([dateLeft, dateRight]);
1082
+
1027
1083
  }
1028
1084
  }
1029
1085
 
1030
1086
  handleConfirm() {
1087
+ this.clickConfirmButton = true;
1031
1088
  const { cachedSelectedValue, value } = this._adapter.getStates();
1032
1089
  const isRangeValueComplete = this._isRangeValueComplete(cachedSelectedValue);
1033
1090
  const newValue = isRangeValueComplete ? cachedSelectedValue : value;
@@ -1127,6 +1184,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
1127
1184
  break;
1128
1185
  case 'dateRange':
1129
1186
  case 'dateTimeRange':
1187
+ case 'monthRange':
1130
1188
  notifyValue = _value.map(v => v && this.localeFormat(v, formatToken));
1131
1189
  notifyDate = [..._value];
1132
1190
  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
 
@@ -271,7 +276,7 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
271
276
  *
272
277
  * Parse out insetInputValue from current date value or inputValue
273
278
  */
274
- getInsetInputValue({ value, insetInputValue } : { value: BaseValueType[]; insetInputValue: InsetInputValue }) {
279
+ getInsetInputValue({ value, insetInputValue }: { value: BaseValueType[]; insetInputValue: InsetInputValue }) {
275
280
  const { type, rangeSeparator, format } = this._adapter.getProps();
276
281
 
277
282
  let inputValueStr = '';
@@ -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; // 上下方位快捷选择面板,固定三列,按钮宽度