@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.
- 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 +21 -8
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +232 -92
- 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/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/scrollList/scrollItem.d.ts +2 -1
- package/lib/cjs/scrollList/scrollItem.js +13 -3
- package/lib/es/_base/base.css +5 -5
- 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/scrollList/scrollItem.d.ts +2 -1
- package/lib/es/scrollList/scrollItem.js +13 -3
- 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/_story/Perf/Virtualized/index.jsx +6 -0
- package/table/_story/v2/FixedHeaderMerge/index.jsx +1 -1
- 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: '
|
|
28
|
-
{ name: '
|
|
29
|
-
{ name: '
|
|
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.
|
|
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
|
}
|
package/form/_story/demo.jsx
CHANGED
|
@@ -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:
|
|
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);
|
package/form/hoc/withField.tsx
CHANGED
package/lib/cjs/_base/base.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);
|
|
@@ -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: "
|
|
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 =>
|
|
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: "
|
|
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: "
|
|
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) => {
|