@html-next/vertical-collection 3.1.0 → 4.0.0-beta.2
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 +18 -11
- package/CHANGELOG.md +15 -0
- package/README.md +16 -15
- package/RELEASE.md +14 -0
- package/addon/-private/data-view/elements/occluded-content.js +2 -9
- package/addon/-private/data-view/elements/virtual-component.js +2 -9
- package/addon/-private/data-view/radar/radar.js +5 -2
- package/addon/components/vertical-collection/component.js +270 -31
- package/bin/run-tests-with-retry.sh +1 -4
- package/index.js +4 -46
- package/package.json +11 -12
- package/addon/-debug/edge-visualization/debug-mixin.js +0 -93
- package/addon/-debug/edge-visualization/visualization.js +0 -134
- package/addon/-debug/index.js +0 -4
- package/addon/-debug/utils/validate-css.js +0 -12
- package/addon/-debug/utils/validate-rect.js +0 -13
- package/addon/-debug/utils/validate-style.js +0 -23
- package/app/initializers/debug.js +0 -6
package/.github/workflows/ci.yml
CHANGED
|
@@ -7,7 +7,7 @@ jobs:
|
|
|
7
7
|
test:
|
|
8
8
|
name: Run Tests
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
|
-
timeout-minutes:
|
|
10
|
+
timeout-minutes: 12
|
|
11
11
|
|
|
12
12
|
steps:
|
|
13
13
|
- name: Checkout
|
|
@@ -30,31 +30,31 @@ jobs:
|
|
|
30
30
|
- name: Lint
|
|
31
31
|
run: yarn lint
|
|
32
32
|
|
|
33
|
+
- name: Run Build
|
|
34
|
+
run: . bin/restore-env.sh && yarn run ember build
|
|
35
|
+
|
|
33
36
|
- name: Run Tests
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
uses: nick-fields/retry@v2
|
|
38
|
+
with:
|
|
39
|
+
timeout_minutes: 2
|
|
40
|
+
max_attempts: 5
|
|
41
|
+
command: . bin/restore-env.sh && CI=true yarn run ember test --path=dist
|
|
37
42
|
|
|
38
43
|
test-ember-try:
|
|
39
44
|
name: Run Tests
|
|
40
45
|
runs-on: ubuntu-latest
|
|
41
|
-
timeout-minutes:
|
|
46
|
+
timeout-minutes: 12
|
|
42
47
|
|
|
43
48
|
strategy:
|
|
44
49
|
fail-fast: false
|
|
45
50
|
matrix:
|
|
46
51
|
ember-version:
|
|
47
52
|
[
|
|
48
|
-
ember-lts-2.18,
|
|
49
|
-
ember-lts-3.4,
|
|
50
|
-
ember-lts-3.8,
|
|
51
53
|
ember-lts-3.12,
|
|
52
54
|
ember-lts-3.16,
|
|
53
55
|
ember-lts-3.20,
|
|
54
|
-
ember-lts-3.24,
|
|
55
56
|
ember-lts-3.28,
|
|
56
57
|
ember-lts-4.4,
|
|
57
|
-
ember-4.5,
|
|
58
58
|
ember-release,
|
|
59
59
|
ember-beta,
|
|
60
60
|
ember-canary,
|
|
@@ -91,5 +91,12 @@ jobs:
|
|
|
91
91
|
if: steps.cache-npm.outputs.cache-hit != 'true'
|
|
92
92
|
run: node_modules/.bin/ember try:one ${{ matrix.ember-version }} --skip-cleanup --- bin/stash-env.sh
|
|
93
93
|
|
|
94
|
+
- name: Run Build
|
|
95
|
+
run: . bin/restore-env.sh && yarn run ember build
|
|
96
|
+
|
|
94
97
|
- name: Run Tests
|
|
95
|
-
|
|
98
|
+
uses: nick-fields/retry@v2
|
|
99
|
+
with:
|
|
100
|
+
timeout_minutes: 2
|
|
101
|
+
max_attempts: 5
|
|
102
|
+
command: . bin/restore-env.sh && CI=true yarn run ember test --path=dist
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@ Changelog
|
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## v4.0.0-beta.2 (2022-09-08)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## v4.0.0-beta.1 (2022-09-07)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## v4.0.0-beta.0 (2022-08-28)
|
|
12
|
+
|
|
13
|
+
* Drop support for Ember versions prior to 3.12
|
|
14
|
+
* Drop support for Ember CLI 2.x
|
|
15
|
+
* Adopt native getters
|
|
16
|
+
* Adopt angle bracket invocation
|
|
17
|
+
* Drop positional param argument for `item`
|
|
18
|
+
|
|
19
|
+
|
|
5
20
|
## v3.1.0 (2022-08-04)
|
|
6
21
|
|
|
7
22
|
#### :rocket: Enhancement
|
package/README.md
CHANGED
|
@@ -30,24 +30,24 @@ ember install @html-next/vertical-collection
|
|
|
30
30
|
## Usage
|
|
31
31
|
|
|
32
32
|
```htmlbars
|
|
33
|
-
|
|
34
|
-
items
|
|
35
|
-
tagName=
|
|
36
|
-
estimateHeight=50
|
|
37
|
-
staticHeight=false
|
|
38
|
-
bufferSize=1
|
|
39
|
-
renderAll=false
|
|
40
|
-
renderFromLast=false
|
|
41
|
-
idForFirstItem=idForFirstItem
|
|
42
|
-
firstReached=
|
|
43
|
-
lastReached=
|
|
44
|
-
firstVisibleChanged=
|
|
45
|
-
lastVisibleChanged=
|
|
46
|
-
as |item i
|
|
33
|
+
<VerticalCollection
|
|
34
|
+
@items={{items}}
|
|
35
|
+
@tagName="ul"
|
|
36
|
+
@estimateHeight={{50}}
|
|
37
|
+
@staticHeight={{false}}
|
|
38
|
+
@bufferSize={{1}}
|
|
39
|
+
@renderAll={{false}}
|
|
40
|
+
@renderFromLast={{false}}
|
|
41
|
+
@idForFirstItem={{idForFirstItem}}
|
|
42
|
+
@firstReached={{firstReachedCallback}}
|
|
43
|
+
@lastReached={{lastReachedCallback}}
|
|
44
|
+
@firstVisibleChanged={{firstVisibleChangedCallback}}
|
|
45
|
+
@lastVisibleChanged={{lastVisibleChangedCallback}}
|
|
46
|
+
as |item i|>
|
|
47
47
|
<li>
|
|
48
48
|
{{item.number}} {{i}}
|
|
49
49
|
</li>
|
|
50
|
-
|
|
50
|
+
</VerticalCollection>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
### Actions
|
|
@@ -67,6 +67,7 @@ ember install @html-next/vertical-collection
|
|
|
67
67
|
| `^v1.x.x` | `v1.12.0 - v3.8.x` | `?` |
|
|
68
68
|
| `^v2.x.x` | `v2.8.0 - v3.26.x` | `v12 - ?` |
|
|
69
69
|
| `^v3.x.x` | `v2.18.0+` | `v14+` |
|
|
70
|
+
| `^v4.x.x` | `v3.12.0+` | `v14+` |
|
|
70
71
|
|
|
71
72
|
## Support, Questions, Collaboration
|
|
72
73
|
|
package/RELEASE.md
CHANGED
|
@@ -58,3 +58,17 @@ release process. It will prompt you to to choose the version number after which
|
|
|
58
58
|
you will have the chance to hand tweak the changelog to be used (for the
|
|
59
59
|
`CHANGELOG.md` and GitHub release), then `release-it` continues on to tagging,
|
|
60
60
|
pushing the tag and commits, etc.
|
|
61
|
+
|
|
62
|
+
To start a prerelease branch for a new major use:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
npx release-it major --preRelease=beta
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
On subsequent prerelease run:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
npx release-it --preRelease
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For more guidance see https://github.com/release-it/release-it/blob/master/docs/pre-releases.md
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { set } from '@ember/object';
|
|
2
2
|
import { DEBUG } from '@glimmer/env';
|
|
3
|
-
import { IS_GLIMMER_2, gte as emberVersionGTE } from 'ember-compatibility-helpers';
|
|
4
3
|
|
|
5
4
|
import document from '../../utils/document-shim';
|
|
6
5
|
|
|
@@ -27,12 +26,6 @@ export default class OccludedContent {
|
|
|
27
26
|
this.isOccludedContent = true;
|
|
28
27
|
this.rendered = false;
|
|
29
28
|
|
|
30
|
-
if (!emberVersionGTE('3.0.0')) {
|
|
31
|
-
// In older versions of Ember, binding anything on an object in the template
|
|
32
|
-
// adds observers which creates __ember_meta__
|
|
33
|
-
this.__ember_meta__ = null; // eslint-disable-line camelcase
|
|
34
|
-
}
|
|
35
|
-
|
|
36
29
|
if (DEBUG) {
|
|
37
30
|
Object.preventExtensions(this);
|
|
38
31
|
}
|
|
@@ -57,11 +50,11 @@ export default class OccludedContent {
|
|
|
57
50
|
}
|
|
58
51
|
|
|
59
52
|
get realUpperBound() {
|
|
60
|
-
return
|
|
53
|
+
return this.upperBound;
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
get realLowerBound() {
|
|
64
|
-
return
|
|
57
|
+
return this.lowerBound;
|
|
65
58
|
}
|
|
66
59
|
|
|
67
60
|
get parentNode() {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { set } from '@ember/object';
|
|
2
2
|
import { assert } from '@ember/debug';
|
|
3
3
|
import { DEBUG } from '@glimmer/env';
|
|
4
|
-
import { IS_GLIMMER_2, gte as emberVersionGTE } from 'ember-compatibility-helpers';
|
|
5
4
|
|
|
6
5
|
import document from '../../utils/document-shim';
|
|
7
6
|
|
|
@@ -22,23 +21,17 @@ export default class VirtualComponent {
|
|
|
22
21
|
|
|
23
22
|
this.rendered = false;
|
|
24
23
|
|
|
25
|
-
if (!emberVersionGTE('3.0.0')) {
|
|
26
|
-
// In older versions of Ember, binding anything on an object in the template
|
|
27
|
-
// adds observers which creates __ember_meta__
|
|
28
|
-
this.__ember_meta__ = null; // eslint-disable-line camelcase
|
|
29
|
-
}
|
|
30
|
-
|
|
31
24
|
if (DEBUG) {
|
|
32
25
|
Object.preventExtensions(this);
|
|
33
26
|
}
|
|
34
27
|
}
|
|
35
28
|
|
|
36
29
|
get realUpperBound() {
|
|
37
|
-
return
|
|
30
|
+
return this.upperBound;
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
get realLowerBound() {
|
|
41
|
-
return
|
|
34
|
+
return this.lowerBound;
|
|
42
35
|
}
|
|
43
36
|
|
|
44
37
|
getBoundingClientRect() {
|
|
@@ -539,6 +539,9 @@ export default class Radar {
|
|
|
539
539
|
if (item) {
|
|
540
540
|
insertRangeBefore(this._domPool, null, component.realUpperBound, component.realLowerBound);
|
|
541
541
|
} else {
|
|
542
|
+
// Insert the virtual component bound back to make sure Glimmer is
|
|
543
|
+
// not confused about the state of the DOM.
|
|
544
|
+
insertRangeBefore(this._itemContainer, null, component.realUpperBound, component.realLowerBound);
|
|
542
545
|
run(() => {
|
|
543
546
|
virtualComponents.removeObject(component);
|
|
544
547
|
});
|
|
@@ -579,7 +582,7 @@ export default class Radar {
|
|
|
579
582
|
if (component.rendered === true) {
|
|
580
583
|
insertRangeBefore(_itemContainer, relativeNode, component.realUpperBound, component.realLowerBound);
|
|
581
584
|
} else {
|
|
582
|
-
virtualComponents.insertAt(virtualComponents.
|
|
585
|
+
virtualComponents.insertAt(virtualComponents.length - 1, component);
|
|
583
586
|
component.rendered = true;
|
|
584
587
|
|
|
585
588
|
// shouldRecycle=false breaks UI when scrolling the elements fast.
|
|
@@ -620,7 +623,7 @@ export default class Radar {
|
|
|
620
623
|
if (component.rendered === true) {
|
|
621
624
|
insertRangeBefore(_itemContainer, relativeNode, component.realUpperBound, component.realLowerBound);
|
|
622
625
|
} else {
|
|
623
|
-
virtualComponents.insertAt(virtualComponents.
|
|
626
|
+
virtualComponents.insertAt(virtualComponents.length - 1, component);
|
|
624
627
|
component.rendered = true;
|
|
625
628
|
|
|
626
629
|
// Components that are both new and prepended still need to be rendered at the end because Glimmer.
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { DEBUG } from '@glimmer/env';
|
|
2
|
+
import { assert } from '@ember/debug';
|
|
3
|
+
|
|
1
4
|
import { empty, readOnly } from '@ember/object/computed';
|
|
2
5
|
|
|
3
6
|
import Component from '@ember/component';
|
|
4
7
|
import { get, computed } from '@ember/object';
|
|
5
8
|
import { run } from '@ember/runloop';
|
|
6
9
|
import layout from './template';
|
|
10
|
+
import { ViewportContainer } from '../../-private';
|
|
7
11
|
|
|
8
12
|
import { scheduler, Token } from 'ember-raf-scheduler';
|
|
9
13
|
|
|
@@ -14,6 +18,166 @@ import {
|
|
|
14
18
|
objectAt
|
|
15
19
|
} from '../../-private';
|
|
16
20
|
|
|
21
|
+
/*
|
|
22
|
+
* BEGIN DEBUG HELPERS
|
|
23
|
+
*
|
|
24
|
+
* These methods and the Visualization class are used by DEBUG code paths.
|
|
25
|
+
*/
|
|
26
|
+
function isNonZero(value) {
|
|
27
|
+
let int = parseInt(value, 10);
|
|
28
|
+
let float = parseFloat(value);
|
|
29
|
+
|
|
30
|
+
return !isNaN(int) && (int !== 0 || float !== 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function hasStyleValue(styles, key, value) {
|
|
34
|
+
return styles[key] === value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function hasStyleWithNonZeroValue(styles, key) {
|
|
38
|
+
return isNonZero(styles[key]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function styleIsOneOf(styles, key, values) {
|
|
42
|
+
return styles[key] && values.indexOf(styles[key]) !== -1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function applyVerticalStyles(element, geography) {
|
|
46
|
+
element.style.height = `${geography.height}px`;
|
|
47
|
+
element.style.top = `${geography.top}px`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class Visualization {
|
|
51
|
+
constructor(radar) {
|
|
52
|
+
this.radar = radar;
|
|
53
|
+
this.satellites = [];
|
|
54
|
+
this.cache = [];
|
|
55
|
+
|
|
56
|
+
this.wrapper = document.createElement('div');
|
|
57
|
+
this.wrapper.className = 'vertical-collection-visual-debugger';
|
|
58
|
+
|
|
59
|
+
this.container = document.createElement('div');
|
|
60
|
+
this.container.className = 'vc_visualization-container';
|
|
61
|
+
this.wrapper.appendChild(this.container);
|
|
62
|
+
|
|
63
|
+
this.itemContainer = document.createElement('div');
|
|
64
|
+
this.itemContainer.className = 'vc_visualization-item-container';
|
|
65
|
+
this.container.appendChild(this.itemContainer);
|
|
66
|
+
|
|
67
|
+
this.scrollContainer = document.createElement('div');
|
|
68
|
+
this.scrollContainer.className = 'vc_visualization-scroll-container';
|
|
69
|
+
this.container.appendChild(this.scrollContainer);
|
|
70
|
+
|
|
71
|
+
this.screen = document.createElement('div');
|
|
72
|
+
this.screen.className = 'vc_visualization-screen';
|
|
73
|
+
this.container.appendChild(this.screen);
|
|
74
|
+
|
|
75
|
+
document.body.appendChild(this.wrapper);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
render() {
|
|
79
|
+
this.styleViewport();
|
|
80
|
+
this.updateSatellites();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
styleViewport() {
|
|
84
|
+
const { _scrollContainer } = this.radar;
|
|
85
|
+
this.container.style.height = `${_scrollContainer.getBoundingClientRect().height}px`;
|
|
86
|
+
|
|
87
|
+
applyVerticalStyles(this.scrollContainer, _scrollContainer.getBoundingClientRect());
|
|
88
|
+
applyVerticalStyles(this.screen, ViewportContainer.getBoundingClientRect());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
makeSatellite() {
|
|
92
|
+
let satellite;
|
|
93
|
+
|
|
94
|
+
if (this.cache.length) {
|
|
95
|
+
satellite = this.cache.pop();
|
|
96
|
+
} else {
|
|
97
|
+
satellite = document.createElement('div');
|
|
98
|
+
satellite.className = 'vc_visualization-virtual-component';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.satellites.push(satellite);
|
|
102
|
+
this.itemContainer.append(satellite);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
updateSatellites() {
|
|
106
|
+
const { satellites: sats } = this;
|
|
107
|
+
let {
|
|
108
|
+
firstItemIndex,
|
|
109
|
+
lastItemIndex,
|
|
110
|
+
|
|
111
|
+
totalItems,
|
|
112
|
+
|
|
113
|
+
totalBefore,
|
|
114
|
+
totalAfter,
|
|
115
|
+
skipList,
|
|
116
|
+
_calculatedEstimateHeight
|
|
117
|
+
} = this.radar;
|
|
118
|
+
|
|
119
|
+
const isDynamic = !!skipList;
|
|
120
|
+
const itemHeights = isDynamic && skipList.values;
|
|
121
|
+
|
|
122
|
+
const firstVisualizedIndex = Math.max(firstItemIndex - 10, 0);
|
|
123
|
+
const lastVisualizedIndex = Math.min(lastItemIndex + 10, totalItems - 1);
|
|
124
|
+
|
|
125
|
+
const lengthWithBuffer = lastVisualizedIndex - firstVisualizedIndex + 1;
|
|
126
|
+
const isShrinking = sats.length > lengthWithBuffer;
|
|
127
|
+
|
|
128
|
+
while (sats.length !== lengthWithBuffer) {
|
|
129
|
+
if (isShrinking) {
|
|
130
|
+
const satellite = sats.pop();
|
|
131
|
+
|
|
132
|
+
satellite.parentNode.removeChild(satellite);
|
|
133
|
+
this.cache.push(satellite);
|
|
134
|
+
} else {
|
|
135
|
+
this.makeSatellite();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
for (let itemIndex = firstVisualizedIndex, i = 0; itemIndex <= lastVisualizedIndex; itemIndex++, i++) {
|
|
140
|
+
const element = sats[i];
|
|
141
|
+
|
|
142
|
+
const itemHeight = isDynamic ? itemHeights[itemIndex] : _calculatedEstimateHeight;
|
|
143
|
+
|
|
144
|
+
element.style.height = `${itemHeight}px`;
|
|
145
|
+
element.setAttribute('index', String(itemIndex));
|
|
146
|
+
element.innerText = String(itemIndex);
|
|
147
|
+
|
|
148
|
+
if (itemIndex < firstItemIndex) {
|
|
149
|
+
element.classList.add('culled');
|
|
150
|
+
totalBefore -= itemHeight;
|
|
151
|
+
} else if (itemIndex > lastItemIndex) {
|
|
152
|
+
element.classList.add('culled');
|
|
153
|
+
totalAfter -= itemHeight;
|
|
154
|
+
} else {
|
|
155
|
+
element.classList.remove('culled');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.itemContainer.style.paddingTop = `${totalBefore}px`;
|
|
160
|
+
this.itemContainer.style.paddingBottom = `${totalAfter}px`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
destroy() {
|
|
164
|
+
this.wrapper.parentNode.removeChild(this.wrapper);
|
|
165
|
+
this.wrapper = null;
|
|
166
|
+
this.radar = null;
|
|
167
|
+
this.component = null;
|
|
168
|
+
this.satellites.forEach((satellite) => {
|
|
169
|
+
if (satellite.parentNode) {
|
|
170
|
+
satellite.parentNode.removeChild(satellite);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
this.satellites = null;
|
|
174
|
+
this.cache = null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/*
|
|
178
|
+
* END DEBUG HELPERS
|
|
179
|
+
*/
|
|
180
|
+
|
|
17
181
|
const VerticalCollection = Component.extend({
|
|
18
182
|
layout,
|
|
19
183
|
|
|
@@ -43,7 +207,7 @@ const VerticalCollection = Component.extend({
|
|
|
43
207
|
|
|
44
208
|
/**
|
|
45
209
|
* List of objects to svelte-render.
|
|
46
|
-
* Can be called like
|
|
210
|
+
* Can be called like `<VerticalCollection @items={{itemsArray}} />`.
|
|
47
211
|
*
|
|
48
212
|
* @property items
|
|
49
213
|
* @type Array
|
|
@@ -155,12 +319,12 @@ const VerticalCollection = Component.extend({
|
|
|
155
319
|
virtualComponents: computed('items.[]', 'renderAll', 'estimateHeight', 'bufferSize', function() {
|
|
156
320
|
const { _radar } = this;
|
|
157
321
|
|
|
158
|
-
const items = this.
|
|
322
|
+
const items = this.items;
|
|
159
323
|
|
|
160
324
|
_radar.items = items === null || items === undefined ? [] : items;
|
|
161
|
-
_radar.estimateHeight = this.
|
|
162
|
-
_radar.renderAll = this.
|
|
163
|
-
_radar.bufferSize = this.
|
|
325
|
+
_radar.estimateHeight = this.estimateHeight;
|
|
326
|
+
_radar.renderAll = this.renderAll;
|
|
327
|
+
_radar.bufferSize = this.bufferSize;
|
|
164
328
|
|
|
165
329
|
_radar.scheduleUpdate(true);
|
|
166
330
|
|
|
@@ -179,8 +343,8 @@ const VerticalCollection = Component.extend({
|
|
|
179
343
|
this._nextSendActions = null;
|
|
180
344
|
|
|
181
345
|
run(() => {
|
|
182
|
-
const items = this.
|
|
183
|
-
const keyPath = this.
|
|
346
|
+
const items = this.items;
|
|
347
|
+
const keyPath = this.key;
|
|
184
348
|
|
|
185
349
|
this._scheduledActions.forEach(([action, index]) => {
|
|
186
350
|
const item = objectAt(items, index);
|
|
@@ -200,7 +364,7 @@ const VerticalCollection = Component.extend({
|
|
|
200
364
|
}
|
|
201
365
|
},
|
|
202
366
|
|
|
203
|
-
/* Public API Methods
|
|
367
|
+
/* Public API Methods
|
|
204
368
|
@index => number
|
|
205
369
|
This will return offset height of the indexed item.
|
|
206
370
|
*/
|
|
@@ -228,11 +392,19 @@ const VerticalCollection = Component.extend({
|
|
|
228
392
|
willDestroy() {
|
|
229
393
|
this.token.cancel();
|
|
230
394
|
this._radar.destroy();
|
|
231
|
-
let registerAPI = this.
|
|
395
|
+
let registerAPI = this.registerAPI;
|
|
232
396
|
if (registerAPI) {
|
|
233
397
|
registerAPI(null);
|
|
234
398
|
}
|
|
235
399
|
clearTimeout(this._nextSendActions);
|
|
400
|
+
|
|
401
|
+
if (DEBUG) {
|
|
402
|
+
if (this.__visualization) {
|
|
403
|
+
console.info('destroying visualization'); // eslint-disable-line no-console
|
|
404
|
+
this.__visualization.destroy();
|
|
405
|
+
this.__visualization = null;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
236
408
|
},
|
|
237
409
|
|
|
238
410
|
init() {
|
|
@@ -241,19 +413,20 @@ const VerticalCollection = Component.extend({
|
|
|
241
413
|
this.token = new Token();
|
|
242
414
|
const RadarClass = this.staticHeight ? StaticRadar : DynamicRadar;
|
|
243
415
|
|
|
244
|
-
const items = this.
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
416
|
+
const items = this.items || [];
|
|
417
|
+
|
|
418
|
+
const {
|
|
419
|
+
bufferSize,
|
|
420
|
+
containerSelector,
|
|
421
|
+
estimateHeight,
|
|
422
|
+
initialRenderCount,
|
|
423
|
+
renderAll,
|
|
424
|
+
renderFromLast,
|
|
425
|
+
shouldRecycle,
|
|
426
|
+
occlusionTagName,
|
|
427
|
+
idForFirstItem,
|
|
428
|
+
key
|
|
429
|
+
} = this;
|
|
257
430
|
|
|
258
431
|
const startingIndex = calculateStartingIndex(items, idForFirstItem, key, renderFromLast);
|
|
259
432
|
|
|
@@ -303,24 +476,24 @@ const VerticalCollection = Component.extend({
|
|
|
303
476
|
};
|
|
304
477
|
}
|
|
305
478
|
|
|
306
|
-
/* Public methods to Expose to parent
|
|
479
|
+
/* Public methods to Expose to parent
|
|
307
480
|
|
|
308
481
|
Usage:
|
|
309
482
|
|
|
310
483
|
Template:
|
|
311
484
|
|
|
312
|
-
|
|
485
|
+
<VerticalCollection @registerAPI={{action "registerAPI"}} />
|
|
313
486
|
|
|
314
487
|
Component:
|
|
315
488
|
|
|
316
|
-
|
|
489
|
+
export default Component.extend({
|
|
317
490
|
actions: {
|
|
318
491
|
registerAPI(api) {
|
|
319
492
|
this.set('collectionAPI', api);
|
|
320
493
|
}
|
|
321
494
|
},
|
|
322
495
|
scrollToItem() {
|
|
323
|
-
let collectionAPI = this.
|
|
496
|
+
let collectionAPI = this.collectionAPI;
|
|
324
497
|
collectionAPI.scrollToItem(index);
|
|
325
498
|
}
|
|
326
499
|
});
|
|
@@ -339,11 +512,77 @@ const VerticalCollection = Component.extend({
|
|
|
339
512
|
};
|
|
340
513
|
registerAPI(publicAPI);
|
|
341
514
|
}
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
515
|
|
|
345
|
-
|
|
346
|
-
|
|
516
|
+
if (DEBUG) {
|
|
517
|
+
this.__visualization = null;
|
|
518
|
+
this._radar._debugDidUpdate = () => {
|
|
519
|
+
|
|
520
|
+
// Update visualization
|
|
521
|
+
//
|
|
522
|
+
// This debugging mode can be controlled via the argument
|
|
523
|
+
// `@debugVis={{true}}` at component invocation.
|
|
524
|
+
//
|
|
525
|
+
if (this.debugVis !== true) {
|
|
526
|
+
if (this.__visualization !== null) {
|
|
527
|
+
console.info('tearing down existing visualization'); // eslint-disable-line no-console
|
|
528
|
+
this.__visualization.destroy();
|
|
529
|
+
this.__visualization = null;
|
|
530
|
+
}
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
if (this.__visualization === null) {
|
|
535
|
+
this.__visualization = new Visualization(this._radar);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
this.__visualization.render();
|
|
539
|
+
|
|
540
|
+
// Detect issues with CSS
|
|
541
|
+
//
|
|
542
|
+
// This debugging mode can be controlled via the argument
|
|
543
|
+
// `@debugCSS={{true}}` at component invocation.
|
|
544
|
+
//
|
|
545
|
+
if (this.debugCSS !== true) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
let radar = this._radar;
|
|
550
|
+
let styles;
|
|
551
|
+
|
|
552
|
+
// check telescope
|
|
553
|
+
if (radar.scrollContainer !== ViewportContainer) {
|
|
554
|
+
styles = window.getComputedStyle(radar.scrollContainer);
|
|
555
|
+
} else {
|
|
556
|
+
styles = window.getComputedStyle(document.body);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
assert(`scrollContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
560
|
+
assert(`scrollContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
561
|
+
assert(`scrollContainer must define height or max-height`, hasStyleWithNonZeroValue(styles, 'height') || hasStyleWithNonZeroValue(styles, 'max-height'));
|
|
562
|
+
|
|
563
|
+
// conditional perf check for non-body scrolling
|
|
564
|
+
if (radar.scrollContainer !== ViewportContainer) {
|
|
565
|
+
assert(`scrollContainer must define overflow-y`, hasStyleValue(styles, 'overflow-y', 'scroll') || hasStyleValue(styles, 'overflow', 'scroll'));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// check itemContainer
|
|
569
|
+
styles = window.getComputedStyle(radar.itemContainer);
|
|
570
|
+
|
|
571
|
+
assert(`itemContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
572
|
+
assert(`itemContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
573
|
+
|
|
574
|
+
// check item defaults
|
|
575
|
+
assert(`You must supply at least one item to the collection to debug it's CSS.`, this.items.length);
|
|
576
|
+
|
|
577
|
+
let element = radar._itemContainer.firstElementChild;
|
|
578
|
+
|
|
579
|
+
styles = window.getComputedStyle(element);
|
|
580
|
+
|
|
581
|
+
assert(`Item cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
582
|
+
assert(`Item must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
}
|
|
347
586
|
});
|
|
348
587
|
|
|
349
588
|
function calculateStartingIndex(items, idForFirstItem, key, renderFromLast) {
|
|
@@ -366,4 +605,4 @@ function calculateStartingIndex(items, idForFirstItem, key, renderFromLast) {
|
|
|
366
605
|
return startingIndex;
|
|
367
606
|
}
|
|
368
607
|
|
|
369
|
-
export default VerticalCollection;
|
|
608
|
+
export default VerticalCollection;
|
package/index.js
CHANGED
|
@@ -6,13 +6,6 @@ const Rollup = require('broccoli-rollup');
|
|
|
6
6
|
const merge = require('broccoli-merge-trees');
|
|
7
7
|
const VersionChecker = require('ember-cli-version-checker');
|
|
8
8
|
|
|
9
|
-
function isProductionEnv() {
|
|
10
|
-
const isProd = /production/.test(process.env.EMBER_ENV);
|
|
11
|
-
const isTest = process.env.EMBER_CLI_TEST_COMMAND;
|
|
12
|
-
|
|
13
|
-
return isProd && !isTest;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
9
|
module.exports = {
|
|
17
10
|
name: require('./package').name,
|
|
18
11
|
|
|
@@ -23,13 +16,7 @@ module.exports = {
|
|
|
23
16
|
},
|
|
24
17
|
|
|
25
18
|
getOutputDirForVersion() {
|
|
26
|
-
|
|
27
|
-
let checker = new VersionChecker(this);
|
|
28
|
-
let emberCli = checker.for('ember-cli', 'npm');
|
|
29
|
-
|
|
30
|
-
let requiresModulesDir = emberCli.satisfies('< 3.0.0');
|
|
31
|
-
|
|
32
|
-
return requiresModulesDir ? 'modules' : '';
|
|
19
|
+
return '';
|
|
33
20
|
},
|
|
34
21
|
|
|
35
22
|
// Borrowed from ember-cli-babel
|
|
@@ -49,10 +36,8 @@ module.exports = {
|
|
|
49
36
|
let withoutPrivate = new Funnel(tree, {
|
|
50
37
|
exclude: [
|
|
51
38
|
'**/**.hbs',
|
|
52
|
-
'-private'
|
|
53
|
-
|
|
54
|
-
].filter(Boolean),
|
|
55
|
-
|
|
39
|
+
'-private'
|
|
40
|
+
],
|
|
56
41
|
destDir: '@html-next/vertical-collection'
|
|
57
42
|
});
|
|
58
43
|
|
|
@@ -170,34 +155,7 @@ module.exports = {
|
|
|
170
155
|
this._setupBabelOptions(app.env);
|
|
171
156
|
|
|
172
157
|
if (!/production/.test(app.env) && !/test/.test(app.env)) {
|
|
173
|
-
|
|
158
|
+
this.import('vendor/debug.css');
|
|
174
159
|
}
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
treeForApp() {
|
|
178
|
-
const tree = this._super.treeForApp.apply(this, arguments);
|
|
179
|
-
|
|
180
|
-
const exclude = [];
|
|
181
|
-
|
|
182
|
-
if (isProductionEnv()) {
|
|
183
|
-
exclude.push('initializers/debug.js');
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return new Funnel(tree, { exclude });
|
|
187
160
|
}
|
|
188
161
|
};
|
|
189
|
-
|
|
190
|
-
function findImporter(addon) {
|
|
191
|
-
if (typeof addon.import === 'function') {
|
|
192
|
-
// If addon.import() is present (CLI 2.7+) use that
|
|
193
|
-
return addon;
|
|
194
|
-
} else {
|
|
195
|
-
// Otherwise, reuse the _findHost implementation that would power addon.import()
|
|
196
|
-
let current = addon;
|
|
197
|
-
let app;
|
|
198
|
-
do {
|
|
199
|
-
app = current.app || app;
|
|
200
|
-
} while (current.parent.parent && (current = current.parent));
|
|
201
|
-
return app;
|
|
202
|
-
}
|
|
203
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@html-next/vertical-collection",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-beta.2",
|
|
4
4
|
"description": "infinite-scroll, done right. done.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"occlusion",
|
|
@@ -52,22 +52,21 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"babel6-plugin-strip-class-callcheck": "^6.0.0",
|
|
55
|
-
"broccoli-funnel": "^
|
|
56
|
-
"broccoli-merge-trees": "^
|
|
57
|
-
"broccoli-rollup": "^
|
|
55
|
+
"broccoli-funnel": "^3.0.8",
|
|
56
|
+
"broccoli-merge-trees": "^4.2.0",
|
|
57
|
+
"broccoli-rollup": "^5.0.0",
|
|
58
58
|
"ember-cli-babel": "^7.12.0",
|
|
59
|
-
"ember-cli-htmlbars": "^
|
|
60
|
-
"ember-cli-version-checker": "^
|
|
61
|
-
"ember-compatibility-helpers": "^1.2.1",
|
|
59
|
+
"ember-cli-htmlbars": "^6.0.0",
|
|
60
|
+
"ember-cli-version-checker": "^5.1.2",
|
|
62
61
|
"ember-raf-scheduler": "^0.3.0"
|
|
63
62
|
},
|
|
64
63
|
"devDependencies": {
|
|
65
64
|
"@ember/optional-features": "^2.0.0",
|
|
66
|
-
"@ember/test-helpers": "^2.
|
|
65
|
+
"@ember/test-helpers": "^2.8.1",
|
|
67
66
|
"babel-eslint": "^10.1.0",
|
|
68
67
|
"bootstrap": "~3.3.5",
|
|
69
68
|
"broccoli-asset-rev": "^3.0.0",
|
|
70
|
-
"ember-auto-import": "^2.
|
|
69
|
+
"ember-auto-import": "^2.4.2",
|
|
71
70
|
"ember-cli": "~3.28.0",
|
|
72
71
|
"ember-cli-dependency-checker": "^3.2.0",
|
|
73
72
|
"ember-cli-eslint": "^5.1.0",
|
|
@@ -82,17 +81,17 @@
|
|
|
82
81
|
"ember-export-application-global": "^2.0.1",
|
|
83
82
|
"ember-load-initializers": "^2.1.2",
|
|
84
83
|
"ember-perf-timeline": "^2.0.0",
|
|
85
|
-
"ember-qunit": "^5.
|
|
84
|
+
"ember-qunit": "^5.1.5",
|
|
86
85
|
"ember-resolver": "^8.0.2",
|
|
87
86
|
"ember-source": "~3.12.0",
|
|
88
87
|
"ember-source-channel-url": "^3.0.0",
|
|
89
|
-
"ember-try": "^
|
|
88
|
+
"ember-try": "^2.0.0",
|
|
90
89
|
"eslint": "^7.32.0",
|
|
91
90
|
"eslint-plugin-ember": "^6.7.1",
|
|
92
91
|
"eslint-plugin-node": "^9.1.0",
|
|
93
92
|
"loader.js": "^4.7.0",
|
|
94
93
|
"npm-run-all": "^4.1.5",
|
|
95
|
-
"qunit": "^2.
|
|
94
|
+
"qunit": "^2.19.1",
|
|
96
95
|
"qunit-dom": "^1.0.0",
|
|
97
96
|
"release-it": "^14.2.1",
|
|
98
97
|
"release-it-lerna-changelog": "^3.1.0",
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { assert } from '@ember/debug';
|
|
2
|
-
import Mixin from '@ember/object/mixin';
|
|
3
|
-
import Visualization from './visualization';
|
|
4
|
-
import { ViewportContainer } from '../../-private';
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
styleIsOneOf,
|
|
8
|
-
hasStyleValue,
|
|
9
|
-
hasStyleWithNonZeroValue
|
|
10
|
-
} from '../utils/validate-style';
|
|
11
|
-
|
|
12
|
-
export default Mixin.create({
|
|
13
|
-
debugVis: false,
|
|
14
|
-
debugCSS: false,
|
|
15
|
-
|
|
16
|
-
__visualization: null,
|
|
17
|
-
|
|
18
|
-
init() {
|
|
19
|
-
this._super(...arguments);
|
|
20
|
-
|
|
21
|
-
this._radar._debugDidUpdate = () => {
|
|
22
|
-
this.updateVisualization();
|
|
23
|
-
this.detectIssuesWithCSS();
|
|
24
|
-
};
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
detectIssuesWithCSS() {
|
|
28
|
-
if (this.get('debugCSS') === false) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let radar = this._radar;
|
|
33
|
-
let styles;
|
|
34
|
-
|
|
35
|
-
// check telescope
|
|
36
|
-
if (radar.scrollContainer !== ViewportContainer) {
|
|
37
|
-
styles = window.getComputedStyle(radar.scrollContainer);
|
|
38
|
-
} else {
|
|
39
|
-
styles = window.getComputedStyle(document.body);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
assert(`scrollContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
43
|
-
assert(`scrollContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
44
|
-
assert(`scrollContainer must define height or max-height`, hasStyleWithNonZeroValue(styles, 'height') || hasStyleWithNonZeroValue(styles, 'max-height'));
|
|
45
|
-
|
|
46
|
-
// conditional perf check for non-body scrolling
|
|
47
|
-
if (radar.scrollContainer !== ViewportContainer) {
|
|
48
|
-
assert(`scrollContainer must define overflow-y`, hasStyleValue(styles, 'overflow-y', 'scroll') || hasStyleValue(styles, 'overflow', 'scroll'));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// check itemContainer
|
|
52
|
-
styles = window.getComputedStyle(radar.itemContainer);
|
|
53
|
-
|
|
54
|
-
assert(`itemContainer cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
55
|
-
assert(`itemContainer must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
56
|
-
|
|
57
|
-
// check item defaults
|
|
58
|
-
assert(`You must supply at least one item to the collection to debug it's CSS.`, this.get('items.length'));
|
|
59
|
-
|
|
60
|
-
let element = radar._itemContainer.firstElementChild;
|
|
61
|
-
|
|
62
|
-
styles = window.getComputedStyle(element);
|
|
63
|
-
|
|
64
|
-
assert(`Item cannot be inline.`, styleIsOneOf(styles, 'display', ['block', 'inline-block', 'flex', 'inline-flex']));
|
|
65
|
-
assert(`Item must define position`, styleIsOneOf(styles, 'position', ['static', 'relative', 'absolute']));
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
updateVisualization() {
|
|
69
|
-
if (this.get('debugVis') === false) {
|
|
70
|
-
if (this.__visualization !== null) {
|
|
71
|
-
console.info('tearing down existing visualization'); // eslint-disable-line no-console
|
|
72
|
-
this.__visualization.destroy();
|
|
73
|
-
this.__visualization = null;
|
|
74
|
-
}
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (this.__visualization === null) {
|
|
79
|
-
this.__visualization = new Visualization(this._radar);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.__visualization.render();
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
willDestroy() {
|
|
86
|
-
this._super();
|
|
87
|
-
if (this.__visualization) {
|
|
88
|
-
console.info('destroying visualization'); // eslint-disable-line no-console
|
|
89
|
-
this.__visualization.destroy();
|
|
90
|
-
this.__visualization = null;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { ViewportContainer } from '../../-private';
|
|
2
|
-
|
|
3
|
-
function applyVerticalStyles(element, geography) {
|
|
4
|
-
element.style.height = `${geography.height}px`;
|
|
5
|
-
element.style.top = `${geography.top}px`;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default class Visualization {
|
|
9
|
-
constructor(radar) {
|
|
10
|
-
this.radar = radar;
|
|
11
|
-
this.satellites = [];
|
|
12
|
-
this.cache = [];
|
|
13
|
-
|
|
14
|
-
this.wrapper = document.createElement('div');
|
|
15
|
-
this.wrapper.className = 'vertical-collection-visual-debugger';
|
|
16
|
-
|
|
17
|
-
this.container = document.createElement('div');
|
|
18
|
-
this.container.className = 'vc_visualization-container';
|
|
19
|
-
this.wrapper.appendChild(this.container);
|
|
20
|
-
|
|
21
|
-
this.itemContainer = document.createElement('div');
|
|
22
|
-
this.itemContainer.className = 'vc_visualization-item-container';
|
|
23
|
-
this.container.appendChild(this.itemContainer);
|
|
24
|
-
|
|
25
|
-
this.scrollContainer = document.createElement('div');
|
|
26
|
-
this.scrollContainer.className = 'vc_visualization-scroll-container';
|
|
27
|
-
this.container.appendChild(this.scrollContainer);
|
|
28
|
-
|
|
29
|
-
this.screen = document.createElement('div');
|
|
30
|
-
this.screen.className = 'vc_visualization-screen';
|
|
31
|
-
this.container.appendChild(this.screen);
|
|
32
|
-
|
|
33
|
-
document.body.appendChild(this.wrapper);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
render() {
|
|
37
|
-
this.styleViewport();
|
|
38
|
-
this.updateSatellites();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
styleViewport() {
|
|
42
|
-
const { _scrollContainer } = this.radar;
|
|
43
|
-
this.container.style.height = `${_scrollContainer.getBoundingClientRect().height}px`;
|
|
44
|
-
|
|
45
|
-
applyVerticalStyles(this.scrollContainer, _scrollContainer.getBoundingClientRect());
|
|
46
|
-
applyVerticalStyles(this.screen, ViewportContainer.getBoundingClientRect());
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
makeSatellite() {
|
|
50
|
-
let satellite;
|
|
51
|
-
|
|
52
|
-
if (this.cache.length) {
|
|
53
|
-
satellite = this.cache.pop();
|
|
54
|
-
} else {
|
|
55
|
-
satellite = document.createElement('div');
|
|
56
|
-
satellite.className = 'vc_visualization-virtual-component';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
this.satellites.push(satellite);
|
|
60
|
-
this.itemContainer.append(satellite);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
updateSatellites() {
|
|
64
|
-
const { satellites: sats } = this;
|
|
65
|
-
let {
|
|
66
|
-
firstItemIndex,
|
|
67
|
-
lastItemIndex,
|
|
68
|
-
|
|
69
|
-
totalItems,
|
|
70
|
-
|
|
71
|
-
totalBefore,
|
|
72
|
-
totalAfter,
|
|
73
|
-
skipList,
|
|
74
|
-
_calculatedEstimateHeight
|
|
75
|
-
} = this.radar;
|
|
76
|
-
|
|
77
|
-
const isDynamic = !!skipList;
|
|
78
|
-
const itemHeights = isDynamic && skipList.values;
|
|
79
|
-
|
|
80
|
-
const firstVisualizedIndex = Math.max(firstItemIndex - 10, 0);
|
|
81
|
-
const lastVisualizedIndex = Math.min(lastItemIndex + 10, totalItems - 1);
|
|
82
|
-
|
|
83
|
-
const lengthWithBuffer = lastVisualizedIndex - firstVisualizedIndex + 1;
|
|
84
|
-
const isShrinking = sats.length > lengthWithBuffer;
|
|
85
|
-
|
|
86
|
-
while (sats.length !== lengthWithBuffer) {
|
|
87
|
-
if (isShrinking) {
|
|
88
|
-
const satellite = sats.pop();
|
|
89
|
-
|
|
90
|
-
satellite.parentNode.removeChild(satellite);
|
|
91
|
-
this.cache.push(satellite);
|
|
92
|
-
} else {
|
|
93
|
-
this.makeSatellite();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
for (let itemIndex = firstVisualizedIndex, i = 0; itemIndex <= lastVisualizedIndex; itemIndex++, i++) {
|
|
98
|
-
const element = sats[i];
|
|
99
|
-
|
|
100
|
-
const itemHeight = isDynamic ? itemHeights[itemIndex] : _calculatedEstimateHeight;
|
|
101
|
-
|
|
102
|
-
element.style.height = `${itemHeight}px`;
|
|
103
|
-
element.setAttribute('index', String(itemIndex));
|
|
104
|
-
element.innerText = String(itemIndex);
|
|
105
|
-
|
|
106
|
-
if (itemIndex < firstItemIndex) {
|
|
107
|
-
element.classList.add('culled');
|
|
108
|
-
totalBefore -= itemHeight;
|
|
109
|
-
} else if (itemIndex > lastItemIndex) {
|
|
110
|
-
element.classList.add('culled');
|
|
111
|
-
totalAfter -= itemHeight;
|
|
112
|
-
} else {
|
|
113
|
-
element.classList.remove('culled');
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
this.itemContainer.style.paddingTop = `${totalBefore}px`;
|
|
118
|
-
this.itemContainer.style.paddingBottom = `${totalAfter}px`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
destroy() {
|
|
122
|
-
this.wrapper.parentNode.removeChild(this.wrapper);
|
|
123
|
-
this.wrapper = null;
|
|
124
|
-
this.radar = null;
|
|
125
|
-
this.component = null;
|
|
126
|
-
this.satellites.forEach((satellite) => {
|
|
127
|
-
if (satellite.parentNode) {
|
|
128
|
-
satellite.parentNode.removeChild(satellite);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
this.satellites = null;
|
|
132
|
-
this.cache = null;
|
|
133
|
-
}
|
|
134
|
-
}
|
package/addon/-debug/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function hasCSSRule(rules, prop, value) {
|
|
2
|
-
let styleStr = `${prop}:\\s*${value}`;
|
|
3
|
-
let expr = new RegExp(styleStr, ['i']);
|
|
4
|
-
|
|
5
|
-
for (let i = 0; i < rules.length; i++) {
|
|
6
|
-
if (expr.test(rules[i].cssText)) {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { isNonZero } from './validate-style';
|
|
2
|
-
|
|
3
|
-
export function hasDimension(rect, prop) {
|
|
4
|
-
return isNonZero(rect[prop]);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function hasDimensionAbove(rect, prop, amount) {
|
|
8
|
-
return hasDimension(rect, prop) && rect[prop] >= amount;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function hasDimensionEqual(rect, prop, amount) {
|
|
12
|
-
return hasDimension(rect, prop) && rect[prop] === amount;
|
|
13
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export function hasStyleValue(styles, key, value) {
|
|
3
|
-
return styles[key] === value;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function isNonZero(value) {
|
|
7
|
-
let int = parseInt(value, 10);
|
|
8
|
-
let float = parseFloat(value);
|
|
9
|
-
|
|
10
|
-
return !isNaN(int) && (int !== 0 || float !== 0);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function hasStyleWithNonZeroValue(styles, key) {
|
|
14
|
-
return isNonZero(styles[key]);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function styleIsOneOf(styles, key, values) {
|
|
18
|
-
return styles[key] && values.indexOf(styles[key]) !== -1;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function containsStyleValue(styles, key, value) {
|
|
22
|
-
return styles[key] && styles[key].indexOf(value) !== -1;
|
|
23
|
-
}
|