@king-design/intact 3.5.1-beta.0 → 3.5.1
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/tree/useChecked.ts +9 -4
- package/components/treeSelect/index.spec.ts +47 -0
- package/components/treeSelect/useValue.ts +7 -4
- package/components/virtualList/index.spec.ts +161 -0
- package/components/virtualList/rows.vdt +2 -1
- package/components/virtualList/useRows.ts +16 -2
- package/components/virtualList/useVirtualRows.ts +28 -24
- package/es/components/tree/useChecked.js +8 -4
- package/es/components/treeSelect/index.spec.js +62 -0
- package/es/components/treeSelect/useValue.d.ts +1 -1
- package/es/components/treeSelect/useValue.js +6 -3
- package/es/components/virtualList/index.spec.js +200 -1
- package/es/components/virtualList/rows.vdt.js +2 -1
- package/es/components/virtualList/useRows.js +15 -2
- package/es/components/virtualList/useVirtualRows.js +24 -21
- package/es/index.d.ts +2 -2
- package/es/index.js +2 -2
- package/es/site/data/components/select/demos/virtual/index.js +1 -1
- package/es/site/data/components/select/demos/virtual/react.js +2 -3
- package/index.ts +2 -2
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import {useState} from '../../hooks/useState';
|
|
|
3
3
|
import {useReceive} from '../../hooks/useReceive';
|
|
4
4
|
import type {Tree} from './';
|
|
5
5
|
import type {Node, DataItem} from './useNodes';
|
|
6
|
+
import { isEqualArray } from '../utils';
|
|
6
7
|
|
|
7
8
|
export function useChecked(getNodes: () => Node<Key>[]) {
|
|
8
9
|
const instance = useInstance() as Tree;
|
|
@@ -38,9 +39,7 @@ export function useChecked(getNodes: () => Node<Key>[]) {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
node.checked = checked;
|
|
41
|
-
|
|
42
|
-
node.indeterminate = false;
|
|
43
|
-
}
|
|
42
|
+
node.indeterminate = false;
|
|
44
43
|
|
|
45
44
|
if (shouldUpdateCheckedKeys) {
|
|
46
45
|
updateCheckedKeys(node);
|
|
@@ -56,6 +55,12 @@ export function useChecked(getNodes: () => Node<Key>[]) {
|
|
|
56
55
|
needRecheckNodes.forEach(node => {
|
|
57
56
|
updateUpward(node);
|
|
58
57
|
});
|
|
58
|
+
|
|
59
|
+
const oldCheckedKeys = instance.get('checkedKeys');
|
|
60
|
+
const newCheckedKeys = Array.from(checkedKeys);
|
|
61
|
+
if (!isEqualArray(oldCheckedKeys, newCheckedKeys)) {
|
|
62
|
+
instance.set('checkedKeys', newCheckedKeys);
|
|
63
|
+
}
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
function updateCheckedKeys(node: Node<Key>) {
|
|
@@ -67,7 +72,7 @@ export function useChecked(getNodes: () => Node<Key>[]) {
|
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
function toggle(node: Node<Key>) {
|
|
70
|
-
const uncorrelated = instance.get('uncorrelated');
|
|
75
|
+
// const uncorrelated = instance.get('uncorrelated');
|
|
71
76
|
updateDownward(node, !node.checked);
|
|
72
77
|
updateUpward(node.parent);
|
|
73
78
|
|
|
@@ -110,4 +110,51 @@ describe('TreeSelect', () => {
|
|
|
110
110
|
await wait(500);
|
|
111
111
|
expect(element.querySelector('.k-form-error')).not.to.be.null;
|
|
112
112
|
});
|
|
113
|
+
|
|
114
|
+
it('should handle parent node correctly when all children are checked initially', async () => {
|
|
115
|
+
const [instance, element] = mount(CheckboxDemo);
|
|
116
|
+
|
|
117
|
+
// init values
|
|
118
|
+
instance.set('values', ['2.1.1', '2.1.2']);
|
|
119
|
+
await wait();
|
|
120
|
+
|
|
121
|
+
// because 2.2 is disabled, so it will select the outermost parent node 2
|
|
122
|
+
expect(instance.get('values')).to.eql(['2']);
|
|
123
|
+
|
|
124
|
+
element.click();
|
|
125
|
+
await wait();
|
|
126
|
+
const dropdown = getElement('.k-tree-select-menu')!;
|
|
127
|
+
// verify parent node is selected
|
|
128
|
+
const parentCheckboxes = dropdown.querySelectorAll('.k-checkbox');
|
|
129
|
+
expect(parentCheckboxes[3].classList.contains('k-checked')).to.be.true; // First floor-2
|
|
130
|
+
expect(parentCheckboxes[4].classList.contains('k-checked')).to.be.true; // Second floor-2.1
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should clear parent node state when setting values to empty array', async () => {
|
|
134
|
+
const [instance, element] = mount(CheckboxDemo);
|
|
135
|
+
|
|
136
|
+
// select a parent node first
|
|
137
|
+
instance.set('values', ['2.1.1']);
|
|
138
|
+
await wait();
|
|
139
|
+
|
|
140
|
+
element.click();
|
|
141
|
+
await wait();
|
|
142
|
+
let dropdown = getElement('.k-tree-select-menu')!;
|
|
143
|
+
// verify related nodes are selected
|
|
144
|
+
const checkboxes = dropdown.querySelectorAll('.k-checkbox');
|
|
145
|
+
expect(checkboxes[3].classList.contains('k-indeterminate')).to.be.true; // First floor-2
|
|
146
|
+
expect(checkboxes[4].classList.contains('k-indeterminate')).to.be.true; // Second floor-2.1
|
|
147
|
+
expect(checkboxes[5].classList.contains('k-checkbox')).to.be.true; // Third floor-2.1.1
|
|
148
|
+
// expect(checkboxes[6].classList.contains('k-checked')).to.be.true; // Third floor-2.1.2
|
|
149
|
+
|
|
150
|
+
// set to empty array
|
|
151
|
+
instance.set('values', []);
|
|
152
|
+
await wait();
|
|
153
|
+
|
|
154
|
+
// verify all nodes are cleared selected state
|
|
155
|
+
checkboxes.forEach(checkbox => {
|
|
156
|
+
expect(checkbox.classList.contains('k-checked')).to.be.false;
|
|
157
|
+
expect(checkbox.classList.contains('k-indeterminate')).to.be.false;
|
|
158
|
+
});
|
|
159
|
+
});
|
|
113
160
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {useInstance, Key, createRef} from 'intact';
|
|
1
|
+
import {useInstance, Key, createRef, nextTick} from 'intact';
|
|
2
2
|
import type {TreeSelect} from './';
|
|
3
3
|
import {useState} from '../../hooks/useState';
|
|
4
4
|
import {isNullOrUndefined} from 'intact-shared';
|
|
5
5
|
import type {Tree} from '../tree';
|
|
6
6
|
import type {Node} from '../tree/useNodes';
|
|
7
|
+
import { isEqualArray } from '../utils';
|
|
7
8
|
|
|
8
9
|
export function useValue() {
|
|
9
10
|
const instance = useInstance() as TreeSelect<Key, boolean, boolean>;
|
|
@@ -23,10 +24,12 @@ export function useValue() {
|
|
|
23
24
|
checkedKeys.set(v as Key[]);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
function onChangeCheckedKeys() {
|
|
27
|
+
function onChangeCheckedKeys(allKeys: Key[]) {
|
|
28
|
+
checkedKeys.set(allKeys);
|
|
27
29
|
const keys = getAllCheckedKeys();
|
|
28
|
-
instance.
|
|
29
|
-
|
|
30
|
+
if (!isEqualArray(keys, instance.get('value'))) {
|
|
31
|
+
instance.set('value', keys);
|
|
32
|
+
}
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
function getAllCheckedKeys() {
|
|
@@ -13,6 +13,7 @@ describe('VirtualList', () => {
|
|
|
13
13
|
|
|
14
14
|
// check basic structure
|
|
15
15
|
const container = element.querySelector('.k-virtual-container')!;
|
|
16
|
+
await wait();
|
|
16
17
|
expect(container.outerHTML).to.matchSnapshot();
|
|
17
18
|
|
|
18
19
|
const wrapper = element.querySelector('.k-virtual-wrapper')!;
|
|
@@ -259,5 +260,165 @@ describe('VirtualList', () => {
|
|
|
259
260
|
const isAtBottom = Math.abs((containerRect.bottom - lastItemRect.bottom)) <= 1;
|
|
260
261
|
expect(isAtBottom).to.be.true;
|
|
261
262
|
});
|
|
263
|
+
|
|
264
|
+
it('should handle async data correctly', async () => {
|
|
265
|
+
class AsyncDemo extends Component<{list: number[]}> {
|
|
266
|
+
static template = `
|
|
267
|
+
const VirtualList = this.VirtualList;
|
|
268
|
+
<VirtualList style="height: 300px">
|
|
269
|
+
<div v-for={this.get('list')} key={$value}>Item {$value}</div>
|
|
270
|
+
</VirtualList>
|
|
271
|
+
`;
|
|
272
|
+
static defaults() {
|
|
273
|
+
return {
|
|
274
|
+
list: []
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
private VirtualList = VirtualList;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const [instance] = mount(AsyncDemo);
|
|
281
|
+
await wait();
|
|
282
|
+
|
|
283
|
+
const container = getElement('.k-virtual-container')!;
|
|
284
|
+
const wrapper = getElement('.k-virtual-wrapper')!;
|
|
285
|
+
const phantom = getElement('.k-virtual-phantom')!;
|
|
286
|
+
|
|
287
|
+
// check initial state
|
|
288
|
+
expect(wrapper.children.length).to.equal(0);
|
|
289
|
+
expect(phantom.style.height).to.equal('0px');
|
|
290
|
+
|
|
291
|
+
// simulate async data loading
|
|
292
|
+
instance.set('list', Array.from({length: 100}, (_, i) => i));
|
|
293
|
+
await wait(50);
|
|
294
|
+
|
|
295
|
+
expect(wrapper.children.length).to.be.equal(23);
|
|
296
|
+
expect(phantom.style.height).to.be.equal('1800px');
|
|
297
|
+
|
|
298
|
+
// check render content
|
|
299
|
+
expect(wrapper.firstElementChild!.textContent).to.equal('Item 0');
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('should handle empty data and re-adding data correctly', async () => {
|
|
303
|
+
class EmptyDemo extends Component<{list: number[]}> {
|
|
304
|
+
static template = `
|
|
305
|
+
const VirtualList = this.VirtualList;
|
|
306
|
+
<VirtualList style="height: 300px">
|
|
307
|
+
<div v-for={this.get('list')} key={$value}>Item {$value}</div>
|
|
308
|
+
</VirtualList>
|
|
309
|
+
`;
|
|
310
|
+
static defaults() {
|
|
311
|
+
return {
|
|
312
|
+
list: Array.from({length: 100}, (_, i) => i)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
private VirtualList = VirtualList;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const [instance] = mount(EmptyDemo);
|
|
319
|
+
await wait();
|
|
320
|
+
|
|
321
|
+
const container = getElement('.k-virtual-container')!;
|
|
322
|
+
const wrapper = getElement('.k-virtual-wrapper')!;
|
|
323
|
+
const phantom = getElement('.k-virtual-phantom')!;
|
|
324
|
+
|
|
325
|
+
// record initial state
|
|
326
|
+
const initialHeight = phantom.style.height;
|
|
327
|
+
const initialChildrenCount = wrapper.children.length;
|
|
328
|
+
|
|
329
|
+
// clear data
|
|
330
|
+
instance.set('list', []);
|
|
331
|
+
await wait(50);
|
|
332
|
+
|
|
333
|
+
// check empty state
|
|
334
|
+
expect(wrapper.children.length).to.equal(0);
|
|
335
|
+
expect(phantom.style.height).to.equal('0px');
|
|
336
|
+
|
|
337
|
+
// re-add data
|
|
338
|
+
instance.set('list', Array.from({length: 50}, (_, i) => i));
|
|
339
|
+
await wait(50);
|
|
340
|
+
|
|
341
|
+
// check re-add data state
|
|
342
|
+
expect(wrapper.children.length).to.be.equal(23);
|
|
343
|
+
expect(parseInt(phantom.style.height)).to.be.equal(900);
|
|
344
|
+
expect(wrapper.firstElementChild!.textContent).to.equal('Item 0');
|
|
345
|
+
|
|
346
|
+
// 滚动测试
|
|
347
|
+
// container.scrollTop = 100;
|
|
348
|
+
// await wait(50);
|
|
349
|
+
|
|
350
|
+
// // 检查滚动后的渲染是否正确
|
|
351
|
+
// expect(wrapper.firstElementChild!.textContent).to.not.equal('Item 0');
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('should handle extreme height differences correctly', async () => {
|
|
355
|
+
class ExtremeHeightDemo extends Component<{list: number[]}> {
|
|
356
|
+
static template = `
|
|
357
|
+
const VirtualList = this.VirtualList;
|
|
358
|
+
<VirtualList style="height: 300px">
|
|
359
|
+
<div v-for={this.get('list')}
|
|
360
|
+
key={$value}
|
|
361
|
+
style={$value < 5 ? 'height: 100px' : 'height: 30px'}
|
|
362
|
+
>
|
|
363
|
+
Item {$value}
|
|
364
|
+
</div>
|
|
365
|
+
</VirtualList>
|
|
366
|
+
`;
|
|
367
|
+
static defaults() {
|
|
368
|
+
return {
|
|
369
|
+
list: Array.from({length: 100}, (_, i) => i)
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
private VirtualList = VirtualList;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const [instance] = mount(ExtremeHeightDemo);
|
|
376
|
+
await wait();
|
|
377
|
+
|
|
378
|
+
const container = getElement('.k-virtual-container')!;
|
|
379
|
+
const wrapper = getElement('.k-virtual-wrapper')!;
|
|
380
|
+
const phantom = getElement('.k-virtual-phantom')!;
|
|
381
|
+
|
|
382
|
+
const initialItems = wrapper.children;
|
|
383
|
+
const initialLength = initialItems.length;
|
|
384
|
+
|
|
385
|
+
// check first 5 elements height
|
|
386
|
+
const firstItem = initialItems[0] as HTMLElement;
|
|
387
|
+
expect(firstItem.offsetHeight).to.equal(100);
|
|
388
|
+
|
|
389
|
+
// record initial average height (calculate by total height and render count)
|
|
390
|
+
const initialTotalHeight = parseInt(phantom.style.height);
|
|
391
|
+
const initialAvgHeight = initialTotalHeight / 100;
|
|
392
|
+
expect(initialAvgHeight).to.be.greaterThan(30);
|
|
393
|
+
|
|
394
|
+
// scroll to small height area
|
|
395
|
+
container.scrollTop = 800;
|
|
396
|
+
await wait(50);
|
|
397
|
+
|
|
398
|
+
// check new render elements
|
|
399
|
+
const newItems = wrapper.children;
|
|
400
|
+
const newLength = newItems.length;
|
|
401
|
+
const firstNewItem = newItems[0] as HTMLElement;
|
|
402
|
+
|
|
403
|
+
// check
|
|
404
|
+
// new render elements should be 30px height
|
|
405
|
+
expect(firstNewItem.offsetHeight).to.equal(30);
|
|
406
|
+
|
|
407
|
+
// because average height is smaller, render elements count should be more
|
|
408
|
+
expect(newLength).to.be.greaterThan(initialLength);
|
|
409
|
+
|
|
410
|
+
// check scroll position is correct
|
|
411
|
+
const firstVisibleIndex = parseInt(firstNewItem.textContent!.replace('Item ', ''));
|
|
412
|
+
expect(firstVisibleIndex).to.be.greaterThan(5);
|
|
413
|
+
|
|
414
|
+
container.scrollTop = 1200;
|
|
415
|
+
await wait();
|
|
416
|
+
|
|
417
|
+
const finalItems = wrapper.children;
|
|
418
|
+
const finalFirstItem = finalItems[0] as HTMLElement;
|
|
419
|
+
expect(finalFirstItem.offsetHeight).to.equal(30);
|
|
420
|
+
expect(finalItems.length).to.equal(newLength); // render count should be stable
|
|
421
|
+
});
|
|
262
422
|
});
|
|
263
423
|
|
|
424
|
+
|
|
@@ -8,11 +8,12 @@ const rows = this.rows;
|
|
|
8
8
|
<VirtualRowsContext.Consumer>
|
|
9
9
|
{({ notifyRows, startIndex, length, disabled }) => {
|
|
10
10
|
if (!disabled) {
|
|
11
|
-
children = rows.value.slice(startIndex, startIndex + length);
|
|
12
11
|
notifyRows(rows.value);
|
|
12
|
+
children = rows.value.slice(startIndex, startIndex + length);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
if (isNullOrUndefined(tagName)) {
|
|
16
|
+
if (!children.length) return;
|
|
16
17
|
return createFragment(children, 8 /* ChildrenTypes.HasKeyedChildren */);
|
|
17
18
|
}
|
|
18
19
|
return createVNode(tagName, null, children);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useInstance, VNode, createRef, createFragment } from 'intact';
|
|
1
|
+
import { useInstance, VNode, createRef, createFragment, Children, isText } from 'intact';
|
|
2
2
|
import { VirtualListRows } from './rows';
|
|
3
3
|
|
|
4
4
|
export function useRows() {
|
|
@@ -12,11 +12,25 @@ export function useRows() {
|
|
|
12
12
|
// convert to array if it has only one child
|
|
13
13
|
const childrenType = vNode.childrenType;
|
|
14
14
|
if (childrenType & 2 /* ChildrenTypes.HasVNodeChildren */) {
|
|
15
|
-
|
|
15
|
+
const children = vNode.children as unknown as VNode;
|
|
16
|
+
if (isText(children)) {
|
|
17
|
+
// ignore void and text vnode
|
|
18
|
+
rows.value = [];
|
|
19
|
+
} else {
|
|
20
|
+
rows.value = [children];
|
|
21
|
+
}
|
|
16
22
|
} else if (childrenType & 1 /* ChildrenTypes.HasInvalidChildren */) {
|
|
17
23
|
rows.value = [];
|
|
18
24
|
} else {
|
|
19
25
|
rows.value = vNode.children as VNode[];
|
|
26
|
+
|
|
27
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
28
|
+
rows.value.forEach(row => {
|
|
29
|
+
if (isText(row)) {
|
|
30
|
+
console.warn('VirtualList: Text node can not been used as children.');
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
20
34
|
}
|
|
21
35
|
});
|
|
22
36
|
|
|
@@ -22,46 +22,51 @@ export function useVirtualRows() {
|
|
|
22
22
|
const length = useState(MIN_LENGTH);
|
|
23
23
|
|
|
24
24
|
let calculatedHeight = 0;
|
|
25
|
-
let rowAvgHeight =
|
|
25
|
+
let rowAvgHeight = 30;
|
|
26
26
|
let rows: VNode[] = [];
|
|
27
27
|
function notifyRows(_rows: VNode[]) {
|
|
28
|
+
if (_rows === rows) return;
|
|
29
|
+
|
|
28
30
|
const oldRows = rows;
|
|
29
31
|
const oldLength = rows.length;
|
|
30
32
|
rows = _rows;
|
|
33
|
+
|
|
31
34
|
// diff oldRows, newRows
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
if (!_rows.length) {
|
|
36
|
+
calculatedHeight = 0;
|
|
37
|
+
rowsHeightMap.clear();
|
|
38
|
+
} else {
|
|
39
|
+
const newKeys = new Set(_rows.map(row => row.key));
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < oldLength; i++) {
|
|
42
|
+
const oldKey = oldRows[i].key!;
|
|
43
|
+
if (!newKeys.has(oldKey)) {
|
|
44
|
+
const height = rowsHeightMap.get(oldKey);
|
|
45
|
+
if (!isNullOrUndefined(height)) {
|
|
46
|
+
calculatedHeight -= height;
|
|
47
|
+
rowsHeightMap.delete(oldKey);
|
|
48
|
+
}
|
|
41
49
|
}
|
|
42
50
|
}
|
|
43
51
|
}
|
|
44
|
-
|
|
45
|
-
// update rowAvgHeight
|
|
46
|
-
if (rowsHeightMap.size === 0) {
|
|
47
|
-
rowAvgHeight = calculatedHeight = 0;
|
|
48
|
-
} else {
|
|
49
|
-
rowAvgHeight = calculatedHeight / rowsHeightMap.size;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
+
|
|
52
53
|
if (_rows.length < oldLength) {
|
|
53
54
|
const maxStartIndex = Math.max(0, _rows.length - length.value);
|
|
54
55
|
if (startIndex.value > maxStartIndex) {
|
|
55
56
|
startIndex.set(maxStartIndex);
|
|
56
|
-
// 重新计算位置
|
|
57
57
|
nextTick(() => {
|
|
58
58
|
handleScroll();
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
instance.forceUpdate(() => {
|
|
64
|
+
calculateRowsHeight();
|
|
65
|
+
});
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
function calculateRowsHeight() {
|
|
69
|
+
if (!rows.length) return;
|
|
65
70
|
for (
|
|
66
71
|
let i = startIndex.value;
|
|
67
72
|
i < startIndex.value + length.value && i < rows.length;
|
|
@@ -79,6 +84,10 @@ export function useVirtualRows() {
|
|
|
79
84
|
|
|
80
85
|
// use the average height to estimate the row height
|
|
81
86
|
rowAvgHeight = calculatedHeight / rowsHeightMap.size;
|
|
87
|
+
|
|
88
|
+
const containerHeight = containerDom.offsetHeight;
|
|
89
|
+
// calculate the length of rows we should render
|
|
90
|
+
length.set(Math.max(Math.ceil(containerHeight / rowAvgHeight) + BUFFER_SIZE * 2, MIN_LENGTH));
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
watchState(startIndex, () => {
|
|
@@ -89,13 +98,8 @@ export function useVirtualRows() {
|
|
|
89
98
|
onMounted(() => {
|
|
90
99
|
// get contains height
|
|
91
100
|
containerDom = findDomFromVNode(instance.$lastInput!, true) as HTMLElement;
|
|
92
|
-
const containerHeight = containerDom.offsetHeight;
|
|
93
101
|
|
|
94
102
|
calculateRowsHeight();
|
|
95
|
-
|
|
96
|
-
// calculate the length of rows we should render
|
|
97
|
-
length.set(Math.max(Math.ceil(containerHeight / rowAvgHeight) + BUFFER_SIZE * 2, MIN_LENGTH));
|
|
98
|
-
|
|
99
103
|
containerDom.addEventListener('scroll', handleScroll);
|
|
100
104
|
});
|
|
101
105
|
|
|
@@ -2,6 +2,7 @@ import _Set from "@babel/runtime-corejs3/core-js/set";
|
|
|
2
2
|
import _Array$from from "@babel/runtime-corejs3/core-js/array/from";
|
|
3
3
|
import { useInstance } from 'intact';
|
|
4
4
|
import { useReceive } from '../../hooks/useReceive';
|
|
5
|
+
import { isEqualArray } from '../utils';
|
|
5
6
|
export function useChecked(getNodes) {
|
|
6
7
|
var instance = useInstance();
|
|
7
8
|
var checkedKeys = new _Set();
|
|
@@ -32,9 +33,7 @@ export function useChecked(getNodes) {
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
node.checked = checked;
|
|
35
|
-
|
|
36
|
-
node.indeterminate = false;
|
|
37
|
-
}
|
|
36
|
+
node.indeterminate = false;
|
|
38
37
|
if (shouldUpdateCheckedKeys) {
|
|
39
38
|
updateCheckedKeys(node);
|
|
40
39
|
}
|
|
@@ -47,6 +46,11 @@ export function useChecked(getNodes) {
|
|
|
47
46
|
needRecheckNodes.forEach(function (node) {
|
|
48
47
|
updateUpward(node);
|
|
49
48
|
});
|
|
49
|
+
var oldCheckedKeys = instance.get('checkedKeys');
|
|
50
|
+
var newCheckedKeys = _Array$from(checkedKeys);
|
|
51
|
+
if (!isEqualArray(oldCheckedKeys, newCheckedKeys)) {
|
|
52
|
+
instance.set('checkedKeys', newCheckedKeys);
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
function updateCheckedKeys(node) {
|
|
52
56
|
if (node.checked) {
|
|
@@ -56,7 +60,7 @@ export function useChecked(getNodes) {
|
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
function toggle(node) {
|
|
59
|
-
|
|
63
|
+
// const uncorrelated = instance.get('uncorrelated');
|
|
60
64
|
updateDownward(node, !node.checked);
|
|
61
65
|
updateUpward(node.parent);
|
|
62
66
|
instance.set('checkedKeys', _Array$from(checkedKeys));
|
|
@@ -168,4 +168,66 @@ describe('TreeSelect', function () {
|
|
|
168
168
|
}
|
|
169
169
|
}, _callee5);
|
|
170
170
|
})));
|
|
171
|
+
it('should handle parent node correctly when all children are checked initially', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
|
|
172
|
+
var _mount6, instance, element, dropdown, parentCheckboxes;
|
|
173
|
+
return _regeneratorRuntime.wrap(function _callee6$(_context7) {
|
|
174
|
+
while (1) switch (_context7.prev = _context7.next) {
|
|
175
|
+
case 0:
|
|
176
|
+
_mount6 = mount(CheckboxDemo), instance = _mount6[0], element = _mount6[1]; // init values
|
|
177
|
+
instance.set('values', ['2.1.1', '2.1.2']);
|
|
178
|
+
_context7.next = 4;
|
|
179
|
+
return wait();
|
|
180
|
+
case 4:
|
|
181
|
+
// because 2.2 is disabled, so it will select the outermost parent node 2
|
|
182
|
+
expect(instance.get('values')).to.eql(['2']);
|
|
183
|
+
element.click();
|
|
184
|
+
_context7.next = 8;
|
|
185
|
+
return wait();
|
|
186
|
+
case 8:
|
|
187
|
+
dropdown = getElement('.k-tree-select-menu'); // verify parent node is selected
|
|
188
|
+
parentCheckboxes = dropdown.querySelectorAll('.k-checkbox');
|
|
189
|
+
expect(parentCheckboxes[3].classList.contains('k-checked')).to.be.true; // First floor-2
|
|
190
|
+
expect(parentCheckboxes[4].classList.contains('k-checked')).to.be.true; // Second floor-2.1
|
|
191
|
+
case 12:
|
|
192
|
+
case "end":
|
|
193
|
+
return _context7.stop();
|
|
194
|
+
}
|
|
195
|
+
}, _callee6);
|
|
196
|
+
})));
|
|
197
|
+
it('should clear parent node state when setting values to empty array', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7() {
|
|
198
|
+
var _mount7, instance, element, dropdown, checkboxes;
|
|
199
|
+
return _regeneratorRuntime.wrap(function _callee7$(_context8) {
|
|
200
|
+
while (1) switch (_context8.prev = _context8.next) {
|
|
201
|
+
case 0:
|
|
202
|
+
_mount7 = mount(CheckboxDemo), instance = _mount7[0], element = _mount7[1]; // select a parent node first
|
|
203
|
+
instance.set('values', ['2.1.1']);
|
|
204
|
+
_context8.next = 4;
|
|
205
|
+
return wait();
|
|
206
|
+
case 4:
|
|
207
|
+
element.click();
|
|
208
|
+
_context8.next = 7;
|
|
209
|
+
return wait();
|
|
210
|
+
case 7:
|
|
211
|
+
dropdown = getElement('.k-tree-select-menu'); // verify related nodes are selected
|
|
212
|
+
checkboxes = dropdown.querySelectorAll('.k-checkbox');
|
|
213
|
+
expect(checkboxes[3].classList.contains('k-indeterminate')).to.be.true; // First floor-2
|
|
214
|
+
expect(checkboxes[4].classList.contains('k-indeterminate')).to.be.true; // Second floor-2.1
|
|
215
|
+
expect(checkboxes[5].classList.contains('k-checkbox')).to.be.true; // Third floor-2.1.1
|
|
216
|
+
// expect(checkboxes[6].classList.contains('k-checked')).to.be.true; // Third floor-2.1.2
|
|
217
|
+
// set to empty array
|
|
218
|
+
instance.set('values', []);
|
|
219
|
+
_context8.next = 15;
|
|
220
|
+
return wait();
|
|
221
|
+
case 15:
|
|
222
|
+
// verify all nodes are cleared selected state
|
|
223
|
+
checkboxes.forEach(function (checkbox) {
|
|
224
|
+
expect(checkbox.classList.contains('k-checked')).to.be.false;
|
|
225
|
+
expect(checkbox.classList.contains('k-indeterminate')).to.be.false;
|
|
226
|
+
});
|
|
227
|
+
case 16:
|
|
228
|
+
case "end":
|
|
229
|
+
return _context8.stop();
|
|
230
|
+
}
|
|
231
|
+
}, _callee7);
|
|
232
|
+
})));
|
|
171
233
|
});
|
|
@@ -4,6 +4,6 @@ export declare function useValue(): {
|
|
|
4
4
|
selectedKeys: import("../../hooks/useState").State<Key[]>;
|
|
5
5
|
checkedKeys: import("../../hooks/useState").State<Key[]>;
|
|
6
6
|
treeRef: import("intact").RefObject<Tree<Key>>;
|
|
7
|
-
onChangeCheckedKeys: () => void;
|
|
7
|
+
onChangeCheckedKeys: (allKeys: Key[]) => void;
|
|
8
8
|
onChangeSelectedKeys: (keys: Key[]) => void;
|
|
9
9
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useInstance, createRef } from 'intact';
|
|
2
2
|
import { useState } from '../../hooks/useState';
|
|
3
3
|
import { isNullOrUndefined } from 'intact-shared';
|
|
4
|
+
import { isEqualArray } from '../utils';
|
|
4
5
|
export function useValue() {
|
|
5
6
|
var instance = useInstance();
|
|
6
7
|
var selectedKeys = useState([]);
|
|
@@ -16,10 +17,12 @@ export function useValue() {
|
|
|
16
17
|
selectedKeys.set(v);
|
|
17
18
|
checkedKeys.set(v);
|
|
18
19
|
}
|
|
19
|
-
function onChangeCheckedKeys() {
|
|
20
|
+
function onChangeCheckedKeys(allKeys) {
|
|
21
|
+
checkedKeys.set(allKeys);
|
|
20
22
|
var keys = getAllCheckedKeys();
|
|
21
|
-
instance.
|
|
22
|
-
|
|
23
|
+
if (!isEqualArray(keys, instance.get('value'))) {
|
|
24
|
+
instance.set('value', keys);
|
|
25
|
+
}
|
|
23
26
|
}
|
|
24
27
|
function getAllCheckedKeys() {
|
|
25
28
|
// if the parent has been checked, ignore the children
|
|
@@ -21,13 +21,16 @@ describe('VirtualList', function () {
|
|
|
21
21
|
case 0:
|
|
22
22
|
_mount = mount(BasicDemo), instance = _mount[0], element = _mount[1]; // check basic structure
|
|
23
23
|
container = element.querySelector('.k-virtual-container');
|
|
24
|
+
_context.next = 4;
|
|
25
|
+
return wait();
|
|
26
|
+
case 4:
|
|
24
27
|
expect(container.outerHTML).to.matchSnapshot();
|
|
25
28
|
wrapper = element.querySelector('.k-virtual-wrapper');
|
|
26
29
|
expect(wrapper).to.exist;
|
|
27
30
|
// check render items is less than total
|
|
28
31
|
items = wrapper.children;
|
|
29
32
|
expect(items.length).to.be.lessThan(100);
|
|
30
|
-
case
|
|
33
|
+
case 9:
|
|
31
34
|
case "end":
|
|
32
35
|
return _context.stop();
|
|
33
36
|
}
|
|
@@ -369,4 +372,200 @@ describe('VirtualList', function () {
|
|
|
369
372
|
}
|
|
370
373
|
}, _callee8);
|
|
371
374
|
})));
|
|
375
|
+
it('should handle async data correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
|
|
376
|
+
var AsyncDemo, _mount9, instance, container, wrapper, phantom;
|
|
377
|
+
return _regeneratorRuntime.wrap(function _callee9$(_context16) {
|
|
378
|
+
while (1) switch (_context16.prev = _context16.next) {
|
|
379
|
+
case 0:
|
|
380
|
+
AsyncDemo = /*#__PURE__*/function (_Component5) {
|
|
381
|
+
_inheritsLoose(AsyncDemo, _Component5);
|
|
382
|
+
function AsyncDemo() {
|
|
383
|
+
var _context15;
|
|
384
|
+
var _this5;
|
|
385
|
+
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
|
|
386
|
+
args[_key5] = arguments[_key5];
|
|
387
|
+
}
|
|
388
|
+
_this5 = _Component5.call.apply(_Component5, _concatInstanceProperty(_context15 = [this]).call(_context15, args)) || this;
|
|
389
|
+
_this5.VirtualList = VirtualList;
|
|
390
|
+
return _this5;
|
|
391
|
+
}
|
|
392
|
+
AsyncDemo.defaults = function defaults() {
|
|
393
|
+
return {
|
|
394
|
+
list: []
|
|
395
|
+
};
|
|
396
|
+
};
|
|
397
|
+
return AsyncDemo;
|
|
398
|
+
}(Component);
|
|
399
|
+
AsyncDemo.template = "\n const VirtualList = this.VirtualList;\n <VirtualList style=\"height: 300px\">\n <div v-for={this.get('list')} key={$value}>Item {$value}</div>\n </VirtualList>\n ";
|
|
400
|
+
_mount9 = mount(AsyncDemo), instance = _mount9[0];
|
|
401
|
+
_context16.next = 5;
|
|
402
|
+
return wait();
|
|
403
|
+
case 5:
|
|
404
|
+
container = getElement('.k-virtual-container');
|
|
405
|
+
wrapper = getElement('.k-virtual-wrapper');
|
|
406
|
+
phantom = getElement('.k-virtual-phantom'); // check initial state
|
|
407
|
+
expect(wrapper.children.length).to.equal(0);
|
|
408
|
+
expect(phantom.style.height).to.equal('0px');
|
|
409
|
+
// simulate async data loading
|
|
410
|
+
instance.set('list', _Array$from({
|
|
411
|
+
length: 100
|
|
412
|
+
}, function (_, i) {
|
|
413
|
+
return i;
|
|
414
|
+
}));
|
|
415
|
+
_context16.next = 13;
|
|
416
|
+
return wait(50);
|
|
417
|
+
case 13:
|
|
418
|
+
expect(wrapper.children.length).to.be.equal(23);
|
|
419
|
+
expect(phantom.style.height).to.be.equal('1800px');
|
|
420
|
+
// check render content
|
|
421
|
+
expect(wrapper.firstElementChild.textContent).to.equal('Item 0');
|
|
422
|
+
case 16:
|
|
423
|
+
case "end":
|
|
424
|
+
return _context16.stop();
|
|
425
|
+
}
|
|
426
|
+
}, _callee9);
|
|
427
|
+
})));
|
|
428
|
+
it('should handle empty data and re-adding data correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
|
|
429
|
+
var EmptyDemo, _mount10, instance, container, wrapper, phantom, initialHeight, initialChildrenCount;
|
|
430
|
+
return _regeneratorRuntime.wrap(function _callee10$(_context18) {
|
|
431
|
+
while (1) switch (_context18.prev = _context18.next) {
|
|
432
|
+
case 0:
|
|
433
|
+
EmptyDemo = /*#__PURE__*/function (_Component6) {
|
|
434
|
+
_inheritsLoose(EmptyDemo, _Component6);
|
|
435
|
+
function EmptyDemo() {
|
|
436
|
+
var _context17;
|
|
437
|
+
var _this6;
|
|
438
|
+
for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
|
|
439
|
+
args[_key6] = arguments[_key6];
|
|
440
|
+
}
|
|
441
|
+
_this6 = _Component6.call.apply(_Component6, _concatInstanceProperty(_context17 = [this]).call(_context17, args)) || this;
|
|
442
|
+
_this6.VirtualList = VirtualList;
|
|
443
|
+
return _this6;
|
|
444
|
+
}
|
|
445
|
+
EmptyDemo.defaults = function defaults() {
|
|
446
|
+
return {
|
|
447
|
+
list: _Array$from({
|
|
448
|
+
length: 100
|
|
449
|
+
}, function (_, i) {
|
|
450
|
+
return i;
|
|
451
|
+
})
|
|
452
|
+
};
|
|
453
|
+
};
|
|
454
|
+
return EmptyDemo;
|
|
455
|
+
}(Component);
|
|
456
|
+
EmptyDemo.template = "\n const VirtualList = this.VirtualList;\n <VirtualList style=\"height: 300px\">\n <div v-for={this.get('list')} key={$value}>Item {$value}</div>\n </VirtualList>\n ";
|
|
457
|
+
_mount10 = mount(EmptyDemo), instance = _mount10[0];
|
|
458
|
+
_context18.next = 5;
|
|
459
|
+
return wait();
|
|
460
|
+
case 5:
|
|
461
|
+
container = getElement('.k-virtual-container');
|
|
462
|
+
wrapper = getElement('.k-virtual-wrapper');
|
|
463
|
+
phantom = getElement('.k-virtual-phantom'); // record initial state
|
|
464
|
+
initialHeight = phantom.style.height;
|
|
465
|
+
initialChildrenCount = wrapper.children.length; // clear data
|
|
466
|
+
instance.set('list', []);
|
|
467
|
+
_context18.next = 13;
|
|
468
|
+
return wait(50);
|
|
469
|
+
case 13:
|
|
470
|
+
// check empty state
|
|
471
|
+
expect(wrapper.children.length).to.equal(0);
|
|
472
|
+
expect(phantom.style.height).to.equal('0px');
|
|
473
|
+
// re-add data
|
|
474
|
+
instance.set('list', _Array$from({
|
|
475
|
+
length: 50
|
|
476
|
+
}, function (_, i) {
|
|
477
|
+
return i;
|
|
478
|
+
}));
|
|
479
|
+
_context18.next = 18;
|
|
480
|
+
return wait(50);
|
|
481
|
+
case 18:
|
|
482
|
+
// check re-add data state
|
|
483
|
+
expect(wrapper.children.length).to.be.equal(23);
|
|
484
|
+
expect(parseInt(phantom.style.height)).to.be.equal(900);
|
|
485
|
+
expect(wrapper.firstElementChild.textContent).to.equal('Item 0');
|
|
486
|
+
// 滚动测试
|
|
487
|
+
// container.scrollTop = 100;
|
|
488
|
+
// await wait(50);
|
|
489
|
+
// // 检查滚动后的渲染是否正确
|
|
490
|
+
// expect(wrapper.firstElementChild!.textContent).to.not.equal('Item 0');
|
|
491
|
+
case 21:
|
|
492
|
+
case "end":
|
|
493
|
+
return _context18.stop();
|
|
494
|
+
}
|
|
495
|
+
}, _callee10);
|
|
496
|
+
})));
|
|
497
|
+
it('should handle extreme height differences correctly', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
|
|
498
|
+
var ExtremeHeightDemo, _mount11, instance, container, wrapper, phantom, initialItems, initialLength, firstItem, initialTotalHeight, initialAvgHeight, newItems, newLength, firstNewItem, firstVisibleIndex, finalItems, finalFirstItem;
|
|
499
|
+
return _regeneratorRuntime.wrap(function _callee11$(_context20) {
|
|
500
|
+
while (1) switch (_context20.prev = _context20.next) {
|
|
501
|
+
case 0:
|
|
502
|
+
ExtremeHeightDemo = /*#__PURE__*/function (_Component7) {
|
|
503
|
+
_inheritsLoose(ExtremeHeightDemo, _Component7);
|
|
504
|
+
function ExtremeHeightDemo() {
|
|
505
|
+
var _context19;
|
|
506
|
+
var _this7;
|
|
507
|
+
for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
|
|
508
|
+
args[_key7] = arguments[_key7];
|
|
509
|
+
}
|
|
510
|
+
_this7 = _Component7.call.apply(_Component7, _concatInstanceProperty(_context19 = [this]).call(_context19, args)) || this;
|
|
511
|
+
_this7.VirtualList = VirtualList;
|
|
512
|
+
return _this7;
|
|
513
|
+
}
|
|
514
|
+
ExtremeHeightDemo.defaults = function defaults() {
|
|
515
|
+
return {
|
|
516
|
+
list: _Array$from({
|
|
517
|
+
length: 100
|
|
518
|
+
}, function (_, i) {
|
|
519
|
+
return i;
|
|
520
|
+
})
|
|
521
|
+
};
|
|
522
|
+
};
|
|
523
|
+
return ExtremeHeightDemo;
|
|
524
|
+
}(Component);
|
|
525
|
+
ExtremeHeightDemo.template = "\n const VirtualList = this.VirtualList;\n <VirtualList style=\"height: 300px\">\n <div v-for={this.get('list')} \n key={$value} \n style={$value < 5 ? 'height: 100px' : 'height: 30px'}\n >\n Item {$value}\n </div>\n </VirtualList>\n ";
|
|
526
|
+
_mount11 = mount(ExtremeHeightDemo), instance = _mount11[0];
|
|
527
|
+
_context20.next = 5;
|
|
528
|
+
return wait();
|
|
529
|
+
case 5:
|
|
530
|
+
container = getElement('.k-virtual-container');
|
|
531
|
+
wrapper = getElement('.k-virtual-wrapper');
|
|
532
|
+
phantom = getElement('.k-virtual-phantom');
|
|
533
|
+
initialItems = wrapper.children;
|
|
534
|
+
initialLength = initialItems.length; // check first 5 elements height
|
|
535
|
+
firstItem = initialItems[0];
|
|
536
|
+
expect(firstItem.offsetHeight).to.equal(100);
|
|
537
|
+
// record initial average height (calculate by total height and render count)
|
|
538
|
+
initialTotalHeight = parseInt(phantom.style.height);
|
|
539
|
+
initialAvgHeight = initialTotalHeight / 100;
|
|
540
|
+
expect(initialAvgHeight).to.be.greaterThan(30);
|
|
541
|
+
// scroll to small height area
|
|
542
|
+
container.scrollTop = 800;
|
|
543
|
+
_context20.next = 18;
|
|
544
|
+
return wait(50);
|
|
545
|
+
case 18:
|
|
546
|
+
// check new render elements
|
|
547
|
+
newItems = wrapper.children;
|
|
548
|
+
newLength = newItems.length;
|
|
549
|
+
firstNewItem = newItems[0]; // check
|
|
550
|
+
// new render elements should be 30px height
|
|
551
|
+
expect(firstNewItem.offsetHeight).to.equal(30);
|
|
552
|
+
// because average height is smaller, render elements count should be more
|
|
553
|
+
expect(newLength).to.be.greaterThan(initialLength);
|
|
554
|
+
// check scroll position is correct
|
|
555
|
+
firstVisibleIndex = parseInt(firstNewItem.textContent.replace('Item ', ''));
|
|
556
|
+
expect(firstVisibleIndex).to.be.greaterThan(5);
|
|
557
|
+
container.scrollTop = 1200;
|
|
558
|
+
_context20.next = 28;
|
|
559
|
+
return wait();
|
|
560
|
+
case 28:
|
|
561
|
+
finalItems = wrapper.children;
|
|
562
|
+
finalFirstItem = finalItems[0];
|
|
563
|
+
expect(finalFirstItem.offsetHeight).to.equal(30);
|
|
564
|
+
expect(finalItems.length).to.equal(newLength); // render count should be stable
|
|
565
|
+
case 32:
|
|
566
|
+
case "end":
|
|
567
|
+
return _context20.stop();
|
|
568
|
+
}
|
|
569
|
+
}, _callee11);
|
|
570
|
+
})));
|
|
372
571
|
});
|
|
@@ -19,10 +19,11 @@ export default function ($props, $blocks, $__proto__) {
|
|
|
19
19
|
disabled = _ref.disabled;
|
|
20
20
|
if (!disabled) {
|
|
21
21
|
var _context;
|
|
22
|
-
_children = _sliceInstanceProperty(_context = rows.value).call(_context, startIndex, startIndex + length);
|
|
23
22
|
notifyRows(rows.value);
|
|
23
|
+
_children = _sliceInstanceProperty(_context = rows.value).call(_context, startIndex, startIndex + length);
|
|
24
24
|
}
|
|
25
25
|
if (isNullOrUndefined(tagName)) {
|
|
26
|
+
if (!_children.length) return;
|
|
26
27
|
return createFragment(_children, 8 /* ChildrenTypes.HasKeyedChildren */);
|
|
27
28
|
}
|
|
28
29
|
return createVNode(tagName, null, _children);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useInstance, createRef, createFragment } from 'intact';
|
|
1
|
+
import { useInstance, createRef, createFragment, isText } from 'intact';
|
|
2
2
|
export function useRows() {
|
|
3
3
|
var instance = useInstance();
|
|
4
4
|
var rows = createRef([]);
|
|
@@ -8,11 +8,24 @@ export function useRows() {
|
|
|
8
8
|
// convert to array if it has only one child
|
|
9
9
|
var childrenType = vNode.childrenType;
|
|
10
10
|
if (childrenType & 2 /* ChildrenTypes.HasVNodeChildren */) {
|
|
11
|
-
|
|
11
|
+
var _children = vNode.children;
|
|
12
|
+
if (isText(_children)) {
|
|
13
|
+
// ignore void and text vnode
|
|
14
|
+
rows.value = [];
|
|
15
|
+
} else {
|
|
16
|
+
rows.value = [_children];
|
|
17
|
+
}
|
|
12
18
|
} else if (childrenType & 1 /* ChildrenTypes.HasInvalidChildren */) {
|
|
13
19
|
rows.value = [];
|
|
14
20
|
} else {
|
|
15
21
|
rows.value = vNode.children;
|
|
22
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
23
|
+
rows.value.forEach(function (row) {
|
|
24
|
+
if (isText(row)) {
|
|
25
|
+
console.warn('VirtualList: Text node can not been used as children.');
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
16
29
|
}
|
|
17
30
|
});
|
|
18
31
|
return rows;
|
|
@@ -14,44 +14,47 @@ export function useVirtualRows() {
|
|
|
14
14
|
var startIndex = useState(0);
|
|
15
15
|
var length = useState(MIN_LENGTH);
|
|
16
16
|
var calculatedHeight = 0;
|
|
17
|
-
var rowAvgHeight =
|
|
17
|
+
var rowAvgHeight = 30;
|
|
18
18
|
var rows = [];
|
|
19
19
|
function notifyRows(_rows) {
|
|
20
|
+
if (_rows === rows) return;
|
|
20
21
|
var oldRows = rows;
|
|
21
22
|
var oldLength = rows.length;
|
|
22
23
|
rows = _rows;
|
|
23
24
|
// diff oldRows, newRows
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
if (!_rows.length) {
|
|
26
|
+
calculatedHeight = 0;
|
|
27
|
+
rowsHeightMap.clear();
|
|
28
|
+
} else {
|
|
29
|
+
var newKeys = new _Set(_mapInstanceProperty(_rows).call(_rows, function (row) {
|
|
30
|
+
return row.key;
|
|
31
|
+
}));
|
|
32
|
+
for (var i = 0; i < oldLength; i++) {
|
|
33
|
+
var oldKey = oldRows[i].key;
|
|
34
|
+
if (!newKeys.has(oldKey)) {
|
|
35
|
+
var height = rowsHeightMap.get(oldKey);
|
|
36
|
+
if (!isNullOrUndefined(height)) {
|
|
37
|
+
calculatedHeight -= height;
|
|
38
|
+
rowsHeightMap.delete(oldKey);
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
|
-
// update rowAvgHeight
|
|
38
|
-
if (rowsHeightMap.size === 0) {
|
|
39
|
-
rowAvgHeight = calculatedHeight = 0;
|
|
40
|
-
} else {
|
|
41
|
-
rowAvgHeight = calculatedHeight / rowsHeightMap.size;
|
|
42
|
-
}
|
|
43
43
|
if (_rows.length < oldLength) {
|
|
44
44
|
var maxStartIndex = Math.max(0, _rows.length - length.value);
|
|
45
45
|
if (startIndex.value > maxStartIndex) {
|
|
46
46
|
startIndex.set(maxStartIndex);
|
|
47
|
-
// 重新计算位置
|
|
48
47
|
nextTick(function () {
|
|
49
48
|
handleScroll();
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
51
|
}
|
|
52
|
+
instance.forceUpdate(function () {
|
|
53
|
+
calculateRowsHeight();
|
|
54
|
+
});
|
|
53
55
|
}
|
|
54
56
|
function calculateRowsHeight() {
|
|
57
|
+
if (!rows.length) return;
|
|
55
58
|
for (var i = startIndex.value; i < startIndex.value + length.value && i < rows.length; i++) {
|
|
56
59
|
var row = rows[i];
|
|
57
60
|
var key = row.key;
|
|
@@ -64,6 +67,9 @@ export function useVirtualRows() {
|
|
|
64
67
|
}
|
|
65
68
|
// use the average height to estimate the row height
|
|
66
69
|
rowAvgHeight = calculatedHeight / rowsHeightMap.size;
|
|
70
|
+
var containerHeight = containerDom.offsetHeight;
|
|
71
|
+
// calculate the length of rows we should render
|
|
72
|
+
length.set(Math.max(Math.ceil(containerHeight / rowAvgHeight) + BUFFER_SIZE * 2, MIN_LENGTH));
|
|
67
73
|
}
|
|
68
74
|
watchState(startIndex, function () {
|
|
69
75
|
nextTick(calculateRowsHeight);
|
|
@@ -72,10 +78,7 @@ export function useVirtualRows() {
|
|
|
72
78
|
onMounted(function () {
|
|
73
79
|
// get contains height
|
|
74
80
|
containerDom = findDomFromVNode(instance.$lastInput, true);
|
|
75
|
-
var containerHeight = containerDom.offsetHeight;
|
|
76
81
|
calculateRowsHeight();
|
|
77
|
-
// calculate the length of rows we should render
|
|
78
|
-
length.set(Math.max(Math.ceil(containerHeight / rowAvgHeight) + BUFFER_SIZE * 2, MIN_LENGTH));
|
|
79
82
|
containerDom.addEventListener('scroll', handleScroll);
|
|
80
83
|
});
|
|
81
84
|
onUnmounted(function () {
|
package/es/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @king-design v3.5.1
|
|
2
|
+
* @king-design v3.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Kingsoft Cloud
|
|
5
5
|
* Released under the MIT License
|
|
@@ -65,4 +65,4 @@ export * from './components/upload';
|
|
|
65
65
|
export * from './components/view';
|
|
66
66
|
export * from './components/virtualList';
|
|
67
67
|
export * from './components/wave';
|
|
68
|
-
export declare const version = "3.5.1
|
|
68
|
+
export declare const version = "3.5.1";
|
package/es/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @king-design v3.5.1
|
|
2
|
+
* @king-design v3.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Kingsoft Cloud
|
|
5
5
|
* Released under the MIT License
|
|
@@ -66,5 +66,5 @@ export * from './components/upload';
|
|
|
66
66
|
export * from './components/view';
|
|
67
67
|
export * from './components/virtualList';
|
|
68
68
|
export * from './components/wave';
|
|
69
|
-
export var version = '3.5.1
|
|
69
|
+
export var version = '3.5.1';
|
|
70
70
|
/* generate end */
|
|
@@ -16,7 +16,7 @@ var default_1 = /*#__PURE__*/function (_Component) {
|
|
|
16
16
|
var _proto = default_1.prototype;
|
|
17
17
|
_proto.init = function init() {
|
|
18
18
|
var arr = [];
|
|
19
|
-
for (var index = 0; index <
|
|
19
|
+
for (var index = 0; index < 10000; index++) {
|
|
20
20
|
arr.push({
|
|
21
21
|
value: index,
|
|
22
22
|
label: "\u6D4B\u8BD5" + index
|
|
@@ -21,7 +21,7 @@ var Demo = /*#__PURE__*/function (_React$Component) {
|
|
|
21
21
|
var _proto = Demo.prototype;
|
|
22
22
|
_proto.componentDidMount = function componentDidMount() {
|
|
23
23
|
var arr = [];
|
|
24
|
-
for (var index = 0; index <
|
|
24
|
+
for (var index = 0; index < 10000; index++) {
|
|
25
25
|
arr.push({
|
|
26
26
|
value: index,
|
|
27
27
|
label: "\u6D4B\u8BD5" + index
|
|
@@ -41,8 +41,7 @@ var Demo = /*#__PURE__*/function (_React$Component) {
|
|
|
41
41
|
day: day
|
|
42
42
|
});
|
|
43
43
|
},
|
|
44
|
-
virtual: true
|
|
45
|
-
filterable: true
|
|
44
|
+
virtual: true
|
|
46
45
|
}, _mapInstanceProperty(_context2 = this.state.data).call(_context2, function ($value, $key) {
|
|
47
46
|
return /*#__PURE__*/React.createElement(Option, {
|
|
48
47
|
value: $value.value
|
package/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @king-design v3.5.1
|
|
2
|
+
* @king-design v3.5.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Kingsoft Cloud
|
|
5
5
|
* Released under the MIT License
|
|
@@ -70,6 +70,6 @@ export * from './components/view';
|
|
|
70
70
|
export * from './components/virtualList';
|
|
71
71
|
export * from './components/wave';
|
|
72
72
|
|
|
73
|
-
export const version = '3.5.1
|
|
73
|
+
export const version = '3.5.1';
|
|
74
74
|
|
|
75
75
|
/* generate end */
|