@douyinfe/semi-foundation 2.5.1 → 2.7.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 (82) hide show
  1. package/button/button.scss +11 -0
  2. package/button/variables.scss +4 -0
  3. package/cascader/foundation.ts +19 -0
  4. package/datePicker/_utils/formatter.ts +2 -2
  5. package/datePicker/_utils/getInsetInputFormatToken.ts +42 -0
  6. package/datePicker/_utils/getInsetInputValueFromInsetInputStr.ts +60 -0
  7. package/datePicker/constants.ts +2 -0
  8. package/datePicker/datePicker.scss +136 -3
  9. package/datePicker/foundation.ts +96 -19
  10. package/datePicker/inputFoundation.ts +133 -5
  11. package/datePicker/monthFoundation.ts +1 -0
  12. package/datePicker/monthsGridFoundation.ts +4 -0
  13. package/datePicker/rtl.scss +8 -0
  14. package/datePicker/variables.scss +30 -0
  15. package/lib/cjs/button/button.css +9 -0
  16. package/lib/cjs/button/button.scss +11 -0
  17. package/lib/cjs/button/variables.scss +4 -0
  18. package/lib/cjs/cascader/foundation.d.ts +19 -0
  19. package/lib/cjs/cascader/foundation.js +22 -0
  20. package/lib/cjs/datePicker/_utils/formatter.d.ts +2 -2
  21. package/lib/cjs/datePicker/_utils/getInsetInputFormatToken.d.ts +20 -0
  22. package/lib/cjs/datePicker/_utils/getInsetInputFormatToken.js +61 -0
  23. package/lib/cjs/datePicker/_utils/getInsetInputValueFromInsetInputStr.d.ts +31 -0
  24. package/lib/cjs/datePicker/_utils/getInsetInputValueFromInsetInputStr.js +76 -0
  25. package/lib/cjs/datePicker/constants.d.ts +2 -0
  26. package/lib/cjs/datePicker/constants.js +4 -3
  27. package/lib/cjs/datePicker/datePicker.css +104 -2
  28. package/lib/cjs/datePicker/datePicker.scss +136 -3
  29. package/lib/cjs/datePicker/foundation.d.ts +34 -11
  30. package/lib/cjs/datePicker/foundation.js +122 -9
  31. package/lib/cjs/datePicker/inputFoundation.d.ts +73 -4
  32. package/lib/cjs/datePicker/inputFoundation.js +196 -3
  33. package/lib/cjs/datePicker/monthFoundation.d.ts +1 -0
  34. package/lib/cjs/datePicker/monthsGridFoundation.d.ts +1 -0
  35. package/lib/cjs/datePicker/monthsGridFoundation.js +4 -2
  36. package/lib/cjs/datePicker/rtl.scss +8 -0
  37. package/lib/cjs/datePicker/variables.scss +30 -0
  38. package/lib/cjs/table/table.css +1 -1
  39. package/lib/cjs/table/table.scss +1 -1
  40. package/lib/cjs/table/variables.scss +1 -0
  41. package/lib/cjs/tag/tag.css +1 -0
  42. package/lib/cjs/tag/tag.scss +1 -0
  43. package/lib/cjs/tooltip/foundation.js +8 -8
  44. package/lib/cjs/treeSelect/foundation.d.ts +3 -2
  45. package/lib/cjs/treeSelect/foundation.js +28 -15
  46. package/lib/es/button/button.css +9 -0
  47. package/lib/es/button/button.scss +11 -0
  48. package/lib/es/button/variables.scss +4 -0
  49. package/lib/es/cascader/foundation.d.ts +19 -0
  50. package/lib/es/cascader/foundation.js +22 -1
  51. package/lib/es/datePicker/_utils/formatter.d.ts +2 -2
  52. package/lib/es/datePicker/_utils/getInsetInputFormatToken.d.ts +20 -0
  53. package/lib/es/datePicker/_utils/getInsetInputFormatToken.js +48 -0
  54. package/lib/es/datePicker/_utils/getInsetInputValueFromInsetInputStr.d.ts +31 -0
  55. package/lib/es/datePicker/_utils/getInsetInputValueFromInsetInputStr.js +66 -0
  56. package/lib/es/datePicker/constants.d.ts +2 -0
  57. package/lib/es/datePicker/constants.js +4 -3
  58. package/lib/es/datePicker/datePicker.css +104 -2
  59. package/lib/es/datePicker/datePicker.scss +136 -3
  60. package/lib/es/datePicker/foundation.d.ts +34 -11
  61. package/lib/es/datePicker/foundation.js +120 -9
  62. package/lib/es/datePicker/inputFoundation.d.ts +73 -4
  63. package/lib/es/datePicker/inputFoundation.js +192 -4
  64. package/lib/es/datePicker/monthFoundation.d.ts +1 -0
  65. package/lib/es/datePicker/monthsGridFoundation.d.ts +1 -0
  66. package/lib/es/datePicker/monthsGridFoundation.js +4 -2
  67. package/lib/es/datePicker/rtl.scss +8 -0
  68. package/lib/es/datePicker/variables.scss +30 -0
  69. package/lib/es/table/table.css +1 -1
  70. package/lib/es/table/table.scss +1 -1
  71. package/lib/es/table/variables.scss +1 -0
  72. package/lib/es/tag/tag.css +1 -0
  73. package/lib/es/tag/tag.scss +1 -0
  74. package/lib/es/tooltip/foundation.js +8 -8
  75. package/lib/es/treeSelect/foundation.d.ts +3 -2
  76. package/lib/es/treeSelect/foundation.js +27 -15
  77. package/package.json +3 -3
  78. package/table/table.scss +1 -1
  79. package/table/variables.scss +1 -0
  80. package/tag/tag.scss +1 -0
  81. package/tooltip/foundation.ts +8 -8
  82. package/treeSelect/foundation.ts +26 -19
@@ -12,10 +12,12 @@ import { getDefaultFormatTokenByType } from './_utils/getDefaultFormatToken';
12
12
  import { strings } from './constants';
13
13
  import { strings as inputStrings } from '../input/constants';
14
14
 
15
- import { Type, DateInputFoundationProps } from './inputFoundation';
15
+ import { Type, DateInputFoundationProps, InsetInputValue } from './inputFoundation';
16
16
  import { MonthsGridFoundationProps } from './monthsGridFoundation';
17
17
  import { WeekStartNumber } from './_utils/getMonthTable';
18
18
  import { ArrayElement, Motion } from '../utils/type';
19
+ import getInsetInputFormatToken from './_utils/getInsetInputFormatToken';
20
+ import getInsetInputValueFromInsetInputStr from './_utils/getInsetInputValueFromInsetInputStr';
19
21
 
20
22
  export type ValidateStatus = ArrayElement<typeof strings.STATUS>;
21
23
  export type InputSize = ArrayElement<typeof strings.SIZE_SET>;
@@ -92,6 +94,8 @@ export interface RenderProps {
92
94
  triggerRender?: TriggerRenderType;
93
95
  }
94
96
 
97
+ export type RangeType = 'rangeStart' | 'rangeEnd' | false;
98
+
95
99
  export interface EventHandlerProps {
96
100
  onCancel?: OnCancelType;
97
101
  onChange?: OnChangeType;
@@ -104,7 +108,7 @@ export interface EventHandlerProps {
104
108
  // onClear?: React.MouseEventHandler<HTMLDivElement>;
105
109
  onClear?: (e: any) => void;
106
110
  // onFocus?: React.MouseEventHandler<HTMLInputElement>;
107
- onFocus?: (e: any, rangType: 'rangeStart' | 'rangeEnd') => void;
111
+ onFocus?: (e: any, rangType: RangeType) => void;
108
112
  onPresetClick?: OnPresetClickType;
109
113
  }
110
114
 
@@ -157,18 +161,21 @@ export interface DatePickerFoundationProps extends ElementProps, RenderProps, Ev
157
161
  dateFnsLocale?: any;
158
162
  localeCode?: string;
159
163
  rangeSeparator?: string;
164
+ insetInput?: boolean;
160
165
  }
161
166
 
162
167
  export interface DatePickerFoundationState {
163
168
  panelShow: boolean;
164
169
  isRange: boolean;
165
170
  inputValue: string;
166
- value: ValueType;
167
- cachedSelectedValue: ValueType;
171
+ value: Date[];
172
+ cachedSelectedValue: Date[];
168
173
  prevTimeZone: string | number;
169
174
  motionEnd: boolean;
170
- rangeInputFocus: 'rangeStart' | 'rangeEnd' | boolean;
175
+ rangeInputFocus: RangeType;
171
176
  autofocus: boolean;
177
+ insetInputValue: InsetInputValue;
178
+ triggerDisabled: boolean;
172
179
  }
173
180
 
174
181
  export { Type, DateInputFoundationProps };
@@ -185,9 +192,9 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
185
192
  notifyConfirm: DatePickerFoundationProps['onConfirm'];
186
193
  notifyOpenChange: DatePickerFoundationProps['onOpenChange'];
187
194
  notifyPresetsClick: DatePickerFoundationProps['onPresetClick'];
188
- updateValue: (value: ValueType) => void;
195
+ updateValue: (value: Date[]) => void;
189
196
  updatePrevTimezone: (prevTimeZone: string | number) => void;
190
- updateCachedSelectedValue: (cachedSelectedValue: ValueType) => void;
197
+ updateCachedSelectedValue: (cachedSelectedValue: Date[]) => void;
191
198
  updateInputValue: (inputValue: string) => void;
192
199
  needConfirm: () => boolean;
193
200
  typeIsYearOrMonth: () => boolean;
@@ -195,6 +202,9 @@ export interface DatePickerAdapter extends DefaultAdapter<DatePickerFoundationPr
195
202
  setRangeInputFocus: (rangeInputFocus: DatePickerFoundationState['rangeInputFocus']) => void;
196
203
  couldPanelClosed: () => boolean;
197
204
  isEventTarget: (e: any) => boolean;
205
+ updateInsetInputValue: (insetInputValue: InsetInputValue) => void;
206
+ setInsetInputFocus: () => void;
207
+ setTriggerDisabled: (disabled: boolean) => void;
198
208
  }
199
209
 
200
210
 
@@ -350,6 +360,16 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
350
360
  }
351
361
  }
352
362
 
363
+ /**
364
+ * clear inset input value when close panel
365
+ */
366
+ clearInsetInputValue() {
367
+ const { insetInput } = this._adapter.getProps();
368
+ if (insetInput) {
369
+ this._adapter.updateInsetInputValue(null);
370
+ }
371
+ }
372
+
353
373
  resetCachedSelectedValue(willUpdateDates?: Date[]) {
354
374
  const { value, cachedSelectedValue } = this._adapter.getStates();
355
375
  const newCachedSelectedValue = Array.isArray(willUpdateDates) ? willUpdateDates : value;
@@ -380,6 +400,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
380
400
  // range type picker, closing panel requires the following side effects
381
401
  this.rangeTypeSideEffectsWhenClosePanel(inputValue, willUpdateDates as Date[]);
382
402
  this.needConfirmSideEffectsWhenClosePanel(willUpdateDates as Date[]);
403
+ this.clearInsetInputValue();
383
404
  this._adapter.notifyOpenChange(false);
384
405
  this._adapter.notifyBlur(e);
385
406
  }
@@ -428,6 +449,37 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
428
449
  }
429
450
  }
430
451
 
452
+ /**
453
+ * inset input 变化时需要更新以下 state 状态
454
+ * - insetInputValue(总是)
455
+ * - inputValue(可以解析为合法日期时)
456
+ * - value(可以解析为合法日期时)
457
+ */
458
+ handleInsetInputChange(options: { insetInputStr: string, format: string, insetInputValue: InsetInputValue }) {
459
+ const { insetInputStr, format, insetInputValue } = options;
460
+ const _isMultiple = this._isMultiple();
461
+ const result = _isMultiple ? this.parseMultipleInput(insetInputStr, format) : this.parseInput(insetInputStr, format);
462
+ const { value: stateValue } = this.getStates();
463
+
464
+ if ((result && result.length)) {
465
+ const changedDates = this._getChangedDates(result);
466
+ if (!this._someDateDisabled(changedDates)) {
467
+ if (this._adapter.needConfirm()) {
468
+ this._adapter.updateCachedSelectedValue(result);
469
+ }
470
+ if (!isEqual(result, stateValue)) {
471
+ if (!this._isControlledComponent()) {
472
+ this._adapter.updateValue(result);
473
+ }
474
+ this._notifyChange(result);
475
+ }
476
+ const triggerInput = _isMultiple ? this.formatMultipleDates(result) : this.formatDates(result);
477
+ this._adapter.updateInputValue(triggerInput);
478
+ }
479
+ }
480
+ this._adapter.updateInsetInputValue(insetInputValue);
481
+ }
482
+
431
483
  /**
432
484
  * Input box blur
433
485
  * @param {String} input
@@ -479,7 +531,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
479
531
  }
480
532
  }
481
533
 
482
- handleSetRangeFocus(rangeInputFocus: boolean | 'rangeStart' | 'rangeEnd') {
534
+ handleSetRangeFocus(rangeInputFocus: RangeType) {
483
535
  this._adapter.setRangeInputFocus(rangeInputFocus);
484
536
  }
485
537
 
@@ -546,14 +598,14 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
546
598
  * @param {string} input
547
599
  * @returns {Date [] | '}
548
600
  */
549
- parseInput(input = '') {
601
+ parseInput(input = '', format?: string) {
550
602
  let result: Date[] = [];
551
603
  // console.log(input);
552
604
  const { dateFnsLocale, rangeSeparator } = this.getProps();
553
605
 
554
606
  if (input && input.length) {
555
607
  const type = this.getProp('type');
556
- const formatToken = this.getProp('format') || getDefaultFormatTokenByType(type);
608
+ const formatToken = format || this.getProp('format') || getDefaultFormatTokenByType(type);
557
609
  let parsedResult,
558
610
  formatedInput;
559
611
  const nowDate = new Date();
@@ -636,13 +688,13 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
636
688
  * @param {Date[]} dates
637
689
  * @returns {string}
638
690
  */
639
- formatDates(dates: Date[] = []) {
691
+ formatDates(dates: Date[] = [], customFormat?: string) {
640
692
  let str = '';
641
693
  const rangeSeparator = this.getProp('rangeSeparator');
642
694
 
643
695
  if (Array.isArray(dates) && dates.length) {
644
696
  const type = this.getProp('type');
645
- const formatToken = this.getProp('format') || getDefaultFormatTokenByType(type);
697
+ const formatToken = customFormat || this.getProp('format') || getDefaultFormatTokenByType(type);
646
698
 
647
699
  switch (type) {
648
700
  case 'date':
@@ -679,7 +731,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
679
731
  * @param {Date[]} dates
680
732
  * @returns {string}
681
733
  */
682
- formatMultipleDates(dates: Date[] = [], separator: string = strings.DEFAULT_SEPARATOR_MULTIPLE) {
734
+ formatMultipleDates(dates: Date[] = [], separator: string = strings.DEFAULT_SEPARATOR_MULTIPLE, customFormat?: string) {
683
735
  const strs = [];
684
736
  if (Array.isArray(dates) && dates.length) {
685
737
  const type = this.getProp('type');
@@ -688,12 +740,12 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
688
740
  case 'date':
689
741
  case 'dateTime':
690
742
  case 'month':
691
- dates.forEach(date => strs.push(this.formatDates([date])));
743
+ dates.forEach(date => strs.push(this.formatDates([date], customFormat)));
692
744
  break;
693
745
  case 'dateRange':
694
746
  case 'dateTimeRange':
695
747
  for (let i = 0; i < dates.length; i += 2) {
696
- strs.push(this.formatDates(dates.slice(i, i + 2)));
748
+ strs.push(this.formatDates(dates.slice(i, i + 2), customFormat));
697
749
  }
698
750
  break;
699
751
  default:
@@ -735,7 +787,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
735
787
  * @param {*} options
736
788
  */
737
789
  handleSelectedChange(value: Date[], options?: { fromPreset?: boolean; needCheckFocusRecord?: boolean }) {
738
- const type = this.getProp('type');
790
+ const { type, format, rangeSeparator, insetInput } = this._adapter.getProps();
739
791
  const { value: stateValue } = this.getStates();
740
792
  const controlled = this._isControlledComponent();
741
793
  const fromPreset = isObject(options) ? options.fromPreset : options;
@@ -754,9 +806,14 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
754
806
  const dates = Array.isArray(value) ? [...value] : value ? [value] : [];
755
807
  const changedDates = this._getChangedDates(dates);
756
808
 
757
- let inputValue;
809
+ let inputValue, insetInputValue;
758
810
  if (!this._someDateDisabled(changedDates)) {
759
811
  inputValue = this._isMultiple() ? this.formatMultipleDates(dates) : this.formatDates(dates);
812
+ if (insetInput) {
813
+ const insetInputFormatToken = getInsetInputFormatToken({ format, type });
814
+ const insetInputStr = this._isMultiple() ? this.formatMultipleDates(dates, undefined, insetInputFormatToken) : this.formatDates(dates, insetInputFormatToken);
815
+ insetInputValue = getInsetInputValueFromInsetInputStr({ inputValue: insetInputStr, type, rangeSeparator });
816
+ }
760
817
  const isRangeTypeAndInputIncomplete = this._isRangeType() && !this._isRangeValueComplete(dates);
761
818
  /**
762
819
  * If the input is incomplete when under control, the notifyChange is not triggered because
@@ -769,14 +826,19 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
769
826
  if (isRangeTypeAndInputIncomplete) {
770
827
  // do not change value when selected value is incomplete
771
828
  this._adapter.updateInputValue(inputValue);
829
+ this._adapter.updateInsetInputValue(insetInputValue);
772
830
  return;
773
831
  } else {
774
- (!controlled || fromPreset) && this._updateValueAndInput(dates, true, inputValue);
832
+ if (!controlled || fromPreset) {
833
+ this._updateValueAndInput(dates, true, inputValue);
834
+ this._adapter.updateInsetInputValue(insetInputValue);
835
+ }
775
836
  }
776
837
  }
777
838
  if (!controlled && this._adapter.needConfirm()) {
778
839
  // select date only change inputValue when needConfirm is true
779
840
  this._adapter.updateInputValue(inputValue);
841
+ this._adapter.updateInsetInputValue(insetInputValue);
780
842
  // if inputValue is not complete, don't notifyChange
781
843
  if (isRangeTypeAndInputIncomplete) {
782
844
  return;
@@ -810,7 +872,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
810
872
  }
811
873
 
812
874
  handleConfirm() {
813
- const { cachedSelectedValue, value } = this.getStates();
875
+ const { cachedSelectedValue, value } = this._adapter.getStates();
814
876
  const isRangeValueComplete = this._isRangeValueComplete(cachedSelectedValue);
815
877
  const newValue = isRangeValueComplete ? cachedSelectedValue : value;
816
878
  if (this._adapter.needConfirm() && !this._isControlledComponent()) {
@@ -1121,4 +1183,19 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
1121
1183
  this.openPanel();
1122
1184
  }
1123
1185
  }
1186
+
1187
+ handlePanelVisibleChange(visible: boolean) {
1188
+ if (visible) {
1189
+ this._adapter.setInsetInputFocus();
1190
+ /**
1191
+ * After the panel is closed, the trigger input is disabled
1192
+ * 面板关闭后,trigger input 禁用
1193
+ */
1194
+ setTimeout(() => {
1195
+ this._adapter.setTriggerDisabled(true);
1196
+ }, 0);
1197
+ } else {
1198
+ this._adapter.setTriggerDisabled(false);
1199
+ }
1200
+ }
1124
1201
  }
@@ -1,8 +1,13 @@
1
1
  /* eslint-disable max-len */
2
+ import { cloneDeep, isObject, set } from 'lodash';
3
+
2
4
  import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
- import { BaseValueType, ValidateStatus, ValueType } from './foundation';
5
+ import { BaseValueType, ValidateStatus } from './foundation';
4
6
  import { formatDateValues } from './_utils/formatter';
5
7
  import { getDefaultFormatTokenByType } from './_utils/getDefaultFormatToken';
8
+ import getInsetInputFormatToken from './_utils/getInsetInputFormatToken';
9
+ import getInsetInputValueFromInsetInputStr from './_utils/getInsetInputValueFromInsetInputStr';
10
+ import { strings } from './constants';
6
11
 
7
12
  const KEY_CODE_ENTER = 'Enter';
8
13
  const KEY_CODE_TAB = 'Tab';
@@ -10,6 +15,7 @@ const KEY_CODE_TAB = 'Tab';
10
15
 
11
16
  export type Type = 'date' | 'dateRange' | 'year' | 'month' | 'dateTime' | 'dateTimeRange';
12
17
  export type RangeType = 'rangeStart' | 'rangeEnd';
18
+ export type PanelType = 'left' | 'right';
13
19
 
14
20
  export interface DateInputEventHandlerProps {
15
21
  onClick?: (e: any) => void;
@@ -20,6 +26,7 @@ export interface DateInputEventHandlerProps {
20
26
  onClear?: (e: any) => void;
21
27
  onRangeInputClear?: (e: any) => void;
22
28
  onRangeEndTabPress?: (e: any) => void;
29
+ onInsetInputChange?: (options: InsetInputChangeProps) => void;
23
30
  }
24
31
 
25
32
  export interface DateInputElementProps {
@@ -29,10 +36,9 @@ export interface DateInputElementProps {
29
36
 
30
37
  export interface DateInputFoundationProps extends DateInputElementProps, DateInputEventHandlerProps {
31
38
  [x: string]: any;
32
- value?: ValueType;
39
+ value?: BaseValueType[];
33
40
  disabled?: boolean;
34
41
  type?: Type;
35
- multiple?: boolean;
36
42
  showClear?: boolean;
37
43
  format?: string;
38
44
  inputStyle?: React.CSSProperties;
@@ -40,12 +46,41 @@ export interface DateInputFoundationProps extends DateInputElementProps, DateInp
40
46
  validateStatus?: ValidateStatus;
41
47
  prefixCls?: string;
42
48
  rangeSeparator?: string;
49
+ panelType?: PanelType;
50
+ insetInput?: boolean;
51
+ insetInputValue?: InsetInputValue;
52
+ density?: typeof strings.DENSITY_SET[number];
53
+ }
54
+
55
+ export interface InsetInputValue {
56
+ monthLeft: {
57
+ dateInput: string;
58
+ timeInput: string;
59
+ },
60
+ monthRight: {
61
+ dateInput: string;
62
+ timeInput: string;
63
+ }
64
+ }
65
+
66
+ export interface InsetInputChangeFoundationProps {
67
+ value: string;
68
+ insetInputValue: InsetInputValue;
69
+ event: any;
70
+ valuePath: string;
71
+ }
72
+
73
+ export interface InsetInputChangeProps {
74
+ insetInputStr: string;
75
+ format: string;
76
+ insetInputValue: InsetInputValue;
43
77
  }
44
78
 
45
79
  export interface DateInputAdapter extends DefaultAdapter {
46
80
  updateIsFocusing: (isFocusing: boolean) => void;
47
81
  notifyClick: DateInputFoundationProps['onClick'];
48
82
  notifyChange: DateInputFoundationProps['onChange'];
83
+ notifyInsetInputChange: DateInputFoundationProps['onInsetInputChange'];
49
84
  notifyEnter: DateInputFoundationProps['onEnterPress'];
50
85
  notifyBlur: DateInputFoundationProps['onBlur'];
51
86
  notifyClear: DateInputFoundationProps['onClear'];
@@ -110,9 +145,9 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
110
145
  this._adapter.notifyRangeInputFocus(e, rangeType);
111
146
  }
112
147
 
113
- formatShowText(value: BaseValueType[]) {
148
+ formatShowText(value: BaseValueType[], customFormat?: string) {
114
149
  const { type, dateFnsLocale, format, rangeSeparator } = this._adapter.getProps();
115
- const formatToken = format || getDefaultFormatTokenByType(type);
150
+ const formatToken = customFormat || format || getDefaultFormatTokenByType(type);
116
151
  let text = '';
117
152
  switch (type) {
118
153
  case 'date':
@@ -135,4 +170,97 @@ export default class InputFoundation extends BaseFoundation<DateInputAdapter> {
135
170
  }
136
171
  return text;
137
172
  }
173
+
174
+ handleInsetInputChange(options: InsetInputChangeFoundationProps) {
175
+ const { value, valuePath, insetInputValue } = options;
176
+ const { format, type } = this._adapter.getProps();
177
+ const insetFormatToken = getInsetInputFormatToken({ type, format });
178
+ const newInsetInputValue = set(cloneDeep(insetInputValue), valuePath, value);
179
+ const newInputValue = this.concatInsetInputValue({ insetInputValue: newInsetInputValue });
180
+ this._adapter.notifyInsetInputChange({ insetInputValue: newInsetInputValue, format: insetFormatToken, insetInputStr: newInputValue });
181
+ }
182
+
183
+ /**
184
+ * 只有传入的 format 符合 formatReg 时,才会使用用户传入的 format
185
+ * 否则会使用默认的 format 作为 placeholder
186
+ *
187
+ * The format passed in by the user will be used only if the incoming format conforms to formatReg
188
+ * Otherwise the default format will be used as placeholder
189
+ */
190
+ getInsetInputPlaceholder() {
191
+ const { type, format } = this._adapter.getProps();
192
+ const insetInputFormat = getInsetInputFormatToken({ type, format });
193
+ let datePlaceholder, timePlaceholder;
194
+
195
+ switch (type) {
196
+ case 'date':
197
+ case 'month':
198
+ case 'dateRange':
199
+ datePlaceholder = insetInputFormat;
200
+ break;
201
+ case 'dateTime':
202
+ case 'dateTimeRange':
203
+ [datePlaceholder, timePlaceholder] = insetInputFormat.split(' ');
204
+ break;
205
+ }
206
+
207
+ return ({
208
+ datePlaceholder,
209
+ timePlaceholder,
210
+ });
211
+ }
212
+
213
+ /**
214
+ * 从当前日期值或 inputValue 中解析出 insetInputValue
215
+ *
216
+ * Parse out insetInputValue from current date value or inputValue
217
+ */
218
+ getInsetInputValue({ value, insetInputValue } : { value: BaseValueType[]; insetInputValue: InsetInputValue }) {
219
+ const { type, rangeSeparator, format } = this._adapter.getProps();
220
+
221
+ let inputValueStr = '';
222
+ if (isObject(insetInputValue)) {
223
+ inputValueStr = this.concatInsetInputValue({ insetInputValue });
224
+ } else {
225
+ const insetInputFormat = getInsetInputFormatToken({ format, type });
226
+ inputValueStr = this.formatShowText(value, insetInputFormat);
227
+ }
228
+
229
+ const newInsetInputValue = getInsetInputValueFromInsetInputStr({ inputValue: inputValueStr, type, rangeSeparator });
230
+ return newInsetInputValue;
231
+ }
232
+
233
+ concatInsetDateAndTime({ date, time }) {
234
+ return `${date} ${time}`;
235
+ }
236
+
237
+ concatInsetDateRange({ rangeStart, rangeEnd }) {
238
+ const { rangeSeparator } = this._adapter.getProps();
239
+ return `${rangeStart}${rangeSeparator}${rangeEnd}`;
240
+ }
241
+
242
+ concatInsetInputValue({ insetInputValue }: { insetInputValue: InsetInputValue }) {
243
+ const { type } = this._adapter.getProps();
244
+ let inputValue = '';
245
+
246
+ switch (type) {
247
+ case 'date':
248
+ case 'month':
249
+ inputValue = insetInputValue.monthLeft.dateInput;
250
+ break;
251
+ case 'dateRange':
252
+ inputValue = this.concatInsetDateRange({ rangeStart: insetInputValue.monthLeft.dateInput, rangeEnd: insetInputValue.monthRight.dateInput });
253
+ break;
254
+ case 'dateTime':
255
+ inputValue = this.concatInsetDateAndTime({ date: insetInputValue.monthLeft.dateInput, time: insetInputValue.monthLeft.timeInput });
256
+ break;
257
+ case 'dateTimeRange':
258
+ const rangeStart = this.concatInsetDateAndTime({ date: insetInputValue.monthLeft.dateInput, time: insetInputValue.monthLeft.timeInput });
259
+ const rangeEnd = this.concatInsetDateAndTime({ date: insetInputValue.monthRight.dateInput, time: insetInputValue.monthRight.timeInput });
260
+ inputValue = this.concatInsetDateRange({ rangeStart, rangeEnd });
261
+ break;
262
+ }
263
+
264
+ return inputValue;
265
+ }
138
266
  }
@@ -28,6 +28,7 @@ export interface MonthFoundationProps {
28
28
  focusRecordsRef: any;
29
29
  locale: any;
30
30
  localeCode: string;
31
+ multiple: boolean;
31
32
  }
32
33
 
33
34
  export type MonthDayInfo = {
@@ -86,6 +86,7 @@ export interface MonthsGridFoundationProps extends MonthsGridElementProps {
86
86
  isAnotherPanelHasOpened?: (currentRangeInput: 'rangeStart' | 'rangeEnd') => boolean;
87
87
  focusRecordsRef?: any;
88
88
  triggerRender?: (props: Record<string, any>) => any;
89
+ insetInput: boolean;
89
90
  }
90
91
 
91
92
  export interface MonthInfo {
@@ -218,6 +219,7 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
218
219
  _initDatePickerFromValue(values: BaseValueType[], refreshPicker = true) {
219
220
  const monthLeft = this.getState('monthLeft');
220
221
  const newMonthLeft = { ...monthLeft };
222
+ // REMOVE:
221
223
  this._adapter.updateMonthOnLeft(newMonthLeft);
222
224
  const newSelected = new Set<string>();
223
225
  if (!this._isMultiple()) {
@@ -230,6 +232,7 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
230
232
  if (refreshPicker) {
231
233
  this.handleShowDateAndTime(strings.PANEL_TYPE_LEFT, values[0] || newMonthLeft.pickerDate);
232
234
  } else {
235
+ // FIXME:
233
236
  this.handleShowDateAndTime(strings.PANEL_TYPE_LEFT, newMonthLeft.pickerDate);
234
237
  }
235
238
  this._adapter.updateDaySelected(newSelected);
@@ -534,6 +537,7 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
534
537
  ) {
535
538
  const { multiple, disabledDate } = this.getProps();
536
539
  const { selected: selectedSet, rangeStart, rangeEnd } = this.getStates();
540
+ // FIXME:
537
541
  const includeRange = ['dateRange', 'dateTimeRange'].includes(type);
538
542
  const options = { closePanel: false };
539
543
  if (!multiple && !includeRange && selectedSet.size) {
@@ -181,5 +181,13 @@ $module: #{$prefix}-datepicker;
181
181
  padding-left: $spacing-datepicker_footer_compact-paddintRight;
182
182
  padding-right: auto;
183
183
  }
184
+
185
+ .#{$module}-inset-input {
186
+ &-separator {
187
+ border-right: $width-datepicker-border solid $color-datepicker_border-bg-default;
188
+ border-left: 0;
189
+ transform: translateX(-50%);
190
+ }
191
+ }
184
192
  }
185
193
  }
@@ -23,6 +23,14 @@ $width-datepicker_quick_control-borderRadius: var(--semi-border-radius-medium);
23
23
  $width-datepicker_slot-border: 1px; // 日期星期分割线宽度
24
24
  $width-datepicker_range_input-border: $border-thickness-control-focus;
25
25
  $width-datepicker_day_main-border: 1px;
26
+ $height-datepicker_timeType_insetInput_yam: 100%; // 时间面板高度 - 内嵌输入框
27
+ $height-datepicker_timeType_insetInput_tpk: 100%; // 时间面板高度 - 内嵌输入框
28
+ $width-datepicker_insetInput_date_type_wrapper: 284px; // 日期类型内嵌输入框宽度
29
+ $width-datepicker_insetInput_date_range_type_wrapper: $width-datepicker_insetInput_date_type_wrapper * 2; // 范围选择内嵌输入框宽度
30
+ $width-datepicker_insetInput_month_type_wrapper: 204px; // 月份类型内嵌输入框宽度
31
+ $height-datepicker_insetInput_separator: 32px;
32
+ $height-datepicker_month_grid_yearType_insetInput: 312px;
33
+ $height-datepicker_month_grid_timeType_insetInput: 314px;
26
34
 
27
35
  // Spacing
28
36
  $spacing-datepicker_day-marginX: ($width-datepicker_day - $width-datepicker_day_main) / 2; // 日期格子水平外边距
@@ -53,6 +61,14 @@ $spacing-datepicker_range_input_suffix-paddingLeft: 8px;
53
61
  $spacing-datepicker_range_input_suffix-paddingRight: 12px;
54
62
  $spacing-datepicker_range_input_clearbtn-paddingLeft: 8px;
55
63
  $spacing-datepicker_range_input_clearbtn-paddingRight: 12px;
64
+ $spacing-datepicker_navigation_insetInput-paddingY: 8px; // 年月切换 header 垂直内边距 - 内嵌输入框
65
+ $spacing-datepicker_insetInput_wrapper-margin: 8px;
66
+ $spacing-datepicker_insetInput_wrapper-paddingY: 12px;
67
+ $spacing-datepicker_insetInput_wrapper-paddingX: 16px;
68
+ $spacing-datepicker_insetInput_wrapper-paddingBottom: 0;
69
+ $spacing-datepicker_insetInput_separator-paddingY: 0;
70
+ $spacing-datepicker_insetInput_separator-paddingX: 4px;
71
+
56
72
 
57
73
  // Color
58
74
  $color-datepicker_panel-bg-default: var(--semi-color-bg-3); // 日期选择器背景颜色
@@ -118,6 +134,7 @@ $color-datepicker_range_input_inputWrapper-bg-default: transparent;
118
134
  $color-datepicker_range_input_inputWrapper-bg-focus: var(--semi-color-fill-1);
119
135
  $color-datepicker_range_input_separator-text-active: var(--semi-color-text-0);
120
136
  $color-datepicker_day_main-border: var(--semi-color-primary-active);
137
+ $color-datepicker_insetInput_separator: var(--semi-color-text-3);
121
138
 
122
139
  // Font
123
140
  $font-datepicker_range_input_prefix_suffix_clearbtn-fontWeight: 600;
@@ -144,9 +161,17 @@ $radius-datepicker_range_input_inputWrapper: var(--semi-border-radius-small);
144
161
  $height-datepicker_range_input-default: 32px;
145
162
  $height-datepicker_range_input-small: 24px;
146
163
  $height-datepicker_range_input-large: 40px;
164
+ $width-datepicker_insetInput_date_type_wrapper_compact: 216px;
165
+ $width-datepicker_insetInput_date_range_type_wrapper_compact: $width-datepicker_insetInput_date_type_wrapper_compact * 2;
166
+ $width-datepicker_insetInput_month_type_wrapper_compact: 195px;
167
+ $height-datepicker_insetInput_tpk_compact: 100%;
168
+ $height-datepicker_timeType_insetInput_yam_compact: 100%;
169
+ $height-datepicker_insetInput_wrapper_compact: 28px;
147
170
 
148
171
  $lineHeight-datepicker_compact: 20px;
149
172
  $lineHeight-datepicker_weekday_item_compact: 28px;
173
+ $height-datepicker_insetInput_compact: 26px;
174
+ $fontSize-datepicker_insetInput_compact-fontSize: 12px;
150
175
 
151
176
  $spacing-datepicker_switch_compact-padding: 6px;
152
177
  $spacing-datepicker_day_compact-margin: ($width-datepicker_day_compact - $width-datepicker_day_main_compact) / 2;
@@ -163,6 +188,11 @@ $spacing-datepicker_footer_compact-paddintBottom: 10px;
163
188
  $spacing-datepicker_footer_compact-paddintRight: 8px;
164
189
  $spacing-datepicker_scrolllist_shade_pre_compact-marginTop: -17px;
165
190
  $spacing-datepicker_scrolllist_shade_post_compact-marginTop: 17px;
191
+ $spacing-datepicker_insetInput_wrapper_compact-margin: 4px;
192
+ $spacing-datepicker_insetInput_wrapper_compact-paddingY: 8px;
193
+ $spacing-datepicker_insetInput_wrapper_compact-paddingX: 8px;
194
+ $spacing-datepicker_insetInput_wrapper_compact-paddingBottom: 0;
195
+ $spacing-datepicker_insetInput_wrapper_rangeType_compact-paddingTop: 0;
166
196
 
167
197
  // Radius
168
198
  $radius-datepicker_range_input: var(--semi-border-radius-small);
@@ -44,6 +44,9 @@
44
44
  vertical-align: middle;
45
45
  white-space: nowrap;
46
46
  }
47
+ .semi-button:focus {
48
+ outline: 2px solid var(--semi-color-primary-light-active);
49
+ }
47
50
  .semi-button-danger {
48
51
  background-color: var(--semi-color-danger);
49
52
  color: white;
@@ -57,6 +60,9 @@
57
60
  .semi-button-danger.semi-button-light, .semi-button-danger.semi-button-borderless {
58
61
  color: var(--semi-color-danger);
59
62
  }
63
+ .semi-button-danger:not(.semi-button-borderless):not(.semi-button-light):focus {
64
+ outline-color: var(--semi-color-danger-light-active);
65
+ }
60
66
  .semi-button-warning {
61
67
  background-color: var(--semi-color-warning);
62
68
  color: white;
@@ -70,6 +76,9 @@
70
76
  .semi-button-warning.semi-button-light, .semi-button-warning.semi-button-borderless {
71
77
  color: var(--semi-color-warning);
72
78
  }
79
+ .semi-button-warning:not(.semi-button-borderless):not(.semi-button-light):focus {
80
+ outline-color: var(--semi-color-warning-light-active);
81
+ }
73
82
  .semi-button-tertiary {
74
83
  background-color: var(--semi-color-tertiary);
75
84
  color: white;
@@ -23,6 +23,11 @@ $module: #{$prefix}-button;
23
23
  outline: none;
24
24
  vertical-align: middle;
25
25
  white-space: nowrap;
26
+
27
+ &:focus {
28
+ outline: $width-button-outline solid $color-button_primary-outline-focus;
29
+ }
30
+
26
31
  &-danger {
27
32
  background-color: $color-button_danger-bg-default;
28
33
  color: $color-button_danger-text-default;
@@ -36,6 +41,9 @@ $module: #{$prefix}-button;
36
41
  &.#{$module}-borderless {
37
42
  color: $color-button_danger-bg-default;
38
43
  }
44
+ &:not(.#{$module}-borderless):not(.#{$module}-light):focus {
45
+ outline-color: $color-button_danger-outline-focus;
46
+ }
39
47
  }
40
48
  &-warning {
41
49
  background-color: $color-button_warning-bg-default;
@@ -50,6 +58,9 @@ $module: #{$prefix}-button;
50
58
  &.#{$module}-borderless {
51
59
  color: $color-button_warning-bg-default;
52
60
  }
61
+ &:not(.#{$module}-borderless):not(.#{$module}-light):focus {
62
+ outline-color: $color-button_warning-outline-focus;
63
+ }
53
64
  }
54
65
  &-tertiary {
55
66
  background-color: $color-button_tertiary-bg-default;