@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.
@@ -7,24 +7,24 @@ jobs:
7
7
  test:
8
8
  name: Run Tests
9
9
  runs-on: ubuntu-latest
10
- timeout-minutes: 12
10
+ timeout-minutes: 8
11
11
 
12
12
  steps:
13
13
  - name: Checkout
14
- uses: actions/checkout@v2
14
+ uses: actions/checkout@v3
15
15
 
16
- - name: Use Node 14
17
- uses: actions/setup-node@v2-beta
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
- uses: actions/cache@v2
20
+ id: cache-npm
21
+ uses: actions/cache@v3
23
22
  with:
24
23
  path: '**/node_modules'
25
- key: ci-yarn-${{ hashFiles('**/yarn.lock') }}
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: 14
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@v2
65
+ uses: actions/checkout@v3
64
66
 
65
- - name: Use Node 14
66
- uses: actions/setup-node@v2-beta
67
- with:
68
- node-version: 14.x
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
- uses: actions/cache@v2
74
+ id: cache-npm
75
+ uses: actions/cache@v3
72
76
  with:
73
- path: '**/node_modules'
74
- key: ci-yarn-${{ matrix.ember-version }}-${{ hashFiles('**/yarn.lock') }}
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: Install
77
- run: yarn install --frozen-lockfile --ignore-engines
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: node_modules/.bin/ember try:one ${{ matrix.ember-version }} --skip-cleanup --- bin/run-tests-with-retry.sh
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', this.afterUpdate.bind(this));
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. If we end up using these components again, we'll grab their DOM and put it back
528
- for (let i = 0; i < _componentPool.length; i++) {
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
- insertRangeBefore(this._domPool, null, component.realUpperBound, component.realLowerBound);
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)
@@ -24,4 +24,4 @@ function retry {
24
24
  fi
25
25
  }
26
26
 
27
- retry yarn test:ember
27
+ yarn run ember build && retry yarn run ember test --path=dist
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@html-next/vertical-collection",
3
- "version": "3.0.0-0",
3
+ "version": "3.1.0",
4
4
  "description": "infinite-scroll, done right. done.",
5
5
  "keywords": [
6
6
  "occlusion",