@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.
- package/button/__test__/button.test.js +7 -0
- package/button/buttonGroup.tsx +5 -2
- package/calendar/monthCalendar.tsx +14 -13
- package/cascader/__test__/cascader.test.js +159 -81
- package/cascader/_story/cascader.stories.js +36 -23
- package/cascader/index.tsx +47 -8
- package/cascader/item.tsx +25 -5
- package/datePicker/_story/v2/InsetInput.jsx +104 -0
- package/datePicker/_story/v2/InsetInputE2E.jsx +69 -0
- package/datePicker/_story/v2/index.js +2 -0
- package/datePicker/dateInput.tsx +102 -13
- package/datePicker/datePicker.tsx +95 -16
- package/datePicker/index.tsx +15 -0
- package/datePicker/insetInput.tsx +76 -0
- package/datePicker/month.tsx +14 -7
- package/datePicker/monthsGrid.tsx +31 -12
- package/datePicker/navigation.tsx +8 -4
- package/datePicker/quickControl.tsx +1 -0
- package/datePicker/yearAndMonth.tsx +1 -1
- package/dist/css/semi.css +120 -8
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +1100 -193
- package/dist/umd/semi-ui.js.map +1 -1
- package/dist/umd/semi-ui.min.js +1 -1
- package/dist/umd/semi-ui.min.js.map +1 -1
- package/form/hoc/withField.tsx +1 -1
- package/input/_story/input.stories.js +13 -0
- package/lib/cjs/_base/base.css +5 -5
- package/lib/cjs/button/buttonGroup.d.ts +1 -0
- package/lib/cjs/button/buttonGroup.js +6 -2
- package/lib/cjs/calendar/monthCalendar.js +21 -5
- package/lib/cjs/cascader/index.d.ts +10 -2
- package/lib/cjs/cascader/index.js +52 -10
- package/lib/cjs/cascader/item.d.ts +6 -2
- package/lib/cjs/cascader/item.js +33 -4
- package/lib/cjs/datePicker/dateInput.d.ts +9 -4
- package/lib/cjs/datePicker/dateInput.js +107 -13
- package/lib/cjs/datePicker/datePicker.d.ts +7 -2
- package/lib/cjs/datePicker/datePicker.js +138 -30
- package/lib/cjs/datePicker/index.js +24 -2
- package/lib/cjs/datePicker/insetInput.d.ts +21 -0
- package/lib/cjs/datePicker/insetInput.js +80 -0
- package/lib/cjs/datePicker/month.d.ts +1 -0
- package/lib/cjs/datePicker/month.js +18 -2
- package/lib/cjs/datePicker/monthsGrid.js +35 -11
- package/lib/cjs/datePicker/navigation.js +8 -0
- package/lib/cjs/datePicker/quickControl.js +1 -0
- package/lib/cjs/datePicker/yearAndMonth.js +1 -0
- package/lib/cjs/form/hoc/withField.js +1 -1
- package/lib/cjs/navigation/Item.d.ts +2 -2
- package/lib/cjs/navigation/Item.js +8 -6
- package/lib/cjs/navigation/SubNav.js +2 -2
- package/lib/cjs/scrollList/scrollItem.d.ts +2 -1
- package/lib/cjs/scrollList/scrollItem.js +13 -3
- package/lib/cjs/table/Body/index.d.ts +2 -0
- package/lib/cjs/table/Body/index.js +13 -4
- package/lib/cjs/tree/index.js +5 -3
- package/lib/cjs/tree/interface.d.ts +1 -0
- package/lib/cjs/tree/nodeList.js +2 -1
- package/lib/cjs/treeSelect/index.js +7 -3
- package/lib/es/_base/base.css +5 -5
- package/lib/es/button/buttonGroup.d.ts +1 -0
- package/lib/es/button/buttonGroup.js +5 -2
- package/lib/es/calendar/monthCalendar.js +22 -5
- package/lib/es/cascader/index.d.ts +10 -2
- package/lib/es/cascader/index.js +49 -7
- package/lib/es/cascader/item.d.ts +6 -2
- package/lib/es/cascader/item.js +31 -4
- package/lib/es/datePicker/dateInput.d.ts +9 -4
- package/lib/es/datePicker/dateInput.js +106 -13
- package/lib/es/datePicker/datePicker.d.ts +7 -2
- package/lib/es/datePicker/datePicker.js +139 -30
- package/lib/es/datePicker/index.js +20 -0
- package/lib/es/datePicker/insetInput.d.ts +21 -0
- package/lib/es/datePicker/insetInput.js +65 -0
- package/lib/es/datePicker/month.d.ts +1 -0
- package/lib/es/datePicker/month.js +18 -2
- package/lib/es/datePicker/monthsGrid.js +35 -11
- package/lib/es/datePicker/navigation.js +8 -0
- package/lib/es/datePicker/quickControl.js +2 -0
- package/lib/es/datePicker/yearAndMonth.js +1 -0
- package/lib/es/form/hoc/withField.js +1 -1
- package/lib/es/navigation/Item.d.ts +2 -2
- package/lib/es/navigation/Item.js +8 -6
- package/lib/es/navigation/SubNav.js +2 -2
- package/lib/es/scrollList/scrollItem.d.ts +2 -1
- package/lib/es/scrollList/scrollItem.js +13 -3
- package/lib/es/table/Body/index.d.ts +2 -0
- package/lib/es/table/Body/index.js +13 -4
- package/lib/es/tree/index.js +5 -3
- package/lib/es/tree/interface.d.ts +1 -0
- package/lib/es/tree/nodeList.js +2 -1
- package/lib/es/treeSelect/index.js +7 -3
- package/navigation/Item.tsx +15 -12
- package/navigation/SubNav.tsx +4 -4
- package/package.json +9 -9
- package/scrollList/_story/ScrollList/index.js +3 -0
- package/scrollList/_story/WheelList/index.js +3 -0
- package/scrollList/scrollItem.tsx +30 -9
- package/table/Body/index.tsx +15 -4
- package/table/__test__/table.test.js +18 -0
- package/table/_story/v2/FixedExpandedRow/index.jsx +95 -0
- package/table/_story/v2/index.js +2 -1
- package/tree/__test__/tree.test.js +87 -2
- package/tree/_story/tree.stories.js +65 -5
- package/tree/index.tsx +4 -2
- package/tree/interface.ts +1 -0
- package/tree/nodeList.tsx +2 -2
- package/treeSelect/__test__/treeSelect.test.js +28 -0
- package/treeSelect/_story/treeSelect.stories.js +55 -2
- 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 && !
|
|
489
|
-
[`${cssClasses.PREFIX}-range-input-disabled`]: isRangeType &&
|
|
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>
|
package/datePicker/index.tsx
CHANGED
|
@@ -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
|
+
}
|
package/datePicker/month.tsx
CHANGED
|
@@ -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/
|
|
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
|
|
584
|
-
|
|
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
|
|
588
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
+
aria-label="Next year"
|
|
140
|
+
icon={<IconDoubleChevronRight aria-hidden size={iconBtnSize} />}
|
|
137
141
|
size={buttonSize}
|
|
138
142
|
theme={btnTheme}
|
|
139
143
|
noHorizontalPadding={btnNoHorizontalPadding}
|
|
@@ -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
|
>
|