@html-next/vertical-collection 3.0.0-0 → 3.1.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/.github/workflows/ci.yml +35 -20
- package/CHANGELOG.md +21 -0
- package/addon/-private/data-view/radar/dynamic-radar.js +2 -2
- package/addon/-private/data-view/radar/radar.js +48 -8
- package/addon/components/vertical-collection/component.js +60 -1
- package/bin/restore-env.sh +1 -0
- package/bin/run-tests-with-retry.sh +1 -1
- package/bin/stash-env.sh +1 -0
- package/index.js +2 -2
- package/package.json +1 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -7,24 +7,24 @@ jobs:
|
|
|
7
7
|
test:
|
|
8
8
|
name: Run Tests
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
|
-
timeout-minutes:
|
|
10
|
+
timeout-minutes: 8
|
|
11
11
|
|
|
12
12
|
steps:
|
|
13
13
|
- name: Checkout
|
|
14
|
-
uses: actions/checkout@
|
|
14
|
+
uses: actions/checkout@v3
|
|
15
15
|
|
|
16
|
-
- name: Use
|
|
17
|
-
uses:
|
|
18
|
-
with:
|
|
19
|
-
node-version: 14.x
|
|
16
|
+
- name: Use Volta
|
|
17
|
+
uses: volta-cli/action@v1
|
|
20
18
|
|
|
21
19
|
- name: Node Modules Cache
|
|
22
|
-
|
|
20
|
+
id: cache-npm
|
|
21
|
+
uses: actions/cache@v3
|
|
23
22
|
with:
|
|
24
23
|
path: '**/node_modules'
|
|
25
|
-
key: ci-yarn-${{ hashFiles('
|
|
24
|
+
key: ci-yarn-${{ hashFiles('yarn.lock') }}
|
|
26
25
|
|
|
27
26
|
- name: Install Dependencies
|
|
27
|
+
if: steps.cache-npm.outputs.cache-hit != 'true'
|
|
28
28
|
run: yarn install --frozen-lockfile
|
|
29
29
|
|
|
30
30
|
- name: Lint
|
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
test-ember-try:
|
|
39
39
|
name: Run Tests
|
|
40
40
|
runs-on: ubuntu-latest
|
|
41
|
-
timeout-minutes:
|
|
41
|
+
timeout-minutes: 15
|
|
42
42
|
|
|
43
43
|
strategy:
|
|
44
44
|
fail-fast: false
|
|
@@ -53,6 +53,8 @@ jobs:
|
|
|
53
53
|
ember-lts-3.20,
|
|
54
54
|
ember-lts-3.24,
|
|
55
55
|
ember-lts-3.28,
|
|
56
|
+
ember-lts-4.4,
|
|
57
|
+
ember-4.5,
|
|
56
58
|
ember-release,
|
|
57
59
|
ember-beta,
|
|
58
60
|
ember-canary,
|
|
@@ -60,21 +62,34 @@ jobs:
|
|
|
60
62
|
|
|
61
63
|
steps:
|
|
62
64
|
- name: Checkout
|
|
63
|
-
uses: actions/checkout@
|
|
65
|
+
uses: actions/checkout@v3
|
|
64
66
|
|
|
65
|
-
- name: Use
|
|
66
|
-
uses:
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
- name: Use Volta
|
|
68
|
+
uses: volta-cli/action@v1
|
|
69
|
+
|
|
70
|
+
- name: Stash yarn.lock for cache key
|
|
71
|
+
run: cp yarn.lock __cache-key
|
|
69
72
|
|
|
70
73
|
- name: Node Modules Cache
|
|
71
|
-
|
|
74
|
+
id: cache-npm
|
|
75
|
+
uses: actions/cache@v3
|
|
72
76
|
with:
|
|
73
|
-
path:
|
|
74
|
-
|
|
77
|
+
path: |
|
|
78
|
+
node_modules
|
|
79
|
+
package.json
|
|
80
|
+
yarn.lock
|
|
81
|
+
__env
|
|
82
|
+
key: ci-yarn-v3-${{ matrix.ember-version }}-${{ hashFiles('config/ember-try.js', '__cache-key') }}
|
|
83
|
+
restore-keys: |
|
|
84
|
+
ci-yarn-${{ hashFiles('yarn.lock') }}
|
|
85
|
+
|
|
86
|
+
- name: Install Dependencies
|
|
87
|
+
if: steps.cache-npm.outputs.cache-hit != 'true'
|
|
88
|
+
run: yarn install --frozen-lockfile
|
|
75
89
|
|
|
76
|
-
- name:
|
|
77
|
-
|
|
90
|
+
- name: Ember-Try Setup
|
|
91
|
+
if: steps.cache-npm.outputs.cache-hit != 'true'
|
|
92
|
+
run: node_modules/.bin/ember try:one ${{ matrix.ember-version }} --skip-cleanup --- bin/stash-env.sh
|
|
78
93
|
|
|
79
94
|
- name: Run Tests
|
|
80
|
-
run:
|
|
95
|
+
run: . bin/restore-env.sh && bin/run-tests-with-retry.sh
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
## v3.1.0 (2022-08-04)
|
|
6
|
+
|
|
7
|
+
#### :rocket: Enhancement
|
|
8
|
+
* [#380](https://github.com/html-next/vertical-collection/pull/380) fix: enable parallel builds ([@runspired](https://github.com/runspired))
|
|
9
|
+
|
|
10
|
+
#### :bug: Bug Fix
|
|
11
|
+
* [#380](https://github.com/html-next/vertical-collection/pull/380) fix: enable parallel builds ([@runspired](https://github.com/runspired))
|
|
12
|
+
* [#358](https://github.com/html-next/vertical-collection/pull/358) Delete virtual element ([@Atrue](https://github.com/Atrue))
|
|
13
|
+
|
|
14
|
+
#### Committers: 3
|
|
15
|
+
- Chris Thoburn ([@runspired](https://github.com/runspired))
|
|
16
|
+
- Matthew Beale ([@mixonic](https://github.com/mixonic))
|
|
17
|
+
- [@Atrue](https://github.com/Atrue)
|
|
18
|
+
|
|
19
|
+
## v3.0.0 (2022-05-03)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## v3.0.0-1 (2022-03-01)
|
|
23
|
+
|
|
24
|
+
|
|
4
25
|
## v3.0.0-0 (2021-12-09)
|
|
5
26
|
|
|
6
27
|
#### What's new
|
|
@@ -32,14 +32,14 @@ export default class DynamicRadar extends Radar {
|
|
|
32
32
|
this.skipList = null;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
scheduleUpdate(didUpdateItems) {
|
|
35
|
+
scheduleUpdate(didUpdateItems, promiseResolve) {
|
|
36
36
|
// Cancel incremental render check, since we'll be remeasuring anyways
|
|
37
37
|
if (this._nextIncrementalRender !== null) {
|
|
38
38
|
this._nextIncrementalRender.cancel();
|
|
39
39
|
this._nextIncrementalRender = null;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
super.scheduleUpdate(didUpdateItems);
|
|
42
|
+
super.scheduleUpdate(didUpdateItems, promiseResolve);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
afterUpdate() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { A } from '@ember/array';
|
|
2
2
|
import { set, get } from '@ember/object';
|
|
3
3
|
import { assert } from '@ember/debug';
|
|
4
|
+
import { run } from '@ember/runloop';
|
|
4
5
|
import { DEBUG } from '@glimmer/env';
|
|
5
6
|
|
|
6
7
|
import { Token, scheduler } from 'ember-raf-scheduler';
|
|
@@ -105,6 +106,7 @@ export default class Radar {
|
|
|
105
106
|
|
|
106
107
|
this._componentPool = [];
|
|
107
108
|
this._prependComponentPool = [];
|
|
109
|
+
this._appendComponentPool = []; // https://github.com/html-next/vertical-collection/issues/296
|
|
108
110
|
|
|
109
111
|
// Boundaries
|
|
110
112
|
this._occludedContentBefore = new OccludedContent(occlusionTagName);
|
|
@@ -223,7 +225,7 @@ export default class Radar {
|
|
|
223
225
|
*
|
|
224
226
|
* @private
|
|
225
227
|
*/
|
|
226
|
-
scheduleUpdate(didUpdateItems) {
|
|
228
|
+
scheduleUpdate(didUpdateItems, promiseResolve) {
|
|
227
229
|
if (didUpdateItems === true) {
|
|
228
230
|
// Set the update items flag first, in case scheduleUpdate has already been called
|
|
229
231
|
// but the RAF hasn't yet run
|
|
@@ -238,11 +240,11 @@ export default class Radar {
|
|
|
238
240
|
this._nextUpdate = null;
|
|
239
241
|
this._scrollTop = this._scrollContainer.scrollTop;
|
|
240
242
|
|
|
241
|
-
this.update();
|
|
243
|
+
this.update(promiseResolve);
|
|
242
244
|
});
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
update() {
|
|
247
|
+
update(promiseResolve) {
|
|
246
248
|
if (this._didUpdateItems === true) {
|
|
247
249
|
this._determineUpdateType();
|
|
248
250
|
this._didUpdateItems = false;
|
|
@@ -252,7 +254,12 @@ export default class Radar {
|
|
|
252
254
|
this._updateIndexes();
|
|
253
255
|
this._updateVirtualComponents();
|
|
254
256
|
|
|
255
|
-
this.schedule('measure',
|
|
257
|
+
this.schedule('measure', () => {
|
|
258
|
+
if (promiseResolve) {
|
|
259
|
+
promiseResolve();
|
|
260
|
+
}
|
|
261
|
+
this.afterUpdate();
|
|
262
|
+
});
|
|
256
263
|
}
|
|
257
264
|
|
|
258
265
|
afterUpdate() {
|
|
@@ -524,11 +531,19 @@ export default class Radar {
|
|
|
524
531
|
if (_componentPool.length > 0) {
|
|
525
532
|
if (shouldRecycle === true) {
|
|
526
533
|
// Grab the DOM of the remaining components and move it to temporary node disconnected from
|
|
527
|
-
// the body
|
|
528
|
-
|
|
534
|
+
// the body if the item can be reused later otherwise delete the component to avoid virtual re-rendering of the
|
|
535
|
+
// deleted item. If we end up using these components again, we'll grab their DOM and put it back
|
|
536
|
+
for (let i = _componentPool.length - 1; i >= 0; i--) {
|
|
529
537
|
const component = _componentPool[i];
|
|
530
|
-
|
|
531
|
-
|
|
538
|
+
const item = objectAt(items, component.index);
|
|
539
|
+
if (item) {
|
|
540
|
+
insertRangeBefore(this._domPool, null, component.realUpperBound, component.realLowerBound);
|
|
541
|
+
} else {
|
|
542
|
+
run(() => {
|
|
543
|
+
virtualComponents.removeObject(component);
|
|
544
|
+
});
|
|
545
|
+
_componentPool.splice(i, 1);
|
|
546
|
+
}
|
|
532
547
|
}
|
|
533
548
|
} else {
|
|
534
549
|
virtualComponents.removeObjects(_componentPool);
|
|
@@ -554,6 +569,8 @@ export default class Radar {
|
|
|
554
569
|
const {
|
|
555
570
|
virtualComponents,
|
|
556
571
|
_occludedContentAfter,
|
|
572
|
+
_appendComponentPool,
|
|
573
|
+
shouldRecycle,
|
|
557
574
|
_itemContainer
|
|
558
575
|
} = this;
|
|
559
576
|
|
|
@@ -564,6 +581,29 @@ export default class Radar {
|
|
|
564
581
|
} else {
|
|
565
582
|
virtualComponents.insertAt(virtualComponents.get('length') - 1, component);
|
|
566
583
|
component.rendered = true;
|
|
584
|
+
|
|
585
|
+
// shouldRecycle=false breaks UI when scrolling the elements fast.
|
|
586
|
+
// Reference https://github.com/html-next/vertical-collection/issues/296
|
|
587
|
+
// Components that are both new and appended still need to be rendered at the end because Glimmer.
|
|
588
|
+
// We have to move them _after_ they render, so we schedule that if they exist
|
|
589
|
+
if(!shouldRecycle) {
|
|
590
|
+
_appendComponentPool.unshift(component);
|
|
591
|
+
|
|
592
|
+
if (this._nextLayout === null) {
|
|
593
|
+
this._nextLayout = this.schedule('layout', () => {
|
|
594
|
+
this._nextLayout = null;
|
|
595
|
+
|
|
596
|
+
while (_appendComponentPool.length > 0) {
|
|
597
|
+
const component = _appendComponentPool.pop();
|
|
598
|
+
|
|
599
|
+
// Changes with each inserted component
|
|
600
|
+
const relativeNode = _occludedContentAfter.realUpperBound;
|
|
601
|
+
|
|
602
|
+
insertRangeBefore(this._itemContainer, relativeNode, component.realUpperBound, component.realLowerBound);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
567
607
|
}
|
|
568
608
|
}
|
|
569
609
|
|
|
@@ -200,6 +200,24 @@ const VerticalCollection = Component.extend({
|
|
|
200
200
|
}
|
|
201
201
|
},
|
|
202
202
|
|
|
203
|
+
/* Public API Methods
|
|
204
|
+
@index => number
|
|
205
|
+
This will return offset height of the indexed item.
|
|
206
|
+
*/
|
|
207
|
+
scrollToItem(index) {
|
|
208
|
+
const { _radar } = this;
|
|
209
|
+
// Getting the offset height from Radar
|
|
210
|
+
let scrollTop = _radar.getOffsetForIndex(index);
|
|
211
|
+
_radar._scrollContainer.scrollTop = scrollTop;
|
|
212
|
+
// To scroll exactly to specified index, we are changing the prevIndex values to specified index
|
|
213
|
+
_radar._prevFirstVisibleIndex = _radar._prevFirstItemIndex = index;
|
|
214
|
+
// Components will be rendered after schedule 'measure' inside 'update' method.
|
|
215
|
+
// In our case, we need to focus the element after component is rendered. So passing the promise.
|
|
216
|
+
return new Promise ((resolve) => {
|
|
217
|
+
_radar.scheduleUpdate(false, resolve);
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
|
|
203
221
|
// –––––––––––––– Setup/Teardown
|
|
204
222
|
didInsertElement() {
|
|
205
223
|
this.schedule('sync', () => {
|
|
@@ -210,6 +228,10 @@ const VerticalCollection = Component.extend({
|
|
|
210
228
|
willDestroy() {
|
|
211
229
|
this.token.cancel();
|
|
212
230
|
this._radar.destroy();
|
|
231
|
+
let registerAPI = this.get('registerAPI');
|
|
232
|
+
if (registerAPI) {
|
|
233
|
+
registerAPI(null);
|
|
234
|
+
}
|
|
213
235
|
clearTimeout(this._nextSendActions);
|
|
214
236
|
},
|
|
215
237
|
|
|
@@ -280,6 +302,43 @@ const VerticalCollection = Component.extend({
|
|
|
280
302
|
}
|
|
281
303
|
};
|
|
282
304
|
}
|
|
305
|
+
|
|
306
|
+
/* Public methods to Expose to parent
|
|
307
|
+
|
|
308
|
+
Usage:
|
|
309
|
+
|
|
310
|
+
Template:
|
|
311
|
+
|
|
312
|
+
{{vertical-collection registerAPI=(action "registerAPI")}}
|
|
313
|
+
|
|
314
|
+
Component:
|
|
315
|
+
|
|
316
|
+
export default Component.extend({
|
|
317
|
+
actions: {
|
|
318
|
+
registerAPI(api) {
|
|
319
|
+
this.set('collectionAPI', api);
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
scrollToItem() {
|
|
323
|
+
let collectionAPI = this.get('collectionAPI');
|
|
324
|
+
collectionAPI.scrollToItem(index);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
Need to pass this property in the vertical-collection template
|
|
329
|
+
Listen in the component actions and do your custom logic
|
|
330
|
+
This API will have below methods.
|
|
331
|
+
1. scrollToItem
|
|
332
|
+
*/
|
|
333
|
+
|
|
334
|
+
let registerAPI = get(this, 'registerAPI');
|
|
335
|
+
if (registerAPI) {
|
|
336
|
+
/* List of methods to be exposed to public should be added here */
|
|
337
|
+
let publicAPI = {
|
|
338
|
+
scrollToItem: this.scrollToItem.bind(this)
|
|
339
|
+
};
|
|
340
|
+
registerAPI(publicAPI);
|
|
341
|
+
}
|
|
283
342
|
}
|
|
284
343
|
});
|
|
285
344
|
|
|
@@ -307,4 +366,4 @@ function calculateStartingIndex(items, idForFirstItem, key, renderFromLast) {
|
|
|
307
366
|
return startingIndex;
|
|
308
367
|
}
|
|
309
368
|
|
|
310
|
-
export default VerticalCollection;
|
|
369
|
+
export default VerticalCollection;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export EMBER_OPTIONAL_FEATURES=$(cat __env)
|
package/bin/stash-env.sh
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
printf '%s' "$EMBER_OPTIONAL_FEATURES" > __env
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const StripClassCallCheckPlugin = require('babel6-plugin-strip-class-callcheck');
|
|
3
|
+
const StripClassCallCheckPlugin = require.resolve('babel6-plugin-strip-class-callcheck');
|
|
4
4
|
const Funnel = require('broccoli-funnel');
|
|
5
5
|
const Rollup = require('broccoli-rollup');
|
|
6
6
|
const merge = require('broccoli-merge-trees');
|
|
@@ -138,7 +138,7 @@ module.exports = {
|
|
|
138
138
|
const opts = {
|
|
139
139
|
loose: true,
|
|
140
140
|
plugins,
|
|
141
|
-
postTransformPlugins: [StripClassCallCheckPlugin]
|
|
141
|
+
postTransformPlugins: [[StripClassCallCheckPlugin, {}]]
|
|
142
142
|
};
|
|
143
143
|
|
|
144
144
|
return opts;
|