@html-next/vertical-collection 3.0.0-0 → 3.0.0-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/CHANGELOG.md CHANGED
@@ -1,6 +1,9 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## v3.0.0-1 (2022-03-01)
5
+
6
+
4
7
  ## v3.0.0-0 (2021-12-09)
5
8
 
6
9
  #### 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() {
@@ -105,6 +105,7 @@ export default class Radar {
105
105
 
106
106
  this._componentPool = [];
107
107
  this._prependComponentPool = [];
108
+ this._appendComponentPool = []; // https://github.com/html-next/vertical-collection/issues/296
108
109
 
109
110
  // Boundaries
110
111
  this._occludedContentBefore = new OccludedContent(occlusionTagName);
@@ -223,7 +224,7 @@ export default class Radar {
223
224
  *
224
225
  * @private
225
226
  */
226
- scheduleUpdate(didUpdateItems) {
227
+ scheduleUpdate(didUpdateItems, promiseResolve) {
227
228
  if (didUpdateItems === true) {
228
229
  // Set the update items flag first, in case scheduleUpdate has already been called
229
230
  // but the RAF hasn't yet run
@@ -238,11 +239,11 @@ export default class Radar {
238
239
  this._nextUpdate = null;
239
240
  this._scrollTop = this._scrollContainer.scrollTop;
240
241
 
241
- this.update();
242
+ this.update(promiseResolve);
242
243
  });
243
244
  }
244
245
 
245
- update() {
246
+ update(promiseResolve) {
246
247
  if (this._didUpdateItems === true) {
247
248
  this._determineUpdateType();
248
249
  this._didUpdateItems = false;
@@ -252,7 +253,12 @@ export default class Radar {
252
253
  this._updateIndexes();
253
254
  this._updateVirtualComponents();
254
255
 
255
- this.schedule('measure', this.afterUpdate.bind(this));
256
+ this.schedule('measure', () => {
257
+ if (promiseResolve) {
258
+ promiseResolve();
259
+ }
260
+ this.afterUpdate();
261
+ });
256
262
  }
257
263
 
258
264
  afterUpdate() {
@@ -554,6 +560,8 @@ export default class Radar {
554
560
  const {
555
561
  virtualComponents,
556
562
  _occludedContentAfter,
563
+ _appendComponentPool,
564
+ shouldRecycle,
557
565
  _itemContainer
558
566
  } = this;
559
567
 
@@ -564,6 +572,29 @@ export default class Radar {
564
572
  } else {
565
573
  virtualComponents.insertAt(virtualComponents.get('length') - 1, component);
566
574
  component.rendered = true;
575
+
576
+ // shouldRecycle=false breaks UI when scrolling the elements fast.
577
+ // Reference https://github.com/html-next/vertical-collection/issues/296
578
+ // Components that are both new and appended still need to be rendered at the end because Glimmer.
579
+ // We have to move them _after_ they render, so we schedule that if they exist
580
+ if(!shouldRecycle) {
581
+ _appendComponentPool.unshift(component);
582
+
583
+ if (this._nextLayout === null) {
584
+ this._nextLayout = this.schedule('layout', () => {
585
+ this._nextLayout = null;
586
+
587
+ while (_appendComponentPool.length > 0) {
588
+ const component = _appendComponentPool.pop();
589
+
590
+ // Changes with each inserted component
591
+ const relativeNode = _occludedContentAfter.realUpperBound;
592
+
593
+ insertRangeBefore(this._itemContainer, relativeNode, component.realUpperBound, component.realLowerBound);
594
+ }
595
+ });
596
+ }
597
+ }
567
598
  }
568
599
  }
569
600
 
@@ -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;
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.0.0-1",
4
4
  "description": "infinite-scroll, done right. done.",
5
5
  "keywords": [
6
6
  "occlusion",