@douyinfe/semi-ui 2.5.0 → 2.6.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/index.tsx +1 -1
- package/calendar/monthCalendar.tsx +14 -13
- package/cascader/index.tsx +21 -3
- package/cascader/item.tsx +25 -5
- package/datePicker/dateInput.tsx +8 -5
- package/datePicker/datePicker.tsx +6 -1
- package/datePicker/month.tsx +14 -7
- package/datePicker/monthsGrid.tsx +17 -5
- package/datePicker/navigation.tsx +8 -4
- package/datePicker/quickControl.tsx +1 -0
- package/datePicker/yearAndMonth.tsx +1 -1
- package/dist/css/semi.css +22 -8
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +259 -104
- 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/__test__/formApi.test.js +182 -0
- package/form/_story/FormApi/arrayDemo.jsx +4 -7
- package/form/_story/Layout/slotDemo.jsx +2 -2
- package/form/_story/demo.jsx +18 -1
- package/form/_story/form.stories.js +6 -6
- package/form/baseForm.tsx +2 -2
- package/form/hoc/withField.tsx +1 -1
- package/lib/cjs/_base/base.css +5 -5
- package/lib/cjs/button/Button.d.ts +4 -4
- package/lib/cjs/button/buttonGroup.d.ts +2 -2
- package/lib/cjs/button/index.d.ts +5 -6
- package/lib/cjs/calendar/monthCalendar.js +21 -5
- package/lib/cjs/cascader/index.d.ts +9 -2
- package/lib/cjs/cascader/index.js +14 -1
- package/lib/cjs/cascader/item.d.ts +6 -2
- package/lib/cjs/cascader/item.js +33 -4
- package/lib/cjs/datePicker/dateInput.d.ts +0 -2
- package/lib/cjs/datePicker/dateInput.js +17 -6
- package/lib/cjs/datePicker/datePicker.js +15 -12
- package/lib/cjs/datePicker/month.d.ts +1 -0
- package/lib/cjs/datePicker/month.js +18 -2
- package/lib/cjs/datePicker/monthsGrid.js +16 -4
- 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/baseForm.js +2 -2
- package/lib/cjs/form/hoc/withField.js +1 -1
- package/lib/cjs/iconButton/index.d.ts +2 -2
- 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/tooltip/index.js +6 -2
- package/lib/es/_base/base.css +5 -5
- package/lib/es/button/Button.d.ts +4 -4
- package/lib/es/button/buttonGroup.d.ts +2 -2
- package/lib/es/button/index.d.ts +5 -6
- package/lib/es/calendar/monthCalendar.js +22 -5
- package/lib/es/cascader/index.d.ts +9 -2
- package/lib/es/cascader/index.js +14 -1
- package/lib/es/cascader/item.d.ts +6 -2
- package/lib/es/cascader/item.js +31 -4
- package/lib/es/datePicker/dateInput.d.ts +0 -2
- package/lib/es/datePicker/dateInput.js +17 -6
- package/lib/es/datePicker/datePicker.js +15 -12
- package/lib/es/datePicker/month.d.ts +1 -0
- package/lib/es/datePicker/month.js +18 -2
- package/lib/es/datePicker/monthsGrid.js +16 -4
- 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/baseForm.js +2 -2
- package/lib/es/form/hoc/withField.js +1 -1
- package/lib/es/iconButton/index.d.ts +2 -2
- 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/tooltip/index.js +6 -2
- 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/Perf/Virtualized/index.jsx +6 -0
- package/table/_story/v2/FixedExpandedRow/index.jsx +95 -0
- package/table/_story/v2/FixedHeaderMerge/index.jsx +1 -1
- package/table/_story/v2/defaultFilteredValue.tsx +0 -9
- package/table/_story/v2/index.js +2 -1
- package/tooltip/_story/tooltip.stories.js +702 -625
- package/tooltip/index.tsx +2 -2
package/button/index.tsx
CHANGED
|
@@ -12,7 +12,7 @@ export { ButtonGroupProps } from './buttonGroup';
|
|
|
12
12
|
export { SplitButtonGroupProps } from './splitButtonGroup';
|
|
13
13
|
|
|
14
14
|
// eslint-disable-next-line
|
|
15
|
-
export interface ButtonProps extends IconButtonProps
|
|
15
|
+
export interface ButtonProps extends IconButtonProps {} // TODO check
|
|
16
16
|
class Button extends React.PureComponent<ButtonProps> {
|
|
17
17
|
static propTypes = {
|
|
18
18
|
...BaseButton.propTypes,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */
|
|
1
2
|
import React, { ReactInstance } from 'react';
|
|
2
3
|
import ReactDOM from 'react-dom';
|
|
3
4
|
import cls from 'classnames';
|
|
@@ -180,16 +181,16 @@ export default class monthCalendar extends BaseComponent<MonthCalendarProps, Mon
|
|
|
180
181
|
const { markWeekend, displayValue } = this.props;
|
|
181
182
|
this.monthlyData = this.foundation.getMonthlyData(displayValue, dateFnsLocale);
|
|
182
183
|
return (
|
|
183
|
-
<div className={`${prefixCls}-header`}>
|
|
184
|
-
<div role="
|
|
185
|
-
<ul className={`${prefixCls}-grid-row`}>
|
|
184
|
+
<div className={`${prefixCls}-header`} role="presentation">
|
|
185
|
+
<div role="presentation" className={`${prefixCls}-grid`}>
|
|
186
|
+
<ul role="row" className={`${prefixCls}-grid-row`}>
|
|
186
187
|
{this.monthlyData[0].map(day => {
|
|
187
188
|
const { weekday } = day;
|
|
188
189
|
const listCls = cls({
|
|
189
190
|
[`${cssClasses.PREFIX}-weekend`]: markWeekend && day.isWeekend,
|
|
190
191
|
});
|
|
191
192
|
return (
|
|
192
|
-
<li key={`${weekday}-monthheader`} className={listCls}>
|
|
193
|
+
<li role="columnheader" aria-label={weekday} key={`${weekday}-monthheader`} className={listCls}>
|
|
193
194
|
<span>{weekday}</span>
|
|
194
195
|
</li>
|
|
195
196
|
);
|
|
@@ -268,7 +269,7 @@ export default class monthCalendar extends BaseComponent<MonthCalendarProps, Mon
|
|
|
268
269
|
const pos = showCard && showCard[key] ? showCard[key][1] : 'leftTopOver';
|
|
269
270
|
const text = (
|
|
270
271
|
<LocaleConsumer componentName="Calendar">
|
|
271
|
-
{(locale: Locale['Calendar']) => (
|
|
272
|
+
{(locale: Locale['Calendar']) => (// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
272
273
|
<div
|
|
273
274
|
className={`${cardCls}-wrapper`}
|
|
274
275
|
style={{ bottom: 0 }}
|
|
@@ -330,8 +331,8 @@ export default class monthCalendar extends BaseComponent<MonthCalendarProps, Mon
|
|
|
330
331
|
const { itemLimit } = this.state;
|
|
331
332
|
const { display, day } = events;
|
|
332
333
|
return (
|
|
333
|
-
<div role="
|
|
334
|
-
<ul className={`${prefixCls}-skeleton`}>
|
|
334
|
+
<div role="presentation" className={`${prefixCls}-weekrow`} ref={this.cellDom} key={`${index}-weekrow`}>
|
|
335
|
+
<ul role="row" className={`${prefixCls}-skeleton`}>
|
|
335
336
|
{weekDay.map(each => {
|
|
336
337
|
const { date, dayString, isToday, isSameMonth, isWeekend, month, ind } = each;
|
|
337
338
|
const listCls = cls({
|
|
@@ -341,7 +342,7 @@ export default class monthCalendar extends BaseComponent<MonthCalendarProps, Mon
|
|
|
341
342
|
});
|
|
342
343
|
const shouldRenderCollapsed = Boolean(day && day[ind] && day[ind].length > itemLimit);
|
|
343
344
|
const inner = (
|
|
344
|
-
<li key={`${date}-weeksk`} className={listCls} onClick={e => this.handleClick(e, [date])}>
|
|
345
|
+
<li role="gridcell" aria-label={date.toLocaleDateString()} aria-current={isToday ? "date" : false} key={`${date}-weeksk`} className={listCls} onClick={e => this.handleClick(e, [date])}>
|
|
345
346
|
{this.formatDayString(month, dayString)}
|
|
346
347
|
{this.renderCusDateGrid(date)}
|
|
347
348
|
</li>
|
|
@@ -362,8 +363,8 @@ export default class monthCalendar extends BaseComponent<MonthCalendarProps, Mon
|
|
|
362
363
|
renderMonthGrid = () => {
|
|
363
364
|
const { parsedEvents } = this.state;
|
|
364
365
|
return (
|
|
365
|
-
<div role="
|
|
366
|
-
<ul className={`${prefixCls}-grid-col`}>
|
|
366
|
+
<div role="presentation" className={`${prefixCls}-week`}>
|
|
367
|
+
<ul role="presentation" className={`${prefixCls}-grid-col`}>
|
|
367
368
|
{Object.keys(this.monthlyData).map(weekInd =>
|
|
368
369
|
this.renderWeekRow(weekInd, this.monthlyData[weekInd], parsedEvents[weekInd])
|
|
369
370
|
)}
|
|
@@ -383,12 +384,12 @@ export default class monthCalendar extends BaseComponent<MonthCalendarProps, Mon
|
|
|
383
384
|
return (
|
|
384
385
|
<LocaleConsumer componentName="Calendar">
|
|
385
386
|
{(locale: Locale['Calendar'], localeCode: string, dateFnsLocale: Locale['dateFnsLocale']) => (
|
|
386
|
-
<div className={monthCls} key={this.state.itemLimit} style={monthStyle}>
|
|
387
|
-
<div className={`${prefixCls}-sticky-top`}>
|
|
387
|
+
<div role="grid" className={monthCls} key={this.state.itemLimit} style={monthStyle}>
|
|
388
|
+
<div role="presentation" className={`${prefixCls}-sticky-top`}>
|
|
388
389
|
{header}
|
|
389
390
|
{this.renderHeader(dateFnsLocale)}
|
|
390
391
|
</div>
|
|
391
|
-
<div className={`${prefixCls}-grid-wrapper`}>
|
|
392
|
+
<div role="presentation" className={`${prefixCls}-grid-wrapper`}>
|
|
392
393
|
{this.renderMonthGrid()}
|
|
393
394
|
</div>
|
|
394
395
|
</div>
|
package/cascader/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Fragment, ReactNode, CSSProperties, MouseEvent } from 'react';
|
|
1
|
+
import React, { Fragment, ReactNode, CSSProperties, MouseEvent, KeyboardEvent } from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom';
|
|
3
3
|
import cls from 'classnames';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
@@ -54,6 +54,7 @@ export interface CascaderProps extends BasicCascaderProps {
|
|
|
54
54
|
'aria-invalid'?: React.AriaAttributes['aria-invalid'];
|
|
55
55
|
'aria-labelledby'?: React.AriaAttributes['aria-labelledby'];
|
|
56
56
|
'aria-required'?: React.AriaAttributes['aria-required'];
|
|
57
|
+
'aria-label'?: React.AriaAttributes['aria-label'];
|
|
57
58
|
arrowIcon?: ReactNode;
|
|
58
59
|
defaultValue?: Value;
|
|
59
60
|
dropdownStyle?: CSSProperties;
|
|
@@ -100,6 +101,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
100
101
|
'aria-errormessage': PropTypes.string,
|
|
101
102
|
'aria-describedby': PropTypes.string,
|
|
102
103
|
'aria-required': PropTypes.bool,
|
|
104
|
+
'aria-label': PropTypes.string,
|
|
103
105
|
arrowIcon: PropTypes.node,
|
|
104
106
|
changeOnSelect: PropTypes.bool,
|
|
105
107
|
defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
|
@@ -197,6 +199,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
197
199
|
onDropdownVisibleChange: noop,
|
|
198
200
|
onListScroll: noop,
|
|
199
201
|
enableLeafClick: false,
|
|
202
|
+
'aria-label': 'Cascader'
|
|
200
203
|
};
|
|
201
204
|
|
|
202
205
|
options: any;
|
|
@@ -584,7 +587,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
584
587
|
);
|
|
585
588
|
}
|
|
586
589
|
|
|
587
|
-
handleItemClick = (e: MouseEvent, item: Entity | Data) => {
|
|
590
|
+
handleItemClick = (e: MouseEvent | KeyboardEvent, item: Entity | Data) => {
|
|
588
591
|
this.foundation.handleItemClick(e, item);
|
|
589
592
|
};
|
|
590
593
|
|
|
@@ -798,6 +801,14 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
798
801
|
this.foundation.handleClear();
|
|
799
802
|
};
|
|
800
803
|
|
|
804
|
+
/**
|
|
805
|
+
* A11y: simulate clear button click
|
|
806
|
+
*/
|
|
807
|
+
handleClearEnterPress = (e: KeyboardEvent) => {
|
|
808
|
+
e && e.stopPropagation();
|
|
809
|
+
this.foundation.handleClearEnterPress();
|
|
810
|
+
};
|
|
811
|
+
|
|
801
812
|
showClearBtn = () => {
|
|
802
813
|
const { showClear, disabled, multiple } = this.props;
|
|
803
814
|
const { selectedKeys, isOpen, isHovering, checkedKeys } = this.state;
|
|
@@ -811,7 +822,13 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
811
822
|
const allowClear = this.showClearBtn();
|
|
812
823
|
if (allowClear) {
|
|
813
824
|
return (
|
|
814
|
-
<div
|
|
825
|
+
<div
|
|
826
|
+
className={clearCls}
|
|
827
|
+
onClick={this.handleClear}
|
|
828
|
+
onKeyPress={this.handleClearEnterPress}
|
|
829
|
+
role='button'
|
|
830
|
+
tabIndex={0}
|
|
831
|
+
>
|
|
815
832
|
<IconClear />
|
|
816
833
|
</div>
|
|
817
834
|
);
|
|
@@ -891,6 +908,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
891
908
|
style={style}
|
|
892
909
|
ref={this.triggerRef}
|
|
893
910
|
onClick={e => this.foundation.handleClick(e)}
|
|
911
|
+
onKeyPress={e => this.foundation.handleSelectionEnterPress(e)}
|
|
894
912
|
aria-invalid={this.props['aria-invalid']}
|
|
895
913
|
aria-errormessage={this.props['aria-errormessage']}
|
|
896
914
|
aria-label={this.props['aria-label']}
|
package/cascader/item.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import React, { PureComponent } from 'react';
|
|
|
2
2
|
import cls from 'classnames';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { cssClasses, strings } from '@douyinfe/semi-foundation/cascader/constants';
|
|
5
|
+
import isEnterPress from '@douyinfe/semi-foundation/utils/isEnterPress';
|
|
5
6
|
import { includes } from 'lodash';
|
|
6
7
|
import ConfigContext from '../configProvider/context';
|
|
7
8
|
import LocaleConsumer from '../locale/localeConsumer';
|
|
@@ -43,7 +44,7 @@ export interface CascaderItemProps {
|
|
|
43
44
|
selectedKeys: Set<string>;
|
|
44
45
|
loadedKeys: Set<string>;
|
|
45
46
|
loadingKeys: Set<string>;
|
|
46
|
-
onItemClick: (e: React.MouseEvent, item: Entity | Data) => void;
|
|
47
|
+
onItemClick: (e: React.MouseEvent | React.KeyboardEvent, item: Entity | Data) => void;
|
|
47
48
|
onItemHover: (e: React.MouseEvent, item: Entity) => void;
|
|
48
49
|
showNext: ShowNextType;
|
|
49
50
|
onItemCheckboxClick: (item: Entity | Data) => void;
|
|
@@ -84,7 +85,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
84
85
|
empty: false,
|
|
85
86
|
};
|
|
86
87
|
|
|
87
|
-
onClick = (e: React.MouseEvent, item: Entity | Data) => {
|
|
88
|
+
onClick = (e: React.MouseEvent | React.KeyboardEvent, item: Entity | Data) => {
|
|
88
89
|
const { onItemClick } = this.props;
|
|
89
90
|
if (item.data.disabled || ('disabled' in item && item.disabled)) {
|
|
90
91
|
return;
|
|
@@ -92,6 +93,15 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
92
93
|
onItemClick(e, item);
|
|
93
94
|
};
|
|
94
95
|
|
|
96
|
+
/**
|
|
97
|
+
* A11y: simulate item click
|
|
98
|
+
*/
|
|
99
|
+
handleItemEnterPress = (keyboardEvent: React.KeyboardEvent, item: Entity | Data) => {
|
|
100
|
+
if (isEnterPress(keyboardEvent)) {
|
|
101
|
+
this.onClick(keyboardEvent, item);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
95
105
|
onHover = (e: React.MouseEvent, item: Entity) => {
|
|
96
106
|
const { showNext, onItemHover } = this.props;
|
|
97
107
|
if (item.data.disabled) {
|
|
@@ -136,7 +146,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
136
146
|
case 'loading':
|
|
137
147
|
return <Spin wrapperClassName={`${prefixcls}-spin-icon`} />;
|
|
138
148
|
case 'empty':
|
|
139
|
-
return (<span className={`${prefixcls}-icon ${prefixcls}-icon-empty`} />);
|
|
149
|
+
return (<span aria-hidden={true} className={`${prefixcls}-icon ${prefixcls}-icon-empty`} />);
|
|
140
150
|
default:
|
|
141
151
|
return null;
|
|
142
152
|
}
|
|
@@ -179,11 +189,13 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
179
189
|
});
|
|
180
190
|
return (
|
|
181
191
|
<li
|
|
192
|
+
role='menuitem'
|
|
182
193
|
className={className}
|
|
183
194
|
key={key}
|
|
184
195
|
onClick={e => {
|
|
185
196
|
this.onClick(e, item);
|
|
186
197
|
}}
|
|
198
|
+
onKeyPress={e => this.handleItemEnterPress(e, item)}
|
|
187
199
|
>
|
|
188
200
|
<span className={`${prefixcls}-label`}>
|
|
189
201
|
{!multiple && this.renderIcon('empty')}
|
|
@@ -211,9 +223,9 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
211
223
|
let showChildItem: Entity;
|
|
212
224
|
const ind = content.length;
|
|
213
225
|
content.push(
|
|
214
|
-
<ul className={`${prefixcls}-list`} key={renderData[0].key} onScroll={e => this.props.onListScroll(e, ind)}>
|
|
226
|
+
<ul role='menu' className={`${prefixcls}-list`} key={renderData[0].key} onScroll={e => this.props.onListScroll(e, ind)}>
|
|
215
227
|
{renderData.map(item => {
|
|
216
|
-
const { data, key } = item;
|
|
228
|
+
const { data, key, parentKey } = item;
|
|
217
229
|
const { children, label, disabled, isLeaf } = data;
|
|
218
230
|
const { active, selected, loading } = this.getItemStatus(key);
|
|
219
231
|
const hasChild = Boolean(children) && children.length;
|
|
@@ -226,13 +238,21 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
226
238
|
[`${prefixcls}-select`]: selected && !multiple,
|
|
227
239
|
[`${prefixcls}-disabled`]: disabled
|
|
228
240
|
});
|
|
241
|
+
const otherAriaProps = parentKey ? { ['aria-owns']: `cascaderItem-${parentKey}` } : {};
|
|
229
242
|
return (
|
|
230
243
|
<li
|
|
244
|
+
role='menuitem'
|
|
245
|
+
id={`cascaderItem-${key}`}
|
|
246
|
+
aria-expanded={active}
|
|
247
|
+
aria-haspopup={Boolean(showExpand)}
|
|
248
|
+
aria-disabled={disabled}
|
|
249
|
+
{...otherAriaProps}
|
|
231
250
|
className={className}
|
|
232
251
|
key={key}
|
|
233
252
|
onClick={e => {
|
|
234
253
|
this.onClick(e, item);
|
|
235
254
|
}}
|
|
255
|
+
onKeyPress={e => this.handleItemEnterPress(e, item)}
|
|
236
256
|
onMouseEnter={e => {
|
|
237
257
|
this.onHover(e, item);
|
|
238
258
|
}}
|
package/datePicker/dateInput.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions,jsx-a11y/interactive-supports-focus */
|
|
1
2
|
/* eslint-disable max-lines-per-function */
|
|
2
3
|
/* eslint-disable no-unused-vars */
|
|
3
4
|
import React from 'react';
|
|
@@ -40,7 +41,6 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
40
41
|
value: PropTypes.array,
|
|
41
42
|
disabled: PropTypes.bool,
|
|
42
43
|
type: PropTypes.oneOf(strings.TYPE_SET),
|
|
43
|
-
multiple: PropTypes.bool,
|
|
44
44
|
showClear: PropTypes.bool,
|
|
45
45
|
format: PropTypes.string, // Attributes not used
|
|
46
46
|
inputStyle: PropTypes.object,
|
|
@@ -65,7 +65,6 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
65
65
|
onBlur: noop,
|
|
66
66
|
onClear: noop,
|
|
67
67
|
onFocus: noop,
|
|
68
|
-
multiple: false,
|
|
69
68
|
type: 'date',
|
|
70
69
|
inputStyle: {},
|
|
71
70
|
inputReadOnly: false,
|
|
@@ -177,9 +176,12 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
177
176
|
const allowClear = (rangeStart || rangeEnd) && showClear;
|
|
178
177
|
return allowClear && !disabled ? (
|
|
179
178
|
<div
|
|
179
|
+
role="button"
|
|
180
|
+
tabIndex={0}
|
|
181
|
+
aria-label="Clear range input value"
|
|
180
182
|
className={`${prefixCls}-range-input-clearbtn`}
|
|
181
183
|
onMouseDown={e => !disabled && this.handleRangeInputClear(e)}>
|
|
182
|
-
<IconClear />
|
|
184
|
+
<IconClear aria-hidden />
|
|
183
185
|
</div>
|
|
184
186
|
) : null;
|
|
185
187
|
}
|
|
@@ -293,6 +295,7 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
293
295
|
validateStatus,
|
|
294
296
|
block,
|
|
295
297
|
prefixCls,
|
|
298
|
+
multiple, // Whether to allow multiple values for email and file types
|
|
296
299
|
dateFnsLocale, // No need to pass to input
|
|
297
300
|
onBlur,
|
|
298
301
|
onClear,
|
|
@@ -310,8 +313,8 @@ export default class DateInput extends BaseComponent<DateInputProps, {}> {
|
|
|
310
313
|
rangeSeparator,
|
|
311
314
|
...rest
|
|
312
315
|
} = this.props;
|
|
313
|
-
const dateIcon = <IconCalendar />;
|
|
314
|
-
const dateTimeIcon = <IconCalendarClock />;
|
|
316
|
+
const dateIcon = <IconCalendar aria-hidden />;
|
|
317
|
+
const dateTimeIcon = <IconCalendarClock aria-hidden />;
|
|
315
318
|
const suffix = type.includes('Time') ? dateTimeIcon : dateIcon;
|
|
316
319
|
let text = '';
|
|
317
320
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events,jsx-a11y/interactive-supports-focus */
|
|
1
2
|
/* eslint-disable max-len */
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import classnames from 'classnames';
|
|
@@ -528,8 +529,12 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
|
|
|
528
529
|
};
|
|
529
530
|
|
|
530
531
|
return (
|
|
531
|
-
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
|
|
532
532
|
<div
|
|
533
|
+
// tooltip will mount a11y props to children
|
|
534
|
+
// eslint-disable-next-line jsx-a11y/role-has-required-aria-props
|
|
535
|
+
role="combobox"
|
|
536
|
+
aria-label={Array.isArray(value) && value.length ? "Change date" : "Choose date"}
|
|
537
|
+
aria-disabled={disabled}
|
|
533
538
|
onClick={this.handleTriggerWrapperClick}
|
|
534
539
|
className={inputCls}>
|
|
535
540
|
{typeof triggerRender === 'function' ? (
|
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,4 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/interactive-supports-focus,jsx-a11y/click-events-have-key-events */
|
|
1
2
|
/* eslint-disable react/no-did-update-set-state */
|
|
2
3
|
/* eslint-disable max-len */
|
|
3
4
|
/* eslint-disable no-nested-ternary */
|
|
@@ -343,7 +344,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
|
|
|
343
344
|
|
|
344
345
|
renderMonth(month: Date, panelType: PanelType) {
|
|
345
346
|
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;
|
|
347
|
+
const { weekStartsOn, disabledDate, locale, localeCode, renderDate, renderFullDate, startDateOffset, endDateOffset, density, rangeInputFocus, syncSwitchMonth, multiple } = this.props;
|
|
347
348
|
let monthText = '';
|
|
348
349
|
// i18n monthText
|
|
349
350
|
if (month) {
|
|
@@ -409,6 +410,7 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
|
|
|
409
410
|
startDateOffset={startDateOffset}
|
|
410
411
|
endDateOffset={endDateOffset}
|
|
411
412
|
focusRecordsRef={this.props.focusRecordsRef}
|
|
413
|
+
multiple={multiple}
|
|
412
414
|
/>
|
|
413
415
|
</div>
|
|
414
416
|
);
|
|
@@ -580,12 +582,22 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
|
|
|
580
582
|
|
|
581
583
|
return (
|
|
582
584
|
<div className={switchCls} ref={current => this.adapter.setCache(`switch-${panelType}`, current)}>
|
|
583
|
-
<div
|
|
584
|
-
|
|
585
|
+
<div
|
|
586
|
+
role="button"
|
|
587
|
+
aria-label="Switch to date panel"
|
|
588
|
+
className={dateCls}
|
|
589
|
+
onClick={e => this.foundation.showDatePanel(panelType)}
|
|
590
|
+
>
|
|
591
|
+
{showSwithIcon && <IconCalendar aria-hidden />}
|
|
585
592
|
<span className={textCls}>{dateText || monthText}</span>
|
|
586
593
|
</div>
|
|
587
|
-
<div
|
|
588
|
-
|
|
594
|
+
<div
|
|
595
|
+
role="button"
|
|
596
|
+
aria-label="Switch to time panel"
|
|
597
|
+
className={timeCls}
|
|
598
|
+
onClick={e => this.foundation.showTimePicker(panelType, true)}
|
|
599
|
+
>
|
|
600
|
+
{showSwithIcon && <IconClock aria-hidden />}
|
|
589
601
|
<span className={textCls}>{timeText}</span>
|
|
590
602
|
</div>
|
|
591
603
|
</div>
|
|
@@ -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
|
>
|
package/dist/css/semi.css
CHANGED
|
@@ -19,7 +19,7 @@ body .semi-always-light {
|
|
|
19
19
|
--semi-blue-2: 152,205,253;
|
|
20
20
|
--semi-blue-3: 101,178,252;
|
|
21
21
|
--semi-blue-4: 50,149,251;
|
|
22
|
-
--semi-blue-5: 0,
|
|
22
|
+
--semi-blue-5: 0,100,250;
|
|
23
23
|
--semi-blue-6: 0,98,214;
|
|
24
24
|
--semi-blue-7: 0,79,179;
|
|
25
25
|
--semi-blue-8: 0,61,143;
|
|
@@ -410,7 +410,7 @@ body, body[theme-mode=dark] .semi-always-light {
|
|
|
410
410
|
--semi-color-bg-4: rgba(var(--semi-white), 1);
|
|
411
411
|
--semi-color-text-0: rgba(var(--semi-grey-9), 1);
|
|
412
412
|
--semi-color-text-1: rgba(var(--semi-grey-9), .8);
|
|
413
|
-
--semi-color-text-2: rgba(var(--semi-grey-9), .
|
|
413
|
+
--semi-color-text-2: rgba(var(--semi-grey-9), .62);
|
|
414
414
|
--semi-color-text-3: rgba(var(--semi-grey-9), .35);
|
|
415
415
|
--semi-shadow-elevated: 0 0 1px rgba(0, 0, 0, .3), 0 4px 14px rgba(0, 0, 0, .1);
|
|
416
416
|
--semi-border-radius-extra-small: 3px;
|
|
@@ -487,9 +487,9 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
487
487
|
--semi-color-nav-bg: rgba(35, 36, 41, 1);
|
|
488
488
|
--semi-shadow-elevated: inset 0 0 0 1px rgba(255, 255, 255, .1), 0 4px 14px rgba(0, 0, 0, .25);
|
|
489
489
|
--semi-color-overlay-bg: rgba(22, 22, 26, .6);
|
|
490
|
-
--semi-color-fill-0: rgba(var(--semi-white), .
|
|
491
|
-
--semi-color-fill-1: rgba(var(--semi-white), .
|
|
492
|
-
--semi-color-fill-2: rgba(var(--semi-white), .
|
|
490
|
+
--semi-color-fill-0: rgba(var(--semi-white), .12);
|
|
491
|
+
--semi-color-fill-1: rgba(var(--semi-white), .16);
|
|
492
|
+
--semi-color-fill-2: rgba(var(--semi-white), .20);
|
|
493
493
|
--semi-color-border: rgba(var(--semi-white), .08);
|
|
494
494
|
--semi-color-shadow: rgba(var(--semi-black), .04);
|
|
495
495
|
--semi-color-bg-0: rgba(22, 22, 26, 1);
|
|
@@ -1588,6 +1588,9 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
1588
1588
|
vertical-align: middle;
|
|
1589
1589
|
white-space: nowrap;
|
|
1590
1590
|
}
|
|
1591
|
+
.semi-button:focus {
|
|
1592
|
+
outline: 2px solid var(--semi-color-primary-light-active);
|
|
1593
|
+
}
|
|
1591
1594
|
.semi-button-danger {
|
|
1592
1595
|
background-color: var(--semi-color-danger);
|
|
1593
1596
|
color: white;
|
|
@@ -1601,6 +1604,9 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
1601
1604
|
.semi-button-danger.semi-button-light, .semi-button-danger.semi-button-borderless {
|
|
1602
1605
|
color: var(--semi-color-danger);
|
|
1603
1606
|
}
|
|
1607
|
+
.semi-button-danger:not(.semi-button-borderless):not(.semi-button-light):focus {
|
|
1608
|
+
outline-color: var(--semi-color-danger-light-active);
|
|
1609
|
+
}
|
|
1604
1610
|
.semi-button-warning {
|
|
1605
1611
|
background-color: var(--semi-color-warning);
|
|
1606
1612
|
color: white;
|
|
@@ -1614,6 +1620,9 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
1614
1620
|
.semi-button-warning.semi-button-light, .semi-button-warning.semi-button-borderless {
|
|
1615
1621
|
color: var(--semi-color-warning);
|
|
1616
1622
|
}
|
|
1623
|
+
.semi-button-warning:not(.semi-button-borderless):not(.semi-button-light):focus {
|
|
1624
|
+
outline-color: var(--semi-color-warning-light-active);
|
|
1625
|
+
}
|
|
1617
1626
|
.semi-button-tertiary {
|
|
1618
1627
|
background-color: var(--semi-color-tertiary);
|
|
1619
1628
|
color: white;
|
|
@@ -2688,7 +2697,7 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
2688
2697
|
color: var(--semi-color-text-2);
|
|
2689
2698
|
}
|
|
2690
2699
|
.semi-cascader-selection-tag {
|
|
2691
|
-
margin: 1px 2px;
|
|
2700
|
+
margin: 1px 2px 1px 0;
|
|
2692
2701
|
}
|
|
2693
2702
|
.semi-cascader-selection-tag:first-child {
|
|
2694
2703
|
margin-left: 0;
|
|
@@ -4740,6 +4749,10 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
4740
4749
|
padding-top: 6px;
|
|
4741
4750
|
padding-bottom: 6px;
|
|
4742
4751
|
}
|
|
4752
|
+
.semi-form-field[x-label-pos=left] .semi-radioGroup-buttonRadio {
|
|
4753
|
+
padding-top: 0;
|
|
4754
|
+
padding-bottom: 0;
|
|
4755
|
+
}
|
|
4743
4756
|
.semi-form-field[x-label-pos=left] .semi-switch,
|
|
4744
4757
|
.semi-form-field[x-label-pos=left] .semi-rating {
|
|
4745
4758
|
vertical-align: middle;
|
|
@@ -11448,6 +11461,7 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
11448
11461
|
cursor: not-allowed;
|
|
11449
11462
|
color: var(--semi-color-disabled-text);
|
|
11450
11463
|
background-color: var(--semi-color-disabled-fill);
|
|
11464
|
+
-webkit-text-fill-color: var(--semi-color-disabled-text);
|
|
11451
11465
|
}
|
|
11452
11466
|
.semi-input-wrapper-disabled:hover {
|
|
11453
11467
|
background-color: var(--semi-color-disabled-fill);
|
|
@@ -16207,7 +16221,6 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
16207
16221
|
word-break: break-all;
|
|
16208
16222
|
word-wrap: break-word;
|
|
16209
16223
|
position: relative;
|
|
16210
|
-
user-select: none;
|
|
16211
16224
|
}
|
|
16212
16225
|
.semi-table-thead > .semi-table-row > .semi-table-row-head.semi-table-cell-fixed-left, .semi-table-thead > .semi-table-row > .semi-table-row-head.semi-table-cell-fixed-right {
|
|
16213
16226
|
z-index: 101;
|
|
@@ -16479,7 +16492,7 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
16479
16492
|
position: relative;
|
|
16480
16493
|
z-index: 1;
|
|
16481
16494
|
padding: 16px 12px;
|
|
16482
|
-
color: var(--semi-color-
|
|
16495
|
+
color: var(--semi-color-text-2);
|
|
16483
16496
|
font-size: 14px;
|
|
16484
16497
|
text-align: center;
|
|
16485
16498
|
background: transparent;
|
|
@@ -17042,6 +17055,7 @@ body[theme-mode=dark], body .semi-always-dark {
|
|
|
17042
17055
|
user-select: none;
|
|
17043
17056
|
overflow: hidden;
|
|
17044
17057
|
white-space: nowrap;
|
|
17058
|
+
vertical-align: bottom;
|
|
17045
17059
|
}
|
|
17046
17060
|
.semi-tag-default, .semi-tag-small {
|
|
17047
17061
|
font-size: 12px;
|