@douyinfe/semi-ui 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 (111) hide show
  1. package/button/__test__/button.test.js +7 -0
  2. package/button/buttonGroup.tsx +5 -2
  3. package/calendar/monthCalendar.tsx +14 -13
  4. package/cascader/__test__/cascader.test.js +159 -81
  5. package/cascader/_story/cascader.stories.js +36 -23
  6. package/cascader/index.tsx +47 -8
  7. package/cascader/item.tsx +25 -5
  8. package/datePicker/_story/v2/InsetInput.jsx +104 -0
  9. package/datePicker/_story/v2/InsetInputE2E.jsx +69 -0
  10. package/datePicker/_story/v2/index.js +2 -0
  11. package/datePicker/dateInput.tsx +102 -13
  12. package/datePicker/datePicker.tsx +95 -16
  13. package/datePicker/index.tsx +15 -0
  14. package/datePicker/insetInput.tsx +76 -0
  15. package/datePicker/month.tsx +14 -7
  16. package/datePicker/monthsGrid.tsx +31 -12
  17. package/datePicker/navigation.tsx +8 -4
  18. package/datePicker/quickControl.tsx +1 -0
  19. package/datePicker/yearAndMonth.tsx +1 -1
  20. package/dist/css/semi.css +120 -8
  21. package/dist/css/semi.min.css +1 -1
  22. package/dist/umd/semi-ui.js +1100 -193
  23. package/dist/umd/semi-ui.js.map +1 -1
  24. package/dist/umd/semi-ui.min.js +1 -1
  25. package/dist/umd/semi-ui.min.js.map +1 -1
  26. package/form/hoc/withField.tsx +1 -1
  27. package/input/_story/input.stories.js +13 -0
  28. package/lib/cjs/_base/base.css +5 -5
  29. package/lib/cjs/button/buttonGroup.d.ts +1 -0
  30. package/lib/cjs/button/buttonGroup.js +6 -2
  31. package/lib/cjs/calendar/monthCalendar.js +21 -5
  32. package/lib/cjs/cascader/index.d.ts +10 -2
  33. package/lib/cjs/cascader/index.js +52 -10
  34. package/lib/cjs/cascader/item.d.ts +6 -2
  35. package/lib/cjs/cascader/item.js +33 -4
  36. package/lib/cjs/datePicker/dateInput.d.ts +9 -4
  37. package/lib/cjs/datePicker/dateInput.js +107 -13
  38. package/lib/cjs/datePicker/datePicker.d.ts +7 -2
  39. package/lib/cjs/datePicker/datePicker.js +138 -30
  40. package/lib/cjs/datePicker/index.js +24 -2
  41. package/lib/cjs/datePicker/insetInput.d.ts +21 -0
  42. package/lib/cjs/datePicker/insetInput.js +80 -0
  43. package/lib/cjs/datePicker/month.d.ts +1 -0
  44. package/lib/cjs/datePicker/month.js +18 -2
  45. package/lib/cjs/datePicker/monthsGrid.js +35 -11
  46. package/lib/cjs/datePicker/navigation.js +8 -0
  47. package/lib/cjs/datePicker/quickControl.js +1 -0
  48. package/lib/cjs/datePicker/yearAndMonth.js +1 -0
  49. package/lib/cjs/form/hoc/withField.js +1 -1
  50. package/lib/cjs/navigation/Item.d.ts +2 -2
  51. package/lib/cjs/navigation/Item.js +8 -6
  52. package/lib/cjs/navigation/SubNav.js +2 -2
  53. package/lib/cjs/scrollList/scrollItem.d.ts +2 -1
  54. package/lib/cjs/scrollList/scrollItem.js +13 -3
  55. package/lib/cjs/table/Body/index.d.ts +2 -0
  56. package/lib/cjs/table/Body/index.js +13 -4
  57. package/lib/cjs/tree/index.js +5 -3
  58. package/lib/cjs/tree/interface.d.ts +1 -0
  59. package/lib/cjs/tree/nodeList.js +2 -1
  60. package/lib/cjs/treeSelect/index.js +7 -3
  61. package/lib/es/_base/base.css +5 -5
  62. package/lib/es/button/buttonGroup.d.ts +1 -0
  63. package/lib/es/button/buttonGroup.js +5 -2
  64. package/lib/es/calendar/monthCalendar.js +22 -5
  65. package/lib/es/cascader/index.d.ts +10 -2
  66. package/lib/es/cascader/index.js +49 -7
  67. package/lib/es/cascader/item.d.ts +6 -2
  68. package/lib/es/cascader/item.js +31 -4
  69. package/lib/es/datePicker/dateInput.d.ts +9 -4
  70. package/lib/es/datePicker/dateInput.js +106 -13
  71. package/lib/es/datePicker/datePicker.d.ts +7 -2
  72. package/lib/es/datePicker/datePicker.js +139 -30
  73. package/lib/es/datePicker/index.js +20 -0
  74. package/lib/es/datePicker/insetInput.d.ts +21 -0
  75. package/lib/es/datePicker/insetInput.js +65 -0
  76. package/lib/es/datePicker/month.d.ts +1 -0
  77. package/lib/es/datePicker/month.js +18 -2
  78. package/lib/es/datePicker/monthsGrid.js +35 -11
  79. package/lib/es/datePicker/navigation.js +8 -0
  80. package/lib/es/datePicker/quickControl.js +2 -0
  81. package/lib/es/datePicker/yearAndMonth.js +1 -0
  82. package/lib/es/form/hoc/withField.js +1 -1
  83. package/lib/es/navigation/Item.d.ts +2 -2
  84. package/lib/es/navigation/Item.js +8 -6
  85. package/lib/es/navigation/SubNav.js +2 -2
  86. package/lib/es/scrollList/scrollItem.d.ts +2 -1
  87. package/lib/es/scrollList/scrollItem.js +13 -3
  88. package/lib/es/table/Body/index.d.ts +2 -0
  89. package/lib/es/table/Body/index.js +13 -4
  90. package/lib/es/tree/index.js +5 -3
  91. package/lib/es/tree/interface.d.ts +1 -0
  92. package/lib/es/tree/nodeList.js +2 -1
  93. package/lib/es/treeSelect/index.js +7 -3
  94. package/navigation/Item.tsx +15 -12
  95. package/navigation/SubNav.tsx +4 -4
  96. package/package.json +9 -9
  97. package/scrollList/_story/ScrollList/index.js +3 -0
  98. package/scrollList/_story/WheelList/index.js +3 -0
  99. package/scrollList/scrollItem.tsx +30 -9
  100. package/table/Body/index.tsx +15 -4
  101. package/table/__test__/table.test.js +18 -0
  102. package/table/_story/v2/FixedExpandedRow/index.jsx +95 -0
  103. package/table/_story/v2/index.js +2 -1
  104. package/tree/__test__/tree.test.js +87 -2
  105. package/tree/_story/tree.stories.js +65 -5
  106. package/tree/index.tsx +4 -2
  107. package/tree/interface.ts +1 -0
  108. package/tree/nodeList.tsx +2 -2
  109. package/treeSelect/__test__/treeSelect.test.js +28 -0
  110. package/treeSelect/_story/treeSelect.stories.js +55 -2
  111. package/treeSelect/index.tsx +11 -3
@@ -1,10 +1,13 @@
1
+ /* eslint-disable jsx-a11y/click-events-have-key-events,jsx-a11y/interactive-supports-focus */
1
2
  /* eslint-disable max-len */
3
+ /* eslint-disable jsx-a11y/click-events-have-key-events */
4
+ /* eslint-disable jsx-a11y/no-static-element-interactions */
2
5
  import React from 'react';
3
6
  import classnames from 'classnames';
4
7
  import PropTypes from 'prop-types';
5
- import { noop, stubFalse, isDate, get, isFunction } from 'lodash';
8
+ import { noop, stubFalse, isDate, get, isFunction, isEqual } from 'lodash';
6
9
  import ConfigContext from '../configProvider/context';
7
- import DatePickerFoundation, { DatePickerAdapter, DatePickerFoundationProps, DatePickerFoundationState, DayStatusType, PresetType, Type } from '@douyinfe/semi-foundation/datePicker/foundation';
10
+ import DatePickerFoundation, { DatePickerAdapter, DatePickerFoundationProps, DatePickerFoundationState, DayStatusType, PresetType, Type, RangeType } from '@douyinfe/semi-foundation/datePicker/foundation';
8
11
  import { cssClasses, strings, numbers } from '@douyinfe/semi-foundation/datePicker/constants';
9
12
  import { strings as popoverStrings, numbers as popoverNumbers } from '@douyinfe/semi-foundation/popover/constants';
10
13
  import BaseComponent from '../_base/baseComponent';
@@ -17,8 +20,8 @@ import Trigger from '../trigger';
17
20
  import YearAndMonth, { YearAndMonthProps } from './yearAndMonth';
18
21
  import '@douyinfe/semi-foundation/datePicker/datePicker.scss';
19
22
  import { Locale } from '../locale/interface';
20
- import { RangeType } from '@douyinfe/semi-foundation/datePicker/inputFoundation';
21
23
  import { TimePickerProps } from '../timePicker/TimePicker';
24
+ import { InsetInputValue, InsetInputChangeProps } from '@douyinfe/semi-foundation/datePicker/inputFoundation';
22
25
 
23
26
  export interface DatePickerProps extends DatePickerFoundationProps {
24
27
  'aria-describedby'?: React.AriaAttributes['aria-describedby'];
@@ -159,6 +162,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
159
162
  autoSwitchDate: true,
160
163
  syncSwitchMonth: false,
161
164
  rangeSeparator: strings.DEFAULT_SEPARATOR_RANGE,
165
+ insetInput: false,
162
166
  };
163
167
 
164
168
  triggerElRef: React.MutableRefObject<HTMLElement>;
@@ -183,7 +187,9 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
183
187
  prevTimeZone: null,
184
188
  motionEnd: false, // Monitor if popover animation ends
185
189
  rangeInputFocus: undefined, // Optional'rangeStart ',' rangeEnd ', false
186
- autofocus: props.autoFocus || (this.isRangeType(props.type, props.triggerRender) && (props.open || props.defaultOpen))
190
+ autofocus: props.autoFocus || (this.isRangeType(props.type, props.triggerRender) && (props.open || props.defaultOpen)),
191
+ insetInputValue: null,
192
+ triggerDisabled: undefined,
187
193
  };
188
194
 
189
195
  this.adapter.setCache('cachedSelectedValue', null);
@@ -254,6 +260,12 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
254
260
  updateInputValue: inputValue => {
255
261
  this.setState({ inputValue });
256
262
  },
263
+ updateInsetInputValue: (insetInputValue: InsetInputValue) => {
264
+ const { insetInput } = this.props;
265
+ if (insetInput && !isEqual(insetInputValue, this.state.insetInputValue)) {
266
+ this.setState({ insetInputValue });
267
+ }
268
+ },
257
269
  needConfirm: () =>
258
270
  ['dateTime', 'dateTimeRange'].includes(this.props.type) && this.props.needConfirm === true,
259
271
  typeIsYearOrMonth: () => ['month', 'year'].includes(this.props.type),
@@ -309,6 +321,27 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
309
321
  },
310
322
  couldPanelClosed: () => this.focusRecordsRef.current.rangeStart && this.focusRecordsRef.current.rangeEnd,
311
323
  isEventTarget: e => e && e.target === e.currentTarget,
324
+ setInsetInputFocus: () => {
325
+ const { rangeInputFocus } = this.state;
326
+ switch (rangeInputFocus) {
327
+ case 'rangeEnd':
328
+ if (document.activeElement !== this.rangeInputEndRef.current) {
329
+ const inputEndNode = get(this, 'rangeInputEndRef.current');
330
+ inputEndNode && inputEndNode.focus();
331
+ }
332
+ break;
333
+ case 'rangeStart':
334
+ default:
335
+ if (document.activeElement !== this.rangeInputStartRef.current) {
336
+ const inputStartNode = get(this, 'rangeInputStartRef.current');
337
+ inputStartNode && inputStartNode.focus();
338
+ }
339
+ break;
340
+ }
341
+ },
342
+ setTriggerDisabled: (disabled: boolean) => {
343
+ this.setState({ triggerDisabled: disabled });
344
+ }
312
345
  };
313
346
  }
314
347
 
@@ -378,7 +411,8 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
378
411
  syncSwitchMonth,
379
412
  onPanelChange,
380
413
  timeZone,
381
- triggerRender
414
+ triggerRender,
415
+ insetInput
382
416
  } = this.props;
383
417
  const { value, cachedSelectedValue, motionEnd, rangeInputFocus } = this.state;
384
418
 
@@ -425,6 +459,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
425
459
  timeZone={timeZone}
426
460
  focusRecordsRef={this.focusRecordsRef}
427
461
  triggerRender={triggerRender}
462
+ insetInput={insetInput}
428
463
  />
429
464
  );
430
465
  }
@@ -442,6 +477,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
442
477
 
443
478
  handleOpenPanel = () => this.foundation.openPanel();
444
479
  handleInputChange: DatePickerFoundation['handleInputChange'] = (...args) => this.foundation.handleInputChange(...args);
480
+ handleInsetInputChange = (options: InsetInputChangeProps) => this.foundation.handleInsetInputChange(options);
445
481
  handleInputComplete: DatePickerFoundation['handleInputComplete'] = v => this.foundation.handleInputComplete(v);
446
482
  handleInputBlur: DateInputProps['onBlur'] = e => this.foundation.handleInputBlur(get(e, 'nativeEvent.target.value'), e);
447
483
  handleInputFocus: DatePickerFoundation['handleInputFocus'] = (...args) => this.foundation.handleInputFocus(...args);
@@ -458,6 +494,25 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
458
494
  return this.focusRecordsRef.current.rangeStart;
459
495
  }
460
496
  };
497
+ handleInsetDateFocus = (e: React.FocusEvent, rangeType: 'rangeStart' | 'rangeEnd') => {
498
+ const monthGridFoundation = get(this, 'monthGrid.current.foundation');
499
+ if (monthGridFoundation) {
500
+ monthGridFoundation.showDatePanel(strings.PANEL_TYPE_LEFT);
501
+ monthGridFoundation.showDatePanel(strings.PANEL_TYPE_RIGHT);
502
+ }
503
+ this.handleInputFocus(e, rangeType);
504
+ }
505
+
506
+ handleInsetTimeFocus = () => {
507
+ const monthGridFoundation = get(this, 'monthGrid.current.foundation');
508
+ if (monthGridFoundation) {
509
+ monthGridFoundation.showTimePicker(strings.PANEL_TYPE_LEFT);
510
+ monthGridFoundation.showTimePicker(strings.PANEL_TYPE_RIGHT);
511
+ }
512
+ }
513
+ handlePanelVisibleChange = (visible: boolean) => {
514
+ this.foundation.handlePanelVisibleChange(visible);
515
+ }
461
516
 
462
517
  renderInner(extraProps?: Partial<DatePickerProps>) {
463
518
  const {
@@ -477,16 +532,18 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
477
532
  triggerRender,
478
533
  size,
479
534
  inputReadOnly,
480
- rangeSeparator
535
+ rangeSeparator,
536
+ insetInput,
481
537
  } = this.props;
482
- const { value, inputValue, rangeInputFocus } = this.state;
538
+ const { value, inputValue, rangeInputFocus, triggerDisabled } = this.state;
483
539
  // This class is not needed when triggerRender is function
484
540
  const isRangeType = this.isRangeType(type, triggerRender);
541
+ const inputDisabled = disabled || insetInput && triggerDisabled;
485
542
  const inputCls = classnames(`${cssClasses.PREFIX}-input`, {
486
543
  [`${cssClasses.PREFIX}-range-input`]: isRangeType,
487
544
  [`${cssClasses.PREFIX}-range-input-${size}`]: isRangeType && size,
488
- [`${cssClasses.PREFIX}-range-input-active`]: isRangeType && rangeInputFocus && !disabled,
489
- [`${cssClasses.PREFIX}-range-input-disabled`]: isRangeType && disabled,
545
+ [`${cssClasses.PREFIX}-range-input-active`]: isRangeType && rangeInputFocus && !inputDisabled,
546
+ [`${cssClasses.PREFIX}-range-input-disabled`]: isRangeType && inputDisabled,
490
547
  [`${cssClasses.PREFIX}-range-input-${validateStatus}`]: isRangeType && validateStatus,
491
548
  });
492
549
  const phText = placeholder || locale.placeholder[type]; // i18n
@@ -494,9 +551,9 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
494
551
  const props = {
495
552
  ...extraProps,
496
553
  placeholder: phText,
497
- disabled,
554
+ disabled: inputDisabled,
498
555
  inputValue,
499
- value,
556
+ value: value as Date[],
500
557
  onChange: this.handleInputChange,
501
558
  onEnterPress: this.handleInputComplete,
502
559
  // TODO: remove in next major version
@@ -509,7 +566,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
509
566
  format,
510
567
  multiple,
511
568
  validateStatus,
512
- inputReadOnly,
569
+ inputReadOnly: inputReadOnly || insetInput,
513
570
  // onClick: this.handleOpenPanel,
514
571
  onBlur: this.handleInputBlur,
515
572
  onFocus: this.handleInputFocus,
@@ -518,18 +575,22 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
518
575
  size,
519
576
  autofocus: this.state.autofocus,
520
577
  dateFnsLocale,
521
- rangeInputStartRef: this.rangeInputStartRef,
522
- rangeInputEndRef: this.rangeInputEndRef,
523
578
  rangeInputFocus,
524
579
  rangeSeparator,
525
580
  onRangeBlur: this.handleRangeInputBlur,
526
581
  onRangeClear: this.handleRangeInputClear,
527
582
  onRangeEndTabPress: this.handleRangeEndTabPress,
583
+ rangeInputStartRef: insetInput ? null : this.rangeInputStartRef,
584
+ rangeInputEndRef: insetInput ? null : this.rangeInputEndRef,
528
585
  };
529
586
 
530
587
  return (
531
- // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
532
588
  <div
589
+ // tooltip will mount a11y props to children
590
+ // eslint-disable-next-line jsx-a11y/role-has-required-aria-props
591
+ role="combobox"
592
+ aria-label={Array.isArray(value) && value.length ? "Change date" : "Choose date"}
593
+ aria-disabled={disabled}
533
594
  onClick={this.handleTriggerWrapperClick}
534
595
  className={inputCls}>
535
596
  {typeof triggerRender === 'function' ? (
@@ -567,7 +628,8 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
567
628
  };
568
629
 
569
630
  renderPanel = (locale: Locale['DatePicker'], localeCode: string, dateFnsLocale: Locale['dateFnsLocale']) => {
570
- const { dropdownClassName, dropdownStyle, density, topSlot, bottomSlot } = this.props;
631
+ const { dropdownClassName, dropdownStyle, density, topSlot, bottomSlot, insetInput, type, format, rangeSeparator } = this.props;
632
+ const { insetInputValue, value } = this.state;
571
633
  const wrapCls = classnames(
572
634
  cssClasses.PREFIX,
573
635
  {
@@ -577,9 +639,25 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
577
639
  dropdownClassName
578
640
  );
579
641
 
642
+ const insetInputProps = {
643
+ dateFnsLocale,
644
+ format,
645
+ insetInputValue,
646
+ rangeSeparator,
647
+ type,
648
+ value: value as Date[],
649
+ handleInsetDateFocus: this.handleInsetDateFocus,
650
+ handleInsetTimeFocus: this.handleInsetTimeFocus,
651
+ onInsetInputChange: this.handleInsetInputChange,
652
+ rangeInputStartRef: this.rangeInputStartRef,
653
+ rangeInputEndRef: this.rangeInputEndRef,
654
+ density,
655
+ };
656
+
580
657
  return (
581
658
  <div ref={this.panelRef} className={wrapCls} style={dropdownStyle}>
582
659
  {topSlot && <div className={`${cssClasses.PREFIX}-topSlot`}>{topSlot}</div>}
660
+ {insetInput && <DateInput {...insetInputProps} insetInput={true} />}
583
661
  {this.adapter.typeIsYearOrMonth() ?
584
662
  this.renderYearMonthPanel(locale, localeCode) :
585
663
  this.renderMonthGrid(locale, localeCode, dateFnsLocale)}
@@ -648,6 +726,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
648
726
  visible={panelShow}
649
727
  stopPropagation={stopPropagation}
650
728
  spacing={spacing}
729
+ onVisibleChange={this.handlePanelVisibleChange}
651
730
  >
652
731
  {children}
653
732
  </Popover>
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
 
3
3
  import { forwardStatics } from '@douyinfe/semi-foundation/utils/object';
4
+ import { numbers, strings } from '@douyinfe/semi-foundation/datePicker/constants';
4
5
  import DatePicker, { DatePickerProps } from './datePicker';
5
6
  import ConfigContext from '../configProvider/context';
6
7
  import LocaleConsumer from '../locale/localeConsumer';
@@ -33,6 +34,20 @@ export default forwardStatics(
33
34
  propsObj.rangeSeparator = ` ${rangeSeparator.trim()} `;
34
35
  }
35
36
 
37
+ if (propsObj.insetInput) {
38
+ if (!propsObj.position) {
39
+ propsObj.position = strings.POSITION_INLINE_INPUT;
40
+ }
41
+ /**
42
+ * When insetInput is `true` and `position` includes `over`, use 1px `spacing` to solve the problem of border-radius leakage in the upper left corner
43
+ *
44
+ * @see https://user-images.githubusercontent.com/26477537/158817185-126a5f33-41f7-414a-8e36-8d1be2dda5cd.png
45
+ */
46
+ if (propsObj.position.includes('Over') && !propsObj.spacing) {
47
+ propsObj.spacing = numbers.SPACING_INSET_INPUT;
48
+ }
49
+ }
50
+
36
51
  return (
37
52
  <ConfigContext.Consumer>
38
53
  {({ timeZone }: { timeZone?: string | number }) => (
@@ -0,0 +1,76 @@
1
+ import React from 'react';
2
+ import { get } from 'lodash';
3
+
4
+ import {
5
+ InsetInputValue,
6
+ Type,
7
+ InsetInputChangeFoundationProps,
8
+ } from '@douyinfe/semi-foundation/datePicker/inputFoundation';
9
+ import Input, { InputProps } from '../input';
10
+
11
+ export interface InsetDateInputProps {
12
+ forwardRef: InputProps['forwardRef'];
13
+ insetInputValue: InsetInputValue;
14
+ placeholder: string;
15
+ valuePath: string;
16
+ onChange: (options: InsetInputChangeFoundationProps) => void;
17
+ onFocus: InputProps['onFocus'];
18
+ }
19
+
20
+ export interface InsetTimeInputProps {
21
+ disabled: boolean;
22
+ insetInputValue: InsetInputValue;
23
+ placeholder: string;
24
+ valuePath: string;
25
+ type: Type;
26
+ onChange: (options: InsetInputChangeFoundationProps) => void;
27
+ onFocus: InputProps['onFocus'];
28
+ }
29
+
30
+ export function InsetDateInput(props: InsetDateInputProps) {
31
+ const { insetInputValue, valuePath, onFocus, onChange, placeholder, forwardRef } = props;
32
+ const value = get(insetInputValue, valuePath);
33
+
34
+ return (
35
+ <Input
36
+ value={value}
37
+ onChange={(value, event) => {
38
+ onChange({
39
+ value,
40
+ event,
41
+ insetInputValue,
42
+ valuePath,
43
+ });
44
+ }}
45
+ onFocus={onFocus}
46
+ placeholder={placeholder}
47
+ ref={forwardRef}
48
+ />
49
+ );
50
+ }
51
+
52
+ export function InsetTimeInput(props: InsetTimeInputProps) {
53
+ const { insetInputValue, valuePath, type, onFocus, onChange, placeholder, disabled } = props;
54
+ const _isTimeType = type.includes('Time');
55
+ if (!_isTimeType) {
56
+ return null;
57
+ }
58
+ const value = get(insetInputValue, valuePath);
59
+
60
+ return (
61
+ <Input
62
+ value={value}
63
+ onChange={(value, event) => {
64
+ onChange({
65
+ value,
66
+ event,
67
+ insetInputValue,
68
+ valuePath,
69
+ });
70
+ }}
71
+ onFocus={onFocus}
72
+ placeholder={placeholder}
73
+ disabled={disabled}
74
+ />
75
+ );
76
+ }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable jsx-a11y/click-events-have-key-events,jsx-a11y/no-noninteractive-element-interactions */
1
2
  /* eslint-disable max-len */
2
3
  import React from 'react';
3
4
  import classNames from 'classnames';
@@ -40,7 +41,8 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
40
41
  startDateOffset: PropTypes.func,
41
42
  endDateOffset: PropTypes.func,
42
43
  rangeInputFocus: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
43
- focusRecordsRef: PropTypes.object
44
+ focusRecordsRef: PropTypes.object,
45
+ multiple: PropTypes.bool,
44
46
  };
45
47
 
46
48
  static defaultProps = {
@@ -275,9 +277,9 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
275
277
  // i18n
276
278
  const weekdaysText = weekdays.map(key => locale.weeks[key]);
277
279
  return (
278
- <div className={weekdayCls}>
280
+ <div role="row" className={weekdayCls}>
279
281
  {weekdaysText.map((E, i) => (
280
- <div key={E + i} className={weekdayItemCls}>
282
+ <div role="columnheader" key={E + i} className={weekdayItemCls}>
281
283
  {E}
282
284
  </div>
283
285
  ))}
@@ -305,7 +307,7 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
305
307
  renderWeek(week: MonthDayInfo[], weekIndex: number) {
306
308
  const weekCls = cssClasses.WEEK;
307
309
  return (
308
- <div className={weekCls} key={weekIndex}>
310
+ <div role="row" className={weekCls} key={weekIndex}>
309
311
  {week.map((day, dayIndex) => this.renderDay(day, dayIndex))}
310
312
  </div>
311
313
  );
@@ -317,7 +319,7 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
317
319
  const { fullDate, dayNumber } = day;
318
320
  if (!fullDate) {
319
321
  return (
320
- <div key={(dayNumber as number) + dayIndex} className={cssClasses.DAY}>
322
+ <div role="gridcell" tabIndex={-1} key={(dayNumber as number) + dayIndex} className={cssClasses.DAY}>
321
323
  <span />
322
324
  </div>
323
325
  );
@@ -356,6 +358,11 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
356
358
 
357
359
  return (
358
360
  <div
361
+ role="gridcell"
362
+ tabIndex={dayStatus.isDisabled ? -1 : 0}
363
+ aria-disabled={dayStatus.isDisabled}
364
+ aria-selected={dayStatus.isSelected}
365
+ aria-label={fullDate}
359
366
  className={!customRender ? dayCls : cssClasses.DAY}
360
367
  title={fullDate}
361
368
  key={(dayNumber as number) + dayIndex}
@@ -373,13 +380,13 @@ export default class Month extends BaseComponent<MonthProps, MonthState> {
373
380
  }
374
381
 
375
382
  render() {
376
- const { forwardRef } = this.props;
383
+ const { forwardRef, multiple } = this.props;
377
384
  const weekday = this.renderDayOfWeek();
378
385
  const weeks = this.renderWeeks();
379
386
  const monthCls = classNames(cssClasses.MONTH);
380
387
  const ref = forwardRef || this.monthRef;
381
388
  return (
382
- <div ref={ref} className={monthCls}>
389
+ <div role="grid" aria-multiselectable={multiple} ref={ref} className={monthCls} >
383
390
  {weekday}
384
391
  {weeks}
385
392
  </div>
@@ -1,3 +1,5 @@
1
+ /* eslint-disable jsx-a11y/interactive-supports-focus,jsx-a11y/click-events-have-key-events */
2
+ /* eslint-disable jsx-a11y/no-static-element-interactions */
1
3
  /* eslint-disable react/no-did-update-set-state */
2
4
  /* eslint-disable max-len */
3
5
  /* eslint-disable no-nested-ternary */
@@ -273,6 +275,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
273
275
  renderPanel(month: Date, panelType: PanelType) {
274
276
  let monthCls = classnames(`${prefixCls}-month-grid-${panelType}`);
275
277
  const { monthLeft, monthRight, currentPanelHeight } = this.state;
278
+ const { insetInput } = this.props;
276
279
  const panelDetail = panelType === strings.PANEL_TYPE_RIGHT ? monthRight : monthLeft;
277
280
  const { isTimePickerOpen, isYearPickerOpen } = panelDetail;
278
281
 
@@ -295,7 +298,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
295
298
  style.minWidth = wrap.getBoundingClientRect().width;
296
299
  }
297
300
 
298
- if (this.leftIsYearOrTime() && this.rightIsYearOrTime()) {
301
+ if (this.leftIsYearOrTime() && this.rightIsYearOrTime() && !insetInput) {
299
302
  /**
300
303
  * left和right同时为tpk时,panel会有一个minHeight
301
304
  * 如果缓存的currentPanelHeight为0,则需要计算滚动列表的高度
@@ -305,7 +308,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
305
308
  * When left and right are tpk at the same time, the panel will have a minHeight
306
309
  * If the cached currentPanelHeight is 0, you need to calculate the height of the scrolling list
307
310
  * If there is a cached value, use currentPanelHeight (if this height is less than the actual value, it will affect the number of cycles in the ScrollList to render the list)
308
- * See packages/semi-foundation/scrollList/itemF oundation.js initWheelList function
311
+ * See packages/semi-foundation/scrollList/itemFoundation.js initWheelList function
309
312
  */
310
313
 
311
314
  style.minHeight = currentPanelHeight ? currentPanelHeight : this.calcScrollListHeight();
@@ -318,8 +321,11 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
318
321
  monthCls = classnames(monthCls, `${prefixCls}-yam-showing`);
319
322
  }
320
323
 
324
+ const _isDatePanelOpen = !(isYearPickerOpen || isTimePickerOpen);
325
+ const xOpenType = _isDatePanelOpen ? 'date' : isYearPickerOpen ? 'year' : 'time';
326
+
321
327
  return (
322
- <div className={monthCls} key={panelType} style={style}>
328
+ <div className={monthCls} key={panelType} style={style} x-open-type={xOpenType}>
323
329
  {yearAndMonthLayer}
324
330
  {timePickerLayer}
325
331
  {/* {isYearPickerOpen || isTimePickerOpen ? null : panelContent} */}
@@ -343,7 +349,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
343
349
 
344
350
  renderMonth(month: Date, panelType: PanelType) {
345
351
  const { selected, rangeStart, rangeEnd, hoverDay, maxWeekNum, offsetRangeStart, offsetRangeEnd } = this.state;
346
- const { weekStartsOn, disabledDate, locale, localeCode, renderDate, renderFullDate, startDateOffset, endDateOffset, density, rangeInputFocus, syncSwitchMonth } = this.props;
352
+ const { weekStartsOn, disabledDate, locale, localeCode, renderDate, renderFullDate, startDateOffset, endDateOffset, density, rangeInputFocus, syncSwitchMonth, multiple } = this.props;
347
353
  let monthText = '';
348
354
  // i18n monthText
349
355
  if (month) {
@@ -409,6 +415,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
409
415
  startDateOffset={startDateOffset}
410
416
  endDateOffset={endDateOffset}
411
417
  focusRecordsRef={this.props.focusRecordsRef}
418
+ multiple={multiple}
412
419
  />
413
420
  </div>
414
421
  );
@@ -534,9 +541,9 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
534
541
 
535
542
  renderSwitch(panelType: PanelType) {
536
543
  const { rangeStart, rangeEnd, monthLeft, monthRight } = this.state;
537
- const { type, locale, disabledTimePicker, density, dateFnsLocale } = this.props;
538
- // Type: date, dateRange, year, month, no rendering required
539
- if (!type.includes('Time')) {
544
+ const { type, locale, disabledTimePicker, density, dateFnsLocale, insetInput } = this.props;
545
+ // Type: date, dateRange, year, month, inset input no rendering required
546
+ if (!type.includes('Time') || insetInput) {
540
547
  return null;
541
548
  }
542
549
 
@@ -580,12 +587,22 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
580
587
 
581
588
  return (
582
589
  <div className={switchCls} ref={current => this.adapter.setCache(`switch-${panelType}`, current)}>
583
- <div className={dateCls} onClick={e => this.foundation.showDatePanel(panelType)}>
584
- {showSwithIcon && <IconCalendar />}
590
+ <div
591
+ role="button"
592
+ aria-label="Switch to date panel"
593
+ className={dateCls}
594
+ onClick={e => this.foundation.showDatePanel(panelType)}
595
+ >
596
+ {showSwithIcon && <IconCalendar aria-hidden />}
585
597
  <span className={textCls}>{dateText || monthText}</span>
586
598
  </div>
587
- <div className={timeCls} onClick={e => this.foundation.showTimePicker(panelType, true)}>
588
- {showSwithIcon && <IconClock />}
599
+ <div
600
+ role="button"
601
+ aria-label="Switch to time panel"
602
+ className={timeCls}
603
+ onClick={e => this.foundation.showTimePicker(panelType, true)}
604
+ >
605
+ {showSwithIcon && <IconClock aria-hidden />}
589
606
  <span className={textCls}>{timeText}</span>
590
607
  </div>
591
608
  </div>
@@ -594,7 +611,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
594
611
 
595
612
  render() {
596
613
  const { monthLeft, monthRight } = this.state;
597
- const { type } = this.props;
614
+ const { type, insetInput } = this.props;
598
615
  const monthGridCls = classnames({
599
616
  [`${prefixCls }-month-grid`]: true,
600
617
  });
@@ -618,6 +635,8 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
618
635
  className={monthGridCls}
619
636
  x-type={type}
620
637
  x-panel-yearandmonth-open-type={yearOpenType}
638
+ // FIXME:
639
+ x-insetInput={insetInput ? "true" : "false"}
621
640
  ref={current => this.cacheRefCurrent('monthGrid', current)}
622
641
  >
623
642
  {content}
@@ -101,7 +101,8 @@ export default class Navigation extends PureComponent<NavigationProps> {
101
101
  <div className={prefixCls} ref={ref}>
102
102
  <IconButton
103
103
  key="double-chevron-left"
104
- icon={<IconDoubleChevronLeft size={iconBtnSize}/>}
104
+ aria-label="Previous year"
105
+ icon={<IconDoubleChevronLeft aria-hidden size={iconBtnSize} />}
105
106
  size={buttonSize}
106
107
  theme={btnTheme}
107
108
  noHorizontalPadding={btnNoHorizontalPadding}
@@ -110,7 +111,8 @@ export default class Navigation extends PureComponent<NavigationProps> {
110
111
  />
111
112
  <IconButton
112
113
  key="chevron-left"
113
- icon={<IconChevronLeft size={iconBtnSize} />}
114
+ aria-label="Previous month"
115
+ icon={<IconChevronLeft aria-hidden size={iconBtnSize} />}
114
116
  size={buttonSize}
115
117
  onClick={onPrevMonth}
116
118
  theme={btnTheme}
@@ -124,7 +126,8 @@ export default class Navigation extends PureComponent<NavigationProps> {
124
126
  </div>
125
127
  <IconButton
126
128
  key="chevron-right"
127
- icon={<IconChevronRight size={iconBtnSize} />}
129
+ aria-label="Next month"
130
+ icon={<IconChevronRight aria-hidden size={iconBtnSize} />}
128
131
  size={buttonSize}
129
132
  onClick={onNextMonth}
130
133
  theme={btnTheme}
@@ -133,7 +136,8 @@ export default class Navigation extends PureComponent<NavigationProps> {
133
136
  />
134
137
  <IconButton
135
138
  key="double-chevron-right"
136
- icon={<IconDoubleChevronRight size={iconBtnSize}/>}
139
+ aria-label="Next year"
140
+ icon={<IconDoubleChevronRight aria-hidden size={iconBtnSize} />}
137
141
  size={buttonSize}
138
142
  theme={btnTheme}
139
143
  noHorizontalPadding={btnNoHorizontalPadding}
@@ -1,3 +1,4 @@
1
+ /* eslint-disable jsx-a11y/no-static-element-interactions,jsx-a11y/click-events-have-key-events */
1
2
  import React, { PureComponent } from 'react';
2
3
  import classNames from 'classnames';
3
4
  import PropTypes from 'prop-types';
@@ -208,7 +208,7 @@ class YearAndMonth extends BaseComponent<YearAndMonthProps, YearAndMonthState> {
208
208
  <div className={prefix}>
209
209
  <IconButton
210
210
  noHorizontalPadding={false}
211
- icon={<IconChevronLeft size={iconSize} />}
211
+ icon={<IconChevronLeft aria-hidden size={iconSize} />}
212
212
  size={buttonSize}
213
213
  onClick={this.backToMain}
214
214
  >