@hrforte/react-pivottable 1.0.1 → 2.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/README.md +45 -0
- package/dist/PivotDataWorker.js +164 -0
- package/dist/PivotDataWorker.js.map +1 -0
- package/dist/PivotTableUI.js +1734 -1612
- package/dist/PivotTableUI.js.map +1 -1
- package/dist/PlotlyRenderers.js +3 -1
- package/dist/PlotlyRenderers.js.map +1 -1
- package/dist/TableRenderers.js +8 -9
- package/dist/TableRenderers.js.map +1 -1
- package/dist/Utilities.js +134 -24
- package/dist/Utilities.js.map +1 -1
- package/dist/__tests__/PivotTableUI-processing-test.js +114 -0
- package/dist/__tests__/PivotTableUI-processing-test.js.map +1 -0
- package/dist/__tests__/pivotCompute-test.js +215 -0
- package/dist/__tests__/pivotCompute-test.js.map +1 -0
- package/dist/pivot-worker.js +3387 -0
- package/dist/pivotCompute.js +274 -0
- package/dist/pivotCompute.js.map +1 -0
- package/dist/pivotWorker.js +91 -0
- package/dist/pivotWorker.js.map +1 -0
- package/dist/pivottable.css +74 -0
- package/package.json +7 -4
package/dist/Utilities.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.PivotData = exports.createSorterByType = exports.detectDataType = exports.builtInSorters = exports.sortAs = exports.getSort = exports.numberFormat = exports.naturalSort = exports.locales = exports.derivers = exports.aggregators = exports.aggregatorTemplates = undefined;
|
|
6
|
+
exports.PivotData = exports.sortersHaveFunctions = exports.createSorterByType = exports.detectDataType = exports.builtInSorters = exports.sortAs = exports.getSort = exports.numberFormat = exports.naturalSort = exports.locales = exports.derivers = exports.aggregators = exports.aggregatorTemplates = undefined;
|
|
7
7
|
|
|
8
8
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
9
9
|
|
|
@@ -391,6 +391,25 @@ var usFmtPct = numberFormat({
|
|
|
391
391
|
suffix: '%'
|
|
392
392
|
});
|
|
393
393
|
|
|
394
|
+
// Emit a progress callback every N processed records without adding
|
|
395
|
+
// measurable overhead to the per-record loop.
|
|
396
|
+
var RECORD_PROGRESS_BATCH_SIZE = 25000;
|
|
397
|
+
|
|
398
|
+
// Returns true when the sorters prop itself, or any of its entries, is a
|
|
399
|
+
// function. Function-based sorters cannot be transferred to a Web Worker, so
|
|
400
|
+
// PivotData re-applies them on the main thread after worker hydration.
|
|
401
|
+
var sortersHaveFunctions = function sortersHaveFunctions(sorters) {
|
|
402
|
+
if (typeof sorters === 'function') {
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
if (!sorters || (typeof sorters === 'undefined' ? 'undefined' : _typeof(sorters)) !== 'object') {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
return Object.keys(sorters).some(function (attr) {
|
|
409
|
+
return typeof sorters[attr] === 'function';
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
|
|
394
413
|
var aggregatorTemplates = {
|
|
395
414
|
count: function count() {
|
|
396
415
|
var formatter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : usFmtInt;
|
|
@@ -855,15 +874,103 @@ var PivotData = function () {
|
|
|
855
874
|
this.allTotal = this.createAggregatorCell([], []);
|
|
856
875
|
this.sorted = false;
|
|
857
876
|
|
|
858
|
-
|
|
859
|
-
|
|
877
|
+
if (this.props.precomputedData) {
|
|
878
|
+
// Results computed by the Web Worker (or any previous pass) are
|
|
879
|
+
// hydrated instead of re-scanning every record on the main thread.
|
|
880
|
+
this.hydrateFromPrecomputed(this.props.precomputedData);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
var progressHook = this.props.onRecordProcessed;
|
|
885
|
+
var recordHandler = function recordHandler(record) {
|
|
860
886
|
if (_this2.filter(record)) {
|
|
861
887
|
_this2.processRecord(record);
|
|
862
888
|
}
|
|
863
|
-
}
|
|
889
|
+
};
|
|
890
|
+
if (typeof progressHook === 'function') {
|
|
891
|
+
var recordsProcessed = 0;
|
|
892
|
+
PivotData.forEachRecord(this.props.data, this.props.derivedAttributes, function (record) {
|
|
893
|
+
recordHandler(record);
|
|
894
|
+
recordsProcessed++;
|
|
895
|
+
if (recordsProcessed % RECORD_PROGRESS_BATCH_SIZE === 0) {
|
|
896
|
+
progressHook(recordsProcessed);
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
} else {
|
|
900
|
+
PivotData.forEachRecord(this.props.data, this.props.derivedAttributes, recordHandler);
|
|
901
|
+
}
|
|
864
902
|
}
|
|
865
903
|
|
|
904
|
+
/*
|
|
905
|
+
* Rebuilds tree/totals from a serialized PivotData payload (as produced by
|
|
906
|
+
* `serializePivotData` inside the worker). Aggregated values are final, so
|
|
907
|
+
* only lightweight stub aggregators with the correct `value()` and
|
|
908
|
+
* `format()` behavior are created per cell.
|
|
909
|
+
*/
|
|
910
|
+
|
|
911
|
+
|
|
866
912
|
_createClass(PivotData, [{
|
|
913
|
+
key: 'hydrateFromPrecomputed',
|
|
914
|
+
value: function hydrateFromPrecomputed(precomputed) {
|
|
915
|
+
var _this3 = this;
|
|
916
|
+
|
|
917
|
+
// One real aggregator instance per aggregation provides `format()` and
|
|
918
|
+
// `numInputs` for every hydrated stub cell.
|
|
919
|
+
var formatSources = {};
|
|
920
|
+
this.aggregations.forEach(function (agg) {
|
|
921
|
+
formatSources[agg.key] = _this3.aggregatorFactories[agg.key](_this3, [], []);
|
|
922
|
+
});
|
|
923
|
+
|
|
924
|
+
var makeCell = function makeCell(serializedCell) {
|
|
925
|
+
var values = serializedCell && serializedCell.values || {};
|
|
926
|
+
var instances = {};
|
|
927
|
+
_this3.aggregations.forEach(function (agg) {
|
|
928
|
+
var source = formatSources[agg.key];
|
|
929
|
+
var _value = values[agg.key];
|
|
930
|
+
instances[agg.key] = {
|
|
931
|
+
push: function push() {},
|
|
932
|
+
value: function value() {
|
|
933
|
+
return _value;
|
|
934
|
+
},
|
|
935
|
+
format: function format(x) {
|
|
936
|
+
return source.format(x);
|
|
937
|
+
},
|
|
938
|
+
|
|
939
|
+
numInputs: source.numInputs,
|
|
940
|
+
outlet: source.outlet
|
|
941
|
+
};
|
|
942
|
+
});
|
|
943
|
+
return new AggregatorCell(instances, _this3.primaryAggregation.key);
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
var hydrateTotals = function hydrateTotals(source, target) {
|
|
947
|
+
Object.keys(source || {}).forEach(function (flatKey) {
|
|
948
|
+
target[flatKey] = makeCell(source[flatKey]);
|
|
949
|
+
});
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
this.rowKeys = (precomputed.rowKeys || []).map(function (key) {
|
|
953
|
+
return key.slice();
|
|
954
|
+
});
|
|
955
|
+
this.colKeys = (precomputed.colKeys || []).map(function (key) {
|
|
956
|
+
return key.slice();
|
|
957
|
+
});
|
|
958
|
+
this.rowTotals = {};
|
|
959
|
+
hydrateTotals(precomputed.rowTotals, this.rowTotals);
|
|
960
|
+
this.colTotals = {};
|
|
961
|
+
hydrateTotals(precomputed.colTotals, this.colTotals);
|
|
962
|
+
this.tree = {};
|
|
963
|
+
Object.keys(precomputed.tree || {}).forEach(function (flatRowKey) {
|
|
964
|
+
_this3.tree[flatRowKey] = {};
|
|
965
|
+
hydrateTotals(precomputed.tree[flatRowKey], _this3.tree[flatRowKey]);
|
|
966
|
+
});
|
|
967
|
+
this.allTotal = makeCell(precomputed.allTotal);
|
|
968
|
+
|
|
969
|
+
// Keys were already sorted inside the worker; only re-sort on the main
|
|
970
|
+
// thread when a sorter could not cross the worker boundary (functions).
|
|
971
|
+
this.sorted = !sortersHaveFunctions(this.props.sorters);
|
|
972
|
+
}
|
|
973
|
+
}, {
|
|
867
974
|
key: 'filter',
|
|
868
975
|
value: function filter(record) {
|
|
869
976
|
for (var k in this.props.valueFilter) {
|
|
@@ -876,10 +983,10 @@ var PivotData = function () {
|
|
|
876
983
|
}, {
|
|
877
984
|
key: 'forEachMatchingRecord',
|
|
878
985
|
value: function forEachMatchingRecord(criteria, callback) {
|
|
879
|
-
var
|
|
986
|
+
var _this4 = this;
|
|
880
987
|
|
|
881
988
|
return PivotData.forEachRecord(this.props.data, this.props.derivedAttributes, function (record) {
|
|
882
|
-
if (!
|
|
989
|
+
if (!_this4.filter(record)) {
|
|
883
990
|
return;
|
|
884
991
|
}
|
|
885
992
|
for (var k in criteria) {
|
|
@@ -894,7 +1001,7 @@ var PivotData = function () {
|
|
|
894
1001
|
}, {
|
|
895
1002
|
key: 'arrSort',
|
|
896
1003
|
value: function arrSort(attrs) {
|
|
897
|
-
var
|
|
1004
|
+
var _this5 = this;
|
|
898
1005
|
|
|
899
1006
|
var a = void 0;
|
|
900
1007
|
var sortersArr = function () {
|
|
@@ -907,7 +1014,7 @@ var PivotData = function () {
|
|
|
907
1014
|
for (var _iterator2 = Array.from(attrs)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
|
908
1015
|
a = _step2.value;
|
|
909
1016
|
|
|
910
|
-
result.push(getSort(
|
|
1017
|
+
result.push(getSort(_this5.props.sorters, a));
|
|
911
1018
|
}
|
|
912
1019
|
} catch (err) {
|
|
913
1020
|
_didIteratorError2 = true;
|
|
@@ -962,12 +1069,12 @@ var PivotData = function () {
|
|
|
962
1069
|
}, {
|
|
963
1070
|
key: 'sortKeys',
|
|
964
1071
|
value: function sortKeys() {
|
|
965
|
-
var
|
|
1072
|
+
var _this6 = this;
|
|
966
1073
|
|
|
967
1074
|
if (!this.sorted) {
|
|
968
1075
|
this.sorted = true;
|
|
969
1076
|
var v = function v(r, c) {
|
|
970
|
-
return
|
|
1077
|
+
return _this6.getAggregator(r, c).value();
|
|
971
1078
|
};
|
|
972
1079
|
|
|
973
1080
|
// Handle per-row sorting
|
|
@@ -975,11 +1082,11 @@ var PivotData = function () {
|
|
|
975
1082
|
var rowSorts = this.props.rowSorts;
|
|
976
1083
|
this.rowKeys.sort(function (a, b) {
|
|
977
1084
|
// First, check if any sorted attribute has a difference
|
|
978
|
-
for (var i = 0; i <
|
|
979
|
-
var attr =
|
|
1085
|
+
for (var i = 0; i < _this6.props.rows.length; i++) {
|
|
1086
|
+
var attr = _this6.props.rows[i];
|
|
980
1087
|
if (attr && rowSorts[attr]) {
|
|
981
1088
|
var sortDir = rowSorts[attr] === 'ASC' ? 1 : -1;
|
|
982
|
-
var sorter = getSort(
|
|
1089
|
+
var sorter = getSort(_this6.props.sorters, attr);
|
|
983
1090
|
var comparison = sorter(a[i] || '', b[i] || '');
|
|
984
1091
|
if (comparison !== 0) {
|
|
985
1092
|
return sortDir * comparison;
|
|
@@ -987,7 +1094,7 @@ var PivotData = function () {
|
|
|
987
1094
|
}
|
|
988
1095
|
}
|
|
989
1096
|
// If sorted attributes are equal, use default sorting for remaining attributes
|
|
990
|
-
return
|
|
1097
|
+
return _this6.arrSort(_this6.props.rows)(a, b);
|
|
991
1098
|
});
|
|
992
1099
|
} else {
|
|
993
1100
|
// Use global row order
|
|
@@ -1012,11 +1119,11 @@ var PivotData = function () {
|
|
|
1012
1119
|
var colSorts = this.props.colSorts;
|
|
1013
1120
|
this.colKeys.sort(function (a, b) {
|
|
1014
1121
|
// First, check if any sorted attribute has a difference
|
|
1015
|
-
for (var i = 0; i <
|
|
1016
|
-
var attr =
|
|
1122
|
+
for (var i = 0; i < _this6.props.cols.length; i++) {
|
|
1123
|
+
var attr = _this6.props.cols[i];
|
|
1017
1124
|
if (attr && colSorts[attr]) {
|
|
1018
1125
|
var sortDir = colSorts[attr] === 'ASC' ? 1 : -1;
|
|
1019
|
-
var sorter = getSort(
|
|
1126
|
+
var sorter = getSort(_this6.props.sorters, attr);
|
|
1020
1127
|
var comparison = sorter(a[i] || '', b[i] || '');
|
|
1021
1128
|
if (comparison !== 0) {
|
|
1022
1129
|
return sortDir * comparison;
|
|
@@ -1024,7 +1131,7 @@ var PivotData = function () {
|
|
|
1024
1131
|
}
|
|
1025
1132
|
}
|
|
1026
1133
|
// If sorted attributes are equal, use default sorting for remaining attributes
|
|
1027
|
-
return
|
|
1134
|
+
return _this6.arrSort(_this6.props.cols)(a, b);
|
|
1028
1135
|
});
|
|
1029
1136
|
} else {
|
|
1030
1137
|
// Use global col order
|
|
@@ -1268,25 +1375,25 @@ var PivotData = function () {
|
|
|
1268
1375
|
}, {
|
|
1269
1376
|
key: 'buildAggregatorFactories',
|
|
1270
1377
|
value: function buildAggregatorFactories() {
|
|
1271
|
-
var
|
|
1378
|
+
var _this7 = this;
|
|
1272
1379
|
|
|
1273
1380
|
var factories = {};
|
|
1274
1381
|
this.aggregations.forEach(function (agg) {
|
|
1275
|
-
if (!(agg.aggregatorName in
|
|
1382
|
+
if (!(agg.aggregatorName in _this7.props.aggregators)) {
|
|
1276
1383
|
throw new Error('unknown aggregator ' + agg.aggregatorName);
|
|
1277
1384
|
}
|
|
1278
|
-
factories[agg.key] =
|
|
1385
|
+
factories[agg.key] = _this7.props.aggregators[agg.aggregatorName](agg.vals);
|
|
1279
1386
|
});
|
|
1280
1387
|
return factories;
|
|
1281
1388
|
}
|
|
1282
1389
|
}, {
|
|
1283
1390
|
key: 'createAggregatorCell',
|
|
1284
1391
|
value: function createAggregatorCell(rowKey, colKey) {
|
|
1285
|
-
var
|
|
1392
|
+
var _this8 = this;
|
|
1286
1393
|
|
|
1287
1394
|
var instances = {};
|
|
1288
1395
|
this.aggregations.forEach(function (agg) {
|
|
1289
|
-
instances[agg.key] =
|
|
1396
|
+
instances[agg.key] = _this8.aggregatorFactories[agg.key](_this8, rowKey, colKey);
|
|
1290
1397
|
});
|
|
1291
1398
|
return new AggregatorCell(instances, this.primaryAggregation.key);
|
|
1292
1399
|
}
|
|
@@ -1453,8 +1560,10 @@ PivotData.propTypes = {
|
|
|
1453
1560
|
rows: _propTypes2.default.arrayOf(_propTypes2.default.string),
|
|
1454
1561
|
vals: _propTypes2.default.arrayOf(_propTypes2.default.string),
|
|
1455
1562
|
valueFilter: _propTypes2.default.objectOf(_propTypes2.default.objectOf(_propTypes2.default.bool)),
|
|
1456
|
-
sorters: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.objectOf(_propTypes2.default.func)]),
|
|
1563
|
+
sorters: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.objectOf(_propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.string, _propTypes2.default.array]))]),
|
|
1457
1564
|
derivedAttributes: _propTypes2.default.objectOf(_propTypes2.default.func),
|
|
1565
|
+
precomputedData: _propTypes2.default.object,
|
|
1566
|
+
onRecordProcessed: _propTypes2.default.func,
|
|
1458
1567
|
rowOrder: _propTypes2.default.oneOf(['key_a_to_z', 'value_a_to_z', 'value_z_to_a']),
|
|
1459
1568
|
colOrder: _propTypes2.default.oneOf(['key_a_to_z', 'value_a_to_z', 'value_z_to_a']),
|
|
1460
1569
|
rowSorts: _propTypes2.default.objectOf(_propTypes2.default.oneOf(['ASC', 'DESC'])),
|
|
@@ -1472,5 +1581,6 @@ exports.sortAs = sortAs;
|
|
|
1472
1581
|
exports.builtInSorters = builtInSorters;
|
|
1473
1582
|
exports.detectDataType = detectDataType;
|
|
1474
1583
|
exports.createSorterByType = createSorterByType;
|
|
1584
|
+
exports.sortersHaveFunctions = sortersHaveFunctions;
|
|
1475
1585
|
exports.PivotData = PivotData;
|
|
1476
1586
|
//# sourceMappingURL=Utilities.js.map
|