@html-next/vertical-collection 4.0.2 → 5.0.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.
Files changed (39) hide show
  1. package/package.json +64 -79
  2. package/{addon → src}/-private/data-view/elements/occluded-content.js +1 -1
  3. package/{addon/-private/data-view → src/-private/data-view/elements}/viewport-container.js +35 -25
  4. package/{addon → src}/-private/data-view/elements/virtual-component.js +13 -5
  5. package/{addon → src}/-private/data-view/radar/dynamic-radar.js +41 -40
  6. package/{addon → src}/-private/data-view/radar/radar.js +211 -112
  7. package/{addon → src}/-private/data-view/radar/static-radar.js +19 -7
  8. package/{addon → src}/-private/data-view/skip-list.js +20 -21
  9. package/{addon → src}/-private/data-view/utils/insert-range-before.js +6 -1
  10. package/{addon → src}/-private/data-view/utils/mutation-checkers.js +12 -4
  11. package/src/-private/data-view/utils/object-at.js +10 -0
  12. package/{addon → src}/-private/data-view/utils/scroll-handler.js +19 -9
  13. package/{addon → src}/-private/data-view/utils/supports-passive.js +2 -2
  14. package/{addon/-private/data-view/elements → src/-private/data-view}/viewport-container.js +35 -25
  15. package/{addon → src}/-private/ember-internals/key-for-item.js +9 -3
  16. package/{addon → src}/-private/index.js +8 -8
  17. package/{addon → src}/-private/utils/element/closest.js +8 -2
  18. package/{addon → src}/-private/utils/element/estimate-element-height.js +11 -5
  19. package/{addon/components/vertical-collection/component.js → src/components/vertical-collection.gjs} +155 -71
  20. package/src/index.js +3 -0
  21. package/{addon/styles/app.css → src/occluded-content.css} +11 -1
  22. package/.github/workflows/ci.yml +0 -102
  23. package/CHANGELOG.md +0 -176
  24. package/README.md +0 -122
  25. package/RELEASE.md +0 -74
  26. package/addon/-private/data-view/utils/object-at.js +0 -7
  27. package/addon/components/vertical-collection/template.hbs +0 -13
  28. package/app/components/vertical-collection.js +0 -1
  29. package/bin/restore-env.sh +0 -1
  30. package/bin/run-tests-with-retry.sh +0 -24
  31. package/bin/stash-env.sh +0 -1
  32. package/config/ember-cli-toolbelts.json +0 -1
  33. package/config/environment.js +0 -5
  34. package/index.js +0 -157
  35. package/vendor/debug.css +0 -62
  36. /package/{addon → src}/-private/data-view/utils/round-to.js +0 -0
  37. /package/{addon → src}/-private/ember-internals/identity.js +0 -0
  38. /package/{addon → src}/-private/utils/document-shim.js +0 -0
  39. /package/{addon → src}/-private/utils/element/get-scaled-client-rect.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@html-next/vertical-collection",
3
- "version": "4.0.2",
3
+ "version": "5.0.0",
4
4
  "description": "infinite-scroll, done right. done.",
5
5
  "keywords": [
6
6
  "occlusion",
@@ -23,6 +23,14 @@
23
23
  "name": "Chris Thoburn (@runspired)",
24
24
  "url": "https://runspired.com"
25
25
  },
26
+ "exports": {
27
+ ".": {
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./-private/index": {
31
+ "default": "./dist/-private/index.js"
32
+ }
33
+ },
26
34
  "contributors": [
27
35
  {
28
36
  "name": "Chris Garrett (@pzuraq)",
@@ -35,94 +43,71 @@
35
43
  "url": "https://github.com/rwwagner90"
36
44
  }
37
45
  ],
38
- "directories": {
39
- "doc": "doc",
40
- "test": "tests"
41
- },
42
- "scripts": {
43
- "build": "ember build --environment=production",
44
- "lint": "npm-run-all --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"",
45
- "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
46
- "lint:js": "eslint . --cache",
47
- "lint:js:fix": "eslint . --fix",
48
- "start": "ember serve",
49
- "test": "npm-run-all lint test:*",
50
- "test:ember": "ember test",
51
- "test:ember-compatibility": "ember try:each"
52
- },
46
+ "files": [
47
+ "src",
48
+ "dist",
49
+ "addon-shim.cjs"
50
+ ],
53
51
  "dependencies": {
54
- "babel6-plugin-strip-class-callcheck": "^6.0.0",
55
- "broccoli-funnel": "^3.0.8",
56
- "broccoli-merge-trees": "^4.2.0",
57
- "broccoli-rollup": "^5.0.0",
58
- "ember-cli-babel": "^7.12.0",
59
- "ember-cli-htmlbars": "^6.0.0",
60
- "ember-cli-version-checker": "^5.1.2",
61
- "ember-raf-scheduler": "^0.3.0"
52
+ "@embroider/addon-shim": "^1.10.2",
53
+ "ember-raf-scheduler": "~0.3.0"
62
54
  },
63
55
  "devDependencies": {
64
- "@ember/optional-features": "^2.0.0",
65
- "@ember/test-helpers": "^2.8.1",
66
- "babel-eslint": "^10.1.0",
67
- "bootstrap": "~3.3.5",
68
- "broccoli-asset-rev": "^3.0.0",
69
- "ember-auto-import": "^2.4.2",
70
- "ember-cli": "~3.28.0",
71
- "ember-cli-dependency-checker": "^3.2.0",
72
- "ember-cli-eslint": "^5.1.0",
73
- "ember-cli-fastboot": "^2.1.3",
74
- "ember-cli-github-pages": "^0.2.2",
75
- "ember-cli-inject-live-reload": "^2.1.0",
76
- "ember-cli-sri": "^2.1.1",
77
- "ember-cli-terser": "^4.0.2",
78
- "ember-code-snippet": "^2.4.1",
79
- "ember-data": "~3.12.0",
80
- "ember-disable-prototype-extensions": "^1.1.3",
81
- "ember-export-application-global": "^2.0.1",
82
- "ember-load-initializers": "^2.1.2",
56
+ "@babel/eslint-parser": "^7.22.10",
57
+ "@ember/test-waiters": "~3.1.0",
58
+ "@embroider/addon-dev": "^8.2.0",
59
+ "@eslint/js": "^9.39.2",
60
+ "@rollup/plugin-babel": "^6.1.0",
61
+ "babel-plugin-ember-template-compilation": "^4.0.0",
62
+ "concurrently": "^8.2.0",
63
+ "ember-inflector": "^6.0.0",
83
64
  "ember-perf-timeline": "^2.0.0",
84
- "ember-qunit": "^5.1.5",
85
- "ember-resolver": "^8.0.2",
86
- "ember-source": "~3.12.0",
87
- "ember-source-channel-url": "^3.0.0",
88
- "ember-try": "^2.0.0",
89
- "eslint": "^7.32.0",
90
- "eslint-plugin-ember": "^6.7.1",
91
- "eslint-plugin-node": "^9.1.0",
92
- "loader.js": "^4.7.0",
93
- "npm-run-all": "^4.1.5",
94
- "qunit": "^2.19.1",
95
- "qunit-dom": "^1.0.0",
96
- "release-it": "^14.2.1",
97
- "release-it-lerna-changelog": "^3.1.0",
98
- "webpack": "^5.0.0"
65
+ "ember-qunit": "^7.0.0",
66
+ "ember-source": "~5.2.0",
67
+ "ember-template-lint": "^5.11.2",
68
+ "eslint": "^9.39.2",
69
+ "eslint-config-prettier": "^10.1.8",
70
+ "eslint-plugin-ember": "^12.7.5",
71
+ "eslint-plugin-import": "^2.32.0",
72
+ "eslint-plugin-n": "^17.23.2",
73
+ "eslint-plugin-prettier": "^5.0.0",
74
+ "eslint-plugin-qunit": "^8.0.0",
75
+ "globals": "^16.5.0",
76
+ "prettier": "^3.0.2",
77
+ "prettier-plugin-ember-template-tag": "^2.0.6",
78
+ "rollup": "^4.56.0",
79
+ "stylelint": "^17.0.0",
80
+ "stylelint-config-standard": "^40.0.0",
81
+ "stylelint-prettier": "^5.0.3"
99
82
  },
100
83
  "engines": {
101
- "node": ">= 14.*"
84
+ "node": ">= 18"
85
+ },
86
+ "volta": {
87
+ "node": "18.20.5",
88
+ "pnpm": "10.10.0"
102
89
  },
103
90
  "publishConfig": {
104
91
  "registry": "https://registry.npmjs.org"
105
92
  },
106
- "ember-addon": {
107
- "configPath": "tests/dummy/config"
93
+ "ember": {
94
+ "edition": "octane"
108
95
  },
109
- "release-it": {
110
- "plugins": {
111
- "release-it-lerna-changelog": {
112
- "infile": "CHANGELOG.md",
113
- "launchEditor": true
114
- }
115
- },
116
- "git": {
117
- "tagName": "v${version}"
118
- },
119
- "github": {
120
- "release": true,
121
- "tokenRef": "GITHUB_AUTH"
122
- }
96
+ "ember-addon": {
97
+ "version": 2,
98
+ "type": "addon",
99
+ "main": "addon-main.cjs",
100
+ "app-js": {}
123
101
  },
124
- "volta": {
125
- "node": "14.18.2",
126
- "yarn": "1.22.17"
102
+ "scripts": {
103
+ "build": "rollup --config",
104
+ "format": "prettier . --cache --write",
105
+ "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"",
106
+ "lint:css": "stylelint \"**/*.css\"",
107
+ "lint:css:fix": "concurrently \"pnpm:lint:css -- --fix\"",
108
+ "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\" && pnpm run format",
109
+ "lint:js": "eslint . --cache",
110
+ "lint:format": "prettier . --cache --check",
111
+ "lint:js:fix": "eslint . --fix"
127
112
  }
128
- }
113
+ }
@@ -1,7 +1,7 @@
1
1
  import { set } from '@ember/object';
2
2
  import { DEBUG } from '@glimmer/env';
3
3
 
4
- import document from '../../utils/document-shim';
4
+ import document from '../../utils/document-shim.js';
5
5
 
6
6
  let OC_IDENTITY = 0;
7
7
 
@@ -13,58 +13,68 @@
13
13
  *
14
14
  */
15
15
  export function ViewportContainer() {
16
-
17
16
  // A bug occurs in Chrome when we reload the browser at a lower
18
17
  // scrollTop, window.scrollY becomes stuck on a single value.
19
18
  Object.defineProperty(this, 'scrollTop', {
20
19
  get() {
21
- return document.body.scrollTop
22
- || document.documentElement.scrollTop;
20
+ return document.body.scrollTop || document.documentElement.scrollTop;
23
21
  },
24
22
  set(v) {
25
23
  document.body.scrollTop = document.documentElement.scrollTop = v;
26
- }
24
+ },
27
25
  });
28
26
 
29
27
  Object.defineProperty(this, 'scrollLeft', {
30
28
  get() {
31
- return window.scrollX
32
- || window.pageXOffset
33
- || document.body.scrollLeft
34
- || document.documentElement.scrollLeft;
29
+ return (
30
+ window.scrollX ||
31
+ window.pageXOffset ||
32
+ document.body.scrollLeft ||
33
+ document.documentElement.scrollLeft
34
+ );
35
35
  },
36
36
  set(v) {
37
- window.scrollX
38
- = window.pageXOffset
39
- = document.body.scrollLeft
40
- = document.documentElement.scrollLeft = v;
41
- }
37
+ window.scrollX =
38
+ window.pageXOffset =
39
+ document.body.scrollLeft =
40
+ document.documentElement.scrollLeft =
41
+ v;
42
+ },
42
43
  });
43
44
 
44
45
  Object.defineProperty(this, 'offsetHeight', {
45
46
  get() {
46
47
  return window.innerHeight;
47
- }
48
+ },
48
49
  });
49
50
  }
50
51
 
51
- ViewportContainer.prototype.addEventListener = function addEventListener(event, handler, options) {
52
+ ViewportContainer.prototype.addEventListener = function addEventListener(
53
+ event,
54
+ handler,
55
+ options,
56
+ ) {
52
57
  return window.addEventListener(event, handler, options);
53
58
  };
54
59
 
55
- ViewportContainer.prototype.removeEventListener = function addEventListener(event, handler, options) {
60
+ ViewportContainer.prototype.removeEventListener = function addEventListener(
61
+ event,
62
+ handler,
63
+ options,
64
+ ) {
56
65
  return window.removeEventListener(event, handler, options);
57
66
  };
58
67
 
59
- ViewportContainer.prototype.getBoundingClientRect = function getBoundingClientRect() {
60
- return {
61
- height: window.innerHeight,
62
- width: window.innerWidth,
63
- top: 0,
64
- left: 0,
65
- right: window.innerWidth,
66
- bottom: window.innerHeight
68
+ ViewportContainer.prototype.getBoundingClientRect =
69
+ function getBoundingClientRect() {
70
+ return {
71
+ height: window.innerHeight,
72
+ width: window.innerWidth,
73
+ top: 0,
74
+ left: 0,
75
+ right: window.innerWidth,
76
+ bottom: window.innerHeight,
77
+ };
67
78
  };
68
- };
69
79
 
70
80
  export default new ViewportContainer();
@@ -2,7 +2,7 @@ import { set } from '@ember/object';
2
2
  import { assert } from '@ember/debug';
3
3
  import { DEBUG } from '@glimmer/env';
4
4
 
5
- import document from '../../utils/document-shim';
5
+ import document from '../../utils/document-shim.js';
6
6
 
7
7
  let VC_IDENTITY = 0;
8
8
 
@@ -16,8 +16,10 @@ export default class VirtualComponent {
16
16
  // We check to see if the document exists in Fastboot. Since RAF won't run in
17
17
  // Fastboot, we'll never have to use these text nodes for measurements, so they
18
18
  // can be empty
19
- this.upperBound = document !== undefined ? document.createTextNode('') : null;
20
- this.lowerBound = document !== undefined ? document.createTextNode('') : null;
19
+ this.upperBound =
20
+ document !== undefined ? document.createTextNode('') : null;
21
+ this.lowerBound =
22
+ document !== undefined ? document.createTextNode('') : null;
21
23
 
22
24
  this.rendered = false;
23
25
 
@@ -55,11 +57,17 @@ export default class VirtualComponent {
55
57
 
56
58
  const text = upperBound.textContent;
57
59
 
58
- assert(`All content inside of vertical-collection must be wrapped in an element. Detected a text node with content: ${text}`, text === '' || text.match(/^\s+$/));
60
+ assert(
61
+ `All content inside of vertical-collection must be wrapped in an element. Detected a text node with content: ${text}`,
62
+ text === '' || text.match(/^\s+$/),
63
+ );
59
64
  }
60
65
  }
61
66
 
62
- assert('Items in a vertical collection require atleast one element in them', top !== Infinity && bottom !== -Infinity);
67
+ assert(
68
+ 'Items in a vertical collection require atleast one element in them',
69
+ top !== Infinity && bottom !== -Infinity,
70
+ );
63
71
 
64
72
  const height = bottom - top;
65
73
 
@@ -1,9 +1,9 @@
1
1
  import { DEBUG } from '@glimmer/env';
2
2
 
3
- import Radar from './radar';
4
- import SkipList from '../skip-list';
5
- import roundTo from '../utils/round-to';
6
- import getScaledClientRect from '../../utils/element/get-scaled-client-rect';
3
+ import Radar from './radar.js';
4
+ import SkipList from '../skip-list.js';
5
+ import roundTo from '../utils/round-to.js';
6
+ import getScaledClientRect from '../../utils/element/get-scaled-client-rect.js';
7
7
 
8
8
  export default class DynamicRadar extends Radar {
9
9
  constructor(parentToken, options) {
@@ -26,9 +26,8 @@ export default class DynamicRadar extends Radar {
26
26
  }
27
27
  }
28
28
 
29
- destroy() {
30
- super.destroy();
31
-
29
+ willDestroy() {
30
+ super.willDestroy();
32
31
  this.skipList = null;
33
32
  }
34
33
 
@@ -66,7 +65,10 @@ export default class DynamicRadar extends Radar {
66
65
 
67
66
  // Create the SkipList only after the estimateHeight has been calculated the first time
68
67
  if (this.skipList === null) {
69
- this.skipList = new SkipList(this.totalItems, this._calculatedEstimateHeight);
68
+ this.skipList = new SkipList(
69
+ this.totalItems,
70
+ this._calculatedEstimateHeight,
71
+ );
70
72
  } else {
71
73
  this.skipList.defaultValue = this._calculatedEstimateHeight;
72
74
  }
@@ -80,7 +82,7 @@ export default class DynamicRadar extends Radar {
80
82
  visibleBottom,
81
83
  totalItems,
82
84
 
83
- _didReset
85
+ _didReset,
84
86
  } = this;
85
87
 
86
88
  if (totalItems === 0) {
@@ -101,8 +103,10 @@ export default class DynamicRadar extends Radar {
101
103
 
102
104
  const { values } = skipList;
103
105
 
104
- let { totalBefore, index: firstVisibleIndex } = this.skipList.find(visibleTop);
105
- let { totalAfter, index: lastVisibleIndex } = this.skipList.find(visibleBottom);
106
+ let { totalBefore, index: firstVisibleIndex } =
107
+ this.skipList.find(visibleTop);
108
+ let { totalAfter, index: lastVisibleIndex } =
109
+ this.skipList.find(visibleBottom);
106
110
 
107
111
  const maxIndex = totalItems - 1;
108
112
 
@@ -127,11 +131,8 @@ export default class DynamicRadar extends Radar {
127
131
  }
128
132
 
129
133
  _calculateScrollDiff() {
130
- const {
131
- firstItemIndex,
132
- _prevFirstVisibleIndex,
133
- _prevFirstItemIndex
134
- } = this;
134
+ const { firstItemIndex, _prevFirstVisibleIndex, _prevFirstItemIndex } =
135
+ this;
135
136
 
136
137
  let beforeVisibleDiff = 0;
137
138
 
@@ -142,7 +143,10 @@ export default class DynamicRadar extends Radar {
142
143
  // (the delta). We want to measure the delta of exactly this number of items, because
143
144
  // items that are after the first visible item should not affect the scroll position,
144
145
  // and neither should items already rendered before the first visible item.
145
- const measureLimit = Math.min(Math.abs(firstItemIndex - _prevFirstItemIndex), _prevFirstVisibleIndex - firstItemIndex);
146
+ const measureLimit = Math.min(
147
+ Math.abs(firstItemIndex - _prevFirstItemIndex),
148
+ _prevFirstVisibleIndex - firstItemIndex,
149
+ );
146
150
 
147
151
  beforeVisibleDiff = Math.round(this._measure(measureLimit));
148
152
  }
@@ -151,10 +155,7 @@ export default class DynamicRadar extends Radar {
151
155
  }
152
156
 
153
157
  _shouldScheduleRerender() {
154
- const {
155
- firstItemIndex,
156
- lastItemIndex
157
- } = this;
158
+ const { firstItemIndex, lastItemIndex } = this;
158
159
 
159
160
  this._updateConstants();
160
161
  this._measure();
@@ -163,7 +164,9 @@ export default class DynamicRadar extends Radar {
163
164
  // case we want to check them _after_ the change.
164
165
  const { firstVisibleIndex, lastVisibleIndex } = this;
165
166
 
166
- return firstVisibleIndex < firstItemIndex || lastVisibleIndex > lastItemIndex;
167
+ return (
168
+ firstVisibleIndex < firstItemIndex || lastVisibleIndex > lastItemIndex
169
+ );
167
170
  }
168
171
 
169
172
  _measure(measureLimit = null) {
@@ -172,12 +175,13 @@ export default class DynamicRadar extends Radar {
172
175
  skipList,
173
176
 
174
177
  _occludedContentBefore,
175
- _transformScale
178
+ _transformScale,
176
179
  } = this;
177
180
 
178
- const numToMeasure = measureLimit !== null
179
- ? Math.min(measureLimit, orderedComponents.length)
180
- : orderedComponents.length;
181
+ const numToMeasure =
182
+ measureLimit !== null
183
+ ? Math.min(measureLimit, orderedComponents.length)
184
+ : orderedComponents.length;
181
185
 
182
186
  let totalDelta = 0;
183
187
 
@@ -186,17 +190,19 @@ export default class DynamicRadar extends Radar {
186
190
  const previousItem = orderedComponents[i - 1];
187
191
  const itemIndex = currentItem.index;
188
192
 
189
- const {
190
- top: currentItemTop,
191
- height: currentItemHeight
192
- } = getScaledClientRect(currentItem, _transformScale);
193
+ const { top: currentItemTop, height: currentItemHeight } =
194
+ getScaledClientRect(currentItem, _transformScale);
193
195
 
194
196
  let margin;
195
197
 
196
198
  if (previousItem !== undefined) {
197
- margin = currentItemTop - getScaledClientRect(previousItem, _transformScale).bottom;
199
+ margin =
200
+ currentItemTop -
201
+ getScaledClientRect(previousItem, _transformScale).bottom;
198
202
  } else {
199
- margin = currentItemTop - getScaledClientRect(_occludedContentBefore, _transformScale).bottom;
203
+ margin =
204
+ currentItemTop -
205
+ getScaledClientRect(_occludedContentBefore, _transformScale).bottom;
200
206
  }
201
207
 
202
208
  const newHeight = roundTo(currentItemHeight + margin);
@@ -215,7 +221,7 @@ export default class DynamicRadar extends Radar {
215
221
  }
216
222
 
217
223
  _didEarthquake(scrollDiff) {
218
- return scrollDiff > (this._minHeight / 2);
224
+ return scrollDiff > this._minHeight / 2;
219
225
  }
220
226
 
221
227
  get total() {
@@ -239,9 +245,7 @@ export default class DynamicRadar extends Radar {
239
245
  }
240
246
 
241
247
  get firstVisibleIndex() {
242
- const {
243
- visibleTop
244
- } = this;
248
+ const { visibleTop } = this;
245
249
 
246
250
  const { index } = this.skipList.find(visibleTop);
247
251
 
@@ -249,10 +253,7 @@ export default class DynamicRadar extends Radar {
249
253
  }
250
254
 
251
255
  get lastVisibleIndex() {
252
- const {
253
- visibleBottom,
254
- totalItems
255
- } = this;
256
+ const { visibleBottom, totalItems } = this;
256
257
 
257
258
  const { index } = this.skipList.find(visibleBottom);
258
259