@douyinfe/semi-ui 2.5.0 → 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.
Files changed (68) hide show
  1. package/calendar/monthCalendar.tsx +14 -13
  2. package/cascader/index.tsx +21 -3
  3. package/cascader/item.tsx +25 -5
  4. package/datePicker/dateInput.tsx +8 -5
  5. package/datePicker/datePicker.tsx +6 -1
  6. package/datePicker/month.tsx +14 -7
  7. package/datePicker/monthsGrid.tsx +17 -5
  8. package/datePicker/navigation.tsx +8 -4
  9. package/datePicker/quickControl.tsx +1 -0
  10. package/datePicker/yearAndMonth.tsx +1 -1
  11. package/dist/css/semi.css +21 -8
  12. package/dist/css/semi.min.css +1 -1
  13. package/dist/umd/semi-ui.js +232 -92
  14. package/dist/umd/semi-ui.js.map +1 -1
  15. package/dist/umd/semi-ui.min.js +1 -1
  16. package/dist/umd/semi-ui.min.js.map +1 -1
  17. package/form/__test__/formApi.test.js +182 -0
  18. package/form/_story/FormApi/arrayDemo.jsx +4 -7
  19. package/form/_story/Layout/slotDemo.jsx +2 -2
  20. package/form/_story/demo.jsx +18 -1
  21. package/form/_story/form.stories.js +6 -6
  22. package/form/baseForm.tsx +2 -2
  23. package/form/hoc/withField.tsx +1 -1
  24. package/lib/cjs/_base/base.css +5 -5
  25. package/lib/cjs/calendar/monthCalendar.js +21 -5
  26. package/lib/cjs/cascader/index.d.ts +9 -2
  27. package/lib/cjs/cascader/index.js +14 -1
  28. package/lib/cjs/cascader/item.d.ts +6 -2
  29. package/lib/cjs/cascader/item.js +33 -4
  30. package/lib/cjs/datePicker/dateInput.d.ts +0 -2
  31. package/lib/cjs/datePicker/dateInput.js +17 -6
  32. package/lib/cjs/datePicker/datePicker.js +15 -12
  33. package/lib/cjs/datePicker/month.d.ts +1 -0
  34. package/lib/cjs/datePicker/month.js +18 -2
  35. package/lib/cjs/datePicker/monthsGrid.js +16 -4
  36. package/lib/cjs/datePicker/navigation.js +8 -0
  37. package/lib/cjs/datePicker/quickControl.js +1 -0
  38. package/lib/cjs/datePicker/yearAndMonth.js +1 -0
  39. package/lib/cjs/form/baseForm.js +2 -2
  40. package/lib/cjs/form/hoc/withField.js +1 -1
  41. package/lib/cjs/scrollList/scrollItem.d.ts +2 -1
  42. package/lib/cjs/scrollList/scrollItem.js +13 -3
  43. package/lib/es/_base/base.css +5 -5
  44. package/lib/es/calendar/monthCalendar.js +22 -5
  45. package/lib/es/cascader/index.d.ts +9 -2
  46. package/lib/es/cascader/index.js +14 -1
  47. package/lib/es/cascader/item.d.ts +6 -2
  48. package/lib/es/cascader/item.js +31 -4
  49. package/lib/es/datePicker/dateInput.d.ts +0 -2
  50. package/lib/es/datePicker/dateInput.js +17 -6
  51. package/lib/es/datePicker/datePicker.js +15 -12
  52. package/lib/es/datePicker/month.d.ts +1 -0
  53. package/lib/es/datePicker/month.js +18 -2
  54. package/lib/es/datePicker/monthsGrid.js +16 -4
  55. package/lib/es/datePicker/navigation.js +8 -0
  56. package/lib/es/datePicker/quickControl.js +2 -0
  57. package/lib/es/datePicker/yearAndMonth.js +1 -0
  58. package/lib/es/form/baseForm.js +2 -2
  59. package/lib/es/form/hoc/withField.js +1 -1
  60. package/lib/es/scrollList/scrollItem.d.ts +2 -1
  61. package/lib/es/scrollList/scrollItem.js +13 -3
  62. package/package.json +9 -9
  63. package/scrollList/_story/ScrollList/index.js +3 -0
  64. package/scrollList/_story/WheelList/index.js +3 -0
  65. package/scrollList/scrollItem.tsx +30 -9
  66. package/table/_story/Perf/Virtualized/index.jsx +6 -0
  67. package/table/_story/v2/FixedHeaderMerge/index.jsx +1 -1
  68. package/table/_story/v2/defaultFilteredValue.tsx +0 -9
@@ -30,6 +30,11 @@ const fields = (
30
30
  </>
31
31
  );
32
32
 
33
+ const getDomValue = (field, form) => {
34
+ let inputDOM = form.find(`[x-field-id="${field}"] input`).getDOMNode();
35
+ return inputDOM.getAttribute("value");
36
+ };
37
+
33
38
  describe('Form-formApi', () => {
34
39
  beforeEach(() => {
35
40
  document.body.innerHTML = '';
@@ -416,6 +421,183 @@ describe('Form-formApi', () => {
416
421
  expect(formApi.getFormState().touched).toEqual({ a: { b: true, c: true }});
417
422
  })
418
423
 
424
+ it('formApi-setValue, field path precise', () => {
425
+ // case like:
426
+ // Exist 3 Field: a.b、a.c、a.d
427
+ // formApi.setValue('a.b', '123');
428
+ let formApi = null;
429
+ const fields = (
430
+ <>
431
+ <Form.Input field='a.b' />
432
+ <Form.Input field='a.c' />
433
+ <Form.Input field='a.d' />
434
+ </>
435
+ );
436
+ const props = {
437
+ children: fields,
438
+ getFormApi: api => {
439
+ formApi = api;
440
+ },
441
+ };
442
+ const form = getForm(props);
443
+ formApi.setValue('a.c', 'semi');
444
+ // check formState.values
445
+ let val = formApi.getValue('a.c');
446
+ expect(val).toEqual('semi');
447
+ form.update();
448
+ // check dom render
449
+ expect(getDomValue('a.c', form)).toEqual('semi');
450
+ });
451
+
452
+ it('formApi-setValue, field path belongs to parent aggregate', () => {
453
+ // case like:
454
+ // Exist 3 Field: a.b、a.c、a.d
455
+ // formApi.setValue('a', { b: 'semi', c: 'design' });
456
+ let formApi = null;
457
+ const fields = (
458
+ <>
459
+ <Form.Input field='a.b' />
460
+ <Form.Input field='a.c' />
461
+ <Form.Input field='a.d' />
462
+ </>
463
+ );
464
+ const props = {
465
+ children: fields,
466
+ getFormApi: api => {
467
+ formApi = api;
468
+ },
469
+ };
470
+ const form = getForm(props);
471
+ formApi.setValue('a', { b: 'semi', c: 'design' });
472
+ let acVal = formApi.getValue('a.c');
473
+ let abVal = formApi.getValue('a.b');
474
+ expect(abVal).toEqual('semi');
475
+ expect(acVal).toEqual('design');
476
+ form.update();
477
+
478
+ // check dom render
479
+ expect(getDomValue('a.b', form)).toEqual('semi');
480
+ expect(getDomValue('a.c', form)).toEqual('design');
481
+ });
482
+
483
+ it('formApi-setValue with array field path, 0 -> 3', () => {
484
+
485
+ const fields = ({ formState, values }) => {
486
+
487
+ return values.a && values.a.map((effect, i) => (
488
+ <div key={effect.key}>
489
+ <Form.Input field={`a[${i}].name`} />
490
+ <Form.Input field={`a[${i}].type`} />
491
+ </div>
492
+ ));
493
+ };
494
+ let formApi = null;
495
+ const props = {
496
+ children: fields,
497
+ getFormApi: api => {
498
+ formApi = api;
499
+ },
500
+ };
501
+ const form = getForm(props);
502
+ let targetValue = [
503
+ { name: '0-name', type: '0-type' },
504
+ { name: '1-name', type: '1-type' },
505
+ { name: '2-name', type: '2-type' },
506
+ ];
507
+ formApi.setValue('a', targetValue);
508
+ let formStateValues = formApi.getValue();
509
+ form.update();
510
+ // check dom render
511
+ expect(getDomValue('a[0].name', form)).toEqual('0-name');
512
+ expect(getDomValue('a[0].type', form)).toEqual('0-type');
513
+ expect(getDomValue('a[1].name', form)).toEqual('1-name');
514
+ expect(getDomValue('a[1].type', form)).toEqual('1-type');
515
+ expect(getDomValue('a[2].name', form)).toEqual('2-name');
516
+ expect(getDomValue('a[2].type', form)).toEqual('2-type');
517
+ });
518
+
519
+ // // this case result was different in cypress / jest, jest result is wrong
520
+ // it('formApi-setValue with array field path, 3 -> 2, delete some field', done => {
521
+ // const fields = ({ formState, values }) => {
522
+ // return values.a && values.a.map((item, i) => (
523
+ // <div key={item.key} style={{ width: 300 }}>
524
+ // <Form.Input field={`a[${i}].name`} />
525
+ // <Form.Input field={`a[${i}].type`} />
526
+ // </div>
527
+ // ));
528
+ // };
529
+ // let formApi = null;
530
+ // const props = {
531
+ // children: fields,
532
+ // initValues: {
533
+ // a: [
534
+ // { name: '0-name', type: '0-type', key: 0 },
535
+ // { name: '1-name', type: '1-type', key: 1 },
536
+ // { name: '2-name', type: '2-type', key: 2 },
537
+ // ]
538
+ // },
539
+ // getFormApi: api => {
540
+ // formApi = api;
541
+ // },
542
+ // };
543
+ // let form = getForm(props);
544
+ // // remove middle one
545
+ // formApi.setValue('a', [
546
+ // { name: '0-name', type: '0-type', key: 0 },
547
+ // { name: '2-name', type: '2-type', key: 2 },
548
+ // ]);
549
+ // let formStateValues = formApi.getValue();
550
+ // form.update();
551
+
552
+ // setTimeout(() => {
553
+ // // check dom render
554
+ // expect(getDomValue('a[0].name', form)).toEqual('0-name');
555
+ // expect(getDomValue('a[0].type', form)).toEqual('0-type');
556
+ // expect(getDomValue('a[1].name', form)).toEqual('2-name');
557
+ // expect(getDomValue('a[1].type', form)).toEqual('2-type');
558
+
559
+ // expect(form.exists(`[x-field-id="a[2].name"] input`)).toEqual(false);
560
+ // expect(form.exists(`[x-field-id="a[2].type"] input`)).toEqual(false);
561
+ // done();
562
+ // }, 5000);
563
+ // });
564
+
565
+ it('formApi-setValue with array field path, 1 -> 3, add some field', () => {
566
+ const fields = ({ formState, values }) => {
567
+ return values.a && values.a.map((effect, i) => (
568
+ <div key={effect.key}>
569
+ <Form.Input field={`a[${i}].name`} />
570
+ <Form.Input field={`a[${i}].type`} />
571
+ </div>
572
+ ));
573
+ };
574
+ let formApi = null;
575
+ const props = {
576
+ children: fields,
577
+ initValues: {
578
+ a: [{ name: 'semi', type: 'design' }]
579
+ },
580
+ getFormApi: api => {
581
+ formApi = api;
582
+ },
583
+ };
584
+ let form = getForm(props);
585
+ formApi.setValue('a', [
586
+ { name: '0-name', type: '0-type' },
587
+ { name: '1-name', type: '1-type' },
588
+ { name: '2-name', type: '2-type' },
589
+ ]);
590
+ let formStateValues = formApi.getValue();
591
+ form.update();
592
+ // check dom render
593
+ expect(getDomValue('a[0].name', form)).toEqual('0-name');
594
+ expect(getDomValue('a[0].type', form)).toEqual('0-type');
595
+ expect(getDomValue('a[1].name', form)).toEqual('1-name');
596
+ expect(getDomValue('a[1].type', form)).toEqual('1-type');
597
+ expect(getDomValue('a[2].name', form)).toEqual('2-name');
598
+ expect(getDomValue('a[2].type', form)).toEqual('2-type');
599
+ });
600
+
419
601
  // it('formApi-submitForm', () => {
420
602
  // // submit should call validate first
421
603
  // });
@@ -24,9 +24,9 @@ class ArrayDemo extends React.Component {
24
24
  this.state = {
25
25
  initValues: {
26
26
  effects: [
27
- { name: '脸部贴纸', type: '2D', key: 0 },
28
- { name: '美妆', type: '2D', key: 1 },
29
- { name: '前景贴纸', type: '3D', key: 2 },
27
+ { name: '1-name', type: '1-type', key: 0 },
28
+ { name: '2-name', type: '2-type', key: 1 },
29
+ { name: '3-name', type: '3-type', key: 2 },
30
30
  ]
31
31
  }
32
32
  };
@@ -59,10 +59,7 @@ class ArrayDemo extends React.Component {
59
59
  return values.effects && values.effects.map((effect, i) => (
60
60
  <div key={effect.key} style={{ width: 1000, display: 'flex' }}>
61
61
  <Form.Input field={`effects[${i}].name`} style={{ width: 200, marginRight: 16 }} />
62
- <Form.Select field={`effects[${i}].type`} style={{ width: 90 }}>
63
- <Form.Select.Option value="2D">2D</Form.Select.Option>
64
- <Form.Select.Option value="3D">3D</Form.Select.Option>
65
- </Form.Select>
62
+ <Form.Input field={`effects[${i}].type`} style={{ width: 90 }} />
66
63
  <Button type="danger" onClick={() => this.remove(effect.key)} style={{ margin: 16 }}>Remove</Button>
67
64
  </div>
68
65
  ));
@@ -98,7 +98,7 @@ class AssistComponent extends React.Component {
98
98
  我是Semi Form SlotB, 我的Label Align、Width与众不同
99
99
  </div>
100
100
  </Form.Slot>
101
- </Form>,
101
+ </Form>
102
102
  <Form.Slot
103
103
  label={{
104
104
  text: 'SlotB',
@@ -117,7 +117,7 @@ class AssistComponent extends React.Component {
117
117
  >
118
118
  我是Slot,我并没有被Form包裹,我是单独使用的
119
119
  </div>
120
- </Form.Slot>,
120
+ </Form.Slot>
121
121
  </>
122
122
  );
123
123
  }
@@ -195,7 +195,7 @@ class BasicDemoWithInit extends Component {
195
195
  initValues={formInitValue}
196
196
  onReset={this.handleReset}
197
197
  onValueChange={(v)=>console.log(v)}
198
- style={{ padding: '10px', width: 600 }}
198
+ style={{ padding: '10px', width: 900 }}
199
199
  autoScrollToError
200
200
  aria-label='Demo Form'
201
201
  id='demo-form-id'
@@ -341,6 +341,23 @@ class BasicDemoWithInit extends Component {
341
341
  <Form.Switch field='switch' label='开关(Switch)'/>
342
342
  </Col>
343
343
  </Row>
344
+ <Form.CheckboxGroup field="cardCheckbox" label='卡片选择' style={{ width: '90%' }} type='card' initValue={['1', '3']} direction={'horizontal'} aria-label="CheckboxGroup 示例">
345
+ <Form.Checkbox value={'1'} disabled extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width:280}}>
346
+ 单选框标题
347
+ </Form.Checkbox>
348
+ <Form.Checkbox value={'2'} disabled extra='Semi Design 是由互娱社区前端团队与 UED 团队共同设计开发并维护的设计系统' style={{width:280}}>
349
+ 单选框标题
350
+ </Form.Checkbox>
351
+ </Form.CheckboxGroup>
352
+ <Row>
353
+ <Col span={12}>
354
+ <Form.RadioGroup field='buttonRadio' type='button' buttonSize='middle' defaultValue={1} aria-label="单选组合示例">
355
+ <Radio value={1}>即时推送</Radio>
356
+ <Radio value={2}>定时推送</Radio>
357
+ <Radio value={3}>动态推送</Radio>
358
+ </Form.RadioGroup>
359
+ </Col>
360
+ </Row>
344
361
  </Form.Section>
345
362
  <Form.Checkbox value="false" field="agree" useOutSideGroup={true} noLabel={true}>
346
363
  我已阅读并清楚相关规定
@@ -158,6 +158,12 @@ FormApiSetValueUsingFieldParentPath.story = {
158
158
  name: 'formApi-setValue using field parent path',
159
159
  };
160
160
 
161
+ export const UseFormApiSetValueUpdateArray = () => <ArrayDemo />;
162
+
163
+ UseFormApiSetValueUpdateArray.story = {
164
+ name: 'formApi-setValue set array',
165
+ };
166
+
161
167
  export const DynamicAddRemoveField = () => (
162
168
  <Form>
163
169
  {({ formState }) => (
@@ -209,12 +215,6 @@ _ArrayFieldCollapseDemo.story = {
209
215
  name: 'ArrayField-CollapseDemo',
210
216
  };
211
217
 
212
- export const ArrayFieldDynamicUpdate = () => <ArrayDemo />;
213
-
214
- ArrayFieldDynamicUpdate.story = {
215
- name: 'ArrayField-dynamic update',
216
- };
217
-
218
218
  export const LinkField = () => <LinkFieldForm />;
219
219
 
220
220
  LinkField.story = {
package/form/baseForm.tsx CHANGED
@@ -160,8 +160,8 @@ class Form extends BaseComponent<BaseFormProps, BaseFormState> {
160
160
  notifySubmitFail: (errors: ErrorMsg, values: any) => {
161
161
  this.props.onSubmitFail(errors, values);
162
162
  },
163
- forceUpdate: () => {
164
- this.forceUpdate();
163
+ forceUpdate: (callback?: () => void) => {
164
+ this.forceUpdate(callback);
165
165
  },
166
166
  notifyChange: (formState: FormState) => {
167
167
  this.props.onChange(formState);
@@ -499,7 +499,7 @@ function withField<
499
499
  text={label || field}
500
500
  id={labelId}
501
501
  required={required}
502
- name={name || field}
502
+ name={a11yId || name || field}
503
503
  width={mergeLabelWidth}
504
504
  align={mergeLabelAlign}
505
505
  {...needSpread}
@@ -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,119,250;
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), .6);
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), .05);
491
- --semi-color-fill-1: rgba(var(--semi-white), .09);
492
- --semi-color-fill-2: rgba(var(--semi-white), .13);
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);
@@ -52,6 +52,7 @@ var _iconButton = _interopRequireDefault(require("../iconButton"));
52
52
 
53
53
  require("@douyinfe/semi-foundation/lib/cjs/calendar/calendar.css");
54
54
 
55
+ /* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */
55
56
  // eslint-disable-next-line max-len
56
57
  const toPercent = num => {
57
58
  const res = num < 1 ? num * 100 : 100;
@@ -95,11 +96,13 @@ class monthCalendar extends _baseComponent.default {
95
96
  } = this.props;
96
97
  this.monthlyData = this.foundation.getMonthlyData(displayValue, dateFnsLocale);
97
98
  return /*#__PURE__*/_react.default.createElement("div", {
98
- className: "".concat(prefixCls, "-header")
99
+ className: "".concat(prefixCls, "-header"),
100
+ role: "presentation"
99
101
  }, /*#__PURE__*/_react.default.createElement("div", {
100
- role: "gridcell",
102
+ role: "presentation",
101
103
  className: "".concat(prefixCls, "-grid")
102
104
  }, /*#__PURE__*/_react.default.createElement("ul", {
105
+ role: "row",
103
106
  className: "".concat(prefixCls, "-grid-row")
104
107
  }, (0, _map.default)(_context = this.monthlyData[0]).call(_context, day => {
105
108
  const {
@@ -109,6 +112,8 @@ class monthCalendar extends _baseComponent.default {
109
112
  ["".concat(_constants.cssClasses.PREFIX, "-weekend")]: markWeekend && day.isWeekend
110
113
  });
111
114
  return /*#__PURE__*/_react.default.createElement("li", {
115
+ role: "columnheader",
116
+ "aria-label": weekday,
112
117
  key: "".concat(weekday, "-monthheader"),
113
118
  className: listCls
114
119
  }, /*#__PURE__*/_react.default.createElement("span", null, weekday));
@@ -195,7 +200,10 @@ class monthCalendar extends _baseComponent.default {
195
200
 
196
201
  const text = /*#__PURE__*/_react.default.createElement(_localeConsumer.default, {
197
202
  componentName: "Calendar"
198
- }, locale => /*#__PURE__*/_react.default.createElement("div", {
203
+ }, locale =>
204
+ /*#__PURE__*/
205
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions
206
+ _react.default.createElement("div", {
199
207
  className: "".concat(cardCls, "-wrapper"),
200
208
  style: {
201
209
  bottom: 0
@@ -264,11 +272,12 @@ class monthCalendar extends _baseComponent.default {
264
272
  day
265
273
  } = events;
266
274
  return /*#__PURE__*/_react.default.createElement("div", {
267
- role: "gridcell",
275
+ role: "presentation",
268
276
  className: "".concat(prefixCls, "-weekrow"),
269
277
  ref: _this.cellDom,
270
278
  key: "".concat(index, "-weekrow")
271
279
  }, /*#__PURE__*/_react.default.createElement("ul", {
280
+ role: "row",
272
281
  className: "".concat(prefixCls, "-skeleton")
273
282
  }, (0, _map.default)(weekDay).call(weekDay, each => {
274
283
  const {
@@ -288,6 +297,9 @@ class monthCalendar extends _baseComponent.default {
288
297
  const shouldRenderCollapsed = Boolean(day && day[ind] && day[ind].length > itemLimit);
289
298
 
290
299
  const inner = /*#__PURE__*/_react.default.createElement("li", {
300
+ role: "gridcell",
301
+ "aria-label": date.toLocaleDateString(),
302
+ "aria-current": isToday ? "date" : false,
291
303
  key: "".concat(date, "-weeksk"),
292
304
  className: listCls,
293
305
  onClick: e => _this.handleClick(e, [date])
@@ -310,9 +322,10 @@ class monthCalendar extends _baseComponent.default {
310
322
  parsedEvents
311
323
  } = this.state;
312
324
  return /*#__PURE__*/_react.default.createElement("div", {
313
- role: "gridcell",
325
+ role: "presentation",
314
326
  className: "".concat(prefixCls, "-week")
315
327
  }, /*#__PURE__*/_react.default.createElement("ul", {
328
+ role: "presentation",
316
329
  className: "".concat(prefixCls, "-grid-col")
317
330
  }, (0, _map.default)(_context3 = (0, _keys.default)(this.monthlyData)).call(_context3, weekInd => this.renderWeekRow(weekInd, this.monthlyData[weekInd], parsedEvents[weekInd]))));
318
331
  };
@@ -439,12 +452,15 @@ class monthCalendar extends _baseComponent.default {
439
452
  return /*#__PURE__*/_react.default.createElement(_localeConsumer.default, {
440
453
  componentName: "Calendar"
441
454
  }, (locale, localeCode, dateFnsLocale) => /*#__PURE__*/_react.default.createElement("div", {
455
+ role: "grid",
442
456
  className: monthCls,
443
457
  key: this.state.itemLimit,
444
458
  style: monthStyle
445
459
  }, /*#__PURE__*/_react.default.createElement("div", {
460
+ role: "presentation",
446
461
  className: "".concat(prefixCls, "-sticky-top")
447
462
  }, header, this.renderHeader(dateFnsLocale)), /*#__PURE__*/_react.default.createElement("div", {
463
+ role: "presentation",
448
464
  className: "".concat(prefixCls, "-grid-wrapper")
449
465
  }, this.renderMonthGrid())));
450
466
  }
@@ -1,4 +1,4 @@
1
- import React, { ReactNode, CSSProperties, MouseEvent } from 'react';
1
+ import React, { ReactNode, CSSProperties, MouseEvent, KeyboardEvent } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { BasicCascaderInnerData, BasicCascaderProps, BasicTriggerRenderProps, BasicScrollPanelProps, CascaderAdapter, CascaderType } from '@douyinfe/semi-foundation/lib/cjs/cascader/foundation';
4
4
  import '@douyinfe/semi-foundation/lib/cjs/cascader/cascader.css';
@@ -24,6 +24,7 @@ export interface CascaderProps extends BasicCascaderProps {
24
24
  'aria-invalid'?: React.AriaAttributes['aria-invalid'];
25
25
  'aria-labelledby'?: React.AriaAttributes['aria-labelledby'];
26
26
  'aria-required'?: React.AriaAttributes['aria-required'];
27
+ 'aria-label'?: React.AriaAttributes['aria-label'];
27
28
  arrowIcon?: ReactNode;
28
29
  defaultValue?: Value;
29
30
  dropdownStyle?: CSSProperties;
@@ -65,6 +66,7 @@ declare class Cascader extends BaseComponent<CascaderProps, CascaderState> {
65
66
  'aria-errormessage': PropTypes.Requireable<string>;
66
67
  'aria-describedby': PropTypes.Requireable<string>;
67
68
  'aria-required': PropTypes.Requireable<boolean>;
69
+ 'aria-label': PropTypes.Requireable<string>;
68
70
  arrowIcon: PropTypes.Requireable<PropTypes.ReactNodeLike>;
69
71
  changeOnSelect: PropTypes.Requireable<boolean>;
70
72
  defaultValue: PropTypes.Requireable<string | any[]>;
@@ -158,6 +160,7 @@ declare class Cascader extends BaseComponent<CascaderProps, CascaderState> {
158
160
  onDropdownVisibleChange: (...args: any[]) => void;
159
161
  onListScroll: (...args: any[]) => void;
160
162
  enableLeafClick: boolean;
163
+ 'aria-label': string;
161
164
  };
162
165
  options: any;
163
166
  isEmpty: boolean;
@@ -177,7 +180,7 @@ declare class Cascader extends BaseComponent<CascaderProps, CascaderState> {
177
180
  renderTagItem: (value: string | Array<string>, idx: number, type: string) => React.ReactNode;
178
181
  renderTagInput(): JSX.Element;
179
182
  renderInput(): JSX.Element;
180
- handleItemClick: (e: MouseEvent, item: Entity | Data) => void;
183
+ handleItemClick: (e: MouseEvent | KeyboardEvent, item: Entity | Data) => void;
181
184
  handleItemHover: (e: MouseEvent, item: Entity) => void;
182
185
  onItemCheckboxClick: (item: Entity | Data) => void;
183
186
  handleListScroll: (e: React.UIEvent<HTMLUListElement, UIEvent>, ind: number) => void;
@@ -191,6 +194,10 @@ declare class Cascader extends BaseComponent<CascaderProps, CascaderState> {
191
194
  handleMouseOver: () => void;
192
195
  handleMouseLeave: () => void;
193
196
  handleClear: (e: MouseEvent) => void;
197
+ /**
198
+ * A11y: simulate clear button click
199
+ */
200
+ handleClearEnterPress: (e: KeyboardEvent) => void;
194
201
  showClearBtn: () => boolean;
195
202
  renderClearBtn: () => JSX.Element;
196
203
  renderArrow: () => JSX.Element;
@@ -387,6 +387,15 @@ class Cascader extends _baseComponent.default {
387
387
  e && e.stopPropagation();
388
388
  this.foundation.handleClear();
389
389
  };
390
+ /**
391
+ * A11y: simulate clear button click
392
+ */
393
+
394
+
395
+ this.handleClearEnterPress = e => {
396
+ e && e.stopPropagation();
397
+ this.foundation.handleClearEnterPress();
398
+ };
390
399
 
391
400
  this.showClearBtn = () => {
392
401
  const {
@@ -413,6 +422,7 @@ class Cascader extends _baseComponent.default {
413
422
  return /*#__PURE__*/_react.default.createElement("div", {
414
423
  className: clearCls,
415
424
  onClick: this.handleClear,
425
+ onKeyPress: this.handleClearEnterPress,
416
426
  role: 'button',
417
427
  tabIndex: 0
418
428
  }, /*#__PURE__*/_react.default.createElement(_semiIcons.IconClear, null));
@@ -502,6 +512,7 @@ class Cascader extends _baseComponent.default {
502
512
  style: style,
503
513
  ref: this.triggerRef,
504
514
  onClick: e => this.foundation.handleClick(e),
515
+ onKeyPress: e => this.foundation.handleSelectionEnterPress(e),
505
516
  "aria-invalid": this.props['aria-invalid'],
506
517
  "aria-errormessage": this.props['aria-errormessage'],
507
518
  "aria-label": this.props['aria-label'],
@@ -941,6 +952,7 @@ Cascader.propTypes = {
941
952
  'aria-errormessage': _propTypes.default.string,
942
953
  'aria-describedby': _propTypes.default.string,
943
954
  'aria-required': _propTypes.default.bool,
955
+ 'aria-label': _propTypes.default.string,
944
956
  arrowIcon: _propTypes.default.node,
945
957
  changeOnSelect: _propTypes.default.bool,
946
958
  defaultValue: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.array]),
@@ -1035,7 +1047,8 @@ Cascader.defaultProps = {
1035
1047
  onClear: _noop2.default,
1036
1048
  onDropdownVisibleChange: _noop2.default,
1037
1049
  onListScroll: _noop2.default,
1038
- enableLeafClick: false
1050
+ enableLeafClick: false,
1051
+ 'aria-label': 'Cascader'
1039
1052
  };
1040
1053
  var _default = Cascader;
1041
1054
  exports.default = _default;
@@ -22,7 +22,7 @@ export interface CascaderItemProps {
22
22
  selectedKeys: Set<string>;
23
23
  loadedKeys: Set<string>;
24
24
  loadingKeys: Set<string>;
25
- onItemClick: (e: React.MouseEvent, item: Entity | Data) => void;
25
+ onItemClick: (e: React.MouseEvent | React.KeyboardEvent, item: Entity | Data) => void;
26
26
  onItemHover: (e: React.MouseEvent, item: Entity) => void;
27
27
  showNext: ShowNextType;
28
28
  onItemCheckboxClick: (item: Entity | Data) => void;
@@ -57,7 +57,11 @@ export default class Item extends PureComponent<CascaderItemProps> {
57
57
  static defaultProps: {
58
58
  empty: boolean;
59
59
  };
60
- onClick: (e: React.MouseEvent, item: Entity | Data) => void;
60
+ onClick: (e: React.MouseEvent | React.KeyboardEvent, item: Entity | Data) => void;
61
+ /**
62
+ * A11y: simulate item click
63
+ */
64
+ handleItemEnterPress: (keyboardEvent: React.KeyboardEvent, item: Entity | Data) => void;
61
65
  onHover: (e: React.MouseEvent, item: Entity) => void;
62
66
  onCheckboxChange: (e: CheckboxEvent, item: Entity | Data) => void;
63
67
  getItemStatus: (key: string) => {