@douyinfe/semi-ui 2.4.1 → 2.6.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/calendar/monthCalendar.tsx +14 -13
- package/cascader/__test__/cascader.test.js +24 -0
- package/cascader/_story/cascader.stories.js +73 -0
- package/cascader/index.tsx +26 -5
- package/cascader/item.tsx +25 -5
- package/datePicker/_story/v2/FixInputRangeFocus.jsx +25 -0
- package/datePicker/_story/v2/index.js +2 -1
- package/datePicker/dateInput.tsx +8 -5
- package/datePicker/datePicker.tsx +9 -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 +71 -35
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +696 -263
- 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/autoComplete/index.d.ts +1 -1
- package/lib/cjs/calendar/monthCalendar.js +21 -5
- package/lib/cjs/cascader/index.d.ts +9 -2
- package/lib/cjs/cascader/index.js +20 -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 +19 -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/dropdown/index.d.ts +1 -1
- package/lib/cjs/form/baseForm.d.ts +1 -1
- package/lib/cjs/form/baseForm.js +2 -2
- package/lib/cjs/form/field.d.ts +1 -1
- package/lib/cjs/form/hoc/withField.js +1 -1
- package/lib/cjs/scrollList/scrollItem.d.ts +2 -1
- package/lib/cjs/scrollList/scrollItem.js +13 -3
- package/lib/cjs/select/index.d.ts +3 -3
- package/lib/cjs/select/index.js +32 -28
- package/lib/cjs/select/option.js +2 -2
- package/lib/cjs/select/virtualRow.js +2 -2
- package/lib/cjs/table/Table.d.ts +1 -1
- package/lib/cjs/table/Table.js +8 -2
- package/lib/cjs/table/interface.d.ts +1 -0
- package/lib/cjs/tabs/interface.d.ts +1 -1
- package/lib/cjs/tooltip/index.d.ts +1 -1
- package/lib/cjs/tooltip/index.js +6 -2
- package/lib/cjs/tree/index.d.ts +2 -0
- package/lib/cjs/tree/index.js +15 -8
- package/lib/cjs/treeSelect/index.d.ts +2 -0
- package/lib/cjs/treeSelect/index.js +64 -27
- package/lib/cjs/upload/fileCard.js +31 -22
- package/lib/cjs/upload/index.d.ts +6 -0
- package/lib/cjs/upload/index.js +15 -8
- package/lib/cjs/upload/interface.d.ts +8 -6
- package/lib/es/_base/base.css +5 -5
- package/lib/es/autoComplete/index.d.ts +1 -1
- package/lib/es/calendar/monthCalendar.js +22 -5
- package/lib/es/cascader/index.d.ts +9 -2
- package/lib/es/cascader/index.js +19 -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 +19 -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/dropdown/index.d.ts +1 -1
- package/lib/es/form/baseForm.d.ts +1 -1
- package/lib/es/form/baseForm.js +2 -2
- package/lib/es/form/field.d.ts +1 -1
- package/lib/es/form/hoc/withField.js +1 -1
- package/lib/es/scrollList/scrollItem.d.ts +2 -1
- package/lib/es/scrollList/scrollItem.js +13 -3
- package/lib/es/select/index.d.ts +3 -3
- package/lib/es/select/index.js +30 -26
- package/lib/es/select/option.js +2 -2
- package/lib/es/select/virtualRow.js +2 -2
- package/lib/es/table/Table.d.ts +1 -1
- package/lib/es/table/Table.js +10 -2
- package/lib/es/table/interface.d.ts +1 -0
- package/lib/es/tabs/interface.d.ts +1 -1
- package/lib/es/tooltip/index.d.ts +1 -1
- package/lib/es/tooltip/index.js +6 -2
- package/lib/es/tree/index.d.ts +2 -0
- package/lib/es/tree/index.js +15 -8
- package/lib/es/treeSelect/index.d.ts +2 -0
- package/lib/es/treeSelect/index.js +64 -27
- package/lib/es/upload/fileCard.js +31 -24
- package/lib/es/upload/index.d.ts +6 -0
- package/lib/es/upload/index.js +14 -8
- package/lib/es/upload/interface.d.ts +8 -6
- 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/select/index.tsx +18 -19
- package/select/option.tsx +2 -2
- package/select/virtualRow.tsx +2 -2
- package/table/Table.tsx +7 -2
- package/table/_story/Perf/Virtualized/index.jsx +6 -0
- package/table/_story/table.stories.js +1 -2
- package/table/_story/v2/FixedHeaderMerge/index.jsx +98 -0
- package/table/_story/v2/FixedResizable/index.jsx +114 -0
- package/table/_story/v2/defaultFilteredValue.tsx +114 -0
- package/table/_story/v2/index.js +5 -0
- package/table/interface.ts +1 -0
- package/tabs/interface.ts +1 -1
- package/tooltip/__test__/tooltip.test.js +48 -4
- package/tooltip/_story/tooltip.stories.js +83 -1
- package/tooltip/index.tsx +4 -4
- package/tree/__test__/treeMultiple.test.js +94 -0
- package/tree/_story/tree.stories.js +169 -0
- package/tree/index.tsx +12 -5
- package/treeSelect/__test__/treeMultiple.test.js +94 -0
- package/treeSelect/_story/treeSelect.stories.js +242 -0
- package/treeSelect/index.tsx +72 -40
- package/upload/_story/upload.stories.js +22 -6
- package/upload/fileCard.tsx +23 -23
- package/upload/index.tsx +15 -6
- package/upload/interface.ts +7 -5
|
@@ -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>
|
|
@@ -195,6 +195,30 @@ describe('Cascader', () => {
|
|
|
195
195
|
// done();
|
|
196
196
|
});
|
|
197
197
|
|
|
198
|
+
it('dynamic treeData in multiple and uncontrolled mode', () => {
|
|
199
|
+
const cascader = render({
|
|
200
|
+
defaultValue: 'Yazhou',
|
|
201
|
+
multiple: true,
|
|
202
|
+
});
|
|
203
|
+
const opt = document.querySelectorAll(`.${BASE_CLASS_PREFIX}-cascader-selection-multiple .${BASE_CLASS_PREFIX}-tag`);
|
|
204
|
+
expect(opt.length).toEqual(1);
|
|
205
|
+
cascader.setProps({ treeData: treeDataWithDisabled });
|
|
206
|
+
cascader.update();
|
|
207
|
+
expect(opt.length).toEqual(1);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('dynamic treeData in multiple and controlled mode', () => {
|
|
211
|
+
const cascader = render({
|
|
212
|
+
value: 'Yazhou',
|
|
213
|
+
multiple: true,
|
|
214
|
+
});
|
|
215
|
+
const opt = document.querySelectorAll(`.${BASE_CLASS_PREFIX}-cascader-selection-multiple .${BASE_CLASS_PREFIX}-tag`);
|
|
216
|
+
expect(opt.length).toEqual(1);
|
|
217
|
+
cascader.setProps({ treeData: treeDataWithDisabled });
|
|
218
|
+
cascader.update();
|
|
219
|
+
expect(opt.length).toEqual(1);
|
|
220
|
+
});
|
|
221
|
+
|
|
198
222
|
it('getPopupContainer', () => {
|
|
199
223
|
let cascader = render({
|
|
200
224
|
getPopupContainer: getPopupContainer,
|
|
@@ -1348,4 +1348,77 @@ export const LeafOnly = () => {
|
|
|
1348
1348
|
/>
|
|
1349
1349
|
</div>
|
|
1350
1350
|
);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
export const DynamicTreeData = () => {
|
|
1354
|
+
const [treeDataDemo1,setTreeData1]=useState(treeData2);
|
|
1355
|
+
const [treeDataDemo2,setTreeData2]=useState(treeData2);
|
|
1356
|
+
const [treeDataDemo3,setTreeData3]=useState(treeData2);
|
|
1357
|
+
const [treeDataDemo4,setTreeData4]=useState(treeData2);
|
|
1358
|
+
const [treeDataDemo5,setTreeData5]=useState(treeData2);
|
|
1359
|
+
const [value3,setValue3]=useState();
|
|
1360
|
+
const [value4,setValue4]=useState();
|
|
1361
|
+
return (
|
|
1362
|
+
<div>
|
|
1363
|
+
<div>多选 + 动态更新 tree</div>
|
|
1364
|
+
<Cascader
|
|
1365
|
+
style={{ width: 300 }}
|
|
1366
|
+
treeData={treeDataDemo1}
|
|
1367
|
+
multiple
|
|
1368
|
+
placeholder="请选择所在地区"
|
|
1369
|
+
/>
|
|
1370
|
+
<Button onClick={()=>{setTreeData1(treeData3)}}>改变treeData</Button>
|
|
1371
|
+
<br />
|
|
1372
|
+
<br />
|
|
1373
|
+
<div>单选 + 动态更新 tree</div>
|
|
1374
|
+
<Cascader
|
|
1375
|
+
style={{ width: 300 }}
|
|
1376
|
+
treeData={treeDataDemo2}
|
|
1377
|
+
placeholder="请选择所在地区"
|
|
1378
|
+
/>
|
|
1379
|
+
<Button onClick={()=>{setTreeData2(treeData3)}}>改变treeData</Button>
|
|
1380
|
+
<br />
|
|
1381
|
+
<br />
|
|
1382
|
+
<div>多选 + 动态更新 tree + 受控</div>
|
|
1383
|
+
<Cascader
|
|
1384
|
+
style={{ width: 300 }}
|
|
1385
|
+
treeData={treeDataDemo3}
|
|
1386
|
+
multiple
|
|
1387
|
+
value={value3}
|
|
1388
|
+
onChange={v=>{
|
|
1389
|
+
console.log(v);
|
|
1390
|
+
setValue3(v);
|
|
1391
|
+
}}
|
|
1392
|
+
placeholder="请选择所在地区"
|
|
1393
|
+
/>
|
|
1394
|
+
<Button onClick={()=>{setTreeData3(treeData3)}}>改变treeData</Button>
|
|
1395
|
+
<br />
|
|
1396
|
+
<br />
|
|
1397
|
+
<div>单选 + 动态更新 tree + 受控</div>
|
|
1398
|
+
<Cascader
|
|
1399
|
+
style={{ width: 300 }}
|
|
1400
|
+
treeData={treeDataDemo4}
|
|
1401
|
+
value={value4}
|
|
1402
|
+
onChange={v=>{
|
|
1403
|
+
console.log(v);
|
|
1404
|
+
setValue4(v);
|
|
1405
|
+
}}
|
|
1406
|
+
placeholder="请选择所在地区"
|
|
1407
|
+
/>
|
|
1408
|
+
<Button onClick={()=>{setTreeData4(treeData3)}}>改变treeData</Button>
|
|
1409
|
+
<br />
|
|
1410
|
+
<br />
|
|
1411
|
+
<div>多选 + 动态更新 tree + defaultValue 为亚洲</div>
|
|
1412
|
+
<Cascader
|
|
1413
|
+
style={{ width: 300 }}
|
|
1414
|
+
treeData={treeDataDemo5}
|
|
1415
|
+
multiple
|
|
1416
|
+
defaultValue='yazhou'
|
|
1417
|
+
placeholder="请选择所在地区"
|
|
1418
|
+
/>
|
|
1419
|
+
<Button onClick={()=>{setTreeData5(treeData3)}}>改变treeData</Button>
|
|
1420
|
+
<br />
|
|
1421
|
+
<br />
|
|
1422
|
+
</div>
|
|
1423
|
+
);
|
|
1351
1424
|
}
|
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';
|
|
@@ -14,7 +14,7 @@ import CascaderFoundation, {
|
|
|
14
14
|
} from '@douyinfe/semi-foundation/cascader/foundation';
|
|
15
15
|
import { cssClasses, strings } from '@douyinfe/semi-foundation/cascader/constants';
|
|
16
16
|
import { numbers as popoverNumbers } from '@douyinfe/semi-foundation/popover/constants';
|
|
17
|
-
import { isEqual, isString, isEmpty, isFunction, isNumber, noop, flatten } from 'lodash';
|
|
17
|
+
import { isSet, isEqual, isString, isEmpty, isFunction, isNumber, noop, flatten } from 'lodash';
|
|
18
18
|
import '@douyinfe/semi-foundation/cascader/cascader.scss';
|
|
19
19
|
import { IconClear, IconChevronDown } from '@douyinfe/semi-icons';
|
|
20
20
|
import { findKeysForValues, convertDataToEntities, calcMergeType } from '@douyinfe/semi-foundation/cascader/util';
|
|
@@ -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;
|
|
@@ -426,7 +429,10 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
426
429
|
});
|
|
427
430
|
realKeys = formatKeys;
|
|
428
431
|
}
|
|
429
|
-
|
|
432
|
+
if (isSet(realKeys)) {
|
|
433
|
+
realKeys = [...realKeys];
|
|
434
|
+
}
|
|
435
|
+
const calRes = calcCheckedKeys(flatten(realKeys), keyEntities);
|
|
430
436
|
const checkedKeys = new Set(calRes.checkedKeys);
|
|
431
437
|
const halfCheckedKeys = new Set(calRes.halfCheckedKeys);
|
|
432
438
|
// disableStrictly
|
|
@@ -581,7 +587,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
581
587
|
);
|
|
582
588
|
}
|
|
583
589
|
|
|
584
|
-
handleItemClick = (e: MouseEvent, item: Entity | Data) => {
|
|
590
|
+
handleItemClick = (e: MouseEvent | KeyboardEvent, item: Entity | Data) => {
|
|
585
591
|
this.foundation.handleItemClick(e, item);
|
|
586
592
|
};
|
|
587
593
|
|
|
@@ -795,6 +801,14 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
795
801
|
this.foundation.handleClear();
|
|
796
802
|
};
|
|
797
803
|
|
|
804
|
+
/**
|
|
805
|
+
* A11y: simulate clear button click
|
|
806
|
+
*/
|
|
807
|
+
handleClearEnterPress = (e: KeyboardEvent) => {
|
|
808
|
+
e && e.stopPropagation();
|
|
809
|
+
this.foundation.handleClearEnterPress();
|
|
810
|
+
};
|
|
811
|
+
|
|
798
812
|
showClearBtn = () => {
|
|
799
813
|
const { showClear, disabled, multiple } = this.props;
|
|
800
814
|
const { selectedKeys, isOpen, isHovering, checkedKeys } = this.state;
|
|
@@ -808,7 +822,13 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
808
822
|
const allowClear = this.showClearBtn();
|
|
809
823
|
if (allowClear) {
|
|
810
824
|
return (
|
|
811
|
-
<div
|
|
825
|
+
<div
|
|
826
|
+
className={clearCls}
|
|
827
|
+
onClick={this.handleClear}
|
|
828
|
+
onKeyPress={this.handleClearEnterPress}
|
|
829
|
+
role='button'
|
|
830
|
+
tabIndex={0}
|
|
831
|
+
>
|
|
812
832
|
<IconClear />
|
|
813
833
|
</div>
|
|
814
834
|
);
|
|
@@ -888,6 +908,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
888
908
|
style={style}
|
|
889
909
|
ref={this.triggerRef}
|
|
890
910
|
onClick={e => this.foundation.handleClick(e)}
|
|
911
|
+
onKeyPress={e => this.foundation.handleSelectionEnterPress(e)}
|
|
891
912
|
aria-invalid={this.props['aria-invalid']}
|
|
892
913
|
aria-errormessage={this.props['aria-errormessage']}
|
|
893
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
|
}}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DatePicker, Button } from '../../../index';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* fix gitlab #1375
|
|
6
|
+
*/
|
|
7
|
+
App.storyName = 'fixed input range focus';
|
|
8
|
+
export default function App() {
|
|
9
|
+
const [visible, setVisible] = React.useState(false);
|
|
10
|
+
return (
|
|
11
|
+
<div>
|
|
12
|
+
{/* <Button onClick={() => { setVisible(false); }}>关闭</Button> */}
|
|
13
|
+
<DatePicker
|
|
14
|
+
type="dateTimeRange"
|
|
15
|
+
bottomSlot={<Button onClick={() => { setVisible(false); }}>关闭</Button>}
|
|
16
|
+
onFocus={() => {
|
|
17
|
+
console.log('focus');
|
|
18
|
+
setVisible(true);
|
|
19
|
+
}}
|
|
20
|
+
open={visible}
|
|
21
|
+
showClear
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
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';
|
|
@@ -331,6 +332,9 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
|
|
|
331
332
|
|
|
332
333
|
if (prevProps.open !== this.props.open) {
|
|
333
334
|
this.foundation.initPanelOpenStatus();
|
|
335
|
+
if (!this.props.open) {
|
|
336
|
+
this.foundation.clearRangeInputFocus();
|
|
337
|
+
}
|
|
334
338
|
}
|
|
335
339
|
}
|
|
336
340
|
|
|
@@ -525,8 +529,12 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
|
|
|
525
529
|
};
|
|
526
530
|
|
|
527
531
|
return (
|
|
528
|
-
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
|
|
529
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}
|
|
530
538
|
onClick={this.handleTriggerWrapperClick}
|
|
531
539
|
className={inputCls}>
|
|
532
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}
|