@king-design/intact 3.6.0 → 3.6.2-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/components/button/demos/basic.md +0 -1
- package/components/copy/index.spec.ts +9 -14
- package/components/datepicker/index.spec.ts +55 -28
- package/components/datepicker/useValueBase.ts +5 -2
- package/components/dropdown/constants.ts +25 -0
- package/components/dropdown/item.ts +1 -2
- package/components/dropdown/menu.ts +1 -1
- package/components/dropdown/useItemKeyboard.ts +38 -0
- package/components/dropdown/{useKeyboard.ts → useMenuKeyboard.ts} +3 -62
- package/components/form/form.ts +4 -0
- package/components/form/index.md +2 -1
- package/components/form/index.spec.ts +2 -0
- package/components/menu/demos/horizontal.md +7 -1
- package/components/menu/index.spec.ts +19 -0
- package/components/menu/styles.ts +2 -1
- package/components/select/index.spec.ts +35 -2
- package/components/select/menu.ts +1 -1
- package/components/select/useCard.ts +22 -4
- package/components/spinner/index.spec.ts +18 -0
- package/components/spinner/useValue.ts +2 -1
- package/es/components/copy/index.spec.js +14 -31
- package/es/components/datepicker/index.spec.js +646 -608
- package/es/components/datepicker/useValueBase.js +5 -2
- package/es/components/dropdown/constants.d.ts +22 -0
- package/es/components/dropdown/constants.js +7 -0
- package/es/components/dropdown/item.js +1 -1
- package/es/components/dropdown/menu.js +1 -1
- package/es/components/dropdown/useItemKeyboard.d.ts +6 -0
- package/es/components/dropdown/useItemKeyboard.js +32 -0
- package/es/components/dropdown/useMenuKeyboard.d.ts +2 -0
- package/es/components/dropdown/{useKeyboard.js → useMenuKeyboard.js} +3 -38
- package/es/components/form/form.d.ts +1 -0
- package/es/components/form/form.js +7 -0
- package/es/components/form/index.spec.js +10 -8
- package/es/components/menu/index.spec.js +28 -0
- package/es/components/menu/styles.js +2 -2
- package/es/components/select/index.spec.js +231 -177
- package/es/components/select/menu.js +1 -1
- package/es/components/select/useCard.d.ts +4 -3
- package/es/components/select/useCard.js +15 -4
- package/es/components/spinner/index.spec.js +82 -44
- package/es/components/spinner/useValue.js +2 -1
- package/es/index.d.ts +2 -2
- package/es/index.js +2 -2
- package/es/site/data/components/button/demos/basic/react.js +0 -2
- package/es/site/data/components/menu/demos/horizontal/react.js +5 -1
- package/es/test/demos.js +1 -1
- package/index.ts +2 -2
- package/package.json +2 -2
- package/components/.DS_Store +0 -0
- package/components/descriptions/.DS_Store +0 -0
- package/components/menu/.DS_Store +0 -0
- package/components/menu/demos/.DS_Store +0 -0
- package/components/table/.DS_Store +0 -0
- package/components/tour/.DS_Store +0 -0
- package/components/virtualList/.DS_Store +0 -0
- package/components/virtualList/demos/.DS_Store +0 -0
- package/es/components/dropdown/useKeyboard.d.ts +0 -23
- package/styles/.DS_Store +0 -0
|
@@ -10,19 +10,18 @@ describe('Copy', () => {
|
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
it('should copy', async function() {
|
|
13
|
+
const spy = sinon.spy(navigator.clipboard, 'writeText');
|
|
13
14
|
const [instance, element] = mount(BasicDemo);
|
|
14
15
|
|
|
15
16
|
element.click();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// Read permisson denied
|
|
21
|
-
console.log(e);
|
|
22
|
-
}
|
|
17
|
+
await wait();
|
|
18
|
+
expect(spy.calledWith('Hello King Desgin!')).to.be.true;
|
|
19
|
+
|
|
20
|
+
spy.restore();
|
|
23
21
|
});
|
|
24
22
|
|
|
25
23
|
it('wrap copy with tooltip', async () => {
|
|
24
|
+
const spy = sinon.spy(navigator.clipboard, 'writeText');
|
|
26
25
|
class Demo extends Component {
|
|
27
26
|
static template = `
|
|
28
27
|
const { Tooltip, Copy } = this;
|
|
@@ -38,12 +37,8 @@ describe('Copy', () => {
|
|
|
38
37
|
|
|
39
38
|
element.click();
|
|
40
39
|
await wait();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} catch (e) {
|
|
45
|
-
// Read permisson denied
|
|
46
|
-
console.log(e);
|
|
47
|
-
}
|
|
40
|
+
expect(spy.calledWith('test')).to.be.true;
|
|
41
|
+
|
|
42
|
+
spy.restore();
|
|
48
43
|
});
|
|
49
44
|
});
|
|
@@ -38,10 +38,10 @@ function getDateString(date: number) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
describe('Datepicker', () => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
afterEach(async () => {
|
|
42
|
+
unmount();
|
|
43
|
+
await wait(500);
|
|
44
|
+
});
|
|
45
45
|
|
|
46
46
|
describe('Pick', () => {
|
|
47
47
|
it('date', async () => {
|
|
@@ -151,37 +151,37 @@ describe('Datepicker', () => {
|
|
|
151
151
|
expect(+_month - 1).eql(month);
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
it('week', async () => {
|
|
155
|
-
const [instance, element] = mount(YearMonthDemo);
|
|
156
|
-
const inputs = element.querySelectorAll<HTMLElement>('.k-input');
|
|
157
|
-
const weekInput = inputs[2];
|
|
154
|
+
// it('week', async () => {
|
|
155
|
+
// const [instance, element] = mount(YearMonthDemo);
|
|
156
|
+
// const inputs = element.querySelectorAll<HTMLElement>('.k-input');
|
|
157
|
+
// const weekInput = inputs[2];
|
|
158
158
|
|
|
159
|
-
weekInput.click();
|
|
160
|
-
await wait();
|
|
159
|
+
// weekInput.click();
|
|
160
|
+
// await wait();
|
|
161
161
|
|
|
162
|
-
const content = getElement('.k-datepicker-content')!;
|
|
163
|
-
const weekItem = content.querySelector('.week-row:nth-child(1) .k-week-number') as HTMLElement;
|
|
164
|
-
weekItem.click();
|
|
162
|
+
// const content = getElement('.k-datepicker-content')!;
|
|
163
|
+
// const weekItem = content.querySelector('.week-row:nth-child(1) .k-week-number') as HTMLElement;
|
|
164
|
+
// weekItem.click();
|
|
165
165
|
|
|
166
|
-
expect(instance.get<string>('week')).to.match(/^\d{4}-\d+周$/)
|
|
167
|
-
});
|
|
166
|
+
// expect(instance.get<string>('week')).to.match(/^\d{4}-\d+周$/)
|
|
167
|
+
// });
|
|
168
168
|
|
|
169
|
-
it('quarter', async () => {
|
|
170
|
-
const [instance, element] = mount(YearMonthDemo);
|
|
171
|
-
const inputs = element.querySelectorAll<HTMLElement>('.k-input');
|
|
172
|
-
const QuarterInput = inputs[3];
|
|
169
|
+
// it('quarter', async () => {
|
|
170
|
+
// const [instance, element] = mount(YearMonthDemo);
|
|
171
|
+
// const inputs = element.querySelectorAll<HTMLElement>('.k-input');
|
|
172
|
+
// const QuarterInput = inputs[3];
|
|
173
173
|
|
|
174
|
-
QuarterInput.click();
|
|
175
|
-
await wait();
|
|
176
|
-
const content = getElement('.k-datepicker-content')!;
|
|
174
|
+
// QuarterInput.click();
|
|
175
|
+
// await wait();
|
|
176
|
+
// const content = getElement('.k-datepicker-content')!;
|
|
177
177
|
|
|
178
|
-
// 选择第一个季度
|
|
179
|
-
const quarterItem = content.querySelector('.k-calendar-item:nth-child(1)') as HTMLElement;
|
|
180
|
-
quarterItem.click();
|
|
178
|
+
// // 选择第一个季度
|
|
179
|
+
// const quarterItem = content.querySelector('.k-calendar-item:nth-child(1)') as HTMLElement;
|
|
180
|
+
// quarterItem.click();
|
|
181
181
|
|
|
182
|
-
// 验证输入框的值是否包含Q1
|
|
183
|
-
expect(instance.get<string>('quarter')).to.include('Q1')
|
|
184
|
-
});
|
|
182
|
+
// // 验证输入框的值是否包含Q1
|
|
183
|
+
// expect(instance.get<string>('quarter')).to.include('Q1')
|
|
184
|
+
// });
|
|
185
185
|
|
|
186
186
|
});
|
|
187
187
|
|
|
@@ -1120,6 +1120,33 @@ describe('Datepicker', () => {
|
|
|
1120
1120
|
await wait();
|
|
1121
1121
|
expect(fn.callCount).to.eql(4);
|
|
1122
1122
|
});
|
|
1123
|
+
|
|
1124
|
+
it('should trigger change event once', async () => {
|
|
1125
|
+
const change = sinon.spy(() => console.log('change'));
|
|
1126
|
+
class Demo extends Component<{value: string}> {
|
|
1127
|
+
static template = `
|
|
1128
|
+
const {Datepicker} = this;
|
|
1129
|
+
<Datepicker range ev-$change:value={this.onChange} v-model="value" clearable />
|
|
1130
|
+
`;
|
|
1131
|
+
private Datepicker = Datepicker;
|
|
1132
|
+
|
|
1133
|
+
onChange() {
|
|
1134
|
+
change();
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
const [instance, element] = mount(Demo);
|
|
1138
|
+
const input = element.querySelector<HTMLInputElement>('.k-input-inner')!;
|
|
1139
|
+
|
|
1140
|
+
input.click();
|
|
1141
|
+
await wait();
|
|
1142
|
+
const calendar = getElement('.k-datepicker-content')!;
|
|
1143
|
+
const [day1, day2] = calendar.querySelectorAll<HTMLElement>('.k-calendar-item:not(.k-exceed)');
|
|
1144
|
+
day1.click();
|
|
1145
|
+
await wait();
|
|
1146
|
+
day2.click();
|
|
1147
|
+
await wait();
|
|
1148
|
+
expect(change.callCount).to.eql(1);
|
|
1149
|
+
});
|
|
1123
1150
|
});
|
|
1124
1151
|
|
|
1125
1152
|
it('should disable some time pickers', async () => {
|
|
@@ -214,8 +214,11 @@ export function useValueBase(
|
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
const valueStr = convertToValueString(_value);
|
|
217
|
-
|
|
218
|
-
instance.
|
|
217
|
+
// only trigger change event once
|
|
218
|
+
if (!isEqualArray(valueStr, instance.get('value'))) {
|
|
219
|
+
instance.set('value', valueStr);
|
|
220
|
+
instance.resetKeywords();
|
|
221
|
+
}
|
|
219
222
|
}
|
|
220
223
|
|
|
221
224
|
// TODO
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {Component} from 'intact';
|
|
2
|
+
import type {DropdownItem} from './item';
|
|
3
|
+
|
|
4
|
+
export interface ItemEvents {
|
|
5
|
+
onFocusin: () => void;
|
|
6
|
+
onFocusout: () => void;
|
|
7
|
+
onShowMenu: () => void;
|
|
8
|
+
onHideMenu: () => void;
|
|
9
|
+
onSelect: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export enum Direction {
|
|
13
|
+
Up,
|
|
14
|
+
Down
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type MenuKeyboardMethods = {
|
|
18
|
+
reset: () => void;
|
|
19
|
+
focus: (item: DropdownItem) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type ItemComponent = Component<{disabled: boolean}>
|
|
23
|
+
|
|
24
|
+
export const ITEM_EVENTS = 'ItemEvents';
|
|
25
|
+
export const MENU_KEYBOARD = 'MenuKeyboard';
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import {Component, TypeDefs, inject, VNodeComponentClass} from 'intact';
|
|
2
2
|
import template from './item.vdt';
|
|
3
3
|
import {bind} from '../utils';
|
|
4
|
-
import {useItemKeyboard
|
|
4
|
+
import {useItemKeyboard} from './useItemKeyboard';
|
|
5
5
|
import {Dropdown, DROPDOWN} from './dropdown';
|
|
6
6
|
import {type DropdownMenu, DROPDOWN_MENU} from './menu';
|
|
7
|
-
import {IgnoreClickEvent} from '../../hooks/useDocumentClick';
|
|
8
7
|
import { Dropdown as ExportDropdown, DropdownMenu as ExportDropdownMenu } from '.';
|
|
9
8
|
import { useConfigContext } from '../config';
|
|
10
9
|
import type { Tooltip } from '../tooltip/tooltip';
|
|
@@ -3,7 +3,7 @@ import template from './menu.vdt';
|
|
|
3
3
|
import {bind} from '../utils';
|
|
4
4
|
import {Dropdown, DROPDOWN} from './dropdown';
|
|
5
5
|
import {useTransition} from './useTransition';
|
|
6
|
-
import {useMenuKeyboard} from './
|
|
6
|
+
import {useMenuKeyboard} from './useMenuKeyboard';
|
|
7
7
|
import {useMouseOutsidable} from '../../hooks/useMouseOutsidable';
|
|
8
8
|
import {FeedbackCallback} from './usePosition';
|
|
9
9
|
import { useConfigContext } from '../config';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {useInstance, inject} from 'intact';
|
|
2
|
+
import {useRecordItem} from '../../hooks/useRecordComponent';
|
|
3
|
+
import {useState} from '../../hooks/useState';
|
|
4
|
+
import type {DropdownItem} from './item';
|
|
5
|
+
import { ItemEvents, MENU_KEYBOARD, MenuKeyboardMethods, ITEM_EVENTS } from './constants';
|
|
6
|
+
|
|
7
|
+
export function useItemKeyboard(itemEvents: Omit<ItemEvents, 'onFocusin' | 'onFocusout'>) {
|
|
8
|
+
const isFocus = useState(false);
|
|
9
|
+
const keyboard = inject<MenuKeyboardMethods>(MENU_KEYBOARD)!;
|
|
10
|
+
const instance = useInstance() as DropdownItem;
|
|
11
|
+
|
|
12
|
+
useRecordItem<DropdownItem, ItemEvents>(ITEM_EVENTS, instance, {
|
|
13
|
+
...itemEvents,
|
|
14
|
+
onFocusin() {
|
|
15
|
+
isFocus.set(true);
|
|
16
|
+
},
|
|
17
|
+
onFocusout() {
|
|
18
|
+
isFocus.set(false);
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
onMouseEnter(e: MouseEvent) {
|
|
24
|
+
instance.trigger('mouseenter', e);
|
|
25
|
+
if (instance.get('disabled')) return;
|
|
26
|
+
keyboard.focus(instance);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
onMouseLeave(e: MouseEvent) {
|
|
30
|
+
instance.trigger('mouseleave', e);
|
|
31
|
+
keyboard.reset();
|
|
32
|
+
// If it is a virtual item, it needs to be reset manually because the DOM is reused.
|
|
33
|
+
isFocus.set(false);
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
isFocus,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -5,47 +5,21 @@ import {
|
|
|
5
5
|
useInstance,
|
|
6
6
|
findDomFromVNode,
|
|
7
7
|
provide,
|
|
8
|
-
inject,
|
|
9
8
|
Component,
|
|
10
|
-
Children,
|
|
11
|
-
VNodeComponentClass,
|
|
12
9
|
isComponentClass,
|
|
13
10
|
isComponentFunction,
|
|
14
11
|
hasVNodeChildren,
|
|
15
12
|
hasMultipleChildren,
|
|
16
13
|
VNode,
|
|
17
14
|
} from 'intact';
|
|
18
|
-
import {useRecordParent
|
|
15
|
+
import {useRecordParent} from '../../hooks/useRecordComponent';
|
|
19
16
|
import {useKeyboard} from '../../hooks/useKeyboard';
|
|
20
|
-
import {
|
|
21
|
-
import {eachChildren, isComponentVNode} from '../utils';
|
|
17
|
+
import {isComponentVNode} from '../utils';
|
|
22
18
|
import {DropdownItem} from './item';
|
|
23
19
|
// can not import DropdownMenu from index.ts, otherwise it will cause circle reference
|
|
24
20
|
// import {DropdownMenu} from './';
|
|
25
21
|
import {DropdownMenu} from './menu';
|
|
26
|
-
|
|
27
|
-
interface ItemEvents {
|
|
28
|
-
onFocusin: () => void;
|
|
29
|
-
onFocusout: () => void;
|
|
30
|
-
onShowMenu: () => void;
|
|
31
|
-
onHideMenu: () => void;
|
|
32
|
-
onSelect: () => void;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export enum Direction {
|
|
36
|
-
Up,
|
|
37
|
-
Down
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type MenuKeyboardMethods = {
|
|
41
|
-
reset: () => void;
|
|
42
|
-
focus: (item: DropdownItem) => void;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
type ItemComponent = Component<{disabled: boolean}>
|
|
46
|
-
|
|
47
|
-
const ITEM_EVENTS = 'ItemEvents';
|
|
48
|
-
const MENU_KEYBOARD = 'MenuKeyboard';
|
|
22
|
+
import { ITEM_EVENTS, ItemEvents, Direction, MenuKeyboardMethods, MENU_KEYBOARD } from './constants';
|
|
49
23
|
|
|
50
24
|
export function useMenuKeyboard() {
|
|
51
25
|
const items: DropdownItem[] = [];
|
|
@@ -178,39 +152,6 @@ export function useMenuKeyboard() {
|
|
|
178
152
|
] as const;
|
|
179
153
|
}
|
|
180
154
|
|
|
181
|
-
export function useItemKeyboard(itemEvents: Omit<ItemEvents, 'onFocusin' | 'onFocusout'>) {
|
|
182
|
-
const isFocus = useState(false);
|
|
183
|
-
const keyboard = inject<MenuKeyboardMethods>(MENU_KEYBOARD)!;
|
|
184
|
-
const instance = useInstance() as DropdownItem;
|
|
185
|
-
|
|
186
|
-
useRecordItem<DropdownItem, ItemEvents>(ITEM_EVENTS, instance, {
|
|
187
|
-
...itemEvents,
|
|
188
|
-
onFocusin() {
|
|
189
|
-
isFocus.set(true);
|
|
190
|
-
},
|
|
191
|
-
onFocusout() {
|
|
192
|
-
isFocus.set(false);
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
return {
|
|
197
|
-
onMouseEnter(e: MouseEvent) {
|
|
198
|
-
instance.trigger('mouseenter', e);
|
|
199
|
-
if (instance.get('disabled')) return;
|
|
200
|
-
keyboard.focus(instance);
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
onMouseLeave(e: MouseEvent) {
|
|
204
|
-
instance.trigger('mouseleave', e);
|
|
205
|
-
keyboard.reset();
|
|
206
|
-
// If it is a virtual item, it needs to be reset manually because the DOM is reused.
|
|
207
|
-
isFocus.set(false);
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
isFocus,
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
155
|
function fixIndex(index: number, max: number) {
|
|
215
156
|
if (index > max) {
|
|
216
157
|
index = 0;
|
package/components/form/form.ts
CHANGED
package/components/form/index.md
CHANGED
|
@@ -63,7 +63,8 @@ export declare type ClassName = string | ((value: any, param: any) => string)
|
|
|
63
63
|
| --- | --- | --- | --- |
|
|
64
64
|
| validate | 验证表单所有规则 | - | `Promise<boolean>`: `.then(valid => {})`,`valid`为`true`验证成功,否则失败 |
|
|
65
65
|
| reset | 重置表单验证状态 | - | `undefined` |
|
|
66
|
-
| getFirstInvalidFormItem |
|
|
66
|
+
| getFirstInvalidFormItem | 获取第一条校验失败的`FormItem` | - | `FormItem` |
|
|
67
|
+
| getAllInvalidFormItems | 获取所有校验失败的`FormItem` | - | `FormItem[]` |
|
|
67
68
|
|
|
68
69
|
# 静态方法
|
|
69
70
|
|
|
@@ -33,6 +33,8 @@ describe('Form', () => {
|
|
|
33
33
|
expect(element.innerHTML).to.matchSnapshot();
|
|
34
34
|
const item = form.getFirstInvalidFormItem()!;
|
|
35
35
|
expect(item.get('label')).to.eql('Input');
|
|
36
|
+
const items = form.getAllInvalidFormItems();
|
|
37
|
+
expect(items.length).to.eql(10);
|
|
36
38
|
|
|
37
39
|
instance.reset();
|
|
38
40
|
await wait();
|
|
@@ -27,7 +27,13 @@ import {Menu, MenuItem, Switch, Icon} from 'kpc';
|
|
|
27
27
|
</MenuItem>
|
|
28
28
|
</Menu>
|
|
29
29
|
</MenuItem>
|
|
30
|
-
<MenuItem key="4"
|
|
30
|
+
<MenuItem key="4">
|
|
31
|
+
<Icon class="ion-gear-b" />menu 4
|
|
32
|
+
<Menu>
|
|
33
|
+
<MenuItem key="4-1">sub menu 1</MenuItem>
|
|
34
|
+
<MenuItem key="4-2">sub menu 2</MenuItem>
|
|
35
|
+
</Menu>
|
|
36
|
+
</MenuItem>
|
|
31
37
|
</Menu>
|
|
32
38
|
<br /><br />
|
|
33
39
|
<Switch
|
|
@@ -3,6 +3,7 @@ import BasicDemo from '~/components/menu/demos/basic';
|
|
|
3
3
|
import CollapseDemo from '~/components/menu/demos/collapse';
|
|
4
4
|
import AccordionDemo from '~/components/menu/demos/accordion';
|
|
5
5
|
import CollapseArrowDemo from '~/components/menu/demos/showCollapseArrow';
|
|
6
|
+
import HorizontalDemo from '~/components/menu/demos/horizontal';
|
|
6
7
|
import {mount, unmount, dispatchEvent, getElement, wait} from '../../test/utils';
|
|
7
8
|
import {Menu, MenuItem} from './';
|
|
8
9
|
|
|
@@ -190,4 +191,22 @@ describe('Menu', () => {
|
|
|
190
191
|
expect(element.outerHTML).to.matchSnapshot();
|
|
191
192
|
expect(getElement('.k-menu-arrow-box')).to.be.undefined;
|
|
192
193
|
});
|
|
194
|
+
|
|
195
|
+
it('detecting pop-up position during rapid mouse hover over menus', async () => {
|
|
196
|
+
const [instance, element] = mount(HorizontalDemo);
|
|
197
|
+
|
|
198
|
+
const [, , menu3, menu4] = element.querySelectorAll<HTMLElement>('.k-menu-item-title');
|
|
199
|
+
dispatchEvent(menu3, 'mouseenter');
|
|
200
|
+
await wait(500);
|
|
201
|
+
const dropdownmenu1 = getElement('.k-dropdown-menu')!;
|
|
202
|
+
const top1 = dropdownmenu1.getBoundingClientRect().top;
|
|
203
|
+
|
|
204
|
+
dispatchEvent(menu3, 'mouseleave');
|
|
205
|
+
dispatchEvent(menu4, 'mouseenter');
|
|
206
|
+
await wait(1000);
|
|
207
|
+
const dropdownmenu2 = getElement('.k-dropdown-menu')!;
|
|
208
|
+
const top2 = dropdownmenu2.getBoundingClientRect().top;
|
|
209
|
+
|
|
210
|
+
expect(top1).to.eql(top2);
|
|
211
|
+
});
|
|
193
212
|
});
|
|
@@ -18,7 +18,7 @@ const defaults = {
|
|
|
18
18
|
item: {
|
|
19
19
|
height: '40px',
|
|
20
20
|
padding: '0 12px',
|
|
21
|
-
bodyPadding: '
|
|
21
|
+
bodyPadding: '4px',
|
|
22
22
|
color: '#aeaeb9',
|
|
23
23
|
hoverColor: '#fff',
|
|
24
24
|
disabledColor: '#53535a',
|
|
@@ -292,6 +292,7 @@ export const makeMenuStyles = cache(function makeMenuStyles(k: string) {
|
|
|
292
292
|
&.${k}-dropdown-menu {
|
|
293
293
|
width: fit-content;
|
|
294
294
|
min-width: ${menu.dropdown.minWidth};
|
|
295
|
+
position: absolute;
|
|
295
296
|
.${k}-menu-item-arrow {
|
|
296
297
|
transform: rotate(-90deg)
|
|
297
298
|
}
|
|
@@ -12,9 +12,9 @@ import SearchableDemo from '~/components/select/demos/searchable';
|
|
|
12
12
|
import ImmutableDemo from '~/components/select/demos/immutable';
|
|
13
13
|
|
|
14
14
|
describe('Select', () => {
|
|
15
|
-
afterEach((
|
|
15
|
+
afterEach(async () => {
|
|
16
16
|
unmount();
|
|
17
|
-
|
|
17
|
+
await wait(500);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
it('should select value correctly', async () => {
|
|
@@ -188,6 +188,39 @@ describe('Select', () => {
|
|
|
188
188
|
expect(dropdown2.innerHTML).to.matchSnapshot();
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
it('should select the first card of group on filtering', async () => {
|
|
192
|
+
const [instance, element] = mount(GroupDemo);
|
|
193
|
+
|
|
194
|
+
instance.set<string>('day', 'Saturday');
|
|
195
|
+
await wait();
|
|
196
|
+
const [, trigger] = element.querySelectorAll<HTMLElement>('.k-select');
|
|
197
|
+
trigger.click();
|
|
198
|
+
await wait();
|
|
199
|
+
const dropdown = getElement('.k-select-menu')!;
|
|
200
|
+
defaultStatusTest();
|
|
201
|
+
|
|
202
|
+
// filter
|
|
203
|
+
const input = trigger.querySelector('.k-input-inner') as HTMLInputElement;
|
|
204
|
+
input.value = 'm';
|
|
205
|
+
dispatchEvent(input, 'input');
|
|
206
|
+
await wait();
|
|
207
|
+
const firstTab = dropdown.querySelector('.k-tab') as HTMLElement;
|
|
208
|
+
expect(firstTab.classList.contains('k-active')).to.eql(true);
|
|
209
|
+
|
|
210
|
+
// clear
|
|
211
|
+
input.value = '';
|
|
212
|
+
dispatchEvent(input, 'input');
|
|
213
|
+
await wait();
|
|
214
|
+
defaultStatusTest();
|
|
215
|
+
|
|
216
|
+
function defaultStatusTest() {
|
|
217
|
+
const secondTab = dropdown.querySelector('.k-tab:nth-child(2)') as HTMLElement;
|
|
218
|
+
const item = dropdown.querySelector('.k-dropdown-item') as HTMLElement;
|
|
219
|
+
expect(secondTab.classList.contains('k-active')).to.eql(true);
|
|
220
|
+
expect(item.classList.contains('k-active')).to.eql(true);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
191
224
|
it('keyboard operations', async () => {
|
|
192
225
|
const [instance, element] = mount(BasicDemo);
|
|
193
226
|
|
|
@@ -12,7 +12,7 @@ export class SelectMenu extends Component<{values: any[]}> {
|
|
|
12
12
|
static template = template;
|
|
13
13
|
|
|
14
14
|
public select: Select<any, boolean> = inject(SELECT)!;
|
|
15
|
-
private card = useCard(this.select.label.activeIndices);
|
|
15
|
+
private card = useCard(this.select.label.activeIndices, this.select.input.keywords);
|
|
16
16
|
private searchable = useSearchable();
|
|
17
17
|
private config = useConfigContext();
|
|
18
18
|
}
|
|
@@ -2,13 +2,31 @@ import {Component, TypeDefs, useInstance, Children, Blocks, createRef, NonNullab
|
|
|
2
2
|
import {eachChildren, isComponentVNode, last} from '../utils';
|
|
3
3
|
import {EMPTY_OBJ} from 'intact-shared';
|
|
4
4
|
import {OptionGroup} from './group';
|
|
5
|
-
import {useState} from '../../hooks/useState';
|
|
5
|
+
import {useState, State, watchState} from '../../hooks/useState';
|
|
6
|
+
import type { SelectMenu } from './menu';
|
|
6
7
|
|
|
7
|
-
export function useCard(
|
|
8
|
-
|
|
8
|
+
export function useCard(
|
|
9
|
+
defaultActiveIndex: NonNullableRefObject<number[]>,
|
|
10
|
+
keywords: State<string>
|
|
11
|
+
) {
|
|
12
|
+
const instance = useInstance() as SelectMenu;
|
|
9
13
|
const activeIndex = useState<number>(last(defaultActiveIndex.value) || 0);
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
watchState(keywords, (keywords) => {
|
|
16
|
+
if (keywords) {
|
|
17
|
+
activeIndex.set(0);
|
|
18
|
+
} else {
|
|
19
|
+
setDefaultActiveIndex();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
instance.select.on('show', setDefaultActiveIndex);
|
|
24
|
+
|
|
25
|
+
function setDefaultActiveIndex() {
|
|
26
|
+
activeIndex.set(last(defaultActiveIndex.value) || 0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function process(children: Children, isSearching: boolean) {
|
|
12
30
|
const groupLabels: Children[] | Blocks[string][] = [];
|
|
13
31
|
const _children: Children[] = [];
|
|
14
32
|
let index = 0;
|
|
@@ -227,6 +227,24 @@ describe('Spinner', () => {
|
|
|
227
227
|
expect(instance.get('value1')).to.eql(8.4);
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
+
it('forceStep without min value', async () => {
|
|
231
|
+
class Demo extends Component {
|
|
232
|
+
static template = `const {Spinner} = this;
|
|
233
|
+
<Spinner step={1} v-model="value" forceStep />
|
|
234
|
+
`;
|
|
235
|
+
static defaults() {
|
|
236
|
+
return {value: 1};
|
|
237
|
+
}
|
|
238
|
+
private Spinner = Spinner;
|
|
239
|
+
}
|
|
240
|
+
const [instance, element] = mount(Demo);
|
|
241
|
+
expect(instance.get('value')).to.eql(1);
|
|
242
|
+
|
|
243
|
+
instance.set<number>('value', -1);
|
|
244
|
+
await wait();
|
|
245
|
+
expect(instance.get('value')).to.eql(-1);
|
|
246
|
+
});
|
|
247
|
+
|
|
230
248
|
it('dynamic step', async () => {
|
|
231
249
|
const [instance, element] = mount(DynamicStepDemo);
|
|
232
250
|
|
|
@@ -78,7 +78,8 @@ export function minMaxStep(value: number, min: number, max: number, step: number
|
|
|
78
78
|
if (value >= max) return max;
|
|
79
79
|
if (value <= min) return min;
|
|
80
80
|
if (step) {
|
|
81
|
-
|
|
81
|
+
let _min = min === -Infinity ? 0 : min;
|
|
82
|
+
value = Number((Math.round((value - _min) / step) * step + _min).toFixed(10))
|
|
82
83
|
// value = Number((Math.round(value / step) * step).toFixed(10))
|
|
83
84
|
return minMaxStep(value, min, max, null);
|
|
84
85
|
}
|