@ohif/app 3.0.0 → 3.5.0-beta.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/dist/151.bundle.07bac9172580a60fae7a.js +2579 -0
- package/dist/192.bundle.ba16a14ce3189030cc9f.js +894 -0
- package/dist/199.bundle.1f36acfb5f33e0a14099.js +480 -0
- package/dist/205.bundle.39e6c847d618ad2b1b7a.js +62 -0
- package/dist/208.bundle.6c4414ed336e1a69f416.js +864 -0
- package/dist/270.bundle.abbdb5348274bae3e8bc.js +23906 -0
- package/dist/283.bundle.e1fa3aae54f3a0443dfd.js +2939 -0
- package/dist/295.bundle.5105ce962be15c92484d.js +48 -0
- package/dist/331.bundle.7ac7b142d249d14fd99e.js +73034 -0
- package/dist/351.bundle.c5d7279ef42e30f61e08.js +1471 -0
- package/dist/351.css +3 -0
- package/dist/36785fbd89b0e17f6099.wasm +0 -0
- package/dist/381.bundle.0905e683605fcbc0895f.js +1009 -0
- package/dist/404.bundle.88ccecdb5420fd182193.js +706 -0
- package/dist/50.bundle.06ab2acc24298a7688be.js +324 -0
- package/dist/5004fdc02f329ce53b69.wasm +0 -0
- package/dist/531.bundle.1bc152c87c7e2e987d2b.js +5935 -0
- package/dist/55.bundle.a5a215e13a8511f7aee7.js +685 -0
- package/dist/55.css +3 -0
- package/dist/569.bundle.d147c0aa0604f8ea2094.js +514 -0
- package/dist/581.bundle.646c89c5c3e3ee096363.js +508 -0
- package/dist/606.bundle.5d876f5f3dd8287f0a28.js +4939 -0
- package/dist/610.min.worker.js +2 -0
- package/dist/610.min.worker.js.map +1 -0
- package/dist/616.bundle.561a252054ca7bfbc031.js +686 -0
- package/dist/62ab5d58a2bea7b5a1dc.wasm +0 -0
- package/dist/642.bundle.08504984389ff9e87459.js +169 -0
- package/dist/65916ef3def695744bda.wasm +0 -0
- package/dist/664.bundle.4792c88ae0d6d4b5ed13.js +901 -0
- package/dist/707.bundle.fdfed44cde7cfebf1cb8.js +9049 -0
- package/dist/707.css +1 -0
- package/dist/728.bundle.d13856835357400fef82.js +26221 -0
- package/dist/744.bundle.af0814741f6bdaf65437.js +2355 -0
- package/dist/75788f12450d4c5ed494.wasm +0 -0
- package/dist/75a0c2dfe07b824c7d21.wasm +0 -0
- package/dist/780.bundle.f60ac1906e0ae080dee8.js +4769 -0
- package/dist/790.bundle.5200456fbf233c876b50.js +454 -0
- package/dist/799.bundle.3fff638815e355b0bdfd.js +271 -0
- package/dist/806.css +1 -0
- package/dist/82.bundle.4d8a96283a3535fb589d.js +6104 -0
- package/dist/917.bundle.23cef6cf0afc99a435ce.js +196 -0
- package/dist/926.bundle.dbc9d0e591cb9217fda2.js +72552 -0
- package/dist/935.bundle.deeffff0e4f7b528e3c3.js +1849 -0
- package/dist/945.min.worker.js +2 -0
- package/dist/945.min.worker.js.map +1 -0
- package/dist/953.bundle.c14d9eb6400f697019ee.js +449 -0
- package/dist/973.bundle.9e6a36aa362f0bbb47f4.js +261 -0
- package/dist/976.bundle.057f1de0494995f8c27e.js +2725 -0
- package/dist/984.bundle.8d6049caa793ac67f956.js +1842 -0
- package/dist/_headers +6 -0
- package/dist/_redirects +6 -0
- package/dist/app-config.js +215 -0
- package/dist/app.bundle.c65e9540d5cbb3bb22f6.js +154621 -0
- package/dist/app.bundle.css +21 -0
- package/dist/assets/android-chrome-144x144.png +0 -0
- package/dist/assets/android-chrome-192x192.png +0 -0
- package/dist/assets/android-chrome-256x256.png +0 -0
- package/dist/assets/android-chrome-36x36.png +0 -0
- package/dist/assets/android-chrome-384x384.png +0 -0
- package/dist/assets/android-chrome-48x48.png +0 -0
- package/dist/assets/android-chrome-512x512.png +0 -0
- package/dist/assets/android-chrome-72x72.png +0 -0
- package/dist/assets/android-chrome-96x96.png +0 -0
- package/dist/assets/apple-touch-icon-1024x1024.png +0 -0
- package/dist/assets/apple-touch-icon-114x114.png +0 -0
- package/dist/assets/apple-touch-icon-120x120.png +0 -0
- package/dist/assets/apple-touch-icon-144x144.png +0 -0
- package/dist/assets/apple-touch-icon-152x152.png +0 -0
- package/dist/assets/apple-touch-icon-167x167.png +0 -0
- package/dist/assets/apple-touch-icon-180x180.png +0 -0
- package/dist/assets/apple-touch-icon-57x57.png +0 -0
- package/dist/assets/apple-touch-icon-60x60.png +0 -0
- package/dist/assets/apple-touch-icon-72x72.png +0 -0
- package/dist/assets/apple-touch-icon-76x76.png +0 -0
- package/dist/assets/apple-touch-icon-precomposed.png +0 -0
- package/dist/assets/apple-touch-icon.png +0 -0
- package/dist/assets/apple-touch-startup-image-1182x2208.png +0 -0
- package/dist/assets/apple-touch-startup-image-1242x2148.png +0 -0
- package/dist/assets/apple-touch-startup-image-1496x2048.png +0 -0
- package/dist/assets/apple-touch-startup-image-1536x2008.png +0 -0
- package/dist/assets/apple-touch-startup-image-320x460.png +0 -0
- package/dist/assets/apple-touch-startup-image-640x1096.png +0 -0
- package/dist/assets/apple-touch-startup-image-640x920.png +0 -0
- package/dist/assets/apple-touch-startup-image-748x1024.png +0 -0
- package/dist/assets/apple-touch-startup-image-750x1294.png +0 -0
- package/dist/assets/apple-touch-startup-image-768x1004.png +0 -0
- package/dist/assets/browserconfig.xml +12 -0
- package/dist/assets/coast-228x228.png +0 -0
- package/dist/assets/favicon-16x16.png +0 -0
- package/dist/assets/favicon-32x32.png +0 -0
- package/dist/assets/favicon.ico +0 -0
- package/dist/assets/firefox_app_128x128.png +0 -0
- package/dist/assets/firefox_app_512x512.png +0 -0
- package/dist/assets/firefox_app_60x60.png +0 -0
- package/dist/assets/manifest.webapp +14 -0
- package/dist/assets/mstile-144x144.png +0 -0
- package/dist/assets/mstile-150x150.png +0 -0
- package/dist/assets/mstile-310x150.png +0 -0
- package/dist/assets/mstile-310x310.png +0 -0
- package/dist/assets/mstile-70x70.png +0 -0
- package/dist/assets/yandex-browser-50x50.png +0 -0
- package/dist/assets/yandex-browser-manifest.json +9 -0
- package/dist/b6b803111e2d06a825bd.wasm +0 -0
- package/dist/c22b37c3488e1d6c3aa4.wasm +0 -0
- package/dist/cornerstoneDICOMImageLoader.min.js +2 -0
- package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -0
- package/dist/dicom-microscopy-viewer.bundle.aa60bdf008c32c39cfd7.js +12 -0
- package/dist/dicomMicroscopyViewer.min.js +3 -0
- package/dist/dicomMicroscopyViewer.min.js.LICENSE.txt +29 -0
- package/dist/es6-shim.min.js +12 -0
- package/dist/google.js +75 -0
- package/dist/index.html +1 -0
- package/dist/index.worker.ea71efba2ce63c499055.worker.js +2 -0
- package/dist/index.worker.ea71efba2ce63c499055.worker.js.map +1 -0
- package/dist/index.worker.min.worker.js +2 -0
- package/dist/index.worker.min.worker.js.map +1 -0
- package/dist/init-service-worker.js +59 -0
- package/dist/manifest.json +59 -0
- package/dist/ohif-logo-light.svg +15 -0
- package/dist/ohif-logo.svg +15 -0
- package/dist/oidc-client.min.js +46 -0
- package/dist/polyfill.min.js +1 -0
- package/dist/silent-refresh.html +16 -0
- package/dist/sw.js +56 -0
- package/package.json +24 -23
|
@@ -0,0 +1,2579 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[151],{
|
|
3
|
+
|
|
4
|
+
/***/ 71251:
|
|
5
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
6
|
+
|
|
7
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8
|
+
/* harmony export */ "d": () => (/* binding */ calculateSUVScalingFactors)
|
|
9
|
+
/* harmony export */ });
|
|
10
|
+
/**
|
|
11
|
+
* Javascript object that handles dates and compute the time.
|
|
12
|
+
*
|
|
13
|
+
* @export
|
|
14
|
+
* @class FullDateInterface
|
|
15
|
+
*/
|
|
16
|
+
class FullDateInterface {
|
|
17
|
+
/**
|
|
18
|
+
* Creates an instance of FullDateInterface.
|
|
19
|
+
* @param {string} date formatted as yyyy-mm-ddTHH:MM:SS.FFFFFFZ
|
|
20
|
+
* @memberof FullDateInterface
|
|
21
|
+
*/
|
|
22
|
+
constructor(date) {
|
|
23
|
+
this.fullDate = date;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* returns time since 1 january 1970
|
|
27
|
+
*
|
|
28
|
+
* @returns {number} time in sec
|
|
29
|
+
* @memberof FullDateInterface
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
getTimeInSec() {
|
|
34
|
+
// yyyy-mm-ddTHH:MM:SS.FFFFFFZ
|
|
35
|
+
const dateString = this.fullDate.substring(0, 10);
|
|
36
|
+
const timeString = this.fullDate.substring(11, 28); // yyyy-mm-dd
|
|
37
|
+
|
|
38
|
+
const yyyy = parseInt(dateString.substring(0, 4), 10);
|
|
39
|
+
const mm = dateString.length >= 7 ? parseInt(dateString.substring(5, 7), 10) : undefined;
|
|
40
|
+
const dd = dateString.length >= 10 ? parseInt(dateString.substring(8, 10), 10) : undefined;
|
|
41
|
+
|
|
42
|
+
if (isNaN(yyyy) || mm !== undefined && isNaN(mm) || dd !== undefined && isNaN(dd) || yyyy > 3000 || mm && (mm < 1 || mm > 12) || dd && (dd < 1 || dd > 31)) {
|
|
43
|
+
throw new Error(`invalid date '${dateString}'`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const dateJS = new Date(`${dateString}T00:00:00.000000Z`); // HHMMSS.FFFFFF
|
|
47
|
+
|
|
48
|
+
const HH = parseInt(timeString.substring(0, 2), 10);
|
|
49
|
+
const MM = timeString.length >= 5 ? parseInt(timeString.substring(3, 5), 10) : undefined;
|
|
50
|
+
const SS = timeString.length >= 8 ? parseInt(timeString.substring(6, 8), 10) : undefined;
|
|
51
|
+
const fractionalStr = timeString.substring(9, 15);
|
|
52
|
+
const FFFFFF = fractionalStr ? parseInt(fractionalStr, 10) * Math.pow(10, -fractionalStr.length) : undefined;
|
|
53
|
+
|
|
54
|
+
if (isNaN(HH) || MM !== undefined && isNaN(MM) || SS !== undefined && isNaN(SS) || FFFFFF !== undefined && isNaN(FFFFFF) || HH < 0 || HH > 23 || MM && (MM < 0 || MM > 59) || SS && (SS < 0 || SS > 59) || FFFFFF && (FFFFFF < 0 || FFFFFF > 999999)) {
|
|
55
|
+
throw new Error(`invalid time '${timeString}'`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let timeInSec = dateJS.getTime() / 1000;
|
|
59
|
+
timeInSec += HH * 3600;
|
|
60
|
+
|
|
61
|
+
if (MM !== undefined) {
|
|
62
|
+
timeInSec += MM * 60;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (SS !== undefined) {
|
|
66
|
+
timeInSec += SS;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (FFFFFF !== undefined) {
|
|
70
|
+
timeInSec += FFFFFF;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return timeInSec;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* returns time since 1 january 1970
|
|
77
|
+
*
|
|
78
|
+
* @returns {number} time in microsec
|
|
79
|
+
* @memberof FullDateInterface
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
getTimeInMicroSec() {
|
|
84
|
+
const timeInMicroSec = this.getTimeInSec() * 1e6;
|
|
85
|
+
return timeInMicroSec;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Combines two javascript objects containing the date and time information
|
|
91
|
+
*
|
|
92
|
+
* @export
|
|
93
|
+
* @param {DateInterface} date
|
|
94
|
+
* @param {TimeInterface} time
|
|
95
|
+
* @returns {FullDateInterface}
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
function combineDateTime(date, time) {
|
|
99
|
+
const hours = `${time.hours || '00'}`.padStart(2, '0');
|
|
100
|
+
const minutes = `${time.minutes || '00'}`.padStart(2, '0');
|
|
101
|
+
const seconds = `${time.seconds || '00'}`.padStart(2, '0');
|
|
102
|
+
const month = `${date.month}`.padStart(2, '0');
|
|
103
|
+
const day = `${date.day}`.padStart(2, '0');
|
|
104
|
+
const fractionalSeconds = `${time.fractionalSeconds || '000000'}`.padEnd(6, '0');
|
|
105
|
+
const dateString = `${date.year}-${month}-${day}`;
|
|
106
|
+
const timeString = `T${hours}:${minutes}:${seconds}.${fractionalSeconds}Z`;
|
|
107
|
+
const fullDateString = `${dateString}${timeString}`;
|
|
108
|
+
return new FullDateInterface(fullDateString);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Check the number of days for a picked month and year
|
|
113
|
+
* algorithm based on http://stackoverflow.com/questions/1433030/validate-number-of-days-in-a-given-month
|
|
114
|
+
*
|
|
115
|
+
* @param {number} m
|
|
116
|
+
* @param {number} y
|
|
117
|
+
* @returns {number} number of days
|
|
118
|
+
*/
|
|
119
|
+
function daysInMonth(m, y) {
|
|
120
|
+
// m is 0 indexed: 0-11
|
|
121
|
+
switch (m) {
|
|
122
|
+
case 2:
|
|
123
|
+
return y % 4 === 0 && y % 100 || y % 400 === 0 ? 29 : 28;
|
|
124
|
+
|
|
125
|
+
case 9:
|
|
126
|
+
case 4:
|
|
127
|
+
case 6:
|
|
128
|
+
case 11:
|
|
129
|
+
return 30;
|
|
130
|
+
|
|
131
|
+
default:
|
|
132
|
+
return 31;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check if the date is valid
|
|
137
|
+
*
|
|
138
|
+
* @param {number} d
|
|
139
|
+
* @param {number} m
|
|
140
|
+
* @param {number} y
|
|
141
|
+
* @returns {boolean} boolean result
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
function isValidDate(d, m, y) {
|
|
146
|
+
// make year is a number
|
|
147
|
+
if (isNaN(y)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return m > 0 && m <= 12 && d > 0 && d <= daysInMonth(m, y);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parses a DA formatted string into a Javascript object
|
|
155
|
+
* @param {string} date a string in the DA VR format
|
|
156
|
+
* @param {boolean} [validate] - true if an exception should be thrown if the date is invalid
|
|
157
|
+
* @returns {DateInterface} Javascript object with properties year, month and day or undefined if not present or not 8 bytes long
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
function parseDA(date) {
|
|
162
|
+
if (date === undefined || date === null || date.length !== 8 || typeof date !== 'string') {
|
|
163
|
+
throw new Error(`invalid DA '${date}'`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const yyyy = parseInt(date.substring(0, 4), 10);
|
|
167
|
+
const mm = parseInt(date.substring(4, 6), 10);
|
|
168
|
+
const dd = parseInt(date.substring(6, 8), 10);
|
|
169
|
+
|
|
170
|
+
if (isValidDate(dd, mm, yyyy) !== true) {
|
|
171
|
+
throw new Error(`invalid DA '${date}'`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
year: yyyy,
|
|
176
|
+
month: mm,
|
|
177
|
+
day: dd
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Parses a TM formatted string into a javascript object with properties for hours, minutes, seconds and fractionalSeconds
|
|
183
|
+
* @param {string} time - a string in the TM VR format
|
|
184
|
+
* @returns {string} javascript object with properties for hours, minutes, seconds and fractionalSeconds or undefined if no element or data. Missing fields are set to undefined
|
|
185
|
+
*/
|
|
186
|
+
function parseTM(time) {
|
|
187
|
+
if (time === null || time === undefined || time.length < 2 || typeof time !== 'string') {
|
|
188
|
+
// must at least have HH
|
|
189
|
+
throw new Error(`invalid TM '${time}'`);
|
|
190
|
+
} // 0123456789
|
|
191
|
+
// HHMMSS.FFFFFF
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
const hh = parseInt(time.substring(0, 2), 10);
|
|
195
|
+
const mm = time.length >= 4 ? parseInt(time.substring(2, 4), 10) : undefined;
|
|
196
|
+
const ss = time.length >= 6 ? parseInt(time.substring(4, 6), 10) : undefined;
|
|
197
|
+
const fractionalStr = time.length >= 8 ? time.substring(7, 13) : undefined;
|
|
198
|
+
const ffffff = fractionalStr ? parseInt(fractionalStr, 10) * Math.pow(10, 6 - fractionalStr.length) : undefined;
|
|
199
|
+
|
|
200
|
+
if (isNaN(hh) || mm !== undefined && isNaN(mm) || ss !== undefined && isNaN(ss) || ffffff !== undefined && isNaN(ffffff) || hh < 0 || hh > 23 || mm && (mm < 0 || mm > 59) || ss && (ss < 0 || ss > 59) || ffffff && (ffffff < 0 || ffffff > 999999)) {
|
|
201
|
+
throw new Error(`invalid TM '${time}'`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
hours: hh,
|
|
206
|
+
minutes: mm,
|
|
207
|
+
seconds: ss,
|
|
208
|
+
fractionalSeconds: ffffff
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Utility to create a FullDateInterface object given a string formatted as yyyy-mm-ddTHH:MM:SS.FFFFFFZ
|
|
214
|
+
*
|
|
215
|
+
* @export
|
|
216
|
+
* @param {string} dateTime
|
|
217
|
+
* @returns {FullDateInterface}
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
function dateTimeToFullDateInterface(dateTime) {
|
|
221
|
+
if (dateTime === undefined || dateTime === null) {
|
|
222
|
+
throw new Error('dateTimeToFullDateInterface : dateTime not defined.');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const date = parseDA(dateTime.substring(0, 8));
|
|
226
|
+
const time = parseTM(dateTime.substring(8));
|
|
227
|
+
return combineDateTime(date, time);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Calculate the scan times
|
|
232
|
+
*
|
|
233
|
+
* @export
|
|
234
|
+
* @param {InstanceMetadataForScanTimes[]} instances
|
|
235
|
+
* @returns {FullDateInterface[]}
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
function calculateScanTimes(instances) {
|
|
239
|
+
const {
|
|
240
|
+
SeriesDate,
|
|
241
|
+
SeriesTime,
|
|
242
|
+
GEPrivatePostInjectionDateTime
|
|
243
|
+
} = instances[0];
|
|
244
|
+
const results = new Array(instances.length);
|
|
245
|
+
const seriesDate = parseDA(SeriesDate);
|
|
246
|
+
const seriesTime = parseTM(SeriesTime);
|
|
247
|
+
const seriesDateTime = combineDateTime(seriesDate, seriesTime);
|
|
248
|
+
let earliestAcquisitionDateTime = new FullDateInterface(`3000-01-01T00:00:00.000000Z`);
|
|
249
|
+
let timeError = earliestAcquisitionDateTime.getTimeInSec();
|
|
250
|
+
instances.forEach(instance => {
|
|
251
|
+
const {
|
|
252
|
+
AcquisitionDate,
|
|
253
|
+
AcquisitionTime
|
|
254
|
+
} = instance;
|
|
255
|
+
const acquisitionDate = parseDA(AcquisitionDate);
|
|
256
|
+
const acquisitionTime = parseTM(AcquisitionTime);
|
|
257
|
+
const acquisitionDateTime = combineDateTime(acquisitionDate, acquisitionTime);
|
|
258
|
+
|
|
259
|
+
if (earliestAcquisitionDateTime.getTimeInSec() >= timeError) {
|
|
260
|
+
earliestAcquisitionDateTime = acquisitionDateTime;
|
|
261
|
+
} else {
|
|
262
|
+
earliestAcquisitionDateTime = acquisitionDateTime.getTimeInSec() < earliestAcquisitionDateTime.getTimeInSec() ? acquisitionDateTime : earliestAcquisitionDateTime;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
if (earliestAcquisitionDateTime.getTimeInSec() >= timeError) {
|
|
267
|
+
throw new Error('Earliest acquisition time or date could not be parsed.');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (seriesDateTime.getTimeInSec() <= earliestAcquisitionDateTime.getTimeInSec()) {
|
|
271
|
+
return results.fill(seriesDateTime);
|
|
272
|
+
} else {
|
|
273
|
+
if (GEPrivatePostInjectionDateTime) {
|
|
274
|
+
// GE Private scan
|
|
275
|
+
return results.fill(dateTimeToFullDateInterface(GEPrivatePostInjectionDateTime));
|
|
276
|
+
} else {
|
|
277
|
+
/*const hasValidFrameTimes = instances.every(instance => {
|
|
278
|
+
return (
|
|
279
|
+
instance.FrameReferenceTime &&
|
|
280
|
+
instance.FrameReferenceTime > 0 &&
|
|
281
|
+
instance.ActualFrameDuration &&
|
|
282
|
+
instance.ActualFrameDuration > 0
|
|
283
|
+
);
|
|
284
|
+
});*/
|
|
285
|
+
// TODO: Temporarily commented out the checks and logic below to
|
|
286
|
+
// investigate the BQML_AC_DT_lessThan_S_DT_SIEMENS-instances case
|
|
287
|
+
//if (!hasValidFrameTimes) {
|
|
288
|
+
return results.fill(earliestAcquisitionDateTime); //}
|
|
289
|
+
|
|
290
|
+
/* Siemens PETsyngo 3.x multi-injection logic
|
|
291
|
+
- backcompute from center (average count rate ) of time window for bed position (frame) in series (reliable in all cases)
|
|
292
|
+
- Acquisition Date (0x0008,0x0022) and Time (0x0008,0x0032) are the start of the bed position (frame)
|
|
293
|
+
- Frame Reference Time (0x0054,0x1300) is the offset (ms) from the scan Date and Time we want to the average count rate time
|
|
294
|
+
*/
|
|
295
|
+
|
|
296
|
+
/*return instances.map(instance => {
|
|
297
|
+
const {
|
|
298
|
+
FrameReferenceTime,
|
|
299
|
+
ActualFrameDuration,
|
|
300
|
+
RadionuclideHalfLife,
|
|
301
|
+
AcquisitionDate,
|
|
302
|
+
AcquisitionTime,
|
|
303
|
+
} = instance;
|
|
304
|
+
// Some of these checks are only here because the compiler is complaining
|
|
305
|
+
// We could potentially use the ! operator instead
|
|
306
|
+
if (!FrameReferenceTime || FrameReferenceTime <= 0) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
`FrameReferenceTime is invalid: ${FrameReferenceTime}`
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
if (!ActualFrameDuration || ActualFrameDuration <= 0) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
`ActualFrameDuration is invalid: ${ActualFrameDuration}`
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
if (!RadionuclideHalfLife) {
|
|
317
|
+
throw new Error('RadionuclideHalfLife is required');
|
|
318
|
+
}
|
|
319
|
+
if (!AcquisitionDate) {
|
|
320
|
+
throw new Error('AcquisitionDate is required');
|
|
321
|
+
}
|
|
322
|
+
if (!AcquisitionTime) {
|
|
323
|
+
throw new Error('AcquisitionTime is required');
|
|
324
|
+
}
|
|
325
|
+
const acquisitionDate: DateInterface = parseDA(AcquisitionDate);
|
|
326
|
+
const acquisitionTime: TimeInterface = parseTM(AcquisitionTime);
|
|
327
|
+
const acquisitionDateTime: FullDateInterface = combineDateTime(
|
|
328
|
+
acquisitionDate,
|
|
329
|
+
acquisitionTime
|
|
330
|
+
);
|
|
331
|
+
const frameDurationInSec = ActualFrameDuration / 1000;
|
|
332
|
+
const decayConstant = Math.log(2) / RadionuclideHalfLife;
|
|
333
|
+
const decayDuringFrame = decayConstant * frameDurationInSec;
|
|
334
|
+
// TODO: double check this is correctly copied from QIBA pseudocode
|
|
335
|
+
const averageCountRateTimeWithinFrameInSec =
|
|
336
|
+
(1 / decayConstant) *
|
|
337
|
+
Math.log(decayDuringFrame / (1 - Math.exp(-decayConstant)));
|
|
338
|
+
const scanDateTimeAsNumber =
|
|
339
|
+
Number(acquisitionDateTime) -
|
|
340
|
+
FrameReferenceTime / 1000 +
|
|
341
|
+
averageCountRateTimeWithinFrameInSec;
|
|
342
|
+
const scanDate = new Date(scanDateTimeAsNumber);
|
|
343
|
+
console.log('SIEMENS PATH');
|
|
344
|
+
console.log(new Date(scanDateTimeAsNumber));
|
|
345
|
+
return scanDate;
|
|
346
|
+
});*/
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function calculateSUVlbmScalingFactor(inputs) {
|
|
352
|
+
const {
|
|
353
|
+
PatientSex,
|
|
354
|
+
PatientWeight,
|
|
355
|
+
PatientSize
|
|
356
|
+
} = inputs;
|
|
357
|
+
let LBM;
|
|
358
|
+
const bodyMassIndex = PatientWeight * PatientWeight / (PatientSize * PatientSize * 10000); // convert size in cm
|
|
359
|
+
// reference: https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/
|
|
360
|
+
|
|
361
|
+
if (PatientSex === 'F') {
|
|
362
|
+
LBM = 1.07 * PatientWeight - 148 * bodyMassIndex;
|
|
363
|
+
} else if (PatientSex === 'M') {
|
|
364
|
+
LBM = 1.1 * PatientWeight - 120 * bodyMassIndex;
|
|
365
|
+
} else {
|
|
366
|
+
throw new Error(`PatientSex is an invalid value: ${PatientSex}`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return LBM * 1000; // convert in gr
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function calculateSUVbsaScalingFactor(inputs) {
|
|
373
|
+
const {
|
|
374
|
+
PatientWeight,
|
|
375
|
+
PatientSize
|
|
376
|
+
} = inputs;
|
|
377
|
+
let BSA = Math.pow(PatientWeight, 0.425) * Math.pow(PatientSize * 100, 0.725) * 71.84;
|
|
378
|
+
return BSA;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Calculate start time
|
|
383
|
+
*
|
|
384
|
+
* @export
|
|
385
|
+
* @param {{
|
|
386
|
+
* RadiopharmaceuticalStartDateTime?: string;
|
|
387
|
+
* RadiopharmaceuticalStartTime?: string;
|
|
388
|
+
* SeriesDate?: string;
|
|
389
|
+
* }} input
|
|
390
|
+
* @returns {FullDateInterface}
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
function calculateStartTime(input) {
|
|
394
|
+
const {
|
|
395
|
+
RadiopharmaceuticalStartDateTime,
|
|
396
|
+
RadiopharmaceuticalStartTime,
|
|
397
|
+
SeriesDate
|
|
398
|
+
} = input;
|
|
399
|
+
let time;
|
|
400
|
+
let date;
|
|
401
|
+
|
|
402
|
+
if (RadiopharmaceuticalStartDateTime) {
|
|
403
|
+
return dateTimeToFullDateInterface(RadiopharmaceuticalStartDateTime);
|
|
404
|
+
} else if (RadiopharmaceuticalStartTime && SeriesDate) {
|
|
405
|
+
// start Date is not explicit - assume same as Series Date;
|
|
406
|
+
// but consider spanning midnight
|
|
407
|
+
// TODO: do we need some logic to check if the scan went over midnight?
|
|
408
|
+
time = parseTM(RadiopharmaceuticalStartTime);
|
|
409
|
+
date = parseDA(SeriesDate);
|
|
410
|
+
return combineDateTime(date, time);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
throw new Error(`Invalid input: ${input}`);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* The injected dose used to calculate SUV is corrected for the
|
|
418
|
+
* decay that occurs between the time of injection and the start of the scan
|
|
419
|
+
*
|
|
420
|
+
* @param {InstanceMetadata[]} instances
|
|
421
|
+
* @returns {number[]}
|
|
422
|
+
*/
|
|
423
|
+
|
|
424
|
+
function calculateDecayCorrection(instances) {
|
|
425
|
+
const {
|
|
426
|
+
RadionuclideTotalDose,
|
|
427
|
+
RadionuclideHalfLife,
|
|
428
|
+
RadiopharmaceuticalStartDateTime,
|
|
429
|
+
RadiopharmaceuticalStartTime,
|
|
430
|
+
SeriesDate
|
|
431
|
+
} = instances[0];
|
|
432
|
+
|
|
433
|
+
if (RadionuclideTotalDose === undefined || RadionuclideTotalDose === null) {
|
|
434
|
+
throw new Error('calculateDecayCorrection : RadionuclideTotalDose value not found.');
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (RadionuclideHalfLife === undefined || RadionuclideHalfLife === null) {
|
|
438
|
+
throw new Error('calculateDecayCorrection : RadionuclideHalfLife value not found.');
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const scanTimes = calculateScanTimes(instances);
|
|
442
|
+
const startTime = calculateStartTime({
|
|
443
|
+
RadiopharmaceuticalStartDateTime,
|
|
444
|
+
RadiopharmaceuticalStartTime,
|
|
445
|
+
SeriesDate
|
|
446
|
+
});
|
|
447
|
+
return instances.map((_, index) => {
|
|
448
|
+
const scanTime = scanTimes[index];
|
|
449
|
+
const decayTimeInSec = scanTime.getTimeInSec() - startTime.getTimeInSec();
|
|
450
|
+
|
|
451
|
+
if (decayTimeInSec < 0) {
|
|
452
|
+
throw new Error('Decay time cannot be less than zero');
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const decayedDose = RadionuclideTotalDose * Math.pow(2, -decayTimeInSec / RadionuclideHalfLife);
|
|
456
|
+
return 1 / decayedDose;
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
*
|
|
461
|
+
* @param a Simple value or array of simple values
|
|
462
|
+
* @param b Simple value or array of simple values
|
|
463
|
+
* @returns boolean true if the values are equal.
|
|
464
|
+
*/
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
const deepEquals = (a, b) => {
|
|
468
|
+
return a === b || Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]);
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Calculate the SUV factor
|
|
472
|
+
*
|
|
473
|
+
* Note: Rescale Slope / Intercept must still be applied. These must be applied
|
|
474
|
+
* on a per-Frame basis, since some scanners may have different values per Frame.
|
|
475
|
+
*
|
|
476
|
+
* @export
|
|
477
|
+
* @param {InstanceMetadata[]} instances
|
|
478
|
+
* @returns {ScalingFactorResult[]}
|
|
479
|
+
*/
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
function calculateSUVScalingFactors(instances) {
|
|
483
|
+
const {
|
|
484
|
+
CorrectedImage,
|
|
485
|
+
Units,
|
|
486
|
+
PhilipsPETPrivateGroup,
|
|
487
|
+
PatientWeight,
|
|
488
|
+
PatientSex,
|
|
489
|
+
PatientSize
|
|
490
|
+
} = instances[0];
|
|
491
|
+
|
|
492
|
+
if (!CorrectedImage.includes('ATTN') || !CorrectedImage.includes('DECY')) {
|
|
493
|
+
throw new Error(`CorrectedImage must contain "ATTN" and "DECY": ${CorrectedImage}`);
|
|
494
|
+
} // Sanity check that every instance provided has identical
|
|
495
|
+
// values for series-level metadata. If not, the provided
|
|
496
|
+
// data is invalid.
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
const isSingleSeries = instances.every(instance => {
|
|
500
|
+
return instance.Units === Units && deepEquals(instance.CorrectedImage, CorrectedImage) && instance.PatientWeight === PatientWeight && instance.PatientSex === PatientSex && instance.PatientSize === PatientSize && instance.RadionuclideHalfLife === instances[0].RadionuclideHalfLife && instance.RadionuclideTotalDose === instances[0].RadionuclideTotalDose && instance.DecayCorrection === instances[0].DecayCorrection && instance.SeriesDate === instances[0].SeriesDate && instance.SeriesTime === instances[0].SeriesTime;
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
if (!isSingleSeries) {
|
|
504
|
+
throw new Error('The set of instances does not appear to come from one Series. Every instance must have identical values for series-level metadata properties');
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (PatientWeight === null || PatientWeight === undefined) {
|
|
508
|
+
throw new Error('PatientWeight value is missing. It is not possible to calculate the SUV factors');
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
let decayCorrectionArray = new Array(instances.length);
|
|
512
|
+
decayCorrectionArray = calculateDecayCorrection(instances);
|
|
513
|
+
let results = new Array(instances.length);
|
|
514
|
+
const weightInGrams = PatientWeight * 1000;
|
|
515
|
+
|
|
516
|
+
if (Units === 'BQML') {
|
|
517
|
+
results = decayCorrectionArray.map(function (value) {
|
|
518
|
+
return value * weightInGrams;
|
|
519
|
+
});
|
|
520
|
+
} else if (Units === 'CNTS') {
|
|
521
|
+
const hasValidSUVScaleFactor = instances.every(instance => {
|
|
522
|
+
var _instance$PhilipsPETP, _instance$PhilipsPETP2, _instance$PhilipsPETP3;
|
|
523
|
+
|
|
524
|
+
return instance.PhilipsPETPrivateGroup && ((_instance$PhilipsPETP = instance.PhilipsPETPrivateGroup) === null || _instance$PhilipsPETP === void 0 ? void 0 : _instance$PhilipsPETP.SUVScaleFactor) !== null && ((_instance$PhilipsPETP2 = instance.PhilipsPETPrivateGroup) === null || _instance$PhilipsPETP2 === void 0 ? void 0 : _instance$PhilipsPETP2.SUVScaleFactor) !== undefined && ((_instance$PhilipsPETP3 = instance.PhilipsPETPrivateGroup) === null || _instance$PhilipsPETP3 === void 0 ? void 0 : _instance$PhilipsPETP3.SUVScaleFactor) !== 0;
|
|
525
|
+
});
|
|
526
|
+
const hasValidActivityConcentrationScaleFactor = instances.every(instance => {
|
|
527
|
+
var _instance$PhilipsPETP4, _instance$PhilipsPETP5, _instance$PhilipsPETP6;
|
|
528
|
+
|
|
529
|
+
return instance.PhilipsPETPrivateGroup && !((_instance$PhilipsPETP4 = instance.PhilipsPETPrivateGroup) !== null && _instance$PhilipsPETP4 !== void 0 && _instance$PhilipsPETP4.SUVScaleFactor) && ((_instance$PhilipsPETP5 = instance.PhilipsPETPrivateGroup) === null || _instance$PhilipsPETP5 === void 0 ? void 0 : _instance$PhilipsPETP5.ActivityConcentrationScaleFactor) !== undefined && ((_instance$PhilipsPETP6 = instance.PhilipsPETPrivateGroup) === null || _instance$PhilipsPETP6 === void 0 ? void 0 : _instance$PhilipsPETP6.ActivityConcentrationScaleFactor) !== 0;
|
|
530
|
+
}); //console.log(`hasValidSUVScaleFactor: ${hasValidSUVScaleFactor}`);
|
|
531
|
+
//console.log(`hasValidActivityConcentrationScaleFactor: ${hasValidActivityConcentrationScaleFactor}`);
|
|
532
|
+
|
|
533
|
+
if (hasValidSUVScaleFactor) {
|
|
534
|
+
results = instances.map( // Added ! to tell Typescript that this can't be undefined, since we are testing it
|
|
535
|
+
// in the .every loop above.
|
|
536
|
+
instance => instance.PhilipsPETPrivateGroup.SUVScaleFactor);
|
|
537
|
+
} else if (hasValidActivityConcentrationScaleFactor) {
|
|
538
|
+
// if (0x7053,0x1000) not present, but (0x7053,0x1009) is present, then (0x7053,0x1009) * Rescale Slope,
|
|
539
|
+
// scales pixels to Bq/ml, and proceed as if Units are BQML
|
|
540
|
+
results = instances.map((instance, index) => {
|
|
541
|
+
// Added ! to tell Typescript that this can't be undefined, since we are testing it
|
|
542
|
+
// in the .every loop above.
|
|
543
|
+
return instance.PhilipsPETPrivateGroup.ActivityConcentrationScaleFactor * decayCorrectionArray[index] * weightInGrams;
|
|
544
|
+
});
|
|
545
|
+
} else {
|
|
546
|
+
throw new Error(`Units are in CNTS, but PhilipsPETPrivateGroup has invalid values: ${JSON.stringify(PhilipsPETPrivateGroup)}`);
|
|
547
|
+
}
|
|
548
|
+
} else if (Units === 'GML') {
|
|
549
|
+
// assumes that GML indicates SUVbw instead of SUVlbm
|
|
550
|
+
results.fill(1);
|
|
551
|
+
} else {
|
|
552
|
+
throw new Error(`Units has an invalid value: ${Units}`);
|
|
553
|
+
} // get BSA
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
let suvbsaFactor;
|
|
557
|
+
|
|
558
|
+
if (PatientSize === null || PatientSize === undefined) {
|
|
559
|
+
console.warn('PatientSize value is missing. It is not possible to calculate the SUV bsa factors');
|
|
560
|
+
} else {
|
|
561
|
+
const sulInputs = {
|
|
562
|
+
PatientWeight,
|
|
563
|
+
PatientSize
|
|
564
|
+
};
|
|
565
|
+
suvbsaFactor = calculateSUVbsaScalingFactor(sulInputs);
|
|
566
|
+
} // get LBM
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
let suvlbmFactor;
|
|
570
|
+
|
|
571
|
+
if (PatientSize === null || PatientSize === undefined) {
|
|
572
|
+
console.warn('PatientSize value is missing. It is not possible to calculate the SUV lbm factors');
|
|
573
|
+
} else if (PatientSex === null || PatientSex === undefined) {
|
|
574
|
+
console.warn('PatientSex value is missing. It is not possible to calculate the SUV lbm factors');
|
|
575
|
+
} else {
|
|
576
|
+
const suvlbmInputs = {
|
|
577
|
+
PatientWeight,
|
|
578
|
+
PatientSex,
|
|
579
|
+
PatientSize
|
|
580
|
+
};
|
|
581
|
+
suvlbmFactor = calculateSUVlbmScalingFactor(suvlbmInputs);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return results.map(function (result, index) {
|
|
585
|
+
const factors = {
|
|
586
|
+
suvbw: result
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
if (suvbsaFactor) {
|
|
590
|
+
// multiply for BSA
|
|
591
|
+
factors.suvbsa = decayCorrectionArray[index] * suvbsaFactor;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (suvlbmFactor) {
|
|
595
|
+
// multiply for LBM
|
|
596
|
+
factors.suvlbm = decayCorrectionArray[index] * suvlbmFactor;
|
|
597
|
+
} // factor formulaes taken from:
|
|
598
|
+
// https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
return factors;
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
//# sourceMappingURL=calculate-suv.esm.js.map
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
/***/ }),
|
|
610
|
+
|
|
611
|
+
/***/ 21767:
|
|
612
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
613
|
+
|
|
614
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
615
|
+
/* harmony export */ "S_": () => (/* binding */ VariableSizeList)
|
|
616
|
+
/* harmony export */ });
|
|
617
|
+
/* unused harmony exports FixedSizeGrid, FixedSizeList, VariableSizeGrid, areEqual, shouldComponentUpdate */
|
|
618
|
+
/* harmony import */ var _babel_runtime_helpers_esm_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20011);
|
|
619
|
+
/* harmony import */ var _babel_runtime_helpers_esm_assertThisInitialized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93173);
|
|
620
|
+
/* harmony import */ var _babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(23788);
|
|
621
|
+
/* harmony import */ var memoize_one__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(89454);
|
|
622
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(32735);
|
|
623
|
+
/* harmony import */ var _babel_runtime_helpers_esm_objectWithoutPropertiesLoose__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(66017);
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
// Animation frame based implementation of setTimeout.
|
|
632
|
+
// Inspired by Joe Lambert, https://gist.github.com/joelambert/1002116#file-requesttimeout-js
|
|
633
|
+
var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';
|
|
634
|
+
var now = hasNativePerformanceNow ? function () {
|
|
635
|
+
return performance.now();
|
|
636
|
+
} : function () {
|
|
637
|
+
return Date.now();
|
|
638
|
+
};
|
|
639
|
+
function cancelTimeout(timeoutID) {
|
|
640
|
+
cancelAnimationFrame(timeoutID.id);
|
|
641
|
+
}
|
|
642
|
+
function requestTimeout(callback, delay) {
|
|
643
|
+
var start = now();
|
|
644
|
+
|
|
645
|
+
function tick() {
|
|
646
|
+
if (now() - start >= delay) {
|
|
647
|
+
callback.call(null);
|
|
648
|
+
} else {
|
|
649
|
+
timeoutID.id = requestAnimationFrame(tick);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
var timeoutID = {
|
|
654
|
+
id: requestAnimationFrame(tick)
|
|
655
|
+
};
|
|
656
|
+
return timeoutID;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
var size = -1; // This utility copied from "dom-helpers" package.
|
|
660
|
+
|
|
661
|
+
function getScrollbarSize(recalculate) {
|
|
662
|
+
if (recalculate === void 0) {
|
|
663
|
+
recalculate = false;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (size === -1 || recalculate) {
|
|
667
|
+
var div = document.createElement('div');
|
|
668
|
+
var style = div.style;
|
|
669
|
+
style.width = '50px';
|
|
670
|
+
style.height = '50px';
|
|
671
|
+
style.overflow = 'scroll';
|
|
672
|
+
document.body.appendChild(div);
|
|
673
|
+
size = div.offsetWidth - div.clientWidth;
|
|
674
|
+
document.body.removeChild(div);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
return size;
|
|
678
|
+
}
|
|
679
|
+
var cachedRTLResult = null; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
680
|
+
// Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
|
|
681
|
+
// Safari's elastic bounce makes detecting this even more complicated wrt potential false positives.
|
|
682
|
+
// The safest way to check this is to intentionally set a negative offset,
|
|
683
|
+
// and then verify that the subsequent "scroll" event matches the negative offset.
|
|
684
|
+
// If it does not match, then we can assume a non-standard RTL scroll implementation.
|
|
685
|
+
|
|
686
|
+
function getRTLOffsetType(recalculate) {
|
|
687
|
+
if (recalculate === void 0) {
|
|
688
|
+
recalculate = false;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
if (cachedRTLResult === null || recalculate) {
|
|
692
|
+
var outerDiv = document.createElement('div');
|
|
693
|
+
var outerStyle = outerDiv.style;
|
|
694
|
+
outerStyle.width = '50px';
|
|
695
|
+
outerStyle.height = '50px';
|
|
696
|
+
outerStyle.overflow = 'scroll';
|
|
697
|
+
outerStyle.direction = 'rtl';
|
|
698
|
+
var innerDiv = document.createElement('div');
|
|
699
|
+
var innerStyle = innerDiv.style;
|
|
700
|
+
innerStyle.width = '100px';
|
|
701
|
+
innerStyle.height = '100px';
|
|
702
|
+
outerDiv.appendChild(innerDiv);
|
|
703
|
+
document.body.appendChild(outerDiv);
|
|
704
|
+
|
|
705
|
+
if (outerDiv.scrollLeft > 0) {
|
|
706
|
+
cachedRTLResult = 'positive-descending';
|
|
707
|
+
} else {
|
|
708
|
+
outerDiv.scrollLeft = 1;
|
|
709
|
+
|
|
710
|
+
if (outerDiv.scrollLeft === 0) {
|
|
711
|
+
cachedRTLResult = 'negative';
|
|
712
|
+
} else {
|
|
713
|
+
cachedRTLResult = 'positive-ascending';
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
document.body.removeChild(outerDiv);
|
|
718
|
+
return cachedRTLResult;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return cachedRTLResult;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
var IS_SCROLLING_DEBOUNCE_INTERVAL = 150;
|
|
725
|
+
|
|
726
|
+
var defaultItemKey = function defaultItemKey(_ref) {
|
|
727
|
+
var columnIndex = _ref.columnIndex,
|
|
728
|
+
data = _ref.data,
|
|
729
|
+
rowIndex = _ref.rowIndex;
|
|
730
|
+
return rowIndex + ":" + columnIndex;
|
|
731
|
+
}; // In DEV mode, this Set helps us only log a warning once per component instance.
|
|
732
|
+
// This avoids spamming the console every time a render happens.
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
var devWarningsOverscanCount = null;
|
|
736
|
+
var devWarningsOverscanRowsColumnsCount = null;
|
|
737
|
+
var devWarningsTagName = null;
|
|
738
|
+
|
|
739
|
+
if (false) {}
|
|
740
|
+
|
|
741
|
+
function createGridComponent(_ref2) {
|
|
742
|
+
var _class;
|
|
743
|
+
|
|
744
|
+
var getColumnOffset = _ref2.getColumnOffset,
|
|
745
|
+
getColumnStartIndexForOffset = _ref2.getColumnStartIndexForOffset,
|
|
746
|
+
getColumnStopIndexForStartIndex = _ref2.getColumnStopIndexForStartIndex,
|
|
747
|
+
getColumnWidth = _ref2.getColumnWidth,
|
|
748
|
+
getEstimatedTotalHeight = _ref2.getEstimatedTotalHeight,
|
|
749
|
+
getEstimatedTotalWidth = _ref2.getEstimatedTotalWidth,
|
|
750
|
+
getOffsetForColumnAndAlignment = _ref2.getOffsetForColumnAndAlignment,
|
|
751
|
+
getOffsetForRowAndAlignment = _ref2.getOffsetForRowAndAlignment,
|
|
752
|
+
getRowHeight = _ref2.getRowHeight,
|
|
753
|
+
getRowOffset = _ref2.getRowOffset,
|
|
754
|
+
getRowStartIndexForOffset = _ref2.getRowStartIndexForOffset,
|
|
755
|
+
getRowStopIndexForStartIndex = _ref2.getRowStopIndexForStartIndex,
|
|
756
|
+
initInstanceProps = _ref2.initInstanceProps,
|
|
757
|
+
shouldResetStyleCacheOnItemSizeChange = _ref2.shouldResetStyleCacheOnItemSizeChange,
|
|
758
|
+
validateProps = _ref2.validateProps;
|
|
759
|
+
return _class = /*#__PURE__*/function (_PureComponent) {
|
|
760
|
+
(0,_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(Grid, _PureComponent);
|
|
761
|
+
|
|
762
|
+
// Always use explicit constructor for React components.
|
|
763
|
+
// It produces less code after transpilation. (#26)
|
|
764
|
+
// eslint-disable-next-line no-useless-constructor
|
|
765
|
+
function Grid(props) {
|
|
766
|
+
var _this;
|
|
767
|
+
|
|
768
|
+
_this = _PureComponent.call(this, props) || this;
|
|
769
|
+
_this._instanceProps = initInstanceProps(_this.props, (0,_babel_runtime_helpers_esm_assertThisInitialized__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(_this));
|
|
770
|
+
_this._resetIsScrollingTimeoutId = null;
|
|
771
|
+
_this._outerRef = void 0;
|
|
772
|
+
_this.state = {
|
|
773
|
+
instance: (0,_babel_runtime_helpers_esm_assertThisInitialized__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(_this),
|
|
774
|
+
isScrolling: false,
|
|
775
|
+
horizontalScrollDirection: 'forward',
|
|
776
|
+
scrollLeft: typeof _this.props.initialScrollLeft === 'number' ? _this.props.initialScrollLeft : 0,
|
|
777
|
+
scrollTop: typeof _this.props.initialScrollTop === 'number' ? _this.props.initialScrollTop : 0,
|
|
778
|
+
scrollUpdateWasRequested: false,
|
|
779
|
+
verticalScrollDirection: 'forward'
|
|
780
|
+
};
|
|
781
|
+
_this._callOnItemsRendered = void 0;
|
|
782
|
+
_this._callOnItemsRendered = (0,memoize_one__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(function (overscanColumnStartIndex, overscanColumnStopIndex, overscanRowStartIndex, overscanRowStopIndex, visibleColumnStartIndex, visibleColumnStopIndex, visibleRowStartIndex, visibleRowStopIndex) {
|
|
783
|
+
return _this.props.onItemsRendered({
|
|
784
|
+
overscanColumnStartIndex: overscanColumnStartIndex,
|
|
785
|
+
overscanColumnStopIndex: overscanColumnStopIndex,
|
|
786
|
+
overscanRowStartIndex: overscanRowStartIndex,
|
|
787
|
+
overscanRowStopIndex: overscanRowStopIndex,
|
|
788
|
+
visibleColumnStartIndex: visibleColumnStartIndex,
|
|
789
|
+
visibleColumnStopIndex: visibleColumnStopIndex,
|
|
790
|
+
visibleRowStartIndex: visibleRowStartIndex,
|
|
791
|
+
visibleRowStopIndex: visibleRowStopIndex
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
_this._callOnScroll = void 0;
|
|
795
|
+
_this._callOnScroll = (0,memoize_one__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(function (scrollLeft, scrollTop, horizontalScrollDirection, verticalScrollDirection, scrollUpdateWasRequested) {
|
|
796
|
+
return _this.props.onScroll({
|
|
797
|
+
horizontalScrollDirection: horizontalScrollDirection,
|
|
798
|
+
scrollLeft: scrollLeft,
|
|
799
|
+
scrollTop: scrollTop,
|
|
800
|
+
verticalScrollDirection: verticalScrollDirection,
|
|
801
|
+
scrollUpdateWasRequested: scrollUpdateWasRequested
|
|
802
|
+
});
|
|
803
|
+
});
|
|
804
|
+
_this._getItemStyle = void 0;
|
|
805
|
+
|
|
806
|
+
_this._getItemStyle = function (rowIndex, columnIndex) {
|
|
807
|
+
var _this$props = _this.props,
|
|
808
|
+
columnWidth = _this$props.columnWidth,
|
|
809
|
+
direction = _this$props.direction,
|
|
810
|
+
rowHeight = _this$props.rowHeight;
|
|
811
|
+
|
|
812
|
+
var itemStyleCache = _this._getItemStyleCache(shouldResetStyleCacheOnItemSizeChange && columnWidth, shouldResetStyleCacheOnItemSizeChange && direction, shouldResetStyleCacheOnItemSizeChange && rowHeight);
|
|
813
|
+
|
|
814
|
+
var key = rowIndex + ":" + columnIndex;
|
|
815
|
+
var style;
|
|
816
|
+
|
|
817
|
+
if (itemStyleCache.hasOwnProperty(key)) {
|
|
818
|
+
style = itemStyleCache[key];
|
|
819
|
+
} else {
|
|
820
|
+
var _offset = getColumnOffset(_this.props, columnIndex, _this._instanceProps);
|
|
821
|
+
|
|
822
|
+
var isRtl = direction === 'rtl';
|
|
823
|
+
itemStyleCache[key] = style = {
|
|
824
|
+
position: 'absolute',
|
|
825
|
+
left: isRtl ? undefined : _offset,
|
|
826
|
+
right: isRtl ? _offset : undefined,
|
|
827
|
+
top: getRowOffset(_this.props, rowIndex, _this._instanceProps),
|
|
828
|
+
height: getRowHeight(_this.props, rowIndex, _this._instanceProps),
|
|
829
|
+
width: getColumnWidth(_this.props, columnIndex, _this._instanceProps)
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
return style;
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
_this._getItemStyleCache = void 0;
|
|
837
|
+
_this._getItemStyleCache = (0,memoize_one__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(function (_, __, ___) {
|
|
838
|
+
return {};
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
_this._onScroll = function (event) {
|
|
842
|
+
var _event$currentTarget = event.currentTarget,
|
|
843
|
+
clientHeight = _event$currentTarget.clientHeight,
|
|
844
|
+
clientWidth = _event$currentTarget.clientWidth,
|
|
845
|
+
scrollLeft = _event$currentTarget.scrollLeft,
|
|
846
|
+
scrollTop = _event$currentTarget.scrollTop,
|
|
847
|
+
scrollHeight = _event$currentTarget.scrollHeight,
|
|
848
|
+
scrollWidth = _event$currentTarget.scrollWidth;
|
|
849
|
+
|
|
850
|
+
_this.setState(function (prevState) {
|
|
851
|
+
if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
|
|
852
|
+
// Scroll position may have been updated by cDM/cDU,
|
|
853
|
+
// In which case we don't need to trigger another render,
|
|
854
|
+
// And we don't want to update state.isScrolling.
|
|
855
|
+
return null;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
var direction = _this.props.direction; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
859
|
+
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
|
860
|
+
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
|
861
|
+
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
|
862
|
+
|
|
863
|
+
var calculatedScrollLeft = scrollLeft;
|
|
864
|
+
|
|
865
|
+
if (direction === 'rtl') {
|
|
866
|
+
switch (getRTLOffsetType()) {
|
|
867
|
+
case 'negative':
|
|
868
|
+
calculatedScrollLeft = -scrollLeft;
|
|
869
|
+
break;
|
|
870
|
+
|
|
871
|
+
case 'positive-descending':
|
|
872
|
+
calculatedScrollLeft = scrollWidth - clientWidth - scrollLeft;
|
|
873
|
+
break;
|
|
874
|
+
}
|
|
875
|
+
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
calculatedScrollLeft = Math.max(0, Math.min(calculatedScrollLeft, scrollWidth - clientWidth));
|
|
879
|
+
var calculatedScrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
|
|
880
|
+
return {
|
|
881
|
+
isScrolling: true,
|
|
882
|
+
horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
|
883
|
+
scrollLeft: calculatedScrollLeft,
|
|
884
|
+
scrollTop: calculatedScrollTop,
|
|
885
|
+
verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward',
|
|
886
|
+
scrollUpdateWasRequested: false
|
|
887
|
+
};
|
|
888
|
+
}, _this._resetIsScrollingDebounced);
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
_this._outerRefSetter = function (ref) {
|
|
892
|
+
var outerRef = _this.props.outerRef;
|
|
893
|
+
_this._outerRef = ref;
|
|
894
|
+
|
|
895
|
+
if (typeof outerRef === 'function') {
|
|
896
|
+
outerRef(ref);
|
|
897
|
+
} else if (outerRef != null && typeof outerRef === 'object' && outerRef.hasOwnProperty('current')) {
|
|
898
|
+
outerRef.current = ref;
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
_this._resetIsScrollingDebounced = function () {
|
|
903
|
+
if (_this._resetIsScrollingTimeoutId !== null) {
|
|
904
|
+
cancelTimeout(_this._resetIsScrollingTimeoutId);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
_this._resetIsScrollingTimeoutId = requestTimeout(_this._resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL);
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
_this._resetIsScrolling = function () {
|
|
911
|
+
_this._resetIsScrollingTimeoutId = null;
|
|
912
|
+
|
|
913
|
+
_this.setState({
|
|
914
|
+
isScrolling: false
|
|
915
|
+
}, function () {
|
|
916
|
+
// Clear style cache after state update has been committed.
|
|
917
|
+
// This way we don't break pure sCU for items that don't use isScrolling param.
|
|
918
|
+
_this._getItemStyleCache(-1);
|
|
919
|
+
});
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
return _this;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
Grid.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
|
|
926
|
+
validateSharedProps(nextProps, prevState);
|
|
927
|
+
validateProps(nextProps);
|
|
928
|
+
return null;
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
var _proto = Grid.prototype;
|
|
932
|
+
|
|
933
|
+
_proto.scrollTo = function scrollTo(_ref3) {
|
|
934
|
+
var scrollLeft = _ref3.scrollLeft,
|
|
935
|
+
scrollTop = _ref3.scrollTop;
|
|
936
|
+
|
|
937
|
+
if (scrollLeft !== undefined) {
|
|
938
|
+
scrollLeft = Math.max(0, scrollLeft);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
if (scrollTop !== undefined) {
|
|
942
|
+
scrollTop = Math.max(0, scrollTop);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
this.setState(function (prevState) {
|
|
946
|
+
if (scrollLeft === undefined) {
|
|
947
|
+
scrollLeft = prevState.scrollLeft;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
if (scrollTop === undefined) {
|
|
951
|
+
scrollTop = prevState.scrollTop;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
if (prevState.scrollLeft === scrollLeft && prevState.scrollTop === scrollTop) {
|
|
955
|
+
return null;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
return {
|
|
959
|
+
horizontalScrollDirection: prevState.scrollLeft < scrollLeft ? 'forward' : 'backward',
|
|
960
|
+
scrollLeft: scrollLeft,
|
|
961
|
+
scrollTop: scrollTop,
|
|
962
|
+
scrollUpdateWasRequested: true,
|
|
963
|
+
verticalScrollDirection: prevState.scrollTop < scrollTop ? 'forward' : 'backward'
|
|
964
|
+
};
|
|
965
|
+
}, this._resetIsScrollingDebounced);
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
_proto.scrollToItem = function scrollToItem(_ref4) {
|
|
969
|
+
var _ref4$align = _ref4.align,
|
|
970
|
+
align = _ref4$align === void 0 ? 'auto' : _ref4$align,
|
|
971
|
+
columnIndex = _ref4.columnIndex,
|
|
972
|
+
rowIndex = _ref4.rowIndex;
|
|
973
|
+
var _this$props2 = this.props,
|
|
974
|
+
columnCount = _this$props2.columnCount,
|
|
975
|
+
height = _this$props2.height,
|
|
976
|
+
rowCount = _this$props2.rowCount,
|
|
977
|
+
width = _this$props2.width;
|
|
978
|
+
var _this$state = this.state,
|
|
979
|
+
scrollLeft = _this$state.scrollLeft,
|
|
980
|
+
scrollTop = _this$state.scrollTop;
|
|
981
|
+
var scrollbarSize = getScrollbarSize();
|
|
982
|
+
|
|
983
|
+
if (columnIndex !== undefined) {
|
|
984
|
+
columnIndex = Math.max(0, Math.min(columnIndex, columnCount - 1));
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
if (rowIndex !== undefined) {
|
|
988
|
+
rowIndex = Math.max(0, Math.min(rowIndex, rowCount - 1));
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
var estimatedTotalHeight = getEstimatedTotalHeight(this.props, this._instanceProps);
|
|
992
|
+
var estimatedTotalWidth = getEstimatedTotalWidth(this.props, this._instanceProps); // The scrollbar size should be considered when scrolling an item into view,
|
|
993
|
+
// to ensure it's fully visible.
|
|
994
|
+
// But we only need to account for its size when it's actually visible.
|
|
995
|
+
|
|
996
|
+
var horizontalScrollbarSize = estimatedTotalWidth > width ? scrollbarSize : 0;
|
|
997
|
+
var verticalScrollbarSize = estimatedTotalHeight > height ? scrollbarSize : 0;
|
|
998
|
+
this.scrollTo({
|
|
999
|
+
scrollLeft: columnIndex !== undefined ? getOffsetForColumnAndAlignment(this.props, columnIndex, align, scrollLeft, this._instanceProps, verticalScrollbarSize) : scrollLeft,
|
|
1000
|
+
scrollTop: rowIndex !== undefined ? getOffsetForRowAndAlignment(this.props, rowIndex, align, scrollTop, this._instanceProps, horizontalScrollbarSize) : scrollTop
|
|
1001
|
+
});
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
_proto.componentDidMount = function componentDidMount() {
|
|
1005
|
+
var _this$props3 = this.props,
|
|
1006
|
+
initialScrollLeft = _this$props3.initialScrollLeft,
|
|
1007
|
+
initialScrollTop = _this$props3.initialScrollTop;
|
|
1008
|
+
|
|
1009
|
+
if (this._outerRef != null) {
|
|
1010
|
+
var outerRef = this._outerRef;
|
|
1011
|
+
|
|
1012
|
+
if (typeof initialScrollLeft === 'number') {
|
|
1013
|
+
outerRef.scrollLeft = initialScrollLeft;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
if (typeof initialScrollTop === 'number') {
|
|
1017
|
+
outerRef.scrollTop = initialScrollTop;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
this._callPropsCallbacks();
|
|
1022
|
+
};
|
|
1023
|
+
|
|
1024
|
+
_proto.componentDidUpdate = function componentDidUpdate() {
|
|
1025
|
+
var direction = this.props.direction;
|
|
1026
|
+
var _this$state2 = this.state,
|
|
1027
|
+
scrollLeft = _this$state2.scrollLeft,
|
|
1028
|
+
scrollTop = _this$state2.scrollTop,
|
|
1029
|
+
scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
|
|
1030
|
+
|
|
1031
|
+
if (scrollUpdateWasRequested && this._outerRef != null) {
|
|
1032
|
+
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
1033
|
+
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
|
1034
|
+
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
|
1035
|
+
var outerRef = this._outerRef;
|
|
1036
|
+
|
|
1037
|
+
if (direction === 'rtl') {
|
|
1038
|
+
switch (getRTLOffsetType()) {
|
|
1039
|
+
case 'negative':
|
|
1040
|
+
outerRef.scrollLeft = -scrollLeft;
|
|
1041
|
+
break;
|
|
1042
|
+
|
|
1043
|
+
case 'positive-ascending':
|
|
1044
|
+
outerRef.scrollLeft = scrollLeft;
|
|
1045
|
+
break;
|
|
1046
|
+
|
|
1047
|
+
default:
|
|
1048
|
+
var clientWidth = outerRef.clientWidth,
|
|
1049
|
+
scrollWidth = outerRef.scrollWidth;
|
|
1050
|
+
outerRef.scrollLeft = scrollWidth - clientWidth - scrollLeft;
|
|
1051
|
+
break;
|
|
1052
|
+
}
|
|
1053
|
+
} else {
|
|
1054
|
+
outerRef.scrollLeft = Math.max(0, scrollLeft);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
outerRef.scrollTop = Math.max(0, scrollTop);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
this._callPropsCallbacks();
|
|
1061
|
+
};
|
|
1062
|
+
|
|
1063
|
+
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
1064
|
+
if (this._resetIsScrollingTimeoutId !== null) {
|
|
1065
|
+
cancelTimeout(this._resetIsScrollingTimeoutId);
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
|
|
1069
|
+
_proto.render = function render() {
|
|
1070
|
+
var _this$props4 = this.props,
|
|
1071
|
+
children = _this$props4.children,
|
|
1072
|
+
className = _this$props4.className,
|
|
1073
|
+
columnCount = _this$props4.columnCount,
|
|
1074
|
+
direction = _this$props4.direction,
|
|
1075
|
+
height = _this$props4.height,
|
|
1076
|
+
innerRef = _this$props4.innerRef,
|
|
1077
|
+
innerElementType = _this$props4.innerElementType,
|
|
1078
|
+
innerTagName = _this$props4.innerTagName,
|
|
1079
|
+
itemData = _this$props4.itemData,
|
|
1080
|
+
_this$props4$itemKey = _this$props4.itemKey,
|
|
1081
|
+
itemKey = _this$props4$itemKey === void 0 ? defaultItemKey : _this$props4$itemKey,
|
|
1082
|
+
outerElementType = _this$props4.outerElementType,
|
|
1083
|
+
outerTagName = _this$props4.outerTagName,
|
|
1084
|
+
rowCount = _this$props4.rowCount,
|
|
1085
|
+
style = _this$props4.style,
|
|
1086
|
+
useIsScrolling = _this$props4.useIsScrolling,
|
|
1087
|
+
width = _this$props4.width;
|
|
1088
|
+
var isScrolling = this.state.isScrolling;
|
|
1089
|
+
|
|
1090
|
+
var _this$_getHorizontalR = this._getHorizontalRangeToRender(),
|
|
1091
|
+
columnStartIndex = _this$_getHorizontalR[0],
|
|
1092
|
+
columnStopIndex = _this$_getHorizontalR[1];
|
|
1093
|
+
|
|
1094
|
+
var _this$_getVerticalRan = this._getVerticalRangeToRender(),
|
|
1095
|
+
rowStartIndex = _this$_getVerticalRan[0],
|
|
1096
|
+
rowStopIndex = _this$_getVerticalRan[1];
|
|
1097
|
+
|
|
1098
|
+
var items = [];
|
|
1099
|
+
|
|
1100
|
+
if (columnCount > 0 && rowCount) {
|
|
1101
|
+
for (var _rowIndex = rowStartIndex; _rowIndex <= rowStopIndex; _rowIndex++) {
|
|
1102
|
+
for (var _columnIndex = columnStartIndex; _columnIndex <= columnStopIndex; _columnIndex++) {
|
|
1103
|
+
items.push((0,react__WEBPACK_IMPORTED_MODULE_4__.createElement)(children, {
|
|
1104
|
+
columnIndex: _columnIndex,
|
|
1105
|
+
data: itemData,
|
|
1106
|
+
isScrolling: useIsScrolling ? isScrolling : undefined,
|
|
1107
|
+
key: itemKey({
|
|
1108
|
+
columnIndex: _columnIndex,
|
|
1109
|
+
data: itemData,
|
|
1110
|
+
rowIndex: _rowIndex
|
|
1111
|
+
}),
|
|
1112
|
+
rowIndex: _rowIndex,
|
|
1113
|
+
style: this._getItemStyle(_rowIndex, _columnIndex)
|
|
1114
|
+
}));
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
} // Read this value AFTER items have been created,
|
|
1118
|
+
// So their actual sizes (if variable) are taken into consideration.
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
var estimatedTotalHeight = getEstimatedTotalHeight(this.props, this._instanceProps);
|
|
1122
|
+
var estimatedTotalWidth = getEstimatedTotalWidth(this.props, this._instanceProps);
|
|
1123
|
+
return (0,react__WEBPACK_IMPORTED_MODULE_4__.createElement)(outerElementType || outerTagName || 'div', {
|
|
1124
|
+
className: className,
|
|
1125
|
+
onScroll: this._onScroll,
|
|
1126
|
+
ref: this._outerRefSetter,
|
|
1127
|
+
style: (0,_babel_runtime_helpers_esm_extends__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)({
|
|
1128
|
+
position: 'relative',
|
|
1129
|
+
height: height,
|
|
1130
|
+
width: width,
|
|
1131
|
+
overflow: 'auto',
|
|
1132
|
+
WebkitOverflowScrolling: 'touch',
|
|
1133
|
+
willChange: 'transform',
|
|
1134
|
+
direction: direction
|
|
1135
|
+
}, style)
|
|
1136
|
+
}, (0,react__WEBPACK_IMPORTED_MODULE_4__.createElement)(innerElementType || innerTagName || 'div', {
|
|
1137
|
+
children: items,
|
|
1138
|
+
ref: innerRef,
|
|
1139
|
+
style: {
|
|
1140
|
+
height: estimatedTotalHeight,
|
|
1141
|
+
pointerEvents: isScrolling ? 'none' : undefined,
|
|
1142
|
+
width: estimatedTotalWidth
|
|
1143
|
+
}
|
|
1144
|
+
}));
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
_proto._callPropsCallbacks = function _callPropsCallbacks() {
|
|
1148
|
+
var _this$props5 = this.props,
|
|
1149
|
+
columnCount = _this$props5.columnCount,
|
|
1150
|
+
onItemsRendered = _this$props5.onItemsRendered,
|
|
1151
|
+
onScroll = _this$props5.onScroll,
|
|
1152
|
+
rowCount = _this$props5.rowCount;
|
|
1153
|
+
|
|
1154
|
+
if (typeof onItemsRendered === 'function') {
|
|
1155
|
+
if (columnCount > 0 && rowCount > 0) {
|
|
1156
|
+
var _this$_getHorizontalR2 = this._getHorizontalRangeToRender(),
|
|
1157
|
+
_overscanColumnStartIndex = _this$_getHorizontalR2[0],
|
|
1158
|
+
_overscanColumnStopIndex = _this$_getHorizontalR2[1],
|
|
1159
|
+
_visibleColumnStartIndex = _this$_getHorizontalR2[2],
|
|
1160
|
+
_visibleColumnStopIndex = _this$_getHorizontalR2[3];
|
|
1161
|
+
|
|
1162
|
+
var _this$_getVerticalRan2 = this._getVerticalRangeToRender(),
|
|
1163
|
+
_overscanRowStartIndex = _this$_getVerticalRan2[0],
|
|
1164
|
+
_overscanRowStopIndex = _this$_getVerticalRan2[1],
|
|
1165
|
+
_visibleRowStartIndex = _this$_getVerticalRan2[2],
|
|
1166
|
+
_visibleRowStopIndex = _this$_getVerticalRan2[3];
|
|
1167
|
+
|
|
1168
|
+
this._callOnItemsRendered(_overscanColumnStartIndex, _overscanColumnStopIndex, _overscanRowStartIndex, _overscanRowStopIndex, _visibleColumnStartIndex, _visibleColumnStopIndex, _visibleRowStartIndex, _visibleRowStopIndex);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
if (typeof onScroll === 'function') {
|
|
1173
|
+
var _this$state3 = this.state,
|
|
1174
|
+
_horizontalScrollDirection = _this$state3.horizontalScrollDirection,
|
|
1175
|
+
_scrollLeft = _this$state3.scrollLeft,
|
|
1176
|
+
_scrollTop = _this$state3.scrollTop,
|
|
1177
|
+
_scrollUpdateWasRequested = _this$state3.scrollUpdateWasRequested,
|
|
1178
|
+
_verticalScrollDirection = _this$state3.verticalScrollDirection;
|
|
1179
|
+
|
|
1180
|
+
this._callOnScroll(_scrollLeft, _scrollTop, _horizontalScrollDirection, _verticalScrollDirection, _scrollUpdateWasRequested);
|
|
1181
|
+
}
|
|
1182
|
+
} // Lazily create and cache item styles while scrolling,
|
|
1183
|
+
// So that pure component sCU will prevent re-renders.
|
|
1184
|
+
// We maintain this cache, and pass a style prop rather than index,
|
|
1185
|
+
// So that List can clear cached styles and force item re-render if necessary.
|
|
1186
|
+
;
|
|
1187
|
+
|
|
1188
|
+
_proto._getHorizontalRangeToRender = function _getHorizontalRangeToRender() {
|
|
1189
|
+
var _this$props6 = this.props,
|
|
1190
|
+
columnCount = _this$props6.columnCount,
|
|
1191
|
+
overscanColumnCount = _this$props6.overscanColumnCount,
|
|
1192
|
+
overscanColumnsCount = _this$props6.overscanColumnsCount,
|
|
1193
|
+
overscanCount = _this$props6.overscanCount,
|
|
1194
|
+
rowCount = _this$props6.rowCount;
|
|
1195
|
+
var _this$state4 = this.state,
|
|
1196
|
+
horizontalScrollDirection = _this$state4.horizontalScrollDirection,
|
|
1197
|
+
isScrolling = _this$state4.isScrolling,
|
|
1198
|
+
scrollLeft = _this$state4.scrollLeft;
|
|
1199
|
+
var overscanCountResolved = overscanColumnCount || overscanColumnsCount || overscanCount || 1;
|
|
1200
|
+
|
|
1201
|
+
if (columnCount === 0 || rowCount === 0) {
|
|
1202
|
+
return [0, 0, 0, 0];
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
var startIndex = getColumnStartIndexForOffset(this.props, scrollLeft, this._instanceProps);
|
|
1206
|
+
var stopIndex = getColumnStopIndexForStartIndex(this.props, startIndex, scrollLeft, this._instanceProps); // Overscan by one item in each direction so that tab/focus works.
|
|
1207
|
+
// If there isn't at least one extra item, tab loops back around.
|
|
1208
|
+
|
|
1209
|
+
var overscanBackward = !isScrolling || horizontalScrollDirection === 'backward' ? Math.max(1, overscanCountResolved) : 1;
|
|
1210
|
+
var overscanForward = !isScrolling || horizontalScrollDirection === 'forward' ? Math.max(1, overscanCountResolved) : 1;
|
|
1211
|
+
return [Math.max(0, startIndex - overscanBackward), Math.max(0, Math.min(columnCount - 1, stopIndex + overscanForward)), startIndex, stopIndex];
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1214
|
+
_proto._getVerticalRangeToRender = function _getVerticalRangeToRender() {
|
|
1215
|
+
var _this$props7 = this.props,
|
|
1216
|
+
columnCount = _this$props7.columnCount,
|
|
1217
|
+
overscanCount = _this$props7.overscanCount,
|
|
1218
|
+
overscanRowCount = _this$props7.overscanRowCount,
|
|
1219
|
+
overscanRowsCount = _this$props7.overscanRowsCount,
|
|
1220
|
+
rowCount = _this$props7.rowCount;
|
|
1221
|
+
var _this$state5 = this.state,
|
|
1222
|
+
isScrolling = _this$state5.isScrolling,
|
|
1223
|
+
verticalScrollDirection = _this$state5.verticalScrollDirection,
|
|
1224
|
+
scrollTop = _this$state5.scrollTop;
|
|
1225
|
+
var overscanCountResolved = overscanRowCount || overscanRowsCount || overscanCount || 1;
|
|
1226
|
+
|
|
1227
|
+
if (columnCount === 0 || rowCount === 0) {
|
|
1228
|
+
return [0, 0, 0, 0];
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
var startIndex = getRowStartIndexForOffset(this.props, scrollTop, this._instanceProps);
|
|
1232
|
+
var stopIndex = getRowStopIndexForStartIndex(this.props, startIndex, scrollTop, this._instanceProps); // Overscan by one item in each direction so that tab/focus works.
|
|
1233
|
+
// If there isn't at least one extra item, tab loops back around.
|
|
1234
|
+
|
|
1235
|
+
var overscanBackward = !isScrolling || verticalScrollDirection === 'backward' ? Math.max(1, overscanCountResolved) : 1;
|
|
1236
|
+
var overscanForward = !isScrolling || verticalScrollDirection === 'forward' ? Math.max(1, overscanCountResolved) : 1;
|
|
1237
|
+
return [Math.max(0, startIndex - overscanBackward), Math.max(0, Math.min(rowCount - 1, stopIndex + overscanForward)), startIndex, stopIndex];
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
return Grid;
|
|
1241
|
+
}(react__WEBPACK_IMPORTED_MODULE_4__.PureComponent), _class.defaultProps = {
|
|
1242
|
+
direction: 'ltr',
|
|
1243
|
+
itemData: undefined,
|
|
1244
|
+
useIsScrolling: false
|
|
1245
|
+
}, _class;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
var validateSharedProps = function validateSharedProps(_ref5, _ref6) {
|
|
1249
|
+
var children = _ref5.children,
|
|
1250
|
+
direction = _ref5.direction,
|
|
1251
|
+
height = _ref5.height,
|
|
1252
|
+
innerTagName = _ref5.innerTagName,
|
|
1253
|
+
outerTagName = _ref5.outerTagName,
|
|
1254
|
+
overscanColumnsCount = _ref5.overscanColumnsCount,
|
|
1255
|
+
overscanCount = _ref5.overscanCount,
|
|
1256
|
+
overscanRowsCount = _ref5.overscanRowsCount,
|
|
1257
|
+
width = _ref5.width;
|
|
1258
|
+
var instance = _ref6.instance;
|
|
1259
|
+
|
|
1260
|
+
if (false) {}
|
|
1261
|
+
};
|
|
1262
|
+
|
|
1263
|
+
var DEFAULT_ESTIMATED_ITEM_SIZE = 50;
|
|
1264
|
+
|
|
1265
|
+
var getEstimatedTotalHeight = function getEstimatedTotalHeight(_ref, _ref2) {
|
|
1266
|
+
var rowCount = _ref.rowCount;
|
|
1267
|
+
var rowMetadataMap = _ref2.rowMetadataMap,
|
|
1268
|
+
estimatedRowHeight = _ref2.estimatedRowHeight,
|
|
1269
|
+
lastMeasuredRowIndex = _ref2.lastMeasuredRowIndex;
|
|
1270
|
+
var totalSizeOfMeasuredRows = 0; // Edge case check for when the number of items decreases while a scroll is in progress.
|
|
1271
|
+
// https://github.com/bvaughn/react-window/pull/138
|
|
1272
|
+
|
|
1273
|
+
if (lastMeasuredRowIndex >= rowCount) {
|
|
1274
|
+
lastMeasuredRowIndex = rowCount - 1;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
if (lastMeasuredRowIndex >= 0) {
|
|
1278
|
+
var itemMetadata = rowMetadataMap[lastMeasuredRowIndex];
|
|
1279
|
+
totalSizeOfMeasuredRows = itemMetadata.offset + itemMetadata.size;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
var numUnmeasuredItems = rowCount - lastMeasuredRowIndex - 1;
|
|
1283
|
+
var totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedRowHeight;
|
|
1284
|
+
return totalSizeOfMeasuredRows + totalSizeOfUnmeasuredItems;
|
|
1285
|
+
};
|
|
1286
|
+
|
|
1287
|
+
var getEstimatedTotalWidth = function getEstimatedTotalWidth(_ref3, _ref4) {
|
|
1288
|
+
var columnCount = _ref3.columnCount;
|
|
1289
|
+
var columnMetadataMap = _ref4.columnMetadataMap,
|
|
1290
|
+
estimatedColumnWidth = _ref4.estimatedColumnWidth,
|
|
1291
|
+
lastMeasuredColumnIndex = _ref4.lastMeasuredColumnIndex;
|
|
1292
|
+
var totalSizeOfMeasuredRows = 0; // Edge case check for when the number of items decreases while a scroll is in progress.
|
|
1293
|
+
// https://github.com/bvaughn/react-window/pull/138
|
|
1294
|
+
|
|
1295
|
+
if (lastMeasuredColumnIndex >= columnCount) {
|
|
1296
|
+
lastMeasuredColumnIndex = columnCount - 1;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
if (lastMeasuredColumnIndex >= 0) {
|
|
1300
|
+
var itemMetadata = columnMetadataMap[lastMeasuredColumnIndex];
|
|
1301
|
+
totalSizeOfMeasuredRows = itemMetadata.offset + itemMetadata.size;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
var numUnmeasuredItems = columnCount - lastMeasuredColumnIndex - 1;
|
|
1305
|
+
var totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedColumnWidth;
|
|
1306
|
+
return totalSizeOfMeasuredRows + totalSizeOfUnmeasuredItems;
|
|
1307
|
+
};
|
|
1308
|
+
|
|
1309
|
+
var getItemMetadata = function getItemMetadata(itemType, props, index, instanceProps) {
|
|
1310
|
+
var itemMetadataMap, itemSize, lastMeasuredIndex;
|
|
1311
|
+
|
|
1312
|
+
if (itemType === 'column') {
|
|
1313
|
+
itemMetadataMap = instanceProps.columnMetadataMap;
|
|
1314
|
+
itemSize = props.columnWidth;
|
|
1315
|
+
lastMeasuredIndex = instanceProps.lastMeasuredColumnIndex;
|
|
1316
|
+
} else {
|
|
1317
|
+
itemMetadataMap = instanceProps.rowMetadataMap;
|
|
1318
|
+
itemSize = props.rowHeight;
|
|
1319
|
+
lastMeasuredIndex = instanceProps.lastMeasuredRowIndex;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
if (index > lastMeasuredIndex) {
|
|
1323
|
+
var offset = 0;
|
|
1324
|
+
|
|
1325
|
+
if (lastMeasuredIndex >= 0) {
|
|
1326
|
+
var itemMetadata = itemMetadataMap[lastMeasuredIndex];
|
|
1327
|
+
offset = itemMetadata.offset + itemMetadata.size;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
for (var i = lastMeasuredIndex + 1; i <= index; i++) {
|
|
1331
|
+
var size = itemSize(i);
|
|
1332
|
+
itemMetadataMap[i] = {
|
|
1333
|
+
offset: offset,
|
|
1334
|
+
size: size
|
|
1335
|
+
};
|
|
1336
|
+
offset += size;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
if (itemType === 'column') {
|
|
1340
|
+
instanceProps.lastMeasuredColumnIndex = index;
|
|
1341
|
+
} else {
|
|
1342
|
+
instanceProps.lastMeasuredRowIndex = index;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
return itemMetadataMap[index];
|
|
1347
|
+
};
|
|
1348
|
+
|
|
1349
|
+
var findNearestItem = function findNearestItem(itemType, props, instanceProps, offset) {
|
|
1350
|
+
var itemMetadataMap, lastMeasuredIndex;
|
|
1351
|
+
|
|
1352
|
+
if (itemType === 'column') {
|
|
1353
|
+
itemMetadataMap = instanceProps.columnMetadataMap;
|
|
1354
|
+
lastMeasuredIndex = instanceProps.lastMeasuredColumnIndex;
|
|
1355
|
+
} else {
|
|
1356
|
+
itemMetadataMap = instanceProps.rowMetadataMap;
|
|
1357
|
+
lastMeasuredIndex = instanceProps.lastMeasuredRowIndex;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
var lastMeasuredItemOffset = lastMeasuredIndex > 0 ? itemMetadataMap[lastMeasuredIndex].offset : 0;
|
|
1361
|
+
|
|
1362
|
+
if (lastMeasuredItemOffset >= offset) {
|
|
1363
|
+
// If we've already measured items within this range just use a binary search as it's faster.
|
|
1364
|
+
return findNearestItemBinarySearch(itemType, props, instanceProps, lastMeasuredIndex, 0, offset);
|
|
1365
|
+
} else {
|
|
1366
|
+
// If we haven't yet measured this high, fallback to an exponential search with an inner binary search.
|
|
1367
|
+
// The exponential search avoids pre-computing sizes for the full set of items as a binary search would.
|
|
1368
|
+
// The overall complexity for this approach is O(log n).
|
|
1369
|
+
return findNearestItemExponentialSearch(itemType, props, instanceProps, Math.max(0, lastMeasuredIndex), offset);
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
|
|
1373
|
+
var findNearestItemBinarySearch = function findNearestItemBinarySearch(itemType, props, instanceProps, high, low, offset) {
|
|
1374
|
+
while (low <= high) {
|
|
1375
|
+
var middle = low + Math.floor((high - low) / 2);
|
|
1376
|
+
var currentOffset = getItemMetadata(itemType, props, middle, instanceProps).offset;
|
|
1377
|
+
|
|
1378
|
+
if (currentOffset === offset) {
|
|
1379
|
+
return middle;
|
|
1380
|
+
} else if (currentOffset < offset) {
|
|
1381
|
+
low = middle + 1;
|
|
1382
|
+
} else if (currentOffset > offset) {
|
|
1383
|
+
high = middle - 1;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
if (low > 0) {
|
|
1388
|
+
return low - 1;
|
|
1389
|
+
} else {
|
|
1390
|
+
return 0;
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
var findNearestItemExponentialSearch = function findNearestItemExponentialSearch(itemType, props, instanceProps, index, offset) {
|
|
1395
|
+
var itemCount = itemType === 'column' ? props.columnCount : props.rowCount;
|
|
1396
|
+
var interval = 1;
|
|
1397
|
+
|
|
1398
|
+
while (index < itemCount && getItemMetadata(itemType, props, index, instanceProps).offset < offset) {
|
|
1399
|
+
index += interval;
|
|
1400
|
+
interval *= 2;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
return findNearestItemBinarySearch(itemType, props, instanceProps, Math.min(index, itemCount - 1), Math.floor(index / 2), offset);
|
|
1404
|
+
};
|
|
1405
|
+
|
|
1406
|
+
var getOffsetForIndexAndAlignment = function getOffsetForIndexAndAlignment(itemType, props, index, align, scrollOffset, instanceProps, scrollbarSize) {
|
|
1407
|
+
var size = itemType === 'column' ? props.width : props.height;
|
|
1408
|
+
var itemMetadata = getItemMetadata(itemType, props, index, instanceProps); // Get estimated total size after ItemMetadata is computed,
|
|
1409
|
+
// To ensure it reflects actual measurements instead of just estimates.
|
|
1410
|
+
|
|
1411
|
+
var estimatedTotalSize = itemType === 'column' ? getEstimatedTotalWidth(props, instanceProps) : getEstimatedTotalHeight(props, instanceProps);
|
|
1412
|
+
var maxOffset = Math.max(0, Math.min(estimatedTotalSize - size, itemMetadata.offset));
|
|
1413
|
+
var minOffset = Math.max(0, itemMetadata.offset - size + scrollbarSize + itemMetadata.size);
|
|
1414
|
+
|
|
1415
|
+
if (align === 'smart') {
|
|
1416
|
+
if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
|
|
1417
|
+
align = 'auto';
|
|
1418
|
+
} else {
|
|
1419
|
+
align = 'center';
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
switch (align) {
|
|
1424
|
+
case 'start':
|
|
1425
|
+
return maxOffset;
|
|
1426
|
+
|
|
1427
|
+
case 'end':
|
|
1428
|
+
return minOffset;
|
|
1429
|
+
|
|
1430
|
+
case 'center':
|
|
1431
|
+
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
|
1432
|
+
|
|
1433
|
+
case 'auto':
|
|
1434
|
+
default:
|
|
1435
|
+
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
|
1436
|
+
return scrollOffset;
|
|
1437
|
+
} else if (minOffset > maxOffset) {
|
|
1438
|
+
// Because we only take into account the scrollbar size when calculating minOffset
|
|
1439
|
+
// this value can be larger than maxOffset when at the end of the list
|
|
1440
|
+
return minOffset;
|
|
1441
|
+
} else if (scrollOffset < minOffset) {
|
|
1442
|
+
return minOffset;
|
|
1443
|
+
} else {
|
|
1444
|
+
return maxOffset;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
|
|
1450
|
+
var VariableSizeGrid = /*#__PURE__*/createGridComponent({
|
|
1451
|
+
getColumnOffset: function getColumnOffset(props, index, instanceProps) {
|
|
1452
|
+
return getItemMetadata('column', props, index, instanceProps).offset;
|
|
1453
|
+
},
|
|
1454
|
+
getColumnStartIndexForOffset: function getColumnStartIndexForOffset(props, scrollLeft, instanceProps) {
|
|
1455
|
+
return findNearestItem('column', props, instanceProps, scrollLeft);
|
|
1456
|
+
},
|
|
1457
|
+
getColumnStopIndexForStartIndex: function getColumnStopIndexForStartIndex(props, startIndex, scrollLeft, instanceProps) {
|
|
1458
|
+
var columnCount = props.columnCount,
|
|
1459
|
+
width = props.width;
|
|
1460
|
+
var itemMetadata = getItemMetadata('column', props, startIndex, instanceProps);
|
|
1461
|
+
var maxOffset = scrollLeft + width;
|
|
1462
|
+
var offset = itemMetadata.offset + itemMetadata.size;
|
|
1463
|
+
var stopIndex = startIndex;
|
|
1464
|
+
|
|
1465
|
+
while (stopIndex < columnCount - 1 && offset < maxOffset) {
|
|
1466
|
+
stopIndex++;
|
|
1467
|
+
offset += getItemMetadata('column', props, stopIndex, instanceProps).size;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
return stopIndex;
|
|
1471
|
+
},
|
|
1472
|
+
getColumnWidth: function getColumnWidth(props, index, instanceProps) {
|
|
1473
|
+
return instanceProps.columnMetadataMap[index].size;
|
|
1474
|
+
},
|
|
1475
|
+
getEstimatedTotalHeight: getEstimatedTotalHeight,
|
|
1476
|
+
getEstimatedTotalWidth: getEstimatedTotalWidth,
|
|
1477
|
+
getOffsetForColumnAndAlignment: function getOffsetForColumnAndAlignment(props, index, align, scrollOffset, instanceProps, scrollbarSize) {
|
|
1478
|
+
return getOffsetForIndexAndAlignment('column', props, index, align, scrollOffset, instanceProps, scrollbarSize);
|
|
1479
|
+
},
|
|
1480
|
+
getOffsetForRowAndAlignment: function getOffsetForRowAndAlignment(props, index, align, scrollOffset, instanceProps, scrollbarSize) {
|
|
1481
|
+
return getOffsetForIndexAndAlignment('row', props, index, align, scrollOffset, instanceProps, scrollbarSize);
|
|
1482
|
+
},
|
|
1483
|
+
getRowOffset: function getRowOffset(props, index, instanceProps) {
|
|
1484
|
+
return getItemMetadata('row', props, index, instanceProps).offset;
|
|
1485
|
+
},
|
|
1486
|
+
getRowHeight: function getRowHeight(props, index, instanceProps) {
|
|
1487
|
+
return instanceProps.rowMetadataMap[index].size;
|
|
1488
|
+
},
|
|
1489
|
+
getRowStartIndexForOffset: function getRowStartIndexForOffset(props, scrollTop, instanceProps) {
|
|
1490
|
+
return findNearestItem('row', props, instanceProps, scrollTop);
|
|
1491
|
+
},
|
|
1492
|
+
getRowStopIndexForStartIndex: function getRowStopIndexForStartIndex(props, startIndex, scrollTop, instanceProps) {
|
|
1493
|
+
var rowCount = props.rowCount,
|
|
1494
|
+
height = props.height;
|
|
1495
|
+
var itemMetadata = getItemMetadata('row', props, startIndex, instanceProps);
|
|
1496
|
+
var maxOffset = scrollTop + height;
|
|
1497
|
+
var offset = itemMetadata.offset + itemMetadata.size;
|
|
1498
|
+
var stopIndex = startIndex;
|
|
1499
|
+
|
|
1500
|
+
while (stopIndex < rowCount - 1 && offset < maxOffset) {
|
|
1501
|
+
stopIndex++;
|
|
1502
|
+
offset += getItemMetadata('row', props, stopIndex, instanceProps).size;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
return stopIndex;
|
|
1506
|
+
},
|
|
1507
|
+
initInstanceProps: function initInstanceProps(props, instance) {
|
|
1508
|
+
var _ref5 = props,
|
|
1509
|
+
estimatedColumnWidth = _ref5.estimatedColumnWidth,
|
|
1510
|
+
estimatedRowHeight = _ref5.estimatedRowHeight;
|
|
1511
|
+
var instanceProps = {
|
|
1512
|
+
columnMetadataMap: {},
|
|
1513
|
+
estimatedColumnWidth: estimatedColumnWidth || DEFAULT_ESTIMATED_ITEM_SIZE,
|
|
1514
|
+
estimatedRowHeight: estimatedRowHeight || DEFAULT_ESTIMATED_ITEM_SIZE,
|
|
1515
|
+
lastMeasuredColumnIndex: -1,
|
|
1516
|
+
lastMeasuredRowIndex: -1,
|
|
1517
|
+
rowMetadataMap: {}
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
instance.resetAfterColumnIndex = function (columnIndex, shouldForceUpdate) {
|
|
1521
|
+
if (shouldForceUpdate === void 0) {
|
|
1522
|
+
shouldForceUpdate = true;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
instance.resetAfterIndices({
|
|
1526
|
+
columnIndex: columnIndex,
|
|
1527
|
+
shouldForceUpdate: shouldForceUpdate
|
|
1528
|
+
});
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1531
|
+
instance.resetAfterRowIndex = function (rowIndex, shouldForceUpdate) {
|
|
1532
|
+
if (shouldForceUpdate === void 0) {
|
|
1533
|
+
shouldForceUpdate = true;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
instance.resetAfterIndices({
|
|
1537
|
+
rowIndex: rowIndex,
|
|
1538
|
+
shouldForceUpdate: shouldForceUpdate
|
|
1539
|
+
});
|
|
1540
|
+
};
|
|
1541
|
+
|
|
1542
|
+
instance.resetAfterIndices = function (_ref6) {
|
|
1543
|
+
var columnIndex = _ref6.columnIndex,
|
|
1544
|
+
rowIndex = _ref6.rowIndex,
|
|
1545
|
+
_ref6$shouldForceUpda = _ref6.shouldForceUpdate,
|
|
1546
|
+
shouldForceUpdate = _ref6$shouldForceUpda === void 0 ? true : _ref6$shouldForceUpda;
|
|
1547
|
+
|
|
1548
|
+
if (typeof columnIndex === 'number') {
|
|
1549
|
+
instanceProps.lastMeasuredColumnIndex = Math.min(instanceProps.lastMeasuredColumnIndex, columnIndex - 1);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
if (typeof rowIndex === 'number') {
|
|
1553
|
+
instanceProps.lastMeasuredRowIndex = Math.min(instanceProps.lastMeasuredRowIndex, rowIndex - 1);
|
|
1554
|
+
} // We could potentially optimize further by only evicting styles after this index,
|
|
1555
|
+
// But since styles are only cached while scrolling is in progress-
|
|
1556
|
+
// It seems an unnecessary optimization.
|
|
1557
|
+
// It's unlikely that resetAfterIndex() will be called while a user is scrolling.
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
instance._getItemStyleCache(-1);
|
|
1561
|
+
|
|
1562
|
+
if (shouldForceUpdate) {
|
|
1563
|
+
instance.forceUpdate();
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
|
|
1567
|
+
return instanceProps;
|
|
1568
|
+
},
|
|
1569
|
+
shouldResetStyleCacheOnItemSizeChange: false,
|
|
1570
|
+
validateProps: function validateProps(_ref7) {
|
|
1571
|
+
var columnWidth = _ref7.columnWidth,
|
|
1572
|
+
rowHeight = _ref7.rowHeight;
|
|
1573
|
+
|
|
1574
|
+
if (false) {}
|
|
1575
|
+
}
|
|
1576
|
+
});
|
|
1577
|
+
|
|
1578
|
+
var IS_SCROLLING_DEBOUNCE_INTERVAL$1 = 150;
|
|
1579
|
+
|
|
1580
|
+
var defaultItemKey$1 = function defaultItemKey(index, data) {
|
|
1581
|
+
return index;
|
|
1582
|
+
}; // In DEV mode, this Set helps us only log a warning once per component instance.
|
|
1583
|
+
// This avoids spamming the console every time a render happens.
|
|
1584
|
+
|
|
1585
|
+
|
|
1586
|
+
var devWarningsDirection = null;
|
|
1587
|
+
var devWarningsTagName$1 = null;
|
|
1588
|
+
|
|
1589
|
+
if (false) {}
|
|
1590
|
+
|
|
1591
|
+
function createListComponent(_ref) {
|
|
1592
|
+
var _class;
|
|
1593
|
+
|
|
1594
|
+
var getItemOffset = _ref.getItemOffset,
|
|
1595
|
+
getEstimatedTotalSize = _ref.getEstimatedTotalSize,
|
|
1596
|
+
getItemSize = _ref.getItemSize,
|
|
1597
|
+
getOffsetForIndexAndAlignment = _ref.getOffsetForIndexAndAlignment,
|
|
1598
|
+
getStartIndexForOffset = _ref.getStartIndexForOffset,
|
|
1599
|
+
getStopIndexForStartIndex = _ref.getStopIndexForStartIndex,
|
|
1600
|
+
initInstanceProps = _ref.initInstanceProps,
|
|
1601
|
+
shouldResetStyleCacheOnItemSizeChange = _ref.shouldResetStyleCacheOnItemSizeChange,
|
|
1602
|
+
validateProps = _ref.validateProps;
|
|
1603
|
+
return _class = /*#__PURE__*/function (_PureComponent) {
|
|
1604
|
+
(0,_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(List, _PureComponent);
|
|
1605
|
+
|
|
1606
|
+
// Always use explicit constructor for React components.
|
|
1607
|
+
// It produces less code after transpilation. (#26)
|
|
1608
|
+
// eslint-disable-next-line no-useless-constructor
|
|
1609
|
+
function List(props) {
|
|
1610
|
+
var _this;
|
|
1611
|
+
|
|
1612
|
+
_this = _PureComponent.call(this, props) || this;
|
|
1613
|
+
_this._instanceProps = initInstanceProps(_this.props, (0,_babel_runtime_helpers_esm_assertThisInitialized__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(_this));
|
|
1614
|
+
_this._outerRef = void 0;
|
|
1615
|
+
_this._resetIsScrollingTimeoutId = null;
|
|
1616
|
+
_this.state = {
|
|
1617
|
+
instance: (0,_babel_runtime_helpers_esm_assertThisInitialized__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(_this),
|
|
1618
|
+
isScrolling: false,
|
|
1619
|
+
scrollDirection: 'forward',
|
|
1620
|
+
scrollOffset: typeof _this.props.initialScrollOffset === 'number' ? _this.props.initialScrollOffset : 0,
|
|
1621
|
+
scrollUpdateWasRequested: false
|
|
1622
|
+
};
|
|
1623
|
+
_this._callOnItemsRendered = void 0;
|
|
1624
|
+
_this._callOnItemsRendered = (0,memoize_one__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(function (overscanStartIndex, overscanStopIndex, visibleStartIndex, visibleStopIndex) {
|
|
1625
|
+
return _this.props.onItemsRendered({
|
|
1626
|
+
overscanStartIndex: overscanStartIndex,
|
|
1627
|
+
overscanStopIndex: overscanStopIndex,
|
|
1628
|
+
visibleStartIndex: visibleStartIndex,
|
|
1629
|
+
visibleStopIndex: visibleStopIndex
|
|
1630
|
+
});
|
|
1631
|
+
});
|
|
1632
|
+
_this._callOnScroll = void 0;
|
|
1633
|
+
_this._callOnScroll = (0,memoize_one__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(function (scrollDirection, scrollOffset, scrollUpdateWasRequested) {
|
|
1634
|
+
return _this.props.onScroll({
|
|
1635
|
+
scrollDirection: scrollDirection,
|
|
1636
|
+
scrollOffset: scrollOffset,
|
|
1637
|
+
scrollUpdateWasRequested: scrollUpdateWasRequested
|
|
1638
|
+
});
|
|
1639
|
+
});
|
|
1640
|
+
_this._getItemStyle = void 0;
|
|
1641
|
+
|
|
1642
|
+
_this._getItemStyle = function (index) {
|
|
1643
|
+
var _this$props = _this.props,
|
|
1644
|
+
direction = _this$props.direction,
|
|
1645
|
+
itemSize = _this$props.itemSize,
|
|
1646
|
+
layout = _this$props.layout;
|
|
1647
|
+
|
|
1648
|
+
var itemStyleCache = _this._getItemStyleCache(shouldResetStyleCacheOnItemSizeChange && itemSize, shouldResetStyleCacheOnItemSizeChange && layout, shouldResetStyleCacheOnItemSizeChange && direction);
|
|
1649
|
+
|
|
1650
|
+
var style;
|
|
1651
|
+
|
|
1652
|
+
if (itemStyleCache.hasOwnProperty(index)) {
|
|
1653
|
+
style = itemStyleCache[index];
|
|
1654
|
+
} else {
|
|
1655
|
+
var _offset = getItemOffset(_this.props, index, _this._instanceProps);
|
|
1656
|
+
|
|
1657
|
+
var size = getItemSize(_this.props, index, _this._instanceProps); // TODO Deprecate direction "horizontal"
|
|
1658
|
+
|
|
1659
|
+
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
|
1660
|
+
var isRtl = direction === 'rtl';
|
|
1661
|
+
var offsetHorizontal = isHorizontal ? _offset : 0;
|
|
1662
|
+
itemStyleCache[index] = style = {
|
|
1663
|
+
position: 'absolute',
|
|
1664
|
+
left: isRtl ? undefined : offsetHorizontal,
|
|
1665
|
+
right: isRtl ? offsetHorizontal : undefined,
|
|
1666
|
+
top: !isHorizontal ? _offset : 0,
|
|
1667
|
+
height: !isHorizontal ? size : '100%',
|
|
1668
|
+
width: isHorizontal ? size : '100%'
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
return style;
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
_this._getItemStyleCache = void 0;
|
|
1676
|
+
_this._getItemStyleCache = (0,memoize_one__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(function (_, __, ___) {
|
|
1677
|
+
return {};
|
|
1678
|
+
});
|
|
1679
|
+
|
|
1680
|
+
_this._onScrollHorizontal = function (event) {
|
|
1681
|
+
var _event$currentTarget = event.currentTarget,
|
|
1682
|
+
clientWidth = _event$currentTarget.clientWidth,
|
|
1683
|
+
scrollLeft = _event$currentTarget.scrollLeft,
|
|
1684
|
+
scrollWidth = _event$currentTarget.scrollWidth;
|
|
1685
|
+
|
|
1686
|
+
_this.setState(function (prevState) {
|
|
1687
|
+
if (prevState.scrollOffset === scrollLeft) {
|
|
1688
|
+
// Scroll position may have been updated by cDM/cDU,
|
|
1689
|
+
// In which case we don't need to trigger another render,
|
|
1690
|
+
// And we don't want to update state.isScrolling.
|
|
1691
|
+
return null;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
var direction = _this.props.direction;
|
|
1695
|
+
var scrollOffset = scrollLeft;
|
|
1696
|
+
|
|
1697
|
+
if (direction === 'rtl') {
|
|
1698
|
+
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
1699
|
+
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
|
1700
|
+
// It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
|
|
1701
|
+
// So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
|
|
1702
|
+
switch (getRTLOffsetType()) {
|
|
1703
|
+
case 'negative':
|
|
1704
|
+
scrollOffset = -scrollLeft;
|
|
1705
|
+
break;
|
|
1706
|
+
|
|
1707
|
+
case 'positive-descending':
|
|
1708
|
+
scrollOffset = scrollWidth - clientWidth - scrollLeft;
|
|
1709
|
+
break;
|
|
1710
|
+
}
|
|
1711
|
+
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
|
1712
|
+
|
|
1713
|
+
|
|
1714
|
+
scrollOffset = Math.max(0, Math.min(scrollOffset, scrollWidth - clientWidth));
|
|
1715
|
+
return {
|
|
1716
|
+
isScrolling: true,
|
|
1717
|
+
scrollDirection: prevState.scrollOffset < scrollLeft ? 'forward' : 'backward',
|
|
1718
|
+
scrollOffset: scrollOffset,
|
|
1719
|
+
scrollUpdateWasRequested: false
|
|
1720
|
+
};
|
|
1721
|
+
}, _this._resetIsScrollingDebounced);
|
|
1722
|
+
};
|
|
1723
|
+
|
|
1724
|
+
_this._onScrollVertical = function (event) {
|
|
1725
|
+
var _event$currentTarget2 = event.currentTarget,
|
|
1726
|
+
clientHeight = _event$currentTarget2.clientHeight,
|
|
1727
|
+
scrollHeight = _event$currentTarget2.scrollHeight,
|
|
1728
|
+
scrollTop = _event$currentTarget2.scrollTop;
|
|
1729
|
+
|
|
1730
|
+
_this.setState(function (prevState) {
|
|
1731
|
+
if (prevState.scrollOffset === scrollTop) {
|
|
1732
|
+
// Scroll position may have been updated by cDM/cDU,
|
|
1733
|
+
// In which case we don't need to trigger another render,
|
|
1734
|
+
// And we don't want to update state.isScrolling.
|
|
1735
|
+
return null;
|
|
1736
|
+
} // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
|
|
1737
|
+
|
|
1738
|
+
|
|
1739
|
+
var scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
|
|
1740
|
+
return {
|
|
1741
|
+
isScrolling: true,
|
|
1742
|
+
scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
|
1743
|
+
scrollOffset: scrollOffset,
|
|
1744
|
+
scrollUpdateWasRequested: false
|
|
1745
|
+
};
|
|
1746
|
+
}, _this._resetIsScrollingDebounced);
|
|
1747
|
+
};
|
|
1748
|
+
|
|
1749
|
+
_this._outerRefSetter = function (ref) {
|
|
1750
|
+
var outerRef = _this.props.outerRef;
|
|
1751
|
+
_this._outerRef = ref;
|
|
1752
|
+
|
|
1753
|
+
if (typeof outerRef === 'function') {
|
|
1754
|
+
outerRef(ref);
|
|
1755
|
+
} else if (outerRef != null && typeof outerRef === 'object' && outerRef.hasOwnProperty('current')) {
|
|
1756
|
+
outerRef.current = ref;
|
|
1757
|
+
}
|
|
1758
|
+
};
|
|
1759
|
+
|
|
1760
|
+
_this._resetIsScrollingDebounced = function () {
|
|
1761
|
+
if (_this._resetIsScrollingTimeoutId !== null) {
|
|
1762
|
+
cancelTimeout(_this._resetIsScrollingTimeoutId);
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
_this._resetIsScrollingTimeoutId = requestTimeout(_this._resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL$1);
|
|
1766
|
+
};
|
|
1767
|
+
|
|
1768
|
+
_this._resetIsScrolling = function () {
|
|
1769
|
+
_this._resetIsScrollingTimeoutId = null;
|
|
1770
|
+
|
|
1771
|
+
_this.setState({
|
|
1772
|
+
isScrolling: false
|
|
1773
|
+
}, function () {
|
|
1774
|
+
// Clear style cache after state update has been committed.
|
|
1775
|
+
// This way we don't break pure sCU for items that don't use isScrolling param.
|
|
1776
|
+
_this._getItemStyleCache(-1, null);
|
|
1777
|
+
});
|
|
1778
|
+
};
|
|
1779
|
+
|
|
1780
|
+
return _this;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
List.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
|
|
1784
|
+
validateSharedProps$1(nextProps, prevState);
|
|
1785
|
+
validateProps(nextProps);
|
|
1786
|
+
return null;
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
var _proto = List.prototype;
|
|
1790
|
+
|
|
1791
|
+
_proto.scrollTo = function scrollTo(scrollOffset) {
|
|
1792
|
+
scrollOffset = Math.max(0, scrollOffset);
|
|
1793
|
+
this.setState(function (prevState) {
|
|
1794
|
+
if (prevState.scrollOffset === scrollOffset) {
|
|
1795
|
+
return null;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
return {
|
|
1799
|
+
scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
|
|
1800
|
+
scrollOffset: scrollOffset,
|
|
1801
|
+
scrollUpdateWasRequested: true
|
|
1802
|
+
};
|
|
1803
|
+
}, this._resetIsScrollingDebounced);
|
|
1804
|
+
};
|
|
1805
|
+
|
|
1806
|
+
_proto.scrollToItem = function scrollToItem(index, align) {
|
|
1807
|
+
if (align === void 0) {
|
|
1808
|
+
align = 'auto';
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
var _this$props2 = this.props,
|
|
1812
|
+
itemCount = _this$props2.itemCount,
|
|
1813
|
+
layout = _this$props2.layout;
|
|
1814
|
+
var scrollOffset = this.state.scrollOffset;
|
|
1815
|
+
index = Math.max(0, Math.min(index, itemCount - 1)); // The scrollbar size should be considered when scrolling an item into view, to ensure it's fully visible.
|
|
1816
|
+
// But we only need to account for its size when it's actually visible.
|
|
1817
|
+
// This is an edge case for lists; normally they only scroll in the dominant direction.
|
|
1818
|
+
|
|
1819
|
+
var scrollbarSize = 0;
|
|
1820
|
+
|
|
1821
|
+
if (this._outerRef) {
|
|
1822
|
+
var outerRef = this._outerRef;
|
|
1823
|
+
|
|
1824
|
+
if (layout === 'vertical') {
|
|
1825
|
+
scrollbarSize = outerRef.scrollWidth > outerRef.clientWidth ? getScrollbarSize() : 0;
|
|
1826
|
+
} else {
|
|
1827
|
+
scrollbarSize = outerRef.scrollHeight > outerRef.clientHeight ? getScrollbarSize() : 0;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
this.scrollTo(getOffsetForIndexAndAlignment(this.props, index, align, scrollOffset, this._instanceProps, scrollbarSize));
|
|
1832
|
+
};
|
|
1833
|
+
|
|
1834
|
+
_proto.componentDidMount = function componentDidMount() {
|
|
1835
|
+
var _this$props3 = this.props,
|
|
1836
|
+
direction = _this$props3.direction,
|
|
1837
|
+
initialScrollOffset = _this$props3.initialScrollOffset,
|
|
1838
|
+
layout = _this$props3.layout;
|
|
1839
|
+
|
|
1840
|
+
if (typeof initialScrollOffset === 'number' && this._outerRef != null) {
|
|
1841
|
+
var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
|
|
1842
|
+
|
|
1843
|
+
if (direction === 'horizontal' || layout === 'horizontal') {
|
|
1844
|
+
outerRef.scrollLeft = initialScrollOffset;
|
|
1845
|
+
} else {
|
|
1846
|
+
outerRef.scrollTop = initialScrollOffset;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
this._callPropsCallbacks();
|
|
1851
|
+
};
|
|
1852
|
+
|
|
1853
|
+
_proto.componentDidUpdate = function componentDidUpdate() {
|
|
1854
|
+
var _this$props4 = this.props,
|
|
1855
|
+
direction = _this$props4.direction,
|
|
1856
|
+
layout = _this$props4.layout;
|
|
1857
|
+
var _this$state = this.state,
|
|
1858
|
+
scrollOffset = _this$state.scrollOffset,
|
|
1859
|
+
scrollUpdateWasRequested = _this$state.scrollUpdateWasRequested;
|
|
1860
|
+
|
|
1861
|
+
if (scrollUpdateWasRequested && this._outerRef != null) {
|
|
1862
|
+
var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
|
|
1863
|
+
|
|
1864
|
+
if (direction === 'horizontal' || layout === 'horizontal') {
|
|
1865
|
+
if (direction === 'rtl') {
|
|
1866
|
+
// TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
|
|
1867
|
+
// This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
|
|
1868
|
+
// So we need to determine which browser behavior we're dealing with, and mimic it.
|
|
1869
|
+
switch (getRTLOffsetType()) {
|
|
1870
|
+
case 'negative':
|
|
1871
|
+
outerRef.scrollLeft = -scrollOffset;
|
|
1872
|
+
break;
|
|
1873
|
+
|
|
1874
|
+
case 'positive-ascending':
|
|
1875
|
+
outerRef.scrollLeft = scrollOffset;
|
|
1876
|
+
break;
|
|
1877
|
+
|
|
1878
|
+
default:
|
|
1879
|
+
var clientWidth = outerRef.clientWidth,
|
|
1880
|
+
scrollWidth = outerRef.scrollWidth;
|
|
1881
|
+
outerRef.scrollLeft = scrollWidth - clientWidth - scrollOffset;
|
|
1882
|
+
break;
|
|
1883
|
+
}
|
|
1884
|
+
} else {
|
|
1885
|
+
outerRef.scrollLeft = scrollOffset;
|
|
1886
|
+
}
|
|
1887
|
+
} else {
|
|
1888
|
+
outerRef.scrollTop = scrollOffset;
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
this._callPropsCallbacks();
|
|
1893
|
+
};
|
|
1894
|
+
|
|
1895
|
+
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
1896
|
+
if (this._resetIsScrollingTimeoutId !== null) {
|
|
1897
|
+
cancelTimeout(this._resetIsScrollingTimeoutId);
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
|
|
1901
|
+
_proto.render = function render() {
|
|
1902
|
+
var _this$props5 = this.props,
|
|
1903
|
+
children = _this$props5.children,
|
|
1904
|
+
className = _this$props5.className,
|
|
1905
|
+
direction = _this$props5.direction,
|
|
1906
|
+
height = _this$props5.height,
|
|
1907
|
+
innerRef = _this$props5.innerRef,
|
|
1908
|
+
innerElementType = _this$props5.innerElementType,
|
|
1909
|
+
innerTagName = _this$props5.innerTagName,
|
|
1910
|
+
itemCount = _this$props5.itemCount,
|
|
1911
|
+
itemData = _this$props5.itemData,
|
|
1912
|
+
_this$props5$itemKey = _this$props5.itemKey,
|
|
1913
|
+
itemKey = _this$props5$itemKey === void 0 ? defaultItemKey$1 : _this$props5$itemKey,
|
|
1914
|
+
layout = _this$props5.layout,
|
|
1915
|
+
outerElementType = _this$props5.outerElementType,
|
|
1916
|
+
outerTagName = _this$props5.outerTagName,
|
|
1917
|
+
style = _this$props5.style,
|
|
1918
|
+
useIsScrolling = _this$props5.useIsScrolling,
|
|
1919
|
+
width = _this$props5.width;
|
|
1920
|
+
var isScrolling = this.state.isScrolling; // TODO Deprecate direction "horizontal"
|
|
1921
|
+
|
|
1922
|
+
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
|
1923
|
+
var onScroll = isHorizontal ? this._onScrollHorizontal : this._onScrollVertical;
|
|
1924
|
+
|
|
1925
|
+
var _this$_getRangeToRend = this._getRangeToRender(),
|
|
1926
|
+
startIndex = _this$_getRangeToRend[0],
|
|
1927
|
+
stopIndex = _this$_getRangeToRend[1];
|
|
1928
|
+
|
|
1929
|
+
var items = [];
|
|
1930
|
+
|
|
1931
|
+
if (itemCount > 0) {
|
|
1932
|
+
for (var _index = startIndex; _index <= stopIndex; _index++) {
|
|
1933
|
+
items.push((0,react__WEBPACK_IMPORTED_MODULE_4__.createElement)(children, {
|
|
1934
|
+
data: itemData,
|
|
1935
|
+
key: itemKey(_index, itemData),
|
|
1936
|
+
index: _index,
|
|
1937
|
+
isScrolling: useIsScrolling ? isScrolling : undefined,
|
|
1938
|
+
style: this._getItemStyle(_index)
|
|
1939
|
+
}));
|
|
1940
|
+
}
|
|
1941
|
+
} // Read this value AFTER items have been created,
|
|
1942
|
+
// So their actual sizes (if variable) are taken into consideration.
|
|
1943
|
+
|
|
1944
|
+
|
|
1945
|
+
var estimatedTotalSize = getEstimatedTotalSize(this.props, this._instanceProps);
|
|
1946
|
+
return (0,react__WEBPACK_IMPORTED_MODULE_4__.createElement)(outerElementType || outerTagName || 'div', {
|
|
1947
|
+
className: className,
|
|
1948
|
+
onScroll: onScroll,
|
|
1949
|
+
ref: this._outerRefSetter,
|
|
1950
|
+
style: (0,_babel_runtime_helpers_esm_extends__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)({
|
|
1951
|
+
position: 'relative',
|
|
1952
|
+
height: height,
|
|
1953
|
+
width: width,
|
|
1954
|
+
overflow: 'auto',
|
|
1955
|
+
WebkitOverflowScrolling: 'touch',
|
|
1956
|
+
willChange: 'transform',
|
|
1957
|
+
direction: direction
|
|
1958
|
+
}, style)
|
|
1959
|
+
}, (0,react__WEBPACK_IMPORTED_MODULE_4__.createElement)(innerElementType || innerTagName || 'div', {
|
|
1960
|
+
children: items,
|
|
1961
|
+
ref: innerRef,
|
|
1962
|
+
style: {
|
|
1963
|
+
height: isHorizontal ? '100%' : estimatedTotalSize,
|
|
1964
|
+
pointerEvents: isScrolling ? 'none' : undefined,
|
|
1965
|
+
width: isHorizontal ? estimatedTotalSize : '100%'
|
|
1966
|
+
}
|
|
1967
|
+
}));
|
|
1968
|
+
};
|
|
1969
|
+
|
|
1970
|
+
_proto._callPropsCallbacks = function _callPropsCallbacks() {
|
|
1971
|
+
if (typeof this.props.onItemsRendered === 'function') {
|
|
1972
|
+
var itemCount = this.props.itemCount;
|
|
1973
|
+
|
|
1974
|
+
if (itemCount > 0) {
|
|
1975
|
+
var _this$_getRangeToRend2 = this._getRangeToRender(),
|
|
1976
|
+
_overscanStartIndex = _this$_getRangeToRend2[0],
|
|
1977
|
+
_overscanStopIndex = _this$_getRangeToRend2[1],
|
|
1978
|
+
_visibleStartIndex = _this$_getRangeToRend2[2],
|
|
1979
|
+
_visibleStopIndex = _this$_getRangeToRend2[3];
|
|
1980
|
+
|
|
1981
|
+
this._callOnItemsRendered(_overscanStartIndex, _overscanStopIndex, _visibleStartIndex, _visibleStopIndex);
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
if (typeof this.props.onScroll === 'function') {
|
|
1986
|
+
var _this$state2 = this.state,
|
|
1987
|
+
_scrollDirection = _this$state2.scrollDirection,
|
|
1988
|
+
_scrollOffset = _this$state2.scrollOffset,
|
|
1989
|
+
_scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
|
|
1990
|
+
|
|
1991
|
+
this._callOnScroll(_scrollDirection, _scrollOffset, _scrollUpdateWasRequested);
|
|
1992
|
+
}
|
|
1993
|
+
} // Lazily create and cache item styles while scrolling,
|
|
1994
|
+
// So that pure component sCU will prevent re-renders.
|
|
1995
|
+
// We maintain this cache, and pass a style prop rather than index,
|
|
1996
|
+
// So that List can clear cached styles and force item re-render if necessary.
|
|
1997
|
+
;
|
|
1998
|
+
|
|
1999
|
+
_proto._getRangeToRender = function _getRangeToRender() {
|
|
2000
|
+
var _this$props6 = this.props,
|
|
2001
|
+
itemCount = _this$props6.itemCount,
|
|
2002
|
+
overscanCount = _this$props6.overscanCount;
|
|
2003
|
+
var _this$state3 = this.state,
|
|
2004
|
+
isScrolling = _this$state3.isScrolling,
|
|
2005
|
+
scrollDirection = _this$state3.scrollDirection,
|
|
2006
|
+
scrollOffset = _this$state3.scrollOffset;
|
|
2007
|
+
|
|
2008
|
+
if (itemCount === 0) {
|
|
2009
|
+
return [0, 0, 0, 0];
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
var startIndex = getStartIndexForOffset(this.props, scrollOffset, this._instanceProps);
|
|
2013
|
+
var stopIndex = getStopIndexForStartIndex(this.props, startIndex, scrollOffset, this._instanceProps); // Overscan by one item in each direction so that tab/focus works.
|
|
2014
|
+
// If there isn't at least one extra item, tab loops back around.
|
|
2015
|
+
|
|
2016
|
+
var overscanBackward = !isScrolling || scrollDirection === 'backward' ? Math.max(1, overscanCount) : 1;
|
|
2017
|
+
var overscanForward = !isScrolling || scrollDirection === 'forward' ? Math.max(1, overscanCount) : 1;
|
|
2018
|
+
return [Math.max(0, startIndex - overscanBackward), Math.max(0, Math.min(itemCount - 1, stopIndex + overscanForward)), startIndex, stopIndex];
|
|
2019
|
+
};
|
|
2020
|
+
|
|
2021
|
+
return List;
|
|
2022
|
+
}(react__WEBPACK_IMPORTED_MODULE_4__.PureComponent), _class.defaultProps = {
|
|
2023
|
+
direction: 'ltr',
|
|
2024
|
+
itemData: undefined,
|
|
2025
|
+
layout: 'vertical',
|
|
2026
|
+
overscanCount: 2,
|
|
2027
|
+
useIsScrolling: false
|
|
2028
|
+
}, _class;
|
|
2029
|
+
} // NOTE: I considered further wrapping individual items with a pure ListItem component.
|
|
2030
|
+
// This would avoid ever calling the render function for the same index more than once,
|
|
2031
|
+
// But it would also add the overhead of a lot of components/fibers.
|
|
2032
|
+
// I assume people already do this (render function returning a class component),
|
|
2033
|
+
// So my doing it would just unnecessarily double the wrappers.
|
|
2034
|
+
|
|
2035
|
+
var validateSharedProps$1 = function validateSharedProps(_ref2, _ref3) {
|
|
2036
|
+
var children = _ref2.children,
|
|
2037
|
+
direction = _ref2.direction,
|
|
2038
|
+
height = _ref2.height,
|
|
2039
|
+
layout = _ref2.layout,
|
|
2040
|
+
innerTagName = _ref2.innerTagName,
|
|
2041
|
+
outerTagName = _ref2.outerTagName,
|
|
2042
|
+
width = _ref2.width;
|
|
2043
|
+
var instance = _ref3.instance;
|
|
2044
|
+
|
|
2045
|
+
if (false) { var isHorizontal; }
|
|
2046
|
+
};
|
|
2047
|
+
|
|
2048
|
+
var DEFAULT_ESTIMATED_ITEM_SIZE$1 = 50;
|
|
2049
|
+
|
|
2050
|
+
var getItemMetadata$1 = function getItemMetadata(props, index, instanceProps) {
|
|
2051
|
+
var _ref = props,
|
|
2052
|
+
itemSize = _ref.itemSize;
|
|
2053
|
+
var itemMetadataMap = instanceProps.itemMetadataMap,
|
|
2054
|
+
lastMeasuredIndex = instanceProps.lastMeasuredIndex;
|
|
2055
|
+
|
|
2056
|
+
if (index > lastMeasuredIndex) {
|
|
2057
|
+
var offset = 0;
|
|
2058
|
+
|
|
2059
|
+
if (lastMeasuredIndex >= 0) {
|
|
2060
|
+
var itemMetadata = itemMetadataMap[lastMeasuredIndex];
|
|
2061
|
+
offset = itemMetadata.offset + itemMetadata.size;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
for (var i = lastMeasuredIndex + 1; i <= index; i++) {
|
|
2065
|
+
var size = itemSize(i);
|
|
2066
|
+
itemMetadataMap[i] = {
|
|
2067
|
+
offset: offset,
|
|
2068
|
+
size: size
|
|
2069
|
+
};
|
|
2070
|
+
offset += size;
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
instanceProps.lastMeasuredIndex = index;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
return itemMetadataMap[index];
|
|
2077
|
+
};
|
|
2078
|
+
|
|
2079
|
+
var findNearestItem$1 = function findNearestItem(props, instanceProps, offset) {
|
|
2080
|
+
var itemMetadataMap = instanceProps.itemMetadataMap,
|
|
2081
|
+
lastMeasuredIndex = instanceProps.lastMeasuredIndex;
|
|
2082
|
+
var lastMeasuredItemOffset = lastMeasuredIndex > 0 ? itemMetadataMap[lastMeasuredIndex].offset : 0;
|
|
2083
|
+
|
|
2084
|
+
if (lastMeasuredItemOffset >= offset) {
|
|
2085
|
+
// If we've already measured items within this range just use a binary search as it's faster.
|
|
2086
|
+
return findNearestItemBinarySearch$1(props, instanceProps, lastMeasuredIndex, 0, offset);
|
|
2087
|
+
} else {
|
|
2088
|
+
// If we haven't yet measured this high, fallback to an exponential search with an inner binary search.
|
|
2089
|
+
// The exponential search avoids pre-computing sizes for the full set of items as a binary search would.
|
|
2090
|
+
// The overall complexity for this approach is O(log n).
|
|
2091
|
+
return findNearestItemExponentialSearch$1(props, instanceProps, Math.max(0, lastMeasuredIndex), offset);
|
|
2092
|
+
}
|
|
2093
|
+
};
|
|
2094
|
+
|
|
2095
|
+
var findNearestItemBinarySearch$1 = function findNearestItemBinarySearch(props, instanceProps, high, low, offset) {
|
|
2096
|
+
while (low <= high) {
|
|
2097
|
+
var middle = low + Math.floor((high - low) / 2);
|
|
2098
|
+
var currentOffset = getItemMetadata$1(props, middle, instanceProps).offset;
|
|
2099
|
+
|
|
2100
|
+
if (currentOffset === offset) {
|
|
2101
|
+
return middle;
|
|
2102
|
+
} else if (currentOffset < offset) {
|
|
2103
|
+
low = middle + 1;
|
|
2104
|
+
} else if (currentOffset > offset) {
|
|
2105
|
+
high = middle - 1;
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
if (low > 0) {
|
|
2110
|
+
return low - 1;
|
|
2111
|
+
} else {
|
|
2112
|
+
return 0;
|
|
2113
|
+
}
|
|
2114
|
+
};
|
|
2115
|
+
|
|
2116
|
+
var findNearestItemExponentialSearch$1 = function findNearestItemExponentialSearch(props, instanceProps, index, offset) {
|
|
2117
|
+
var itemCount = props.itemCount;
|
|
2118
|
+
var interval = 1;
|
|
2119
|
+
|
|
2120
|
+
while (index < itemCount && getItemMetadata$1(props, index, instanceProps).offset < offset) {
|
|
2121
|
+
index += interval;
|
|
2122
|
+
interval *= 2;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
return findNearestItemBinarySearch$1(props, instanceProps, Math.min(index, itemCount - 1), Math.floor(index / 2), offset);
|
|
2126
|
+
};
|
|
2127
|
+
|
|
2128
|
+
var getEstimatedTotalSize = function getEstimatedTotalSize(_ref2, _ref3) {
|
|
2129
|
+
var itemCount = _ref2.itemCount;
|
|
2130
|
+
var itemMetadataMap = _ref3.itemMetadataMap,
|
|
2131
|
+
estimatedItemSize = _ref3.estimatedItemSize,
|
|
2132
|
+
lastMeasuredIndex = _ref3.lastMeasuredIndex;
|
|
2133
|
+
var totalSizeOfMeasuredItems = 0; // Edge case check for when the number of items decreases while a scroll is in progress.
|
|
2134
|
+
// https://github.com/bvaughn/react-window/pull/138
|
|
2135
|
+
|
|
2136
|
+
if (lastMeasuredIndex >= itemCount) {
|
|
2137
|
+
lastMeasuredIndex = itemCount - 1;
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
if (lastMeasuredIndex >= 0) {
|
|
2141
|
+
var itemMetadata = itemMetadataMap[lastMeasuredIndex];
|
|
2142
|
+
totalSizeOfMeasuredItems = itemMetadata.offset + itemMetadata.size;
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
var numUnmeasuredItems = itemCount - lastMeasuredIndex - 1;
|
|
2146
|
+
var totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedItemSize;
|
|
2147
|
+
return totalSizeOfMeasuredItems + totalSizeOfUnmeasuredItems;
|
|
2148
|
+
};
|
|
2149
|
+
|
|
2150
|
+
var VariableSizeList = /*#__PURE__*/createListComponent({
|
|
2151
|
+
getItemOffset: function getItemOffset(props, index, instanceProps) {
|
|
2152
|
+
return getItemMetadata$1(props, index, instanceProps).offset;
|
|
2153
|
+
},
|
|
2154
|
+
getItemSize: function getItemSize(props, index, instanceProps) {
|
|
2155
|
+
return instanceProps.itemMetadataMap[index].size;
|
|
2156
|
+
},
|
|
2157
|
+
getEstimatedTotalSize: getEstimatedTotalSize,
|
|
2158
|
+
getOffsetForIndexAndAlignment: function getOffsetForIndexAndAlignment(props, index, align, scrollOffset, instanceProps, scrollbarSize) {
|
|
2159
|
+
var direction = props.direction,
|
|
2160
|
+
height = props.height,
|
|
2161
|
+
layout = props.layout,
|
|
2162
|
+
width = props.width; // TODO Deprecate direction "horizontal"
|
|
2163
|
+
|
|
2164
|
+
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
|
2165
|
+
var size = isHorizontal ? width : height;
|
|
2166
|
+
var itemMetadata = getItemMetadata$1(props, index, instanceProps); // Get estimated total size after ItemMetadata is computed,
|
|
2167
|
+
// To ensure it reflects actual measurements instead of just estimates.
|
|
2168
|
+
|
|
2169
|
+
var estimatedTotalSize = getEstimatedTotalSize(props, instanceProps);
|
|
2170
|
+
var maxOffset = Math.max(0, Math.min(estimatedTotalSize - size, itemMetadata.offset));
|
|
2171
|
+
var minOffset = Math.max(0, itemMetadata.offset - size + itemMetadata.size + scrollbarSize);
|
|
2172
|
+
|
|
2173
|
+
if (align === 'smart') {
|
|
2174
|
+
if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
|
|
2175
|
+
align = 'auto';
|
|
2176
|
+
} else {
|
|
2177
|
+
align = 'center';
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
switch (align) {
|
|
2182
|
+
case 'start':
|
|
2183
|
+
return maxOffset;
|
|
2184
|
+
|
|
2185
|
+
case 'end':
|
|
2186
|
+
return minOffset;
|
|
2187
|
+
|
|
2188
|
+
case 'center':
|
|
2189
|
+
return Math.round(minOffset + (maxOffset - minOffset) / 2);
|
|
2190
|
+
|
|
2191
|
+
case 'auto':
|
|
2192
|
+
default:
|
|
2193
|
+
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
|
2194
|
+
return scrollOffset;
|
|
2195
|
+
} else if (scrollOffset < minOffset) {
|
|
2196
|
+
return minOffset;
|
|
2197
|
+
} else {
|
|
2198
|
+
return maxOffset;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
}
|
|
2202
|
+
},
|
|
2203
|
+
getStartIndexForOffset: function getStartIndexForOffset(props, offset, instanceProps) {
|
|
2204
|
+
return findNearestItem$1(props, instanceProps, offset);
|
|
2205
|
+
},
|
|
2206
|
+
getStopIndexForStartIndex: function getStopIndexForStartIndex(props, startIndex, scrollOffset, instanceProps) {
|
|
2207
|
+
var direction = props.direction,
|
|
2208
|
+
height = props.height,
|
|
2209
|
+
itemCount = props.itemCount,
|
|
2210
|
+
layout = props.layout,
|
|
2211
|
+
width = props.width; // TODO Deprecate direction "horizontal"
|
|
2212
|
+
|
|
2213
|
+
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
|
2214
|
+
var size = isHorizontal ? width : height;
|
|
2215
|
+
var itemMetadata = getItemMetadata$1(props, startIndex, instanceProps);
|
|
2216
|
+
var maxOffset = scrollOffset + size;
|
|
2217
|
+
var offset = itemMetadata.offset + itemMetadata.size;
|
|
2218
|
+
var stopIndex = startIndex;
|
|
2219
|
+
|
|
2220
|
+
while (stopIndex < itemCount - 1 && offset < maxOffset) {
|
|
2221
|
+
stopIndex++;
|
|
2222
|
+
offset += getItemMetadata$1(props, stopIndex, instanceProps).size;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
return stopIndex;
|
|
2226
|
+
},
|
|
2227
|
+
initInstanceProps: function initInstanceProps(props, instance) {
|
|
2228
|
+
var _ref4 = props,
|
|
2229
|
+
estimatedItemSize = _ref4.estimatedItemSize;
|
|
2230
|
+
var instanceProps = {
|
|
2231
|
+
itemMetadataMap: {},
|
|
2232
|
+
estimatedItemSize: estimatedItemSize || DEFAULT_ESTIMATED_ITEM_SIZE$1,
|
|
2233
|
+
lastMeasuredIndex: -1
|
|
2234
|
+
};
|
|
2235
|
+
|
|
2236
|
+
instance.resetAfterIndex = function (index, shouldForceUpdate) {
|
|
2237
|
+
if (shouldForceUpdate === void 0) {
|
|
2238
|
+
shouldForceUpdate = true;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
instanceProps.lastMeasuredIndex = Math.min(instanceProps.lastMeasuredIndex, index - 1); // We could potentially optimize further by only evicting styles after this index,
|
|
2242
|
+
// But since styles are only cached while scrolling is in progress-
|
|
2243
|
+
// It seems an unnecessary optimization.
|
|
2244
|
+
// It's unlikely that resetAfterIndex() will be called while a user is scrolling.
|
|
2245
|
+
|
|
2246
|
+
instance._getItemStyleCache(-1);
|
|
2247
|
+
|
|
2248
|
+
if (shouldForceUpdate) {
|
|
2249
|
+
instance.forceUpdate();
|
|
2250
|
+
}
|
|
2251
|
+
};
|
|
2252
|
+
|
|
2253
|
+
return instanceProps;
|
|
2254
|
+
},
|
|
2255
|
+
shouldResetStyleCacheOnItemSizeChange: false,
|
|
2256
|
+
validateProps: function validateProps(_ref5) {
|
|
2257
|
+
var itemSize = _ref5.itemSize;
|
|
2258
|
+
|
|
2259
|
+
if (false) {}
|
|
2260
|
+
}
|
|
2261
|
+
});
|
|
2262
|
+
|
|
2263
|
+
var FixedSizeGrid = /*#__PURE__*/createGridComponent({
|
|
2264
|
+
getColumnOffset: function getColumnOffset(_ref, index) {
|
|
2265
|
+
var columnWidth = _ref.columnWidth;
|
|
2266
|
+
return index * columnWidth;
|
|
2267
|
+
},
|
|
2268
|
+
getColumnWidth: function getColumnWidth(_ref2, index) {
|
|
2269
|
+
var columnWidth = _ref2.columnWidth;
|
|
2270
|
+
return columnWidth;
|
|
2271
|
+
},
|
|
2272
|
+
getRowOffset: function getRowOffset(_ref3, index) {
|
|
2273
|
+
var rowHeight = _ref3.rowHeight;
|
|
2274
|
+
return index * rowHeight;
|
|
2275
|
+
},
|
|
2276
|
+
getRowHeight: function getRowHeight(_ref4, index) {
|
|
2277
|
+
var rowHeight = _ref4.rowHeight;
|
|
2278
|
+
return rowHeight;
|
|
2279
|
+
},
|
|
2280
|
+
getEstimatedTotalHeight: function getEstimatedTotalHeight(_ref5) {
|
|
2281
|
+
var rowCount = _ref5.rowCount,
|
|
2282
|
+
rowHeight = _ref5.rowHeight;
|
|
2283
|
+
return rowHeight * rowCount;
|
|
2284
|
+
},
|
|
2285
|
+
getEstimatedTotalWidth: function getEstimatedTotalWidth(_ref6) {
|
|
2286
|
+
var columnCount = _ref6.columnCount,
|
|
2287
|
+
columnWidth = _ref6.columnWidth;
|
|
2288
|
+
return columnWidth * columnCount;
|
|
2289
|
+
},
|
|
2290
|
+
getOffsetForColumnAndAlignment: function getOffsetForColumnAndAlignment(_ref7, columnIndex, align, scrollLeft, instanceProps, scrollbarSize) {
|
|
2291
|
+
var columnCount = _ref7.columnCount,
|
|
2292
|
+
columnWidth = _ref7.columnWidth,
|
|
2293
|
+
width = _ref7.width;
|
|
2294
|
+
var lastColumnOffset = Math.max(0, columnCount * columnWidth - width);
|
|
2295
|
+
var maxOffset = Math.min(lastColumnOffset, columnIndex * columnWidth);
|
|
2296
|
+
var minOffset = Math.max(0, columnIndex * columnWidth - width + scrollbarSize + columnWidth);
|
|
2297
|
+
|
|
2298
|
+
if (align === 'smart') {
|
|
2299
|
+
if (scrollLeft >= minOffset - width && scrollLeft <= maxOffset + width) {
|
|
2300
|
+
align = 'auto';
|
|
2301
|
+
} else {
|
|
2302
|
+
align = 'center';
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
switch (align) {
|
|
2307
|
+
case 'start':
|
|
2308
|
+
return maxOffset;
|
|
2309
|
+
|
|
2310
|
+
case 'end':
|
|
2311
|
+
return minOffset;
|
|
2312
|
+
|
|
2313
|
+
case 'center':
|
|
2314
|
+
// "Centered" offset is usually the average of the min and max.
|
|
2315
|
+
// But near the edges of the list, this doesn't hold true.
|
|
2316
|
+
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
|
2317
|
+
|
|
2318
|
+
if (middleOffset < Math.ceil(width / 2)) {
|
|
2319
|
+
return 0; // near the beginning
|
|
2320
|
+
} else if (middleOffset > lastColumnOffset + Math.floor(width / 2)) {
|
|
2321
|
+
return lastColumnOffset; // near the end
|
|
2322
|
+
} else {
|
|
2323
|
+
return middleOffset;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
case 'auto':
|
|
2327
|
+
default:
|
|
2328
|
+
if (scrollLeft >= minOffset && scrollLeft <= maxOffset) {
|
|
2329
|
+
return scrollLeft;
|
|
2330
|
+
} else if (minOffset > maxOffset) {
|
|
2331
|
+
// Because we only take into account the scrollbar size when calculating minOffset
|
|
2332
|
+
// this value can be larger than maxOffset when at the end of the list
|
|
2333
|
+
return minOffset;
|
|
2334
|
+
} else if (scrollLeft < minOffset) {
|
|
2335
|
+
return minOffset;
|
|
2336
|
+
} else {
|
|
2337
|
+
return maxOffset;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
}
|
|
2341
|
+
},
|
|
2342
|
+
getOffsetForRowAndAlignment: function getOffsetForRowAndAlignment(_ref8, rowIndex, align, scrollTop, instanceProps, scrollbarSize) {
|
|
2343
|
+
var rowHeight = _ref8.rowHeight,
|
|
2344
|
+
height = _ref8.height,
|
|
2345
|
+
rowCount = _ref8.rowCount;
|
|
2346
|
+
var lastRowOffset = Math.max(0, rowCount * rowHeight - height);
|
|
2347
|
+
var maxOffset = Math.min(lastRowOffset, rowIndex * rowHeight);
|
|
2348
|
+
var minOffset = Math.max(0, rowIndex * rowHeight - height + scrollbarSize + rowHeight);
|
|
2349
|
+
|
|
2350
|
+
if (align === 'smart') {
|
|
2351
|
+
if (scrollTop >= minOffset - height && scrollTop <= maxOffset + height) {
|
|
2352
|
+
align = 'auto';
|
|
2353
|
+
} else {
|
|
2354
|
+
align = 'center';
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
switch (align) {
|
|
2359
|
+
case 'start':
|
|
2360
|
+
return maxOffset;
|
|
2361
|
+
|
|
2362
|
+
case 'end':
|
|
2363
|
+
return minOffset;
|
|
2364
|
+
|
|
2365
|
+
case 'center':
|
|
2366
|
+
// "Centered" offset is usually the average of the min and max.
|
|
2367
|
+
// But near the edges of the list, this doesn't hold true.
|
|
2368
|
+
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
|
2369
|
+
|
|
2370
|
+
if (middleOffset < Math.ceil(height / 2)) {
|
|
2371
|
+
return 0; // near the beginning
|
|
2372
|
+
} else if (middleOffset > lastRowOffset + Math.floor(height / 2)) {
|
|
2373
|
+
return lastRowOffset; // near the end
|
|
2374
|
+
} else {
|
|
2375
|
+
return middleOffset;
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
case 'auto':
|
|
2379
|
+
default:
|
|
2380
|
+
if (scrollTop >= minOffset && scrollTop <= maxOffset) {
|
|
2381
|
+
return scrollTop;
|
|
2382
|
+
} else if (minOffset > maxOffset) {
|
|
2383
|
+
// Because we only take into account the scrollbar size when calculating minOffset
|
|
2384
|
+
// this value can be larger than maxOffset when at the end of the list
|
|
2385
|
+
return minOffset;
|
|
2386
|
+
} else if (scrollTop < minOffset) {
|
|
2387
|
+
return minOffset;
|
|
2388
|
+
} else {
|
|
2389
|
+
return maxOffset;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
}
|
|
2393
|
+
},
|
|
2394
|
+
getColumnStartIndexForOffset: function getColumnStartIndexForOffset(_ref9, scrollLeft) {
|
|
2395
|
+
var columnWidth = _ref9.columnWidth,
|
|
2396
|
+
columnCount = _ref9.columnCount;
|
|
2397
|
+
return Math.max(0, Math.min(columnCount - 1, Math.floor(scrollLeft / columnWidth)));
|
|
2398
|
+
},
|
|
2399
|
+
getColumnStopIndexForStartIndex: function getColumnStopIndexForStartIndex(_ref10, startIndex, scrollLeft) {
|
|
2400
|
+
var columnWidth = _ref10.columnWidth,
|
|
2401
|
+
columnCount = _ref10.columnCount,
|
|
2402
|
+
width = _ref10.width;
|
|
2403
|
+
var left = startIndex * columnWidth;
|
|
2404
|
+
var numVisibleColumns = Math.ceil((width + scrollLeft - left) / columnWidth);
|
|
2405
|
+
return Math.max(0, Math.min(columnCount - 1, startIndex + numVisibleColumns - 1 // -1 is because stop index is inclusive
|
|
2406
|
+
));
|
|
2407
|
+
},
|
|
2408
|
+
getRowStartIndexForOffset: function getRowStartIndexForOffset(_ref11, scrollTop) {
|
|
2409
|
+
var rowHeight = _ref11.rowHeight,
|
|
2410
|
+
rowCount = _ref11.rowCount;
|
|
2411
|
+
return Math.max(0, Math.min(rowCount - 1, Math.floor(scrollTop / rowHeight)));
|
|
2412
|
+
},
|
|
2413
|
+
getRowStopIndexForStartIndex: function getRowStopIndexForStartIndex(_ref12, startIndex, scrollTop) {
|
|
2414
|
+
var rowHeight = _ref12.rowHeight,
|
|
2415
|
+
rowCount = _ref12.rowCount,
|
|
2416
|
+
height = _ref12.height;
|
|
2417
|
+
var top = startIndex * rowHeight;
|
|
2418
|
+
var numVisibleRows = Math.ceil((height + scrollTop - top) / rowHeight);
|
|
2419
|
+
return Math.max(0, Math.min(rowCount - 1, startIndex + numVisibleRows - 1 // -1 is because stop index is inclusive
|
|
2420
|
+
));
|
|
2421
|
+
},
|
|
2422
|
+
initInstanceProps: function initInstanceProps(props) {// Noop
|
|
2423
|
+
},
|
|
2424
|
+
shouldResetStyleCacheOnItemSizeChange: true,
|
|
2425
|
+
validateProps: function validateProps(_ref13) {
|
|
2426
|
+
var columnWidth = _ref13.columnWidth,
|
|
2427
|
+
rowHeight = _ref13.rowHeight;
|
|
2428
|
+
|
|
2429
|
+
if (false) {}
|
|
2430
|
+
}
|
|
2431
|
+
});
|
|
2432
|
+
|
|
2433
|
+
var FixedSizeList = /*#__PURE__*/createListComponent({
|
|
2434
|
+
getItemOffset: function getItemOffset(_ref, index) {
|
|
2435
|
+
var itemSize = _ref.itemSize;
|
|
2436
|
+
return index * itemSize;
|
|
2437
|
+
},
|
|
2438
|
+
getItemSize: function getItemSize(_ref2, index) {
|
|
2439
|
+
var itemSize = _ref2.itemSize;
|
|
2440
|
+
return itemSize;
|
|
2441
|
+
},
|
|
2442
|
+
getEstimatedTotalSize: function getEstimatedTotalSize(_ref3) {
|
|
2443
|
+
var itemCount = _ref3.itemCount,
|
|
2444
|
+
itemSize = _ref3.itemSize;
|
|
2445
|
+
return itemSize * itemCount;
|
|
2446
|
+
},
|
|
2447
|
+
getOffsetForIndexAndAlignment: function getOffsetForIndexAndAlignment(_ref4, index, align, scrollOffset, instanceProps, scrollbarSize) {
|
|
2448
|
+
var direction = _ref4.direction,
|
|
2449
|
+
height = _ref4.height,
|
|
2450
|
+
itemCount = _ref4.itemCount,
|
|
2451
|
+
itemSize = _ref4.itemSize,
|
|
2452
|
+
layout = _ref4.layout,
|
|
2453
|
+
width = _ref4.width;
|
|
2454
|
+
// TODO Deprecate direction "horizontal"
|
|
2455
|
+
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
|
2456
|
+
var size = isHorizontal ? width : height;
|
|
2457
|
+
var lastItemOffset = Math.max(0, itemCount * itemSize - size);
|
|
2458
|
+
var maxOffset = Math.min(lastItemOffset, index * itemSize);
|
|
2459
|
+
var minOffset = Math.max(0, index * itemSize - size + itemSize + scrollbarSize);
|
|
2460
|
+
|
|
2461
|
+
if (align === 'smart') {
|
|
2462
|
+
if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
|
|
2463
|
+
align = 'auto';
|
|
2464
|
+
} else {
|
|
2465
|
+
align = 'center';
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
switch (align) {
|
|
2470
|
+
case 'start':
|
|
2471
|
+
return maxOffset;
|
|
2472
|
+
|
|
2473
|
+
case 'end':
|
|
2474
|
+
return minOffset;
|
|
2475
|
+
|
|
2476
|
+
case 'center':
|
|
2477
|
+
{
|
|
2478
|
+
// "Centered" offset is usually the average of the min and max.
|
|
2479
|
+
// But near the edges of the list, this doesn't hold true.
|
|
2480
|
+
var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
|
|
2481
|
+
|
|
2482
|
+
if (middleOffset < Math.ceil(size / 2)) {
|
|
2483
|
+
return 0; // near the beginning
|
|
2484
|
+
} else if (middleOffset > lastItemOffset + Math.floor(size / 2)) {
|
|
2485
|
+
return lastItemOffset; // near the end
|
|
2486
|
+
} else {
|
|
2487
|
+
return middleOffset;
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
case 'auto':
|
|
2492
|
+
default:
|
|
2493
|
+
if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
|
|
2494
|
+
return scrollOffset;
|
|
2495
|
+
} else if (scrollOffset < minOffset) {
|
|
2496
|
+
return minOffset;
|
|
2497
|
+
} else {
|
|
2498
|
+
return maxOffset;
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
}
|
|
2502
|
+
},
|
|
2503
|
+
getStartIndexForOffset: function getStartIndexForOffset(_ref5, offset) {
|
|
2504
|
+
var itemCount = _ref5.itemCount,
|
|
2505
|
+
itemSize = _ref5.itemSize;
|
|
2506
|
+
return Math.max(0, Math.min(itemCount - 1, Math.floor(offset / itemSize)));
|
|
2507
|
+
},
|
|
2508
|
+
getStopIndexForStartIndex: function getStopIndexForStartIndex(_ref6, startIndex, scrollOffset) {
|
|
2509
|
+
var direction = _ref6.direction,
|
|
2510
|
+
height = _ref6.height,
|
|
2511
|
+
itemCount = _ref6.itemCount,
|
|
2512
|
+
itemSize = _ref6.itemSize,
|
|
2513
|
+
layout = _ref6.layout,
|
|
2514
|
+
width = _ref6.width;
|
|
2515
|
+
// TODO Deprecate direction "horizontal"
|
|
2516
|
+
var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
|
|
2517
|
+
var offset = startIndex * itemSize;
|
|
2518
|
+
var size = isHorizontal ? width : height;
|
|
2519
|
+
var numVisibleItems = Math.ceil((size + scrollOffset - offset) / itemSize);
|
|
2520
|
+
return Math.max(0, Math.min(itemCount - 1, startIndex + numVisibleItems - 1 // -1 is because stop index is inclusive
|
|
2521
|
+
));
|
|
2522
|
+
},
|
|
2523
|
+
initInstanceProps: function initInstanceProps(props) {// Noop
|
|
2524
|
+
},
|
|
2525
|
+
shouldResetStyleCacheOnItemSizeChange: true,
|
|
2526
|
+
validateProps: function validateProps(_ref7) {
|
|
2527
|
+
var itemSize = _ref7.itemSize;
|
|
2528
|
+
|
|
2529
|
+
if (false) {}
|
|
2530
|
+
}
|
|
2531
|
+
});
|
|
2532
|
+
|
|
2533
|
+
// Pulled from react-compat
|
|
2534
|
+
// https://github.com/developit/preact-compat/blob/7c5de00e7c85e2ffd011bf3af02899b63f699d3a/src/index.js#L349
|
|
2535
|
+
function shallowDiffers(prev, next) {
|
|
2536
|
+
for (var attribute in prev) {
|
|
2537
|
+
if (!(attribute in next)) {
|
|
2538
|
+
return true;
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
for (var _attribute in next) {
|
|
2543
|
+
if (prev[_attribute] !== next[_attribute]) {
|
|
2544
|
+
return true;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
return false;
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
var _excluded = (/* unused pure expression or super */ null && (["style"])),
|
|
2552
|
+
_excluded2 = (/* unused pure expression or super */ null && (["style"]));
|
|
2553
|
+
// It knows to compare individual style props and ignore the wrapper object.
|
|
2554
|
+
// See https://reactjs.org/docs/react-api.html#reactmemo
|
|
2555
|
+
|
|
2556
|
+
function areEqual(prevProps, nextProps) {
|
|
2557
|
+
var prevStyle = prevProps.style,
|
|
2558
|
+
prevRest = _objectWithoutPropertiesLoose(prevProps, _excluded);
|
|
2559
|
+
|
|
2560
|
+
var nextStyle = nextProps.style,
|
|
2561
|
+
nextRest = _objectWithoutPropertiesLoose(nextProps, _excluded2);
|
|
2562
|
+
|
|
2563
|
+
return !shallowDiffers(prevStyle, nextStyle) && !shallowDiffers(prevRest, nextRest);
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
// It knows to compare individual style props and ignore the wrapper object.
|
|
2567
|
+
// See https://reactjs.org/docs/react-component.html#shouldcomponentupdate
|
|
2568
|
+
|
|
2569
|
+
function shouldComponentUpdate(nextProps, nextState) {
|
|
2570
|
+
return !areEqual(this.props, nextProps) || shallowDiffers(this.state, nextState);
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
//# sourceMappingURL=index.esm.js.map
|
|
2575
|
+
|
|
2576
|
+
|
|
2577
|
+
/***/ })
|
|
2578
|
+
|
|
2579
|
+
}]);
|