@douyinfe/semi-foundation 2.14.0 → 2.15.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/cascader/cascader.scss +20 -0
- package/cascader/foundation.ts +21 -0
- package/cascader/variables.scss +2 -0
- package/checkbox/checkboxFoundation.ts +1 -0
- package/datePicker/foundation.ts +1 -0
- package/dropdown/dropdown.scss +4 -0
- package/dropdown/foundation.ts +38 -1
- package/dropdown/menuFoundation.ts +77 -0
- package/lib/cjs/cascader/cascader.css +15 -0
- package/lib/cjs/cascader/cascader.scss +20 -0
- package/lib/cjs/cascader/foundation.d.ts +6 -0
- package/lib/cjs/cascader/foundation.js +23 -0
- package/lib/cjs/cascader/variables.scss +2 -0
- package/lib/cjs/checkbox/checkboxFoundation.d.ts +1 -0
- package/lib/cjs/datePicker/foundation.d.ts +1 -0
- package/lib/cjs/dropdown/dropdown.css +4 -0
- package/lib/cjs/dropdown/dropdown.scss +4 -0
- package/lib/cjs/dropdown/foundation.d.ts +4 -0
- package/lib/cjs/dropdown/foundation.js +48 -0
- package/lib/cjs/dropdown/menuFoundation.d.ts +9 -0
- package/lib/cjs/dropdown/menuFoundation.js +119 -0
- package/lib/cjs/list/list.css +1 -1
- package/lib/cjs/list/list.scss +1 -1
- package/lib/cjs/list/variables.scss +2 -1
- package/lib/cjs/modal/modalFoundation.d.ts +1 -0
- package/lib/cjs/rating/foundation.d.ts +13 -0
- package/lib/cjs/rating/foundation.js +123 -35
- package/lib/cjs/rating/rating.css +14 -5
- package/lib/cjs/rating/rating.scss +21 -8
- package/lib/cjs/rating/variables.scss +4 -0
- package/lib/cjs/tabs/foundation.js +28 -6
- package/lib/cjs/tooltip/foundation.js +39 -9
- package/lib/cjs/tree/foundation.d.ts +1 -0
- package/lib/cjs/treeSelect/foundation.js +9 -1
- package/lib/cjs/utils/FocusHandle.d.ts +1 -0
- package/lib/cjs/utils/FocusHandle.js +6 -1
- package/lib/cjs/utils/a11y.d.ts +9 -0
- package/lib/cjs/utils/a11y.js +123 -0
- package/lib/es/cascader/cascader.css +15 -0
- package/lib/es/cascader/cascader.scss +20 -0
- package/lib/es/cascader/foundation.d.ts +6 -0
- package/lib/es/cascader/foundation.js +23 -0
- package/lib/es/cascader/variables.scss +2 -0
- package/lib/es/checkbox/checkboxFoundation.d.ts +1 -0
- package/lib/es/datePicker/foundation.d.ts +1 -0
- package/lib/es/dropdown/dropdown.css +4 -0
- package/lib/es/dropdown/dropdown.scss +4 -0
- package/lib/es/dropdown/foundation.d.ts +4 -0
- package/lib/es/dropdown/foundation.js +45 -0
- package/lib/es/dropdown/menuFoundation.d.ts +9 -0
- package/lib/es/dropdown/menuFoundation.js +99 -0
- package/lib/es/list/list.css +1 -1
- package/lib/es/list/list.scss +1 -1
- package/lib/es/list/variables.scss +2 -1
- package/lib/es/modal/modalFoundation.d.ts +1 -0
- package/lib/es/rating/foundation.d.ts +13 -0
- package/lib/es/rating/foundation.js +116 -32
- package/lib/es/rating/rating.css +14 -5
- package/lib/es/rating/rating.scss +21 -8
- package/lib/es/rating/variables.scss +4 -0
- package/lib/es/tabs/foundation.js +30 -6
- package/lib/es/tooltip/foundation.js +38 -9
- package/lib/es/tree/foundation.d.ts +1 -0
- package/lib/es/treeSelect/foundation.js +9 -1
- package/lib/es/utils/FocusHandle.d.ts +1 -0
- package/lib/es/utils/FocusHandle.js +6 -1
- package/lib/es/utils/a11y.d.ts +9 -0
- package/lib/es/utils/a11y.js +101 -0
- package/list/list.scss +1 -1
- package/list/variables.scss +2 -1
- package/modal/modalFoundation.ts +1 -0
- package/package.json +2 -2
- package/rating/foundation.ts +90 -31
- package/rating/rating.scss +21 -8
- package/rating/variables.scss +4 -0
- package/tabs/foundation.ts +9 -6
- package/tooltip/foundation.ts +16 -8
- package/tree/foundation.ts +1 -0
- package/treeSelect/foundation.ts +5 -1
- package/utils/FocusHandle.ts +3 -1
- package/utils/a11y.ts +105 -0
package/cascader/cascader.scss
CHANGED
|
@@ -175,6 +175,17 @@ $module: #{$prefix}-cascader;
|
|
|
175
175
|
height: $height-cascader_selection_tagInput_input_large;
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
+
|
|
179
|
+
&-text {
|
|
180
|
+
|
|
181
|
+
&-inactive {
|
|
182
|
+
color: $color-cascader_selection_text_inactive;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&-hide {
|
|
186
|
+
display: none;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
178
189
|
}
|
|
179
190
|
|
|
180
191
|
&-arrow,
|
|
@@ -294,8 +305,17 @@ $module: #{$prefix}-cascader;
|
|
|
294
305
|
.#{$module}-selection {
|
|
295
306
|
.#{$module}-search-wrapper {
|
|
296
307
|
width: 100%;
|
|
308
|
+
height: $height-cascader_selection_wrapper;
|
|
309
|
+
display: flex;
|
|
310
|
+
align-items: center;
|
|
311
|
+
position: relative;
|
|
297
312
|
|
|
298
313
|
.#{$prefix}-input-wrapper {
|
|
314
|
+
position: absolute;
|
|
315
|
+
top: 0;
|
|
316
|
+
left: 0;
|
|
317
|
+
border: none;
|
|
318
|
+
background-color: transparent;
|
|
299
319
|
height: 100%;
|
|
300
320
|
width: 100%;
|
|
301
321
|
border: $color-cascader_input-border-default;
|
package/cascader/foundation.ts
CHANGED
|
@@ -145,6 +145,7 @@ export interface BasicCascaderProps {
|
|
|
145
145
|
disableStrictly?: boolean;
|
|
146
146
|
leafOnly?: boolean;
|
|
147
147
|
enableLeafClick?: boolean;
|
|
148
|
+
preventScroll?: boolean;
|
|
148
149
|
onClear?: () => void;
|
|
149
150
|
triggerRender?: (props: BasicTriggerRenderProps) => any;
|
|
150
151
|
onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
|
|
@@ -183,6 +184,7 @@ export interface BasicCascaderInnerData {
|
|
|
183
184
|
isFocus?: boolean;
|
|
184
185
|
isInput?: boolean;
|
|
185
186
|
disabledKeys?: Set<string>;
|
|
187
|
+
showInput?: boolean;
|
|
186
188
|
}
|
|
187
189
|
|
|
188
190
|
export interface CascaderAdapter extends DefaultAdapter<BasicCascaderProps, BasicCascaderInnerData> {
|
|
@@ -208,6 +210,8 @@ export interface CascaderAdapter extends DefaultAdapter<BasicCascaderProps, Basi
|
|
|
208
210
|
notifyOnLoad: (newLoadedKeys: Set<string>, data: BasicCascaderData) => void;
|
|
209
211
|
notifyListScroll: (e: any, panel: BasicScrollPanelProps) => void;
|
|
210
212
|
notifyOnExceed: (data: BasicEntity[]) => void;
|
|
213
|
+
toggleInputShow: (show: boolean, cb: () => void) => void;
|
|
214
|
+
updateFocusState: (focus: boolean) => void,
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
// eslint-disable-next-line max-len
|
|
@@ -484,9 +488,11 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
|
|
|
484
488
|
|
|
485
489
|
open() {
|
|
486
490
|
const filterable = this._isFilterable();
|
|
491
|
+
const { multiple } = this.getProps();
|
|
487
492
|
this._adapter.openMenu();
|
|
488
493
|
if (filterable) {
|
|
489
494
|
this._clearInput();
|
|
495
|
+
!multiple && this.toggle2SearchInput(true);
|
|
490
496
|
}
|
|
491
497
|
if (this._isControlledComponent()) {
|
|
492
498
|
this.reCalcActiveKeys();
|
|
@@ -524,10 +530,25 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
|
|
|
524
530
|
inputValue = this.renderDisplayText([...selectedKeys][0]);
|
|
525
531
|
}
|
|
526
532
|
this._adapter.updateStates({ inputValue });
|
|
533
|
+
!multiple && this.toggle2SearchInput(false);
|
|
534
|
+
!multiple && this._adapter.updateFocusState(false);
|
|
527
535
|
}
|
|
528
536
|
this._notifyBlur(e);
|
|
529
537
|
}
|
|
530
538
|
|
|
539
|
+
toggle2SearchInput(isShow: boolean) {
|
|
540
|
+
if (isShow) {
|
|
541
|
+
this._adapter.toggleInputShow(isShow, () => this.focusInput());
|
|
542
|
+
} else {
|
|
543
|
+
this._adapter.toggleInputShow(isShow, () => undefined);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
focusInput() {
|
|
548
|
+
this._adapter.focusInput();
|
|
549
|
+
this._adapter.updateFocusState(true);
|
|
550
|
+
}
|
|
551
|
+
|
|
531
552
|
getMergedMotion = () => {
|
|
532
553
|
const { motion } = this.getProps();
|
|
533
554
|
const { isSearching } = this.getStates();
|
package/cascader/variables.scss
CHANGED
|
@@ -54,6 +54,7 @@ $spacing-cascader_clearBtn-marginRight: 12px; // 级联选择触发器清空按
|
|
|
54
54
|
|
|
55
55
|
$color-cascader_selection_n-text-default: var(--semi-color-text-0); // 超出 maxTagCount 后,+n 的文字默认颜色
|
|
56
56
|
$color-cascader_selection_n-text-disabled: var(--semi-color-disabled-text); // 超出 maxTagCount 后,+n 的文字disabled颜色
|
|
57
|
+
$color-cascader_selection_text_inactive: var(--semi-color-text-2); // 级联选择单选inpu输入框和text并存时,text颜色
|
|
57
58
|
$color-cascader_selection-text-default: var(--semi-color-text-0); // 级联选择选中项文字颜色
|
|
58
59
|
$color-cascader_placeholder-text-default: var(--semi-color-text-2); // 级联选择未选中项文字颜色
|
|
59
60
|
$color-cascader-icon-default: var(--semi-color-text-2); // 级联选择图标颜色 - 默认
|
|
@@ -94,6 +95,7 @@ $height-cascader_option_list: 180px; // 级联选择菜单高度
|
|
|
94
95
|
$height-cascader_selection_tagInput_input_small: 22px;
|
|
95
96
|
$height-cascader_selection_tagInput_input_default: 30px;
|
|
96
97
|
$height-cascader_selection_tagInput_input_large: 38px;
|
|
98
|
+
$height-cascader_selection_wrapper: 30px;
|
|
97
99
|
|
|
98
100
|
$spacing-cascader_text-marginX: $spacing-base-tight; // 级联选择 prefix/suffix 文字水平内间距
|
|
99
101
|
$spacing-cascader_icon-marginX: $spacing-tight; // 级联选择 prefix/suffix 图标水平内间距
|
package/datePicker/foundation.ts
CHANGED
package/dropdown/dropdown.scss
CHANGED
|
@@ -50,6 +50,10 @@ $module: #{$prefix}-dropdown;
|
|
|
50
50
|
&:not(.#{$module}-item-active):active {
|
|
51
51
|
background-color: $color-dropdown_item-bg-active;
|
|
52
52
|
}
|
|
53
|
+
&:focus-visible {
|
|
54
|
+
background-color: $color-dropdown_item-bg-hover;
|
|
55
|
+
outline: 0;
|
|
56
|
+
}
|
|
53
57
|
&-icon {
|
|
54
58
|
display: inline-flex;
|
|
55
59
|
align-items: center;
|
package/dropdown/foundation.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
2
|
-
|
|
2
|
+
import { handlePrevent, setFocusToFirstItem, setFocusToLastItem } from '../utils/a11y';
|
|
3
3
|
|
|
4
4
|
export interface DropdownAdapter extends Partial<DefaultAdapter> {
|
|
5
5
|
setPopVisible(visible: boolean): void;
|
|
@@ -11,4 +11,41 @@ export default class DropdownFoundation extends BaseFoundation<DropdownAdapter>
|
|
|
11
11
|
this._adapter.setPopVisible(visible);
|
|
12
12
|
this._adapter.notifyVisibleChange(visible);
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
getMenuItemNodes(target: any): HTMLElement[] {
|
|
16
|
+
const id = target.attributes['data-popupId'].value;
|
|
17
|
+
const menuWrapper = document.getElementById(id);
|
|
18
|
+
// if has dropdown item, the item must wrapped by li
|
|
19
|
+
return menuWrapper ? Array.from(menuWrapper.getElementsByTagName('li')).filter(item => item.ariaDisabled === "false") : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setFocusToFirstMenuItem(target: any): void {
|
|
23
|
+
const menuItemNodes = this.getMenuItemNodes(target);
|
|
24
|
+
menuItemNodes && setFocusToFirstItem(menuItemNodes);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setFocusToLastMenuItem(target: any): void {
|
|
28
|
+
const menuItemNodes = this.getMenuItemNodes(target);
|
|
29
|
+
menuItemNodes && setFocusToLastItem(menuItemNodes);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
handleKeyDown(event: any): void {
|
|
33
|
+
switch (event.key) {
|
|
34
|
+
case ' ':
|
|
35
|
+
case 'Enter':
|
|
36
|
+
event.target.click();
|
|
37
|
+
handlePrevent(event);
|
|
38
|
+
break;
|
|
39
|
+
case 'ArrowDown':
|
|
40
|
+
this.setFocusToFirstMenuItem(event.target);
|
|
41
|
+
handlePrevent(event);
|
|
42
|
+
break;
|
|
43
|
+
case 'ArrowUp':
|
|
44
|
+
this.setFocusToLastMenuItem(event.target);
|
|
45
|
+
handlePrevent(event);
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
14
51
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
|
|
2
|
+
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
3
|
+
import { handlePrevent, isPrintableCharacter, findIndexByCharacter, getAncestorNodeByRole, getMenuButton, setFocusToFirstItem, setFocusToItem, setFocusToNextMenuitem, setFocusToPreviousMenuItem } from '../utils/a11y';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export default class DropdownMenuFoundation extends BaseFoundation<Partial<DefaultAdapter>> {
|
|
7
|
+
menuItemNodes: HTMLElement[] = null;
|
|
8
|
+
firstChars: string[] = [];
|
|
9
|
+
|
|
10
|
+
// if trigger is click, auto focus to the first menu item
|
|
11
|
+
autoFocus(ulElement: any): void {
|
|
12
|
+
const trigger = this._adapter.getContext('trigger');
|
|
13
|
+
if (trigger === 'click'){
|
|
14
|
+
// find all non-disabled li under this menu and set focus to the first menu
|
|
15
|
+
this.menuItemNodes = [...ulElement.getElementsByTagName('li')].filter(item => item.ariaDisabled !== "true");
|
|
16
|
+
setFocusToFirstItem(this.menuItemNodes);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
handleEscape(menu: Element): void {
|
|
21
|
+
const trigger = this._adapter.getContext('trigger');
|
|
22
|
+
if (trigger === 'custom'){
|
|
23
|
+
const menuButton = menu && getMenuButton(document.querySelectorAll(`[data-popupId]`), menu.id);
|
|
24
|
+
menuButton.focus();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setFocusByFirstCharacter(curItem: any, char: string): void {
|
|
29
|
+
const index = findIndexByCharacter(this.menuItemNodes, curItem, this.firstChars, char);
|
|
30
|
+
|
|
31
|
+
if (index >= 0) {
|
|
32
|
+
setFocusToItem(this.menuItemNodes, this.menuItemNodes[index]);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
onMenuKeydown(event: any): void {
|
|
37
|
+
const menu = getAncestorNodeByRole(event.target, 'tooltip');
|
|
38
|
+
|
|
39
|
+
if (!this.menuItemNodes){
|
|
40
|
+
this.menuItemNodes = [...(event.target.parentNode).getElementsByTagName('li')].filter(item => item.ariaDisabled !== "true");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (this.firstChars.length === 0){
|
|
44
|
+
this.menuItemNodes.forEach((item: Element) => {
|
|
45
|
+
this.firstChars.push(item.textContent.trim()[0].toLowerCase());
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// get the currently focused menu item
|
|
50
|
+
const curItem = this.menuItemNodes.find(item => item.tabIndex === 0);
|
|
51
|
+
|
|
52
|
+
switch (event.key) {
|
|
53
|
+
case ' ':
|
|
54
|
+
case 'Enter':
|
|
55
|
+
event.target.click();
|
|
56
|
+
handlePrevent(event);
|
|
57
|
+
break;
|
|
58
|
+
case 'Escape':
|
|
59
|
+
this.handleEscape(menu);
|
|
60
|
+
break;
|
|
61
|
+
case 'ArrowUp':
|
|
62
|
+
setFocusToPreviousMenuItem(this.menuItemNodes, curItem);
|
|
63
|
+
handlePrevent(event);
|
|
64
|
+
break;
|
|
65
|
+
case 'ArrowDown':
|
|
66
|
+
setFocusToNextMenuitem(this.menuItemNodes, curItem);
|
|
67
|
+
handlePrevent(event);
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
if (isPrintableCharacter(event.key)) {
|
|
71
|
+
this.setFocusByFirstCharacter(curItem, event.key);
|
|
72
|
+
handlePrevent(event);
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -149,6 +149,12 @@
|
|
|
149
149
|
.semi-cascader-selection .semi-tagInput .semi-input-wrapper-large {
|
|
150
150
|
height: 38px;
|
|
151
151
|
}
|
|
152
|
+
.semi-cascader-selection-text-inactive {
|
|
153
|
+
color: var(--semi-color-text-2);
|
|
154
|
+
}
|
|
155
|
+
.semi-cascader-selection-text-hide {
|
|
156
|
+
display: none;
|
|
157
|
+
}
|
|
152
158
|
.semi-cascader-arrow, .semi-cascader-clearbtn {
|
|
153
159
|
display: inline-flex;
|
|
154
160
|
align-items: center;
|
|
@@ -242,8 +248,17 @@
|
|
|
242
248
|
}
|
|
243
249
|
.semi-cascader-single.semi-cascader-filterable .semi-cascader-selection .semi-cascader-search-wrapper {
|
|
244
250
|
width: 100%;
|
|
251
|
+
height: 30px;
|
|
252
|
+
display: flex;
|
|
253
|
+
align-items: center;
|
|
254
|
+
position: relative;
|
|
245
255
|
}
|
|
246
256
|
.semi-cascader-single.semi-cascader-filterable .semi-cascader-selection .semi-cascader-search-wrapper .semi-input-wrapper {
|
|
257
|
+
position: absolute;
|
|
258
|
+
top: 0;
|
|
259
|
+
left: 0;
|
|
260
|
+
border: none;
|
|
261
|
+
background-color: transparent;
|
|
247
262
|
height: 100%;
|
|
248
263
|
width: 100%;
|
|
249
264
|
border: none;
|
|
@@ -175,6 +175,17 @@ $module: #{$prefix}-cascader;
|
|
|
175
175
|
height: $height-cascader_selection_tagInput_input_large;
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
+
|
|
179
|
+
&-text {
|
|
180
|
+
|
|
181
|
+
&-inactive {
|
|
182
|
+
color: $color-cascader_selection_text_inactive;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&-hide {
|
|
186
|
+
display: none;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
178
189
|
}
|
|
179
190
|
|
|
180
191
|
&-arrow,
|
|
@@ -294,8 +305,17 @@ $module: #{$prefix}-cascader;
|
|
|
294
305
|
.#{$module}-selection {
|
|
295
306
|
.#{$module}-search-wrapper {
|
|
296
307
|
width: 100%;
|
|
308
|
+
height: $height-cascader_selection_wrapper;
|
|
309
|
+
display: flex;
|
|
310
|
+
align-items: center;
|
|
311
|
+
position: relative;
|
|
297
312
|
|
|
298
313
|
.#{$prefix}-input-wrapper {
|
|
314
|
+
position: absolute;
|
|
315
|
+
top: 0;
|
|
316
|
+
left: 0;
|
|
317
|
+
border: none;
|
|
318
|
+
background-color: transparent;
|
|
299
319
|
height: 100%;
|
|
300
320
|
width: 100%;
|
|
301
321
|
border: $color-cascader_input-border-default;
|
|
@@ -99,6 +99,7 @@ export interface BasicCascaderProps {
|
|
|
99
99
|
disableStrictly?: boolean;
|
|
100
100
|
leafOnly?: boolean;
|
|
101
101
|
enableLeafClick?: boolean;
|
|
102
|
+
preventScroll?: boolean;
|
|
102
103
|
onClear?: () => void;
|
|
103
104
|
triggerRender?: (props: BasicTriggerRenderProps) => any;
|
|
104
105
|
onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
|
|
@@ -136,6 +137,7 @@ export interface BasicCascaderInnerData {
|
|
|
136
137
|
isFocus?: boolean;
|
|
137
138
|
isInput?: boolean;
|
|
138
139
|
disabledKeys?: Set<string>;
|
|
140
|
+
showInput?: boolean;
|
|
139
141
|
}
|
|
140
142
|
export interface CascaderAdapter extends DefaultAdapter<BasicCascaderProps, BasicCascaderInnerData> {
|
|
141
143
|
notifyClear?: () => void;
|
|
@@ -160,6 +162,8 @@ export interface CascaderAdapter extends DefaultAdapter<BasicCascaderProps, Basi
|
|
|
160
162
|
notifyOnLoad: (newLoadedKeys: Set<string>, data: BasicCascaderData) => void;
|
|
161
163
|
notifyListScroll: (e: any, panel: BasicScrollPanelProps) => void;
|
|
162
164
|
notifyOnExceed: (data: BasicEntity[]) => void;
|
|
165
|
+
toggleInputShow: (show: boolean, cb: () => void) => void;
|
|
166
|
+
updateFocusState: (focus: boolean) => void;
|
|
163
167
|
}
|
|
164
168
|
export default class CascaderFoundation extends BaseFoundation<CascaderAdapter, BasicCascaderProps, BasicCascaderInnerData> {
|
|
165
169
|
constructor(adapter: CascaderAdapter);
|
|
@@ -187,6 +191,8 @@ export default class CascaderFoundation extends BaseFoundation<CascaderAdapter,
|
|
|
187
191
|
open(): void;
|
|
188
192
|
reCalcActiveKeys(): void;
|
|
189
193
|
close(e: any, key?: string): void;
|
|
194
|
+
toggle2SearchInput(isShow: boolean): void;
|
|
195
|
+
focusInput(): void;
|
|
190
196
|
getMergedMotion: () => any;
|
|
191
197
|
handleItemClick(e: any, item: BasicEntity | BasicData): void;
|
|
192
198
|
handleItemHover(e: any, item: BasicEntity): void;
|
|
@@ -423,10 +423,16 @@ class CascaderFoundation extends _foundation.default {
|
|
|
423
423
|
open() {
|
|
424
424
|
const filterable = this._isFilterable();
|
|
425
425
|
|
|
426
|
+
const {
|
|
427
|
+
multiple
|
|
428
|
+
} = this.getProps();
|
|
429
|
+
|
|
426
430
|
this._adapter.openMenu();
|
|
427
431
|
|
|
428
432
|
if (filterable) {
|
|
429
433
|
this._clearInput();
|
|
434
|
+
|
|
435
|
+
!multiple && this.toggle2SearchInput(true);
|
|
430
436
|
}
|
|
431
437
|
|
|
432
438
|
if (this._isControlledComponent()) {
|
|
@@ -486,11 +492,28 @@ class CascaderFoundation extends _foundation.default {
|
|
|
486
492
|
this._adapter.updateStates({
|
|
487
493
|
inputValue
|
|
488
494
|
});
|
|
495
|
+
|
|
496
|
+
!multiple && this.toggle2SearchInput(false);
|
|
497
|
+
!multiple && this._adapter.updateFocusState(false);
|
|
489
498
|
}
|
|
490
499
|
|
|
491
500
|
this._notifyBlur(e);
|
|
492
501
|
}
|
|
493
502
|
|
|
503
|
+
toggle2SearchInput(isShow) {
|
|
504
|
+
if (isShow) {
|
|
505
|
+
this._adapter.toggleInputShow(isShow, () => this.focusInput());
|
|
506
|
+
} else {
|
|
507
|
+
this._adapter.toggleInputShow(isShow, () => undefined);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
focusInput() {
|
|
512
|
+
this._adapter.focusInput();
|
|
513
|
+
|
|
514
|
+
this._adapter.updateFocusState(true);
|
|
515
|
+
}
|
|
516
|
+
|
|
494
517
|
handleItemClick(e, item) {
|
|
495
518
|
const isDisabled = this._isDisabled();
|
|
496
519
|
|
|
@@ -54,6 +54,7 @@ $spacing-cascader_clearBtn-marginRight: 12px; // 级联选择触发器清空按
|
|
|
54
54
|
|
|
55
55
|
$color-cascader_selection_n-text-default: var(--semi-color-text-0); // 超出 maxTagCount 后,+n 的文字默认颜色
|
|
56
56
|
$color-cascader_selection_n-text-disabled: var(--semi-color-disabled-text); // 超出 maxTagCount 后,+n 的文字disabled颜色
|
|
57
|
+
$color-cascader_selection_text_inactive: var(--semi-color-text-2); // 级联选择单选inpu输入框和text并存时,text颜色
|
|
57
58
|
$color-cascader_selection-text-default: var(--semi-color-text-0); // 级联选择选中项文字颜色
|
|
58
59
|
$color-cascader_placeholder-text-default: var(--semi-color-text-2); // 级联选择未选中项文字颜色
|
|
59
60
|
$color-cascader-icon-default: var(--semi-color-text-2); // 级联选择图标颜色 - 默认
|
|
@@ -94,6 +95,7 @@ $height-cascader_option_list: 180px; // 级联选择菜单高度
|
|
|
94
95
|
$height-cascader_selection_tagInput_input_small: 22px;
|
|
95
96
|
$height-cascader_selection_tagInput_input_default: 30px;
|
|
96
97
|
$height-cascader_selection_tagInput_input_large: 38px;
|
|
98
|
+
$height-cascader_selection_wrapper: 30px;
|
|
97
99
|
|
|
98
100
|
$spacing-cascader_text-marginX: $spacing-base-tight; // 级联选择 prefix/suffix 文字水平内间距
|
|
99
101
|
$spacing-cascader_icon-marginX: $spacing-tight; // 级联选择 prefix/suffix 图标水平内间距
|
|
@@ -131,6 +131,7 @@ export interface DatePickerFoundationProps extends ElementProps, RenderProps, Ev
|
|
|
131
131
|
localeCode?: string;
|
|
132
132
|
rangeSeparator?: string;
|
|
133
133
|
insetInput?: boolean;
|
|
134
|
+
preventScroll?: boolean;
|
|
134
135
|
}
|
|
135
136
|
export interface DatePickerFoundationState {
|
|
136
137
|
panelShow: boolean;
|
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
.semi-dropdown-item:not(.semi-dropdown-item-active):active {
|
|
54
54
|
background-color: var(--semi-color-fill-1);
|
|
55
55
|
}
|
|
56
|
+
.semi-dropdown-item:focus-visible {
|
|
57
|
+
background-color: var(--semi-color-fill-0);
|
|
58
|
+
outline: 0;
|
|
59
|
+
}
|
|
56
60
|
.semi-dropdown-item-icon {
|
|
57
61
|
display: inline-flex;
|
|
58
62
|
align-items: center;
|
|
@@ -50,6 +50,10 @@ $module: #{$prefix}-dropdown;
|
|
|
50
50
|
&:not(.#{$module}-item-active):active {
|
|
51
51
|
background-color: $color-dropdown_item-bg-active;
|
|
52
52
|
}
|
|
53
|
+
&:focus-visible {
|
|
54
|
+
background-color: $color-dropdown_item-bg-hover;
|
|
55
|
+
outline: 0;
|
|
56
|
+
}
|
|
53
57
|
&-icon {
|
|
54
58
|
display: inline-flex;
|
|
55
59
|
align-items: center;
|
|
@@ -5,4 +5,8 @@ export interface DropdownAdapter extends Partial<DefaultAdapter> {
|
|
|
5
5
|
}
|
|
6
6
|
export default class DropdownFoundation extends BaseFoundation<DropdownAdapter> {
|
|
7
7
|
handleVisibleChange(visible: boolean): void;
|
|
8
|
+
getMenuItemNodes(target: any): HTMLElement[];
|
|
9
|
+
setFocusToFirstMenuItem(target: any): void;
|
|
10
|
+
setFocusToLastMenuItem(target: any): void;
|
|
11
|
+
handleKeyDown(event: any): void;
|
|
8
12
|
}
|
|
@@ -10,8 +10,14 @@ _Object$defineProperty(exports, "__esModule", {
|
|
|
10
10
|
|
|
11
11
|
exports.default = void 0;
|
|
12
12
|
|
|
13
|
+
var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
|
|
14
|
+
|
|
15
|
+
var _from = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/from"));
|
|
16
|
+
|
|
13
17
|
var _foundation = _interopRequireDefault(require("../base/foundation"));
|
|
14
18
|
|
|
19
|
+
var _a11y = require("../utils/a11y");
|
|
20
|
+
|
|
15
21
|
class DropdownFoundation extends _foundation.default {
|
|
16
22
|
handleVisibleChange(visible) {
|
|
17
23
|
this._adapter.setPopVisible(visible);
|
|
@@ -19,6 +25,48 @@ class DropdownFoundation extends _foundation.default {
|
|
|
19
25
|
this._adapter.notifyVisibleChange(visible);
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
getMenuItemNodes(target) {
|
|
29
|
+
var _context;
|
|
30
|
+
|
|
31
|
+
const id = target.attributes['data-popupId'].value;
|
|
32
|
+
const menuWrapper = document.getElementById(id); // if has dropdown item, the item must wrapped by li
|
|
33
|
+
|
|
34
|
+
return menuWrapper ? (0, _filter.default)(_context = (0, _from.default)(menuWrapper.getElementsByTagName('li'))).call(_context, item => item.ariaDisabled === "false") : null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setFocusToFirstMenuItem(target) {
|
|
38
|
+
const menuItemNodes = this.getMenuItemNodes(target);
|
|
39
|
+
menuItemNodes && (0, _a11y.setFocusToFirstItem)(menuItemNodes);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
setFocusToLastMenuItem(target) {
|
|
43
|
+
const menuItemNodes = this.getMenuItemNodes(target);
|
|
44
|
+
menuItemNodes && (0, _a11y.setFocusToLastItem)(menuItemNodes);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
handleKeyDown(event) {
|
|
48
|
+
switch (event.key) {
|
|
49
|
+
case ' ':
|
|
50
|
+
case 'Enter':
|
|
51
|
+
event.target.click();
|
|
52
|
+
(0, _a11y.handlePrevent)(event);
|
|
53
|
+
break;
|
|
54
|
+
|
|
55
|
+
case 'ArrowDown':
|
|
56
|
+
this.setFocusToFirstMenuItem(event.target);
|
|
57
|
+
(0, _a11y.handlePrevent)(event);
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
case 'ArrowUp':
|
|
61
|
+
this.setFocusToLastMenuItem(event.target);
|
|
62
|
+
(0, _a11y.handlePrevent)(event);
|
|
63
|
+
break;
|
|
64
|
+
|
|
65
|
+
default:
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
22
70
|
}
|
|
23
71
|
|
|
24
72
|
exports.default = DropdownFoundation;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
2
|
+
export default class DropdownMenuFoundation extends BaseFoundation<Partial<DefaultAdapter>> {
|
|
3
|
+
menuItemNodes: HTMLElement[];
|
|
4
|
+
firstChars: string[];
|
|
5
|
+
autoFocus(ulElement: any): void;
|
|
6
|
+
handleEscape(menu: Element): void;
|
|
7
|
+
setFocusByFirstCharacter(curItem: any, char: string): void;
|
|
8
|
+
onMenuKeydown(event: any): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
|
|
4
|
+
|
|
5
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
|
|
6
|
+
|
|
7
|
+
_Object$defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
exports.default = void 0;
|
|
12
|
+
|
|
13
|
+
var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter"));
|
|
14
|
+
|
|
15
|
+
var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
|
|
16
|
+
|
|
17
|
+
var _trim = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/trim"));
|
|
18
|
+
|
|
19
|
+
var _find = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/find"));
|
|
20
|
+
|
|
21
|
+
var _foundation = _interopRequireDefault(require("../base/foundation"));
|
|
22
|
+
|
|
23
|
+
var _a11y = require("../utils/a11y");
|
|
24
|
+
|
|
25
|
+
class DropdownMenuFoundation extends _foundation.default {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.menuItemNodes = null;
|
|
29
|
+
this.firstChars = [];
|
|
30
|
+
} // if trigger is click, auto focus to the first menu item
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
autoFocus(ulElement) {
|
|
34
|
+
const trigger = this._adapter.getContext('trigger');
|
|
35
|
+
|
|
36
|
+
if (trigger === 'click') {
|
|
37
|
+
var _context;
|
|
38
|
+
|
|
39
|
+
// find all non-disabled li under this menu and set focus to the first menu
|
|
40
|
+
this.menuItemNodes = (0, _filter.default)(_context = [...ulElement.getElementsByTagName('li')]).call(_context, item => item.ariaDisabled !== "true");
|
|
41
|
+
(0, _a11y.setFocusToFirstItem)(this.menuItemNodes);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
handleEscape(menu) {
|
|
46
|
+
const trigger = this._adapter.getContext('trigger');
|
|
47
|
+
|
|
48
|
+
if (trigger === 'custom') {
|
|
49
|
+
const menuButton = menu && (0, _a11y.getMenuButton)(document.querySelectorAll("[data-popupId]"), menu.id);
|
|
50
|
+
menuButton.focus();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setFocusByFirstCharacter(curItem, char) {
|
|
55
|
+
const index = (0, _a11y.findIndexByCharacter)(this.menuItemNodes, curItem, this.firstChars, char);
|
|
56
|
+
|
|
57
|
+
if (index >= 0) {
|
|
58
|
+
(0, _a11y.setFocusToItem)(this.menuItemNodes, this.menuItemNodes[index]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
onMenuKeydown(event) {
|
|
63
|
+
var _context5;
|
|
64
|
+
|
|
65
|
+
const menu = (0, _a11y.getAncestorNodeByRole)(event.target, 'tooltip');
|
|
66
|
+
|
|
67
|
+
if (!this.menuItemNodes) {
|
|
68
|
+
var _context2;
|
|
69
|
+
|
|
70
|
+
this.menuItemNodes = (0, _filter.default)(_context2 = [...event.target.parentNode.getElementsByTagName('li')]).call(_context2, item => item.ariaDisabled !== "true");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (this.firstChars.length === 0) {
|
|
74
|
+
var _context3;
|
|
75
|
+
|
|
76
|
+
(0, _forEach.default)(_context3 = this.menuItemNodes).call(_context3, item => {
|
|
77
|
+
var _context4;
|
|
78
|
+
|
|
79
|
+
this.firstChars.push((0, _trim.default)(_context4 = item.textContent).call(_context4)[0].toLowerCase());
|
|
80
|
+
});
|
|
81
|
+
} // get the currently focused menu item
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
const curItem = (0, _find.default)(_context5 = this.menuItemNodes).call(_context5, item => item.tabIndex === 0);
|
|
85
|
+
|
|
86
|
+
switch (event.key) {
|
|
87
|
+
case ' ':
|
|
88
|
+
case 'Enter':
|
|
89
|
+
event.target.click();
|
|
90
|
+
(0, _a11y.handlePrevent)(event);
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
case 'Escape':
|
|
94
|
+
this.handleEscape(menu);
|
|
95
|
+
break;
|
|
96
|
+
|
|
97
|
+
case 'ArrowUp':
|
|
98
|
+
(0, _a11y.setFocusToPreviousMenuItem)(this.menuItemNodes, curItem);
|
|
99
|
+
(0, _a11y.handlePrevent)(event);
|
|
100
|
+
break;
|
|
101
|
+
|
|
102
|
+
case 'ArrowDown':
|
|
103
|
+
(0, _a11y.setFocusToNextMenuitem)(this.menuItemNodes, curItem);
|
|
104
|
+
(0, _a11y.handlePrevent)(event);
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
default:
|
|
108
|
+
if ((0, _a11y.isPrintableCharacter)(event.key)) {
|
|
109
|
+
this.setFocusByFirstCharacter(curItem, event.key);
|
|
110
|
+
(0, _a11y.handlePrevent)(event);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
exports.default = DropdownMenuFoundation;
|