@hrforte/react-pivottable 2.2.1 → 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 +145 -48
- package/dist/PivotTableUI.js.map +1 -1
- package/dist/TableRenderers.js +629 -118
- 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 +42 -3
- package/dist/__tests__/PivotTableUI-processing-test.js.map +1 -1
- package/dist/__tests__/PivotTableUI-rerender-test.js +314 -0
- package/dist/__tests__/PivotTableUI-rerender-test.js.map +1 -0
- 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 +510 -201
- package/dist/pivotCompute.js +238 -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 +277 -235
- 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"]}
|