@douyinfe/semi-foundation 2.14.0-beta.2 → 2.15.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/checkbox.scss +9 -9
- package/checkbox/checkboxFoundation.ts +1 -0
- package/datePicker/foundation.ts +32 -8
- package/datePicker/monthsGridFoundation.ts +1 -2
- 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/checkbox.css +5 -5
- package/lib/cjs/checkbox/checkbox.scss +9 -9
- package/lib/cjs/checkbox/checkboxFoundation.d.ts +1 -0
- package/lib/cjs/datePicker/foundation.d.ts +7 -0
- package/lib/cjs/datePicker/foundation.js +38 -7
- package/lib/cjs/datePicker/monthsGridFoundation.js +1 -4
- 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/checkbox.css +5 -5
- package/lib/es/checkbox/checkbox.scss +9 -9
- package/lib/es/checkbox/checkboxFoundation.d.ts +1 -0
- package/lib/es/datePicker/foundation.d.ts +7 -0
- package/lib/es/datePicker/foundation.js +37 -7
- package/lib/es/datePicker/monthsGridFoundation.js +1 -3
- 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/checkbox/checkbox.scss
CHANGED
|
@@ -101,15 +101,6 @@ $module: #{$prefix}-checkbox;
|
|
|
101
101
|
font-size: 16px;
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
&-pureCardType {
|
|
106
|
-
// Reasons to use opacity:0 & width: 0 instead of display: none
|
|
107
|
-
// The a11y keyboard focus event of the checkbox depends on the implementation of the input focus/blur event
|
|
108
|
-
// input focus/blur cannot take effect when display: none
|
|
109
|
-
opacity: 0;
|
|
110
|
-
width: 0;
|
|
111
|
-
margin-right: 0 !important;
|
|
112
|
-
}
|
|
113
104
|
}
|
|
114
105
|
|
|
115
106
|
&-inner-checked {
|
|
@@ -196,6 +187,15 @@ $module: #{$prefix}-checkbox;
|
|
|
196
187
|
flex-shrink: 0;
|
|
197
188
|
}
|
|
198
189
|
|
|
190
|
+
.#{$module}-inner-pureCardType {
|
|
191
|
+
// Reasons to use opacity:0 & width: 0 instead of display: none
|
|
192
|
+
// The a11y keyboard focus event of the checkbox depends on the implementation of the input focus/blur event
|
|
193
|
+
// input focus/blur cannot take effect when display: none
|
|
194
|
+
opacity: 0;
|
|
195
|
+
width: 0;
|
|
196
|
+
margin-right: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
199
|
.#{$module}-addon {
|
|
200
200
|
font-weight: $font-checkbox_cardType_addon-fontWeight;
|
|
201
201
|
font-size: $font-checkbox_cardType_addon-size;
|
package/datePicker/foundation.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-nested-ternary */
|
|
2
2
|
/* eslint-disable max-len, max-depth, */
|
|
3
3
|
import { format, isValid, isSameSecond, isEqual as isDateEqual, isDate } from 'date-fns';
|
|
4
|
-
import { get, isObject, isString, isEqual } from 'lodash';
|
|
4
|
+
import { get, isObject, isString, isEqual, isFunction } from 'lodash';
|
|
5
5
|
|
|
6
6
|
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
7
7
|
import { isValidDate, isTimestamp } from './_utils/index';
|
|
@@ -162,6 +162,7 @@ export interface DatePickerFoundationProps extends ElementProps, RenderProps, Ev
|
|
|
162
162
|
localeCode?: string;
|
|
163
163
|
rangeSeparator?: string;
|
|
164
164
|
insetInput?: boolean;
|
|
165
|
+
preventScroll?: boolean;
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
export interface DatePickerFoundationState {
|
|
@@ -245,6 +246,23 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
|
|
|
245
246
|
this._adapter.updateInputValue(null);
|
|
246
247
|
this._adapter.updateValue(result);
|
|
247
248
|
this.resetCachedSelectedValue(result);
|
|
249
|
+
this.initRangeInputFocus(result);
|
|
250
|
+
|
|
251
|
+
if (this._adapter.needConfirm()) {
|
|
252
|
+
this._adapter.updateCachedSelectedValue(result);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 如果用户传了一个空的 value,需要把 range input focus 设置为 rangeStart,这样用户可以清除完之后继续从开始选择
|
|
258
|
+
*
|
|
259
|
+
* If the user passes an empty value, you need to set the range input focus to rangeStart, so that the user can continue to select from the beginning after clearing
|
|
260
|
+
*/
|
|
261
|
+
initRangeInputFocus(result: Date[]) {
|
|
262
|
+
const { triggerRender } = this.getProps();
|
|
263
|
+
if (this._isRangeType() && isFunction(triggerRender) && result.length === 0) {
|
|
264
|
+
this._adapter.setRangeInputFocus('rangeStart');
|
|
265
|
+
}
|
|
248
266
|
}
|
|
249
267
|
|
|
250
268
|
parseWithTimezone(value: ValueType, timeZone: string | number, prevTimeZone: string | number) {
|
|
@@ -1285,7 +1303,7 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
|
|
|
1285
1303
|
* @returns
|
|
1286
1304
|
*/
|
|
1287
1305
|
handleTriggerWrapperClick(e: any) {
|
|
1288
|
-
const { disabled } = this._adapter.getProps();
|
|
1306
|
+
const { disabled, triggerRender } = this._adapter.getProps();
|
|
1289
1307
|
const { rangeInputFocus } = this._adapter.getStates();
|
|
1290
1308
|
if (disabled) {
|
|
1291
1309
|
return;
|
|
@@ -1297,12 +1315,18 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
|
|
|
1297
1315
|
* - When type is not range type, Input component will automatically focus in the same case
|
|
1298
1316
|
* - isEventTarget is used to judge whether the event is a bubbling event
|
|
1299
1317
|
*/
|
|
1300
|
-
if (this._isRangeType() && !rangeInputFocus
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1318
|
+
if (this._isRangeType() && !rangeInputFocus) {
|
|
1319
|
+
if (this._adapter.isEventTarget(e)) {
|
|
1320
|
+
setTimeout(() => {
|
|
1321
|
+
// using setTimeout get correct state value 'rangeInputFocus'
|
|
1322
|
+
this.handleInputFocus(e, 'rangeStart');
|
|
1323
|
+
}, 0);
|
|
1324
|
+
} else if (isFunction(triggerRender)) {
|
|
1325
|
+
// 如果是 triggerRender 场景,因为没有 input,因此打开面板时默认 focus 在 rangeStart
|
|
1326
|
+
// If it is a triggerRender scene, because there is no input, the default focus is rangeStart when the panel is opened
|
|
1327
|
+
this._adapter.setRangeInputFocus('rangeStart');
|
|
1328
|
+
}
|
|
1329
|
+
this.openPanel();
|
|
1306
1330
|
} else {
|
|
1307
1331
|
this.openPanel();
|
|
1308
1332
|
}
|
|
@@ -724,9 +724,8 @@ export default class MonthsGridFoundation extends BaseFoundation<MonthsGridAdapt
|
|
|
724
724
|
/**
|
|
725
725
|
* no need to check focus then
|
|
726
726
|
* - dateRange and isDateRangeAndHasOffset
|
|
727
|
-
* - dateRange and triggerRender
|
|
728
727
|
*/
|
|
729
|
-
const needCheckFocusRecord = !(type === 'dateRange' &&
|
|
728
|
+
const needCheckFocusRecord = !(type === 'dateRange' && isDateRangeAndHasOffset);
|
|
730
729
|
this._adapter.notifySelectedChange(date, { needCheckFocusRecord });
|
|
731
730
|
}
|
|
732
731
|
}
|
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 图标水平内间距
|
|
@@ -75,11 +75,6 @@
|
|
|
75
75
|
.semi-checkbox-inner-display .semi-icon {
|
|
76
76
|
font-size: 16px;
|
|
77
77
|
}
|
|
78
|
-
.semi-checkbox-inner-pureCardType {
|
|
79
|
-
opacity: 0;
|
|
80
|
-
width: 0;
|
|
81
|
-
margin-right: 0 !important;
|
|
82
|
-
}
|
|
83
78
|
.semi-checkbox-inner-checked .semi-checkbox-inner-display {
|
|
84
79
|
background: var(--semi-color-primary);
|
|
85
80
|
color: var(--semi-color-white);
|
|
@@ -138,6 +133,11 @@
|
|
|
138
133
|
.semi-checkbox-cardType .semi-checkbox-inner-display {
|
|
139
134
|
background: var(--semi-color-white);
|
|
140
135
|
}
|
|
136
|
+
.semi-checkbox-cardType .semi-checkbox-inner-pureCardType {
|
|
137
|
+
opacity: 0;
|
|
138
|
+
width: 0;
|
|
139
|
+
margin-right: 0;
|
|
140
|
+
}
|
|
141
141
|
.semi-checkbox-cardType .semi-checkbox-addon {
|
|
142
142
|
font-weight: 600;
|
|
143
143
|
font-size: 14px;
|
|
@@ -101,15 +101,6 @@ $module: #{$prefix}-checkbox;
|
|
|
101
101
|
font-size: 16px;
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
&-pureCardType {
|
|
106
|
-
// Reasons to use opacity:0 & width: 0 instead of display: none
|
|
107
|
-
// The a11y keyboard focus event of the checkbox depends on the implementation of the input focus/blur event
|
|
108
|
-
// input focus/blur cannot take effect when display: none
|
|
109
|
-
opacity: 0;
|
|
110
|
-
width: 0;
|
|
111
|
-
margin-right: 0 !important;
|
|
112
|
-
}
|
|
113
104
|
}
|
|
114
105
|
|
|
115
106
|
&-inner-checked {
|
|
@@ -196,6 +187,15 @@ $module: #{$prefix}-checkbox;
|
|
|
196
187
|
flex-shrink: 0;
|
|
197
188
|
}
|
|
198
189
|
|
|
190
|
+
.#{$module}-inner-pureCardType {
|
|
191
|
+
// Reasons to use opacity:0 & width: 0 instead of display: none
|
|
192
|
+
// The a11y keyboard focus event of the checkbox depends on the implementation of the input focus/blur event
|
|
193
|
+
// input focus/blur cannot take effect when display: none
|
|
194
|
+
opacity: 0;
|
|
195
|
+
width: 0;
|
|
196
|
+
margin-right: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
199
|
.#{$module}-addon {
|
|
200
200
|
font-weight: $font-checkbox_cardType_addon-fontWeight;
|
|
201
201
|
font-size: $font-checkbox_cardType_addon-size;
|
|
@@ -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;
|
|
@@ -184,6 +185,12 @@ export default class DatePickerFoundation extends BaseFoundation<DatePickerAdapt
|
|
|
184
185
|
initFromProps({ value, timeZone, prevTimeZone }: Pick<DatePickerFoundationProps, 'value' | 'timeZone'> & {
|
|
185
186
|
prevTimeZone?: string | number;
|
|
186
187
|
}): void;
|
|
188
|
+
/**
|
|
189
|
+
* 如果用户传了一个空的 value,需要把 range input focus 设置为 rangeStart,这样用户可以清除完之后继续从开始选择
|
|
190
|
+
*
|
|
191
|
+
* If the user passes an empty value, you need to set the range input focus to rangeStart, so that the user can continue to select from the beginning after clearing
|
|
192
|
+
*/
|
|
193
|
+
initRangeInputFocus(result: Date[]): void;
|
|
187
194
|
parseWithTimezone(value: ValueType, timeZone: string | number, prevTimeZone: string | number): Date[];
|
|
188
195
|
_isMultiple(): boolean;
|
|
189
196
|
/**
|