@hrforte/react-pivottable 2.2.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PivotDataWorker.js +219 -13
- package/dist/PivotDataWorker.js.map +1 -1
- package/dist/PivotTable.js +2 -1
- package/dist/PivotTable.js.map +1 -1
- package/dist/PivotTableUI.js +39 -66
- package/dist/PivotTableUI.js.map +1 -1
- package/dist/TableRenderers.js +568 -106
- package/dist/TableRenderers.js.map +1 -1
- package/dist/Utilities.js +104 -179
- package/dist/Utilities.js.map +1 -1
- package/dist/__tests__/PivotDataWorker-test.js +437 -7
- package/dist/__tests__/PivotDataWorker-test.js.map +1 -1
- package/dist/__tests__/PivotTableUI-processing-test.js +41 -2
- package/dist/__tests__/PivotTableUI-processing-test.js.map +1 -1
- package/dist/__tests__/TableRenderers-showNumericalOrder-test.js +449 -0
- package/dist/__tests__/TableRenderers-showNumericalOrder-test.js.map +1 -1
- package/dist/__tests__/pivotCompute-test.js +137 -0
- package/dist/__tests__/pivotCompute-test.js.map +1 -1
- package/dist/pivot-worker.js +509 -201
- package/dist/pivotCompute.js +237 -12
- package/dist/pivotCompute.js.map +1 -1
- package/dist/pivotWorker.js +165 -9
- package/dist/pivotWorker.js.map +1 -1
- package/dist/pivottable.css +274 -266
- package/package.json +1 -1
package/dist/PivotDataWorker.js
CHANGED
|
@@ -6,7 +6,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.DEFAULT_WORKER_URL = undefined;
|
|
7
7
|
exports.setWorkerDebug = setWorkerDebug;
|
|
8
8
|
exports.configureWorkerUrl = configureWorkerUrl;
|
|
9
|
+
exports.retainPivotWorker = retainPivotWorker;
|
|
10
|
+
exports.releasePivotWorker = releasePivotWorker;
|
|
9
11
|
exports.computePivotInWorker = computePivotInWorker;
|
|
12
|
+
exports.computePivotViewportInWorker = computePivotViewportInWorker;
|
|
13
|
+
exports.releasePivotInWorker = releasePivotInWorker;
|
|
14
|
+
exports.releaseDatasetInWorker = releaseDatasetInWorker;
|
|
10
15
|
exports.computePivotSynchronously = computePivotSynchronously;
|
|
11
16
|
exports.computePivotWithFallback = computePivotWithFallback;
|
|
12
17
|
|
|
@@ -21,8 +26,7 @@ var DEFAULT_WORKER_URL = exports.DEFAULT_WORKER_URL = 'pivot-worker.js'; /* esli
|
|
|
21
26
|
* Responsibilities:
|
|
22
27
|
* - lazily create a single shared Worker (at `workerUrl`, overrideable),
|
|
23
28
|
* - route result/error messages to the matching request,
|
|
24
|
-
* -
|
|
25
|
-
* workers are unavailable or the worker bundle fails to load.
|
|
29
|
+
* - surface worker errors instead of silently recomputing on the main thread.
|
|
26
30
|
*
|
|
27
31
|
* Debug logging is off by default. Turn it on with the `workerDebug` prop of
|
|
28
32
|
* PivotTableUI (or by setting `window.__PVT_WORKER_DEBUG__ = true` before
|
|
@@ -32,6 +36,8 @@ var DEFAULT_WORKER_URL = exports.DEFAULT_WORKER_URL = 'pivot-worker.js'; /* esli
|
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
var REQUEST_TIMEOUT_MS = 300000;
|
|
39
|
+
var VIEWPORT_TIMEOUT_MS = 10000;
|
|
40
|
+
var DATA_CHUNK_SIZE = 500;
|
|
35
41
|
|
|
36
42
|
var workerUrl = DEFAULT_WORKER_URL;
|
|
37
43
|
var sharedWorker = null;
|
|
@@ -42,8 +48,11 @@ var sharedWorkerBroken = false;
|
|
|
42
48
|
var hasResultEver = false;
|
|
43
49
|
var nextRequestId = 1;
|
|
44
50
|
var lastStagedDataKey = null;
|
|
51
|
+
var stagingPromises = new Map();
|
|
45
52
|
var workerDebug = false;
|
|
46
53
|
var pendingRequests = new Map();
|
|
54
|
+
var pendingViewportByPivot = new Map();
|
|
55
|
+
var workerOwners = new Set();
|
|
47
56
|
|
|
48
57
|
function setWorkerDebug(enabled) {
|
|
49
58
|
var next = Boolean(enabled);
|
|
@@ -97,6 +106,24 @@ var failAllPending = function failAllPending(error) {
|
|
|
97
106
|
entry.reject(error);
|
|
98
107
|
});
|
|
99
108
|
pendingRequests.clear();
|
|
109
|
+
pendingViewportByPivot.clear();
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
var cancelPendingViewport = function cancelPendingViewport(viewportKey) {
|
|
113
|
+
var requestId = pendingViewportByPivot.get(viewportKey);
|
|
114
|
+
if (typeof requestId !== 'number') {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
pendingViewportByPivot.delete(viewportKey);
|
|
118
|
+
var entry = pendingRequests.get(requestId);
|
|
119
|
+
if (!entry) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
clearTimeout(entry.timer);
|
|
123
|
+
pendingRequests.delete(requestId);
|
|
124
|
+
var error = new Error('Pivot viewport request was replaced');
|
|
125
|
+
error.code = 'PIVOT_VIEWPORT_CANCELLED';
|
|
126
|
+
entry.reject(error);
|
|
100
127
|
};
|
|
101
128
|
|
|
102
129
|
function configureWorkerUrl(url) {
|
|
@@ -111,10 +138,36 @@ function configureWorkerUrl(url) {
|
|
|
111
138
|
sharedWorkerBroken = false;
|
|
112
139
|
hasResultEver = false;
|
|
113
140
|
lastStagedDataKey = null;
|
|
141
|
+
stagingPromises.clear();
|
|
114
142
|
}
|
|
115
143
|
}
|
|
116
144
|
}
|
|
117
145
|
|
|
146
|
+
function retainPivotWorker(ownerKey) {
|
|
147
|
+
if (ownerKey) {
|
|
148
|
+
workerOwners.add(ownerKey);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function releasePivotWorker(ownerKey) {
|
|
153
|
+
if (!ownerKey) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
workerOwners.delete(ownerKey);
|
|
157
|
+
if (sharedWorker) {
|
|
158
|
+
sharedWorker.postMessage({ type: 'pivot:releaseOwner', ownerKey: ownerKey });
|
|
159
|
+
}
|
|
160
|
+
if (sharedWorker && workerOwners.size === 0) {
|
|
161
|
+
failAllPending(new Error('Pivot worker was released'));
|
|
162
|
+
sharedWorker.terminate();
|
|
163
|
+
sharedWorker = null;
|
|
164
|
+
sharedWorkerBroken = false;
|
|
165
|
+
hasResultEver = false;
|
|
166
|
+
lastStagedDataKey = null;
|
|
167
|
+
stagingPromises.clear();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
118
171
|
var handleWorkerMessage = function handleWorkerMessage(event) {
|
|
119
172
|
var message = event.data || {};
|
|
120
173
|
if (message.type === 'pivot:log') {
|
|
@@ -133,7 +186,15 @@ var handleWorkerMessage = function handleWorkerMessage(event) {
|
|
|
133
186
|
}
|
|
134
187
|
clearTimeout(entry.timer);
|
|
135
188
|
pendingRequests.delete(message.id);
|
|
136
|
-
if (
|
|
189
|
+
if (entry.viewportKey !== undefined && pendingViewportByPivot.get(entry.viewportKey) === message.id) {
|
|
190
|
+
pendingViewportByPivot.delete(entry.viewportKey);
|
|
191
|
+
}
|
|
192
|
+
if (message.type === 'pivot:result' || message.type === 'pivot:viewportResult') {
|
|
193
|
+
if (message.type === 'pivot:viewportResult') {
|
|
194
|
+
log('#' + message.id + ' viewport received in ' + (Date.now() - entry.startedAt) + 'ms');
|
|
195
|
+
entry.resolve(message.result);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
137
198
|
hasResultEver = true;
|
|
138
199
|
var result = message.result;
|
|
139
200
|
log('#' + message.id + ' result received in ' + (Date.now() - entry.startedAt) + 'ms', {
|
|
@@ -149,6 +210,48 @@ var handleWorkerMessage = function handleWorkerMessage(event) {
|
|
|
149
210
|
}
|
|
150
211
|
};
|
|
151
212
|
|
|
213
|
+
// `Worker.postMessage()` structured-clones its payload on the calling thread.
|
|
214
|
+
// Sending a wide dataset in one message can therefore freeze the UI before
|
|
215
|
+
// the worker has even started. Large inputs are split across macrotasks so
|
|
216
|
+
// pointer and paint work can run between chunks.
|
|
217
|
+
var stageDataInWorker = function stageDataInWorker(worker, id, dataKey, data, ownerKey) {
|
|
218
|
+
var owner = ownerKey ? { ownerKey: ownerKey } : {};
|
|
219
|
+
if (!Array.isArray(data) || data.length <= DATA_CHUNK_SIZE) {
|
|
220
|
+
worker.postMessage(Object.assign({ type: 'pivot:setData', id: id, dataKey: dataKey, data: data }, owner));
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return new Promise(function (resolve, reject) {
|
|
225
|
+
try {
|
|
226
|
+
worker.postMessage(Object.assign({ type: 'pivot:setDataStart', id: id, dataKey: dataKey }, owner));
|
|
227
|
+
var offset = 0;
|
|
228
|
+
var postNextChunk = function postNextChunk() {
|
|
229
|
+
try {
|
|
230
|
+
var end = Math.min(offset + DATA_CHUNK_SIZE, data.length);
|
|
231
|
+
worker.postMessage({
|
|
232
|
+
type: 'pivot:setDataChunk',
|
|
233
|
+
id: id,
|
|
234
|
+
dataKey: dataKey,
|
|
235
|
+
data: data.slice(offset, end)
|
|
236
|
+
});
|
|
237
|
+
offset = end;
|
|
238
|
+
if (offset < data.length) {
|
|
239
|
+
setTimeout(postNextChunk, 0);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
worker.postMessage({ type: 'pivot:setDataEnd', id: id, dataKey: dataKey });
|
|
243
|
+
resolve();
|
|
244
|
+
} catch (error) {
|
|
245
|
+
reject(error);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
postNextChunk();
|
|
249
|
+
} catch (error) {
|
|
250
|
+
reject(error);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
|
|
152
255
|
var ensureWorker = function ensureWorker() {
|
|
153
256
|
if (sharedWorkerBroken) {
|
|
154
257
|
return null;
|
|
@@ -191,7 +294,7 @@ var ensureWorker = function ensureWorker() {
|
|
|
191
294
|
* worker reuse the materialized dataset across consecutive computations and
|
|
192
295
|
* lets the client skip re-staging identical data.
|
|
193
296
|
*/
|
|
194
|
-
function computePivotInWorker(data, dataKey, config) {
|
|
297
|
+
function computePivotInWorker(data, dataKey, config, ownerKey) {
|
|
195
298
|
var worker = ensureWorker();
|
|
196
299
|
if (!worker) {
|
|
197
300
|
log('worker unavailable -> synchronous fallback');
|
|
@@ -212,14 +315,118 @@ function computePivotInWorker(data, dataKey, config) {
|
|
|
212
315
|
});
|
|
213
316
|
var mustStage = lastStagedDataKey !== dataKey;
|
|
214
317
|
log('#' + id + ' dispatching to worker (dataKey=' + dataKey + (mustStage ? ', staging ' + (data || []).length + ' records' : ', cached dataset') + ', ' + describeConfig(config) + ')');
|
|
318
|
+
var dataReady = null;
|
|
215
319
|
if (mustStage) {
|
|
216
|
-
worker.postMessage({ type: 'pivot:setData', id: id, dataKey: dataKey, data: data });
|
|
217
320
|
lastStagedDataKey = dataKey;
|
|
321
|
+
dataReady = stageDataInWorker(worker, id, dataKey, data, ownerKey);
|
|
322
|
+
if (dataReady) {
|
|
323
|
+
stagingPromises.set(dataKey, dataReady);
|
|
324
|
+
dataReady.then(function () {
|
|
325
|
+
if (stagingPromises.get(dataKey) === dataReady) {
|
|
326
|
+
stagingPromises.delete(dataKey);
|
|
327
|
+
}
|
|
328
|
+
}, function () {
|
|
329
|
+
return stagingPromises.delete(dataKey);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
} else if (stagingPromises.has(dataKey)) {
|
|
333
|
+
dataReady = stagingPromises.get(dataKey);
|
|
334
|
+
}
|
|
335
|
+
var postCompute = function postCompute() {
|
|
336
|
+
if (pendingRequests.has(id)) {
|
|
337
|
+
worker.postMessage({
|
|
338
|
+
type: 'pivot:compute',
|
|
339
|
+
id: id,
|
|
340
|
+
dataKey: dataKey,
|
|
341
|
+
config: config,
|
|
342
|
+
ownerKey: ownerKey
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
if (dataReady) {
|
|
347
|
+
dataReady.then(postCompute).catch(function (error) {
|
|
348
|
+
clearTimeout(timer);
|
|
349
|
+
pendingRequests.delete(id);
|
|
350
|
+
reject(error);
|
|
351
|
+
});
|
|
352
|
+
} else {
|
|
353
|
+
postCompute();
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Request a small row window from a pivot result already cached in the worker.
|
|
359
|
+
// No dataset or full pivot state is cloned for a scroll request.
|
|
360
|
+
function computePivotViewportInWorker(viewportKey, start, end, columnMode) {
|
|
361
|
+
var columnStart = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
|
|
362
|
+
var columnEnd = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : Number.MAX_SAFE_INTEGER;
|
|
363
|
+
|
|
364
|
+
var worker = ensureWorker();
|
|
365
|
+
if (!worker) {
|
|
366
|
+
return Promise.reject(new Error('Web worker unavailable'));
|
|
367
|
+
}
|
|
368
|
+
cancelPendingViewport(viewportKey);
|
|
369
|
+
var id = nextRequestId++;
|
|
370
|
+
return new Promise(function (resolve, reject) {
|
|
371
|
+
var timer = setTimeout(function () {
|
|
372
|
+
pendingRequests.delete(id);
|
|
373
|
+
if (pendingViewportByPivot.get(viewportKey) === id) {
|
|
374
|
+
pendingViewportByPivot.delete(viewportKey);
|
|
375
|
+
}
|
|
376
|
+
reject(new Error('Pivot viewport timed out'));
|
|
377
|
+
}, VIEWPORT_TIMEOUT_MS);
|
|
378
|
+
pendingRequests.set(id, {
|
|
379
|
+
resolve: resolve,
|
|
380
|
+
reject: reject,
|
|
381
|
+
timer: timer,
|
|
382
|
+
startedAt: Date.now(),
|
|
383
|
+
viewportKey: viewportKey
|
|
384
|
+
});
|
|
385
|
+
pendingViewportByPivot.set(viewportKey, id);
|
|
386
|
+
log('#' + id + ' viewport dispatch (rows=' + start + '-' + end + ', ' + ('columns=' + columnStart + '-' + columnEnd + ', pivot=' + viewportKey + ')'));
|
|
387
|
+
try {
|
|
388
|
+
worker.postMessage({
|
|
389
|
+
type: 'pivot:viewport',
|
|
390
|
+
id: id,
|
|
391
|
+
viewportKey: viewportKey,
|
|
392
|
+
start: start,
|
|
393
|
+
end: end,
|
|
394
|
+
columnMode: columnMode,
|
|
395
|
+
columnStart: columnStart,
|
|
396
|
+
columnEnd: columnEnd
|
|
397
|
+
});
|
|
398
|
+
} catch (error) {
|
|
399
|
+
clearTimeout(timer);
|
|
400
|
+
pendingRequests.delete(id);
|
|
401
|
+
if (pendingViewportByPivot.get(viewportKey) === id) {
|
|
402
|
+
pendingViewportByPivot.delete(viewportKey);
|
|
403
|
+
}
|
|
404
|
+
reject(error);
|
|
218
405
|
}
|
|
219
|
-
worker.postMessage({ type: 'pivot:compute', id: id, dataKey: dataKey, config: config });
|
|
220
406
|
});
|
|
221
407
|
}
|
|
222
408
|
|
|
409
|
+
// Release a full virtual pivot as soon as its table no longer references it.
|
|
410
|
+
// This intentionally does not create a worker during component cleanup.
|
|
411
|
+
function releasePivotInWorker(viewportKey) {
|
|
412
|
+
if (!sharedWorker || typeof viewportKey !== 'number') {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
cancelPendingViewport(viewportKey);
|
|
416
|
+
sharedWorker.postMessage({ type: 'pivot:release', viewportKey: viewportKey });
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function releaseDatasetInWorker(dataKey) {
|
|
420
|
+
if (!sharedWorker || !dataKey) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (lastStagedDataKey === dataKey) {
|
|
424
|
+
lastStagedDataKey = null;
|
|
425
|
+
}
|
|
426
|
+
stagingPromises.delete(dataKey);
|
|
427
|
+
sharedWorker.postMessage({ type: 'pivot:releaseData', dataKey: dataKey });
|
|
428
|
+
}
|
|
429
|
+
|
|
223
430
|
/*
|
|
224
431
|
* Same contract as the worker path, executed on the main thread. Used as the
|
|
225
432
|
* automatic fallback whenever the worker path is unavailable. Deferred by
|
|
@@ -248,14 +455,13 @@ function computePivotSynchronously(data, config) {
|
|
|
248
455
|
}
|
|
249
456
|
|
|
250
457
|
/*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* either way.
|
|
458
|
+
* Keep the existing entry point while testing worker failures without a
|
|
459
|
+
* synchronous fallback. Rejections reach PivotTableUI's error state.
|
|
254
460
|
*/
|
|
255
|
-
function computePivotWithFallback(data, dataKey, config) {
|
|
256
|
-
return computePivotInWorker(data, dataKey, config).catch(function (error) {
|
|
257
|
-
log('worker request failed
|
|
258
|
-
|
|
461
|
+
function computePivotWithFallback(data, dataKey, config, ownerKey) {
|
|
462
|
+
return computePivotInWorker(data, dataKey, config, ownerKey).catch(function (error) {
|
|
463
|
+
log('worker request failed (synchronous fallback disabled):', error);
|
|
464
|
+
throw error;
|
|
259
465
|
});
|
|
260
466
|
}
|
|
261
467
|
//# sourceMappingURL=PivotDataWorker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PivotDataWorker.js"],"names":["setWorkerDebug","configureWorkerUrl","computePivotInWorker","computePivotSynchronously","computePivotWithFallback","DEFAULT_WORKER_URL","REQUEST_TIMEOUT_MS","workerUrl","sharedWorker","sharedWorkerBroken","hasResultEver","nextRequestId","lastStagedDataKey","workerDebug","pendingRequests","Map","enabled","next","Boolean","wasEnabled","log","postMessage","type","isDebugEnabled","window","__PVT_WORKER_DEBUG__","args","describeConfig","config","rows","join","cols","aggregations","length","countOf","Array","isArray","value","undefined","failAllPending","forEach","clearTimeout","entry","timer","reject","error","clear","url","Error","terminate","handleWorkerMessage","message","event","data","detail","get","id","delete","result","Date","now","startedAt","totalRecords","rowKeys","colKeys","resolve","ensureWorker","Worker","onmessage","onerror","dataKey","worker","Promise","setTimeout","set","mustStage","materialized","catch"],"mappings":"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","file":"PivotDataWorker.js","sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable no-console */\n/* eslint-disable no-undefined */\n/*\n * Main-thread client for the pivot Web Worker (src/pivotWorker.js).\n *\n * Responsibilities:\n * - lazily create a single shared Worker (at `workerUrl`, overrideable),\n * - route result/error messages to the matching request,\n * - transparently fall back to a synchronous main-thread computation when\n * workers are unavailable or the worker bundle fails to load.\n *\n * Debug logging is off by default. Turn it on with the `workerDebug` prop of\n * PivotTableUI (or by setting `window.__PVT_WORKER_DEBUG__ = true` before\n * rendering) to trace worker creation, staging, computation, progress,\n * results, errors and fallbacks in the browser console.\n */\nimport {materializeData, computePivotState} from './pivotCompute';\n\nexport const DEFAULT_WORKER_URL = 'pivot-worker.js';\n\nconst REQUEST_TIMEOUT_MS = 300000;\n\nlet workerUrl = DEFAULT_WORKER_URL;\nlet sharedWorker = null;\n// The worker is marked broken only if it fails before ever producing a\n// result (e.g. a 404 worker script); runtime hiccups later on just reject\n// the affected request and fall back once.\nlet sharedWorkerBroken = false;\nlet hasResultEver = false;\nlet nextRequestId = 1;\nlet lastStagedDataKey = null;\nlet workerDebug = false;\nconst pendingRequests = new Map();\n\nexport function setWorkerDebug(enabled) {\n const next = Boolean(enabled);\n const wasEnabled = workerDebug;\n if (next === wasEnabled) {\n return;\n }\n if (next) {\n workerDebug = true;\n log('debug logging enabled');\n } else {\n // Log while logging is still active, so the \"disabled\" notice is shown.\n log('debug logging disabled');\n workerDebug = false;\n }\n if (sharedWorker) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: workerDebug});\n }\n}\n\nconst isDebugEnabled = () =>\n workerDebug ||\n (typeof window !== 'undefined' && window.__PVT_WORKER_DEBUG__ === true);\n\nfunction log(...args) {\n if (!isDebugEnabled()) {\n return;\n }\n console.log(\n '%c[pivottable worker]',\n 'color:#ff6600;font-weight:bold',\n ...args\n );\n}\n\nconst describeConfig = config =>\n `rows=[${(config.rows || []).join(', ')}] cols=[${(config.cols || []).join(\n ', '\n )}] aggregations=${(config.aggregations || []).length}`;\n\n// Length of an optional array field, used for defensive debug logging.\nconst countOf = value => (Array.isArray(value) ? value.length : undefined);\n\nconst failAllPending = error => {\n pendingRequests.forEach(entry => {\n clearTimeout(entry.timer);\n entry.reject(error);\n });\n pendingRequests.clear();\n};\n\nexport function configureWorkerUrl(url) {\n if (url && url !== workerUrl) {\n workerUrl = url;\n if (sharedWorker) {\n // Reject in-flight requests first so callers fall back to the\n // synchronous path instead of waiting for the request timeout.\n failAllPending(new Error('Pivot worker was reconfigured'));\n sharedWorker.terminate();\n sharedWorker = null;\n sharedWorkerBroken = false;\n hasResultEver = false;\n lastStagedDataKey = null;\n }\n }\n}\n\nconst handleWorkerMessage = event => {\n const message = event.data || {};\n if (message.type === 'pivot:log') {\n log('(in worker)', message.message, message.detail || '');\n return;\n }\n const entry = pendingRequests.get(message.id);\n if (!entry) {\n return;\n }\n if (message.type === 'pivot:progress') {\n // Progress reporting was removed: the UI only shows a loading overlay\n // until `pivot:result` arrives. Ignore messages from older worker\n // bundles that still emit progress so the request is not corrupted.\n return;\n }\n clearTimeout(entry.timer);\n pendingRequests.delete(message.id);\n if (message.type === 'pivot:result') {\n hasResultEver = true;\n const result = message.result;\n log(`#${message.id} result received in ${Date.now() - entry.startedAt}ms`, {\n totalRecords: result && result.totalRecords,\n rowKeys: countOf(result && result.rowKeys),\n colKeys: countOf(result && result.colKeys),\n aggregations: countOf(result && result.aggregations),\n });\n entry.resolve(message.result);\n } else if (message.type === 'pivot:error') {\n log(`#${message.id} worker reported an error:`, message.message);\n entry.reject(new Error(message.message || 'Pivot worker error'));\n }\n};\n\nconst ensureWorker = () => {\n if (sharedWorkerBroken) {\n return null;\n }\n\n if (typeof Worker === 'undefined') {\n log('no Worker support in this environment');\n return null;\n }\n\n if (!sharedWorker) {\n try {\n sharedWorker = new Worker(workerUrl);\n log('worker created:', workerUrl);\n } catch (error) {\n sharedWorkerBroken = true;\n log('worker creation failed:', error && error.message);\n return null;\n }\n sharedWorker.onmessage = handleWorkerMessage;\n sharedWorker.onerror = event => {\n log(\n 'worker error event (script failed to load / runtime error):',\n (event && event.message) || ''\n );\n failAllPending(new Error('Pivot worker failed to load'));\n if (!hasResultEver) {\n sharedWorkerBroken = true;\n log('worker marked unusable -> will use the synchronous fallback');\n }\n };\n if (isDebugEnabled()) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: true});\n }\n }\n return sharedWorker;\n};\n\n/*\n * Runs a full computation inside the shared worker.\n *\n * `dataKey` must change whenever the underlying dataset changes. It lets the\n * worker reuse the materialized dataset across consecutive computations and\n * lets the client skip re-staging identical data.\n */\nexport function computePivotInWorker(data, dataKey, config) {\n const worker = ensureWorker();\n if (!worker) {\n log('worker unavailable -> synchronous fallback');\n return Promise.reject(new Error('Web worker unavailable'));\n }\n const id = nextRequestId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(id);\n log(`#${id} timed out after ${REQUEST_TIMEOUT_MS}ms`);\n reject(new Error('Pivot worker timed out'));\n }, REQUEST_TIMEOUT_MS);\n pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n startedAt: Date.now(),\n });\n const mustStage = lastStagedDataKey !== dataKey;\n log(\n `#${id} dispatching to worker (dataKey=${dataKey}${\n mustStage\n ? ', staging ' + (data || []).length + ' records'\n : ', cached dataset'\n }, ${describeConfig(config)})`\n );\n if (mustStage) {\n worker.postMessage({type: 'pivot:setData', id, dataKey, data});\n lastStagedDataKey = dataKey;\n }\n worker.postMessage({type: 'pivot:compute', id, dataKey, config});\n });\n}\n\n/*\n * Same contract as the worker path, executed on the main thread. Used as the\n * automatic fallback whenever the worker path is unavailable. Deferred by\n * one tick so a loading indicator can paint before the blocking work starts.\n */\nexport function computePivotSynchronously(data, config) {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n const startedAt = Date.now();\n log('running synchronous computation on the main thread...');\n try {\n const materialized = materializeData(data, {});\n const result = computePivotState(materialized, config);\n log(`synchronous computation finished in ${Date.now() - startedAt}ms`, {\n totalRecords: result.totalRecords,\n rowKeys: result.rowKeys.length,\n colKeys: result.colKeys.length,\n });\n resolve(result);\n } catch (error) {\n log('synchronous computation failed:', error && error.message);\n reject(error);\n }\n }, 0);\n });\n}\n\n/*\n * Worker-first entry point with automatic synchronous fallback. The fallback\n * produces the exact same serialized shape, so callers render identically\n * either way.\n */\nexport function computePivotWithFallback(data, dataKey, config) {\n return computePivotInWorker(data, dataKey, config).catch(error => {\n log(\n 'worker request failed, falling back to the main thread:',\n (error && error.message) || error\n );\n return computePivotSynchronously(data, config);\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/PivotDataWorker.js"],"names":["setWorkerDebug","configureWorkerUrl","retainPivotWorker","releasePivotWorker","computePivotInWorker","computePivotViewportInWorker","releasePivotInWorker","releaseDatasetInWorker","computePivotSynchronously","computePivotWithFallback","DEFAULT_WORKER_URL","REQUEST_TIMEOUT_MS","VIEWPORT_TIMEOUT_MS","DATA_CHUNK_SIZE","workerUrl","sharedWorker","sharedWorkerBroken","hasResultEver","nextRequestId","lastStagedDataKey","stagingPromises","Map","workerDebug","pendingRequests","pendingViewportByPivot","workerOwners","Set","enabled","next","Boolean","wasEnabled","log","postMessage","type","isDebugEnabled","window","__PVT_WORKER_DEBUG__","args","describeConfig","config","rows","join","cols","aggregations","length","countOf","Array","isArray","value","undefined","failAllPending","forEach","clearTimeout","entry","timer","reject","error","clear","cancelPendingViewport","requestId","get","viewportKey","delete","Error","code","url","terminate","ownerKey","add","size","handleWorkerMessage","message","event","data","detail","id","Date","now","startedAt","resolve","result","totalRecords","rowKeys","colKeys","stageDataInWorker","worker","dataKey","owner","Object","assign","Promise","offset","postNextChunk","end","Math","min","slice","setTimeout","ensureWorker","Worker","onmessage","onerror","set","mustStage","dataReady","then","has","postCompute","catch","start","columnMode","columnStart","columnEnd","Number","MAX_SAFE_INTEGER","materialized"],"mappings":"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","file":"PivotDataWorker.js","sourcesContent":["/* eslint-disable valid-jsdoc */\n/* eslint-disable no-console */\n/* eslint-disable no-undefined */\n/*\n * Main-thread client for the pivot Web Worker (src/pivotWorker.js).\n *\n * Responsibilities:\n * - lazily create a single shared Worker (at `workerUrl`, overrideable),\n * - route result/error messages to the matching request,\n * - surface worker errors instead of silently recomputing on the main thread.\n *\n * Debug logging is off by default. Turn it on with the `workerDebug` prop of\n * PivotTableUI (or by setting `window.__PVT_WORKER_DEBUG__ = true` before\n * rendering) to trace worker creation, staging, computation, progress,\n * results, errors and fallbacks in the browser console.\n */\nimport {materializeData, computePivotState} from './pivotCompute';\n\nexport const DEFAULT_WORKER_URL = 'pivot-worker.js';\n\nconst REQUEST_TIMEOUT_MS = 300000;\nconst VIEWPORT_TIMEOUT_MS = 10000;\nconst DATA_CHUNK_SIZE = 500;\n\nlet workerUrl = DEFAULT_WORKER_URL;\nlet sharedWorker = null;\n// The worker is marked broken only if it fails before ever producing a\n// result (e.g. a 404 worker script); runtime hiccups later on just reject\n// the affected request and fall back once.\nlet sharedWorkerBroken = false;\nlet hasResultEver = false;\nlet nextRequestId = 1;\nlet lastStagedDataKey = null;\nconst stagingPromises = new Map();\nlet workerDebug = false;\nconst pendingRequests = new Map();\nconst pendingViewportByPivot = new Map();\nconst workerOwners = new Set();\n\nexport function setWorkerDebug(enabled) {\n const next = Boolean(enabled);\n const wasEnabled = workerDebug;\n if (next === wasEnabled) {\n return;\n }\n if (next) {\n workerDebug = true;\n log('debug logging enabled');\n } else {\n // Log while logging is still active, so the \"disabled\" notice is shown.\n log('debug logging disabled');\n workerDebug = false;\n }\n if (sharedWorker) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: workerDebug});\n }\n}\n\nconst isDebugEnabled = () =>\n workerDebug ||\n (typeof window !== 'undefined' && window.__PVT_WORKER_DEBUG__ === true);\n\nfunction log(...args) {\n if (!isDebugEnabled()) {\n return;\n }\n console.log(\n '%c[pivottable worker]',\n 'color:#ff6600;font-weight:bold',\n ...args\n );\n}\n\nconst describeConfig = config =>\n `rows=[${(config.rows || []).join(', ')}] cols=[${(config.cols || []).join(\n ', '\n )}] aggregations=${(config.aggregations || []).length}`;\n\n// Length of an optional array field, used for defensive debug logging.\nconst countOf = value => (Array.isArray(value) ? value.length : undefined);\n\nconst failAllPending = error => {\n pendingRequests.forEach(entry => {\n clearTimeout(entry.timer);\n entry.reject(error);\n });\n pendingRequests.clear();\n pendingViewportByPivot.clear();\n};\n\nconst cancelPendingViewport = viewportKey => {\n const requestId = pendingViewportByPivot.get(viewportKey);\n if (typeof requestId !== 'number') {\n return;\n }\n pendingViewportByPivot.delete(viewportKey);\n const entry = pendingRequests.get(requestId);\n if (!entry) {\n return;\n }\n clearTimeout(entry.timer);\n pendingRequests.delete(requestId);\n const error = new Error('Pivot viewport request was replaced');\n error.code = 'PIVOT_VIEWPORT_CANCELLED';\n entry.reject(error);\n};\n\nexport function configureWorkerUrl(url) {\n if (url && url !== workerUrl) {\n workerUrl = url;\n if (sharedWorker) {\n // Reject in-flight requests first so callers fall back to the\n // synchronous path instead of waiting for the request timeout.\n failAllPending(new Error('Pivot worker was reconfigured'));\n sharedWorker.terminate();\n sharedWorker = null;\n sharedWorkerBroken = false;\n hasResultEver = false;\n lastStagedDataKey = null;\n stagingPromises.clear();\n }\n }\n}\n\nexport function retainPivotWorker(ownerKey) {\n if (ownerKey) {\n workerOwners.add(ownerKey);\n }\n}\n\nexport function releasePivotWorker(ownerKey) {\n if (!ownerKey) {\n return;\n }\n workerOwners.delete(ownerKey);\n if (sharedWorker) {\n sharedWorker.postMessage({type: 'pivot:releaseOwner', ownerKey});\n }\n if (sharedWorker && workerOwners.size === 0) {\n failAllPending(new Error('Pivot worker was released'));\n sharedWorker.terminate();\n sharedWorker = null;\n sharedWorkerBroken = false;\n hasResultEver = false;\n lastStagedDataKey = null;\n stagingPromises.clear();\n }\n}\n\nconst handleWorkerMessage = event => {\n const message = event.data || {};\n if (message.type === 'pivot:log') {\n log('(in worker)', message.message, message.detail || '');\n return;\n }\n const entry = pendingRequests.get(message.id);\n if (!entry) {\n return;\n }\n if (message.type === 'pivot:progress') {\n // Progress reporting was removed: the UI only shows a loading overlay\n // until `pivot:result` arrives. Ignore messages from older worker\n // bundles that still emit progress so the request is not corrupted.\n return;\n }\n clearTimeout(entry.timer);\n pendingRequests.delete(message.id);\n if (\n entry.viewportKey !== undefined &&\n pendingViewportByPivot.get(entry.viewportKey) === message.id\n ) {\n pendingViewportByPivot.delete(entry.viewportKey);\n }\n if (\n message.type === 'pivot:result' ||\n message.type === 'pivot:viewportResult'\n ) {\n if (message.type === 'pivot:viewportResult') {\n log(\n `#${message.id} viewport received in ${Date.now() - entry.startedAt}ms`\n );\n entry.resolve(message.result);\n return;\n }\n hasResultEver = true;\n const result = message.result;\n log(`#${message.id} result received in ${Date.now() - entry.startedAt}ms`, {\n totalRecords: result && result.totalRecords,\n rowKeys: countOf(result && result.rowKeys),\n colKeys: countOf(result && result.colKeys),\n aggregations: countOf(result && result.aggregations),\n });\n entry.resolve(message.result);\n } else if (message.type === 'pivot:error') {\n log(`#${message.id} worker reported an error:`, message.message);\n entry.reject(new Error(message.message || 'Pivot worker error'));\n }\n};\n\n// `Worker.postMessage()` structured-clones its payload on the calling thread.\n// Sending a wide dataset in one message can therefore freeze the UI before\n// the worker has even started. Large inputs are split across macrotasks so\n// pointer and paint work can run between chunks.\nconst stageDataInWorker = (worker, id, dataKey, data, ownerKey) => {\n const owner = ownerKey ? {ownerKey} : {};\n if (!Array.isArray(data) || data.length <= DATA_CHUNK_SIZE) {\n worker.postMessage(\n Object.assign({type: 'pivot:setData', id, dataKey, data}, owner)\n );\n return null;\n }\n\n return new Promise((resolve, reject) => {\n try {\n worker.postMessage(\n Object.assign({type: 'pivot:setDataStart', id, dataKey}, owner)\n );\n let offset = 0;\n const postNextChunk = () => {\n try {\n const end = Math.min(offset + DATA_CHUNK_SIZE, data.length);\n worker.postMessage({\n type: 'pivot:setDataChunk',\n id,\n dataKey,\n data: data.slice(offset, end),\n });\n offset = end;\n if (offset < data.length) {\n setTimeout(postNextChunk, 0);\n return;\n }\n worker.postMessage({type: 'pivot:setDataEnd', id, dataKey});\n resolve();\n } catch (error) {\n reject(error);\n }\n };\n postNextChunk();\n } catch (error) {\n reject(error);\n }\n });\n};\n\nconst ensureWorker = () => {\n if (sharedWorkerBroken) {\n return null;\n }\n\n if (typeof Worker === 'undefined') {\n log('no Worker support in this environment');\n return null;\n }\n\n if (!sharedWorker) {\n try {\n sharedWorker = new Worker(workerUrl);\n log('worker created:', workerUrl);\n } catch (error) {\n sharedWorkerBroken = true;\n log('worker creation failed:', error && error.message);\n return null;\n }\n sharedWorker.onmessage = handleWorkerMessage;\n sharedWorker.onerror = event => {\n log(\n 'worker error event (script failed to load / runtime error):',\n (event && event.message) || ''\n );\n failAllPending(new Error('Pivot worker failed to load'));\n if (!hasResultEver) {\n sharedWorkerBroken = true;\n log('worker marked unusable -> will use the synchronous fallback');\n }\n };\n if (isDebugEnabled()) {\n sharedWorker.postMessage({type: 'pivot:debug', enabled: true});\n }\n }\n return sharedWorker;\n};\n\n/*\n * Runs a full computation inside the shared worker.\n *\n * `dataKey` must change whenever the underlying dataset changes. It lets the\n * worker reuse the materialized dataset across consecutive computations and\n * lets the client skip re-staging identical data.\n */\nexport function computePivotInWorker(data, dataKey, config, ownerKey) {\n const worker = ensureWorker();\n if (!worker) {\n log('worker unavailable -> synchronous fallback');\n return Promise.reject(new Error('Web worker unavailable'));\n }\n const id = nextRequestId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(id);\n log(`#${id} timed out after ${REQUEST_TIMEOUT_MS}ms`);\n reject(new Error('Pivot worker timed out'));\n }, REQUEST_TIMEOUT_MS);\n pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n startedAt: Date.now(),\n });\n const mustStage = lastStagedDataKey !== dataKey;\n log(\n `#${id} dispatching to worker (dataKey=${dataKey}${\n mustStage\n ? ', staging ' + (data || []).length + ' records'\n : ', cached dataset'\n }, ${describeConfig(config)})`\n );\n let dataReady = null;\n if (mustStage) {\n lastStagedDataKey = dataKey;\n dataReady = stageDataInWorker(worker, id, dataKey, data, ownerKey);\n if (dataReady) {\n stagingPromises.set(dataKey, dataReady);\n dataReady.then(\n () => {\n if (stagingPromises.get(dataKey) === dataReady) {\n stagingPromises.delete(dataKey);\n }\n },\n () => stagingPromises.delete(dataKey)\n );\n }\n } else if (stagingPromises.has(dataKey)) {\n dataReady = stagingPromises.get(dataKey);\n }\n const postCompute = () => {\n if (pendingRequests.has(id)) {\n worker.postMessage({\n type: 'pivot:compute',\n id,\n dataKey,\n config,\n ownerKey,\n });\n }\n };\n if (dataReady) {\n dataReady.then(postCompute).catch(error => {\n clearTimeout(timer);\n pendingRequests.delete(id);\n reject(error);\n });\n } else {\n postCompute();\n }\n });\n}\n\n// Request a small row window from a pivot result already cached in the worker.\n// No dataset or full pivot state is cloned for a scroll request.\nexport function computePivotViewportInWorker(\n viewportKey,\n start,\n end,\n columnMode,\n columnStart = 0,\n columnEnd = Number.MAX_SAFE_INTEGER\n) {\n const worker = ensureWorker();\n if (!worker) {\n return Promise.reject(new Error('Web worker unavailable'));\n }\n cancelPendingViewport(viewportKey);\n const id = nextRequestId++;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequests.delete(id);\n if (pendingViewportByPivot.get(viewportKey) === id) {\n pendingViewportByPivot.delete(viewportKey);\n }\n reject(new Error('Pivot viewport timed out'));\n }, VIEWPORT_TIMEOUT_MS);\n pendingRequests.set(id, {\n resolve,\n reject,\n timer,\n startedAt: Date.now(),\n viewportKey,\n });\n pendingViewportByPivot.set(viewportKey, id);\n log(\n `#${id} viewport dispatch (rows=${start}-${end}, ` +\n `columns=${columnStart}-${columnEnd}, pivot=${viewportKey})`\n );\n try {\n worker.postMessage({\n type: 'pivot:viewport',\n id,\n viewportKey,\n start,\n end,\n columnMode,\n columnStart,\n columnEnd,\n });\n } catch (error) {\n clearTimeout(timer);\n pendingRequests.delete(id);\n if (pendingViewportByPivot.get(viewportKey) === id) {\n pendingViewportByPivot.delete(viewportKey);\n }\n reject(error);\n }\n });\n}\n\n// Release a full virtual pivot as soon as its table no longer references it.\n// This intentionally does not create a worker during component cleanup.\nexport function releasePivotInWorker(viewportKey) {\n if (!sharedWorker || typeof viewportKey !== 'number') {\n return;\n }\n cancelPendingViewport(viewportKey);\n sharedWorker.postMessage({type: 'pivot:release', viewportKey});\n}\n\nexport function releaseDatasetInWorker(dataKey) {\n if (!sharedWorker || !dataKey) {\n return;\n }\n if (lastStagedDataKey === dataKey) {\n lastStagedDataKey = null;\n }\n stagingPromises.delete(dataKey);\n sharedWorker.postMessage({type: 'pivot:releaseData', dataKey});\n}\n\n/*\n * Same contract as the worker path, executed on the main thread. Used as the\n * automatic fallback whenever the worker path is unavailable. Deferred by\n * one tick so a loading indicator can paint before the blocking work starts.\n */\nexport function computePivotSynchronously(data, config) {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n const startedAt = Date.now();\n log('running synchronous computation on the main thread...');\n try {\n const materialized = materializeData(data, {});\n const result = computePivotState(materialized, config);\n log(`synchronous computation finished in ${Date.now() - startedAt}ms`, {\n totalRecords: result.totalRecords,\n rowKeys: result.rowKeys.length,\n colKeys: result.colKeys.length,\n });\n resolve(result);\n } catch (error) {\n log('synchronous computation failed:', error && error.message);\n reject(error);\n }\n }, 0);\n });\n}\n\n/*\n * Keep the existing entry point while testing worker failures without a\n * synchronous fallback. Rejections reach PivotTableUI's error state.\n */\nexport function computePivotWithFallback(data, dataKey, config, ownerKey) {\n return computePivotInWorker(data, dataKey, config, ownerKey).catch(error => {\n log('worker request failed (synchronous fallback disabled):', error);\n throw error;\n });\n}\n"]}
|
package/dist/PivotTable.js
CHANGED
|
@@ -58,7 +58,8 @@ PivotTable.propTypes = Object.assign({}, _Utilities.PivotData.propTypes, {
|
|
|
58
58
|
rowSorts: _propTypes2.default.objectOf(_propTypes2.default.oneOf(['ASC', 'DESC'])),
|
|
59
59
|
onColSort: _propTypes2.default.func,
|
|
60
60
|
onRowSort: _propTypes2.default.func,
|
|
61
|
-
tableOptions: _propTypes2.default.object
|
|
61
|
+
tableOptions: _propTypes2.default.object,
|
|
62
|
+
virtualizeRows: _propTypes2.default.bool
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
PivotTable.defaultProps = Object.assign({}, _Utilities.PivotData.defaultProps, {
|
package/dist/PivotTable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PivotTable.jsx"],"names":["PivotTable","Renderer","props","renderers","rendererName","Object","keys","React","PureComponent","propTypes","assign","PivotData","PropTypes","string","objectOf","func","colSorts","oneOf","rowSorts","onColSort","onRowSort","tableOptions","object","defaultProps","TableRenderers"],"mappings":";;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;;;;;;;;;AAEA;AACA;;IAEMA,U;;;;;;;;;;;6BACK;AACP,UAAMC,WAAW,KAAKC,KAAL,CAAWC,SAAX,CACf,KAAKD,KAAL,CAAWE,YAAX,IAA2B,KAAKF,KAAL,CAAWC,SAAtC,GACI,KAAKD,KAAL,CAAWE,YADf,GAEIC,OAAOC,IAAP,CAAY,KAAKJ,KAAL,CAAWC,SAAvB,EAAkC,CAAlC,CAHW,CAAjB;AAKA,aAAO,8BAAC,QAAD,EAAc,KAAKD,KAAnB,CAAP;AACD;;;;EARsBK,gBAAMC,a;;AAW/BR,WAAWS,SAAX,GAAuBJ,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUF,SAA5B,EAAuC;AAC5DL,gBAAcQ,oBAAUC,MADoC;AAE5DV,aAAWS,oBAAUE,QAAV,CAAmBF,oBAAUG,IAA7B,CAFiD;AAG5DC,YAAUJ,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAHkD;AAI5DC,YAAUN,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAJkD;AAK5DE,aAAWP,oBAAUG,IALuC;AAM5DK,aAAWR,oBAAUG,IANuC;AAO5DM,gBAAcT,oBAAUU;
|
|
1
|
+
{"version":3,"sources":["../src/PivotTable.jsx"],"names":["PivotTable","Renderer","props","renderers","rendererName","Object","keys","React","PureComponent","propTypes","assign","PivotData","PropTypes","string","objectOf","func","colSorts","oneOf","rowSorts","onColSort","onRowSort","tableOptions","object","virtualizeRows","bool","defaultProps","TableRenderers"],"mappings":";;;;;;;;AAAA;;;;AACA;;;;AACA;;AACA;;;;;;;;;;;;AAEA;AACA;;IAEMA,U;;;;;;;;;;;6BACK;AACP,UAAMC,WAAW,KAAKC,KAAL,CAAWC,SAAX,CACf,KAAKD,KAAL,CAAWE,YAAX,IAA2B,KAAKF,KAAL,CAAWC,SAAtC,GACI,KAAKD,KAAL,CAAWE,YADf,GAEIC,OAAOC,IAAP,CAAY,KAAKJ,KAAL,CAAWC,SAAvB,EAAkC,CAAlC,CAHW,CAAjB;AAKA,aAAO,8BAAC,QAAD,EAAc,KAAKD,KAAnB,CAAP;AACD;;;;EARsBK,gBAAMC,a;;AAW/BR,WAAWS,SAAX,GAAuBJ,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUF,SAA5B,EAAuC;AAC5DL,gBAAcQ,oBAAUC,MADoC;AAE5DV,aAAWS,oBAAUE,QAAV,CAAmBF,oBAAUG,IAA7B,CAFiD;AAG5DC,YAAUJ,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAHkD;AAI5DC,YAAUN,oBAAUE,QAAV,CAAmBF,oBAAUK,KAAV,CAAgB,CAAC,KAAD,EAAQ,MAAR,CAAhB,CAAnB,CAJkD;AAK5DE,aAAWP,oBAAUG,IALuC;AAM5DK,aAAWR,oBAAUG,IANuC;AAO5DM,gBAAcT,oBAAUU,MAPoC;AAQ5DC,kBAAgBX,oBAAUY;AARkC,CAAvC,CAAvB;;AAWAxB,WAAWyB,YAAX,GAA0BpB,OAAOK,MAAP,CAAc,EAAd,EAAkBC,qBAAUc,YAA5B,EAA0C;AAClErB,gBAAc,OADoD;AAElED,aAAWuB,wBAFuD;AAGlEL,gBAAc;AAHoD,CAA1C,CAA1B;;kBAMerB,U","file":"PivotTable.js","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport {PivotData} from './Utilities';\nimport TableRenderers from './TableRenderers';\n\n/* eslint-disable react/prop-types */\n// eslint can't see inherited propTypes!\n\nclass PivotTable extends React.PureComponent {\n render() {\n const Renderer = this.props.renderers[\n this.props.rendererName in this.props.renderers\n ? this.props.rendererName\n : Object.keys(this.props.renderers)[0]\n ];\n return <Renderer {...this.props} />;\n }\n}\n\nPivotTable.propTypes = Object.assign({}, PivotData.propTypes, {\n rendererName: PropTypes.string,\n renderers: PropTypes.objectOf(PropTypes.func),\n colSorts: PropTypes.objectOf(PropTypes.oneOf(['ASC', 'DESC'])),\n rowSorts: PropTypes.objectOf(PropTypes.oneOf(['ASC', 'DESC'])),\n onColSort: PropTypes.func,\n onRowSort: PropTypes.func,\n tableOptions: PropTypes.object,\n virtualizeRows: PropTypes.bool,\n});\n\nPivotTable.defaultProps = Object.assign({}, PivotData.defaultProps, {\n rendererName: 'Table',\n renderers: TableRenderers,\n tableOptions: {},\n});\n\nexport default PivotTable;\n"]}
|
package/dist/PivotTableUI.js
CHANGED
|
@@ -58,6 +58,7 @@ var AGG_KEY_LENGTH = 7;
|
|
|
58
58
|
// inline `{}` literal would be a new object on every render, which makes the
|
|
59
59
|
// rendered table re-render even when nothing about the pivot changed.
|
|
60
60
|
var EMPTY_SORTS = {};
|
|
61
|
+
var EMPTY_ATTR_VALUES = {};
|
|
61
62
|
|
|
62
63
|
/* eslint-disable react/prop-types */
|
|
63
64
|
// eslint can't see inherited propTypes!
|
|
@@ -248,6 +249,7 @@ function DraggableAttribute(props) {
|
|
|
248
249
|
}
|
|
249
250
|
|
|
250
251
|
DraggableAttribute.defaultProps = {
|
|
252
|
+
attrValues: EMPTY_ATTR_VALUES,
|
|
251
253
|
valueFilter: {}
|
|
252
254
|
};
|
|
253
255
|
|
|
@@ -1132,61 +1134,7 @@ function PivotLoadingOverlay() {
|
|
|
1132
1134
|
_react2.default.createElement(
|
|
1133
1135
|
'div',
|
|
1134
1136
|
{ className: 'pvtLoadingText' },
|
|
1135
|
-
|
|
1136
|
-
'span',
|
|
1137
|
-
null,
|
|
1138
|
-
'P'
|
|
1139
|
-
),
|
|
1140
|
-
_react2.default.createElement(
|
|
1141
|
-
'span',
|
|
1142
|
-
null,
|
|
1143
|
-
'r'
|
|
1144
|
-
),
|
|
1145
|
-
_react2.default.createElement(
|
|
1146
|
-
'span',
|
|
1147
|
-
null,
|
|
1148
|
-
'o'
|
|
1149
|
-
),
|
|
1150
|
-
_react2.default.createElement(
|
|
1151
|
-
'span',
|
|
1152
|
-
null,
|
|
1153
|
-
'c'
|
|
1154
|
-
),
|
|
1155
|
-
_react2.default.createElement(
|
|
1156
|
-
'span',
|
|
1157
|
-
null,
|
|
1158
|
-
'e'
|
|
1159
|
-
),
|
|
1160
|
-
_react2.default.createElement(
|
|
1161
|
-
'span',
|
|
1162
|
-
null,
|
|
1163
|
-
's'
|
|
1164
|
-
),
|
|
1165
|
-
_react2.default.createElement(
|
|
1166
|
-
'span',
|
|
1167
|
-
null,
|
|
1168
|
-
's'
|
|
1169
|
-
),
|
|
1170
|
-
_react2.default.createElement(
|
|
1171
|
-
'span',
|
|
1172
|
-
null,
|
|
1173
|
-
'i'
|
|
1174
|
-
),
|
|
1175
|
-
_react2.default.createElement(
|
|
1176
|
-
'span',
|
|
1177
|
-
null,
|
|
1178
|
-
'n'
|
|
1179
|
-
),
|
|
1180
|
-
_react2.default.createElement(
|
|
1181
|
-
'span',
|
|
1182
|
-
null,
|
|
1183
|
-
'g'
|
|
1184
|
-
),
|
|
1185
|
-
_react2.default.createElement(
|
|
1186
|
-
'span',
|
|
1187
|
-
null,
|
|
1188
|
-
'\u2026'
|
|
1189
|
-
)
|
|
1137
|
+
'Processing'
|
|
1190
1138
|
)
|
|
1191
1139
|
);
|
|
1192
1140
|
}
|
|
@@ -1288,7 +1236,7 @@ function PivotTableUI(props) {
|
|
|
1288
1236
|
|
|
1289
1237
|
var computeSignature = (0, _react.useMemo)(function () {
|
|
1290
1238
|
return (0, _pivotCompute.createComputeSignature)(props);
|
|
1291
|
-
}, [props.rows, props.cols, props.aggregatorName, props.aggregations, props.vals, props.valueFilter, props.sorters, props.rowOrder, props.colOrder, props.rowSorts, props.colSorts]);
|
|
1239
|
+
}, [props.rows, props.cols, props.aggregatorName, props.aggregations, props.vals, props.valueFilter, props.sorters, props.rowOrder, props.colOrder, props.rowSorts, props.colSorts, props.virtualizeRows, props.rendererName, props.tableOptions && props.tableOptions.aggregationDisplayMode]);
|
|
1292
1240
|
|
|
1293
1241
|
// Version the dataset during render instead of inside the compute effect.
|
|
1294
1242
|
// The effect runs *after* the render, so bumping the version there left one
|
|
@@ -1333,11 +1281,20 @@ function PivotTableUI(props) {
|
|
|
1333
1281
|
}, [props.data, workerEligible]);
|
|
1334
1282
|
|
|
1335
1283
|
(0, _react.useEffect)(function () {
|
|
1284
|
+
(0, _PivotDataWorker.retainPivotWorker)(instanceIdRef.current);
|
|
1336
1285
|
return function () {
|
|
1337
1286
|
unmountedRef.current = true;
|
|
1287
|
+
(0, _PivotDataWorker.releasePivotWorker)(instanceIdRef.current);
|
|
1338
1288
|
};
|
|
1339
1289
|
}, []);
|
|
1340
1290
|
|
|
1291
|
+
(0, _react.useEffect)(function () {
|
|
1292
|
+
var viewportKey = workerEligible && precomputed && precomputed.data ? precomputed.data.viewportKey : null;
|
|
1293
|
+
return function () {
|
|
1294
|
+
return (0, _PivotDataWorker.releasePivotInWorker)(viewportKey);
|
|
1295
|
+
};
|
|
1296
|
+
}, [precomputed, workerEligible]);
|
|
1297
|
+
|
|
1341
1298
|
// Forward the `workerDebug` prop to the worker client so the whole
|
|
1342
1299
|
// worker pipeline can be traced from the browser console.
|
|
1343
1300
|
(0, _react.useEffect)(function () {
|
|
@@ -1387,6 +1344,10 @@ function PivotTableUI(props) {
|
|
|
1387
1344
|
// overlay on screen for a result nothing is going to read. `attrValues` and
|
|
1388
1345
|
// `materializedInput` are handled by the effect above.
|
|
1389
1346
|
if (!workerEligible) {
|
|
1347
|
+
if (precomputedRef.current) {
|
|
1348
|
+
precomputedRef.current = null;
|
|
1349
|
+
setPrecomputed(null);
|
|
1350
|
+
}
|
|
1390
1351
|
setIsProcessing(false);
|
|
1391
1352
|
setResultReady(false);
|
|
1392
1353
|
setComputeError(null);
|
|
@@ -1408,14 +1369,21 @@ function PivotTableUI(props) {
|
|
|
1408
1369
|
var timer = setTimeout(function () {
|
|
1409
1370
|
var requestId = activeRequestRef.current;
|
|
1410
1371
|
var dataKey = instanceIdRef.current + '-data-' + dataVersionRef.current;
|
|
1411
|
-
(0, _PivotDataWorker.computePivotWithFallback)(props.data, dataKey, (0, _pivotCompute.createWorkerConfig)(props)).then(function (result) {
|
|
1372
|
+
(0, _PivotDataWorker.computePivotWithFallback)(props.data, dataKey, (0, _pivotCompute.createWorkerConfig)(props), instanceIdRef.current).then(function (result) {
|
|
1412
1373
|
if (unmountedRef.current || requestId !== activeRequestRef.current) {
|
|
1374
|
+
(0, _PivotDataWorker.releasePivotInWorker)(result && result.viewportKey);
|
|
1413
1375
|
return;
|
|
1414
1376
|
}
|
|
1415
1377
|
precomputedRef.current = { signature: currentSignature, data: result };
|
|
1416
1378
|
setPrecomputed(precomputedRef.current);
|
|
1417
|
-
|
|
1418
|
-
|
|
1379
|
+
if (result.attrValues) {
|
|
1380
|
+
setAttrValues(result.attrValues);
|
|
1381
|
+
}
|
|
1382
|
+
(0, _PivotDataWorker.releaseDatasetInWorker)(dataKey);
|
|
1383
|
+
// The worker received this exact array when the request was staged.
|
|
1384
|
+
// Reusing it avoids structured-cloning the full dataset back to the
|
|
1385
|
+
// main thread with every result.
|
|
1386
|
+
setMaterializedInput(props.data);
|
|
1419
1387
|
setComputeError(null);
|
|
1420
1388
|
// Keep the overlay up for one more render: `resultReady` makes the
|
|
1421
1389
|
// fresh table render underneath, and the layout effect above turns
|
|
@@ -1432,7 +1400,7 @@ function PivotTableUI(props) {
|
|
|
1432
1400
|
return function () {
|
|
1433
1401
|
clearTimeout(timer);
|
|
1434
1402
|
};
|
|
1435
|
-
}, [props.data, computeSignature]);
|
|
1403
|
+
}, [props.data, computeSignature, workerEligible]);
|
|
1436
1404
|
|
|
1437
1405
|
// Event handlers are referentially stable (they read the latest props from
|
|
1438
1406
|
// `propsRef`): a new handler identity on every render would defeat
|
|
@@ -1698,9 +1666,9 @@ function PivotTableUI(props) {
|
|
|
1698
1666
|
return _react2.default.createElement(DraggableAttribute, {
|
|
1699
1667
|
name: x,
|
|
1700
1668
|
key: x,
|
|
1701
|
-
attrValues: attrValues[x],
|
|
1669
|
+
attrValues: attrValues[x] || EMPTY_ATTR_VALUES,
|
|
1702
1670
|
valueFilter: props.valueFilter[x] || {},
|
|
1703
|
-
sorter: (0, _Utilities.getSort)(props.sorters, x, attrValues[x]),
|
|
1671
|
+
sorter: (0, _Utilities.getSort)(props.sorters, x, attrValues[x] || EMPTY_ATTR_VALUES),
|
|
1704
1672
|
menuLimit: props.menuLimit,
|
|
1705
1673
|
setValuesInFilter: setValuesInFilter,
|
|
1706
1674
|
addValuesToFilter: addValuesToFilter,
|
|
@@ -1989,6 +1957,9 @@ function PivotTableUI(props) {
|
|
|
1989
1957
|
outputContent = liveViewElement;
|
|
1990
1958
|
}
|
|
1991
1959
|
|
|
1960
|
+
// Keep the processing layer scoped to the output cell. Rendering it next to
|
|
1961
|
+
// the table made its absolute inset resolve against a much larger ancestor,
|
|
1962
|
+
// which intercepted pointer events across the surrounding application UI.
|
|
1992
1963
|
var outputCell = _react2.default.createElement(
|
|
1993
1964
|
'td',
|
|
1994
1965
|
{ className: 'pvtOutput' },
|
|
@@ -1997,8 +1968,10 @@ function PivotTableUI(props) {
|
|
|
1997
1968
|
|
|
1998
1969
|
if (horizUnused) {
|
|
1999
1970
|
return _react2.default.createElement(
|
|
2000
|
-
|
|
2001
|
-
|
|
1971
|
+
'div',
|
|
1972
|
+
{
|
|
1973
|
+
style: { borderRadius: 5, width: 'max-content', height: 'max-content' }
|
|
1974
|
+
},
|
|
2002
1975
|
showProcessing ? _react2.default.createElement(PivotLoadingOverlay, null) : null,
|
|
2003
1976
|
_react2.default.createElement(
|
|
2004
1977
|
'table',
|
|
@@ -2032,8 +2005,8 @@ function PivotTableUI(props) {
|
|
|
2032
2005
|
}
|
|
2033
2006
|
|
|
2034
2007
|
return _react2.default.createElement(
|
|
2035
|
-
|
|
2036
|
-
|
|
2008
|
+
'div',
|
|
2009
|
+
{ style: { borderRadius: 5, width: 'max-content', height: 'max-content' } },
|
|
2037
2010
|
showProcessing ? _react2.default.createElement(PivotLoadingOverlay, null) : null,
|
|
2038
2011
|
_react2.default.createElement(
|
|
2039
2012
|
'table',
|