@hrforte/react-pivottable 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,822 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ 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; }; }();
8
+
9
+ exports.default = createPlotlyRenderers;
10
+
11
+ var _react = require('react');
12
+
13
+ var _react2 = _interopRequireDefault(_react);
14
+
15
+ var _propTypes = require('prop-types');
16
+
17
+ var _propTypes2 = _interopRequireDefault(_propTypes);
18
+
19
+ var _Utilities = require('./Utilities');
20
+
21
+ var _TableRenderers = require('./TableRenderers');
22
+
23
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
+
25
+ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
26
+
27
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
28
+
29
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
30
+
31
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
32
+
33
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
34
+
35
+ var CHART_WIDTH_RATIO = 1.5; // Ratio to scale down from full window width
36
+ var CHART_HEIGHT_RATIO = 1.4; // Ratio to scale down from full window height
37
+ var CHART_HEIGHT_OFFSET = 50; // Fixed offset to subtract from height calculation
38
+
39
+
40
+ // ============================================================================
41
+ // Helper Functions
42
+ // ============================================================================
43
+
44
+ /**
45
+ * Ensures keys array is not empty by adding an empty array if needed
46
+ */
47
+ function ensureNonEmptyKeys(keys) {
48
+ return keys.length > 0 ? keys : [[]];
49
+ }
50
+
51
+ /**
52
+ * Combines category and datum labels into a single display label
53
+ */
54
+ function combineCategoryLabels(categoryKey, datumKey) {
55
+ var categoryLabel = categoryKey.join(' ') || '';
56
+ var datumLabel = datumKey.join(' ') || '';
57
+
58
+ // if (categoryLabel && datumLabel) {
59
+ // return `${categoryLabel} - ${datumLabel}`;
60
+ // }
61
+ return categoryLabel || datumLabel || ' ';
62
+ }
63
+
64
+ /**
65
+ * Builds axis title from row and column titles
66
+ */
67
+ function buildAxisTitle(categoryTitle, datumTitle) {
68
+ var defaultTitle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'Categories';
69
+
70
+ if (categoryTitle && datumTitle) {
71
+ return categoryTitle + ' - ' + datumTitle;
72
+ }
73
+ return categoryTitle || datumTitle || defaultTitle;
74
+ }
75
+
76
+ /**
77
+ * Collects aggregation values and labels across all categories
78
+ */
79
+ function collectAggregationData(pivotData, categoryKeys, datumKeys, aggregationKey) {
80
+ var values = [];
81
+ var labels = [];
82
+
83
+ var _iteratorNormalCompletion = true;
84
+ var _didIteratorError = false;
85
+ var _iteratorError = undefined;
86
+
87
+ try {
88
+ for (var _iterator = categoryKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
89
+ var categoryKey = _step.value;
90
+ var _iteratorNormalCompletion2 = true;
91
+ var _didIteratorError2 = false;
92
+ var _iteratorError2 = undefined;
93
+
94
+ try {
95
+ for (var _iterator2 = datumKeys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
96
+ var datumKey = _step2.value;
97
+
98
+ var val = parseFloat(pivotData.getAggregator(categoryKey, datumKey, aggregationKey).value());
99
+ values.push(isFinite(val) ? val : null);
100
+ labels.push(combineCategoryLabels(categoryKey, datumKey));
101
+ }
102
+ } catch (err) {
103
+ _didIteratorError2 = true;
104
+ _iteratorError2 = err;
105
+ } finally {
106
+ try {
107
+ if (!_iteratorNormalCompletion2 && _iterator2.return) {
108
+ _iterator2.return();
109
+ }
110
+ } finally {
111
+ if (_didIteratorError2) {
112
+ throw _iteratorError2;
113
+ }
114
+ }
115
+ }
116
+ }
117
+ } catch (err) {
118
+ _didIteratorError = true;
119
+ _iteratorError = err;
120
+ } finally {
121
+ try {
122
+ if (!_iteratorNormalCompletion && _iterator.return) {
123
+ _iterator.return();
124
+ }
125
+ } finally {
126
+ if (_didIteratorError) {
127
+ throw _iteratorError;
128
+ }
129
+ }
130
+ }
131
+
132
+ return { values: values, labels: labels };
133
+ }
134
+
135
+ /**
136
+ * Calculates chart dimensions
137
+ */
138
+ function getChartDimensions() {
139
+ var rowMultiplier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
140
+
141
+ return {
142
+ width: window.innerWidth / CHART_WIDTH_RATIO,
143
+ height: (window.innerHeight / CHART_HEIGHT_RATIO - CHART_HEIGHT_OFFSET) * rowMultiplier
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Creates common renderer props
149
+ */
150
+ function createRendererProps() {
151
+ return {
152
+ defaultProps: Object.assign({}, _Utilities.PivotData.defaultProps, {
153
+ plotlyOptions: {},
154
+ plotlyConfig: {}
155
+ }),
156
+ propTypes: Object.assign({}, _Utilities.PivotData.propTypes, {
157
+ plotlyOptions: _propTypes2.default.object,
158
+ plotlyConfig: _propTypes2.default.object,
159
+ onRendererUpdate: _propTypes2.default.func
160
+ })
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Determines chart rendering strategy based on trace options
166
+ */
167
+ function getChartRenderingStrategy(traceOptions) {
168
+ if (traceOptions.type === 'pie') {
169
+ return 'pie-totals';
170
+ }
171
+ if (traceOptions.mode && traceOptions.mode.includes('lines')) {
172
+ return 'category-data';
173
+ }
174
+ // Bar, area, scatter charts also need category data
175
+ return 'category-data';
176
+ }
177
+
178
+ // ============================================================================
179
+ // Renderer Factory Functions
180
+ // ============================================================================
181
+
182
+ function makeRenderer(PlotlyComponent) {
183
+ var traceOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
184
+ var layoutOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
185
+ var transpose = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
186
+
187
+ var Renderer = function (_React$PureComponent) {
188
+ _inherits(Renderer, _React$PureComponent);
189
+
190
+ function Renderer() {
191
+ _classCallCheck(this, Renderer);
192
+
193
+ return _possibleConstructorReturn(this, (Renderer.__proto__ || Object.getPrototypeOf(Renderer)).apply(this, arguments));
194
+ }
195
+
196
+ _createClass(Renderer, [{
197
+ key: 'render',
198
+ value: function render() {
199
+ var _this2 = this;
200
+
201
+ var pivotData = new _Utilities.PivotData(this.props);
202
+ var rowKeys = pivotData.getRowKeys();
203
+ var colKeys = pivotData.getColKeys();
204
+ var traceKeys = ensureNonEmptyKeys(transpose ? colKeys : rowKeys);
205
+ var datumKeys = ensureNonEmptyKeys(transpose ? rowKeys : colKeys);
206
+
207
+ var primaryAggregation = pivotData.getPrimaryAggregation();
208
+ var fallbackAggregator = Object.keys(this.props.aggregators)[0] || 'Value';
209
+ var aggregatorName = primaryAggregation && primaryAggregation.aggregatorName || fallbackAggregator;
210
+ var aggregationVals = primaryAggregation && primaryAggregation.vals || [];
211
+ var fullAggName = primaryAggregation && primaryAggregation.label || (aggregationVals.length ? aggregatorName + ' of ' + aggregationVals.join(', ') : aggregatorName);
212
+
213
+ var data = traceKeys.map(function (traceKey) {
214
+ var values = [];
215
+ var labels = [];
216
+ var textValues = [];
217
+
218
+ var _iteratorNormalCompletion3 = true;
219
+ var _didIteratorError3 = false;
220
+ var _iteratorError3 = undefined;
221
+
222
+ try {
223
+ for (var _iterator3 = datumKeys[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
224
+ var datumKey = _step3.value;
225
+
226
+ var aggregator = pivotData.getAggregator(transpose ? datumKey : traceKey, transpose ? traceKey : datumKey);
227
+ var val = parseFloat(aggregator.value());
228
+ // Get cell formatting from plotlyOptions (similar to tableOptions)
229
+ var cellFormatting = _this2.props.plotlyOptions && _this2.props.plotlyOptions.cellFormatting || null;
230
+
231
+ // Apply cell formatting to the formatted value
232
+ var finalFormattedValue = (0, _TableRenderers.applyCellFormatting)(aggregator.value(), cellFormatting, aggregator.format.bind(aggregator), aggregatorName);
233
+ values.push(isFinite(val) ? val : null);
234
+ labels.push(datumKey.join('-') || ' ');
235
+ textValues.push(finalFormattedValue);
236
+ }
237
+ } catch (err) {
238
+ _didIteratorError3 = true;
239
+ _iteratorError3 = err;
240
+ } finally {
241
+ try {
242
+ if (!_iteratorNormalCompletion3 && _iterator3.return) {
243
+ _iterator3.return();
244
+ }
245
+ } finally {
246
+ if (_didIteratorError3) {
247
+ throw _iteratorError3;
248
+ }
249
+ }
250
+ }
251
+
252
+ var trace = {
253
+ name: traceKey.join('-') || fullAggName,
254
+ text: textValues
255
+ };
256
+
257
+ if (traceOptions.type === 'pie') {
258
+ trace.values = values;
259
+ trace.labels = labels.length > 1 ? labels : [fullAggName];
260
+ trace.hovertemplate = '<b>%{label}</b><br>' + fullAggName + '<br><b>%{value}</b><extra></extra>';
261
+ trace.textinfo = 'value';
262
+ trace.textposition = 'inside';
263
+ } else {
264
+ trace.x = transpose ? values : labels;
265
+ trace.y = transpose ? labels : values;
266
+ trace.hovertemplate = transpose ? '<b>%{y}</b><br>' + fullAggName + '<br><b>%{x}</b><extra></extra>' : '<b>%{x}</b><br>' + fullAggName + '<br><b>%{y}</b><extra></extra>';
267
+
268
+ // Configure text display based on chart type
269
+ if (traceOptions.type === 'bar') {
270
+ trace.textposition = traceOptions.orientation === 'h' ? 'middle right' : 'outside';
271
+ trace.textmode = 'text';
272
+ } else if (traceOptions.mode && traceOptions.mode.includes('lines')) {
273
+ trace.textposition = 'top center';
274
+ trace.textmode = 'lines+markers+text'; // Show text on markers for line charts
275
+ } else if (traceOptions.mode === 'markers') {
276
+ trace.textposition = 'middle right';
277
+ trace.textmode = 'text+markers'; // Show text with markers
278
+ } else if (traceOptions.stackgroup) {
279
+ trace.textposition = 'middle center';
280
+ trace.textmode = 'text';
281
+ } else {
282
+ trace.textposition = 'outside';
283
+ trace.textmode = 'text';
284
+ }
285
+ }
286
+
287
+ return Object.assign(trace, traceOptions);
288
+ });
289
+
290
+ var titleText = fullAggName;
291
+ var hAxisTitle = transpose ? this.props.rows.join('-') : this.props.cols.join('-');
292
+ var groupByTitle = transpose ? this.props.cols.join('-') : this.props.rows.join('-');
293
+ if (hAxisTitle !== '') {
294
+ titleText += ' vs ' + hAxisTitle;
295
+ }
296
+ if (groupByTitle !== '') {
297
+ titleText += ' by ' + groupByTitle;
298
+ }
299
+
300
+ var dimensions = getChartDimensions();
301
+ var layout = {
302
+ title: titleText,
303
+ hovermode: 'closest',
304
+ width: dimensions.width,
305
+ height: dimensions.height
306
+ };
307
+
308
+ if (traceOptions.type === 'pie') {
309
+ var columns = Math.ceil(Math.sqrt(data.length));
310
+ var rows = Math.ceil(data.length / columns);
311
+ layout.grid = { columns: columns, rows: rows };
312
+ data.forEach(function (d, i) {
313
+ d.domain = {
314
+ row: Math.floor(i / columns),
315
+ column: i - columns * Math.floor(i / columns)
316
+ };
317
+ if (data.length > 1) {
318
+ d.title = d.name;
319
+ }
320
+ });
321
+ if (data[0].labels.length === 1) {
322
+ layout.showlegend = false;
323
+ }
324
+ } else {
325
+ layout.xaxis = {
326
+ title: transpose ? fullAggName : null,
327
+ automargin: true
328
+ };
329
+ layout.yaxis = {
330
+ title: transpose ? null : fullAggName,
331
+ automargin: true
332
+ };
333
+ }
334
+
335
+ return _react2.default.createElement(PlotlyComponent, {
336
+ data: data,
337
+ layout: Object.assign(layout, layoutOptions, this.props.plotlyOptions),
338
+ config: this.props.plotlyConfig,
339
+ onUpdate: this.props.onRendererUpdate
340
+ });
341
+ }
342
+ }]);
343
+
344
+ return Renderer;
345
+ }(_react2.default.PureComponent);
346
+
347
+ var rendererProps = createRendererProps();
348
+ Renderer.defaultProps = rendererProps.defaultProps;
349
+ Renderer.propTypes = rendererProps.propTypes;
350
+
351
+ return Renderer;
352
+ }
353
+
354
+ /**
355
+ * Creates a pie chart trace showing category-level breakdown for a single aggregation
356
+ */
357
+ function createPieCategoryTrace(pivotData, aggregation, categoryKeys, datumKeys, subplotIndex, traceOptions) {
358
+ var cellFormatting = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
359
+
360
+ var values = [];
361
+ var labels = [];
362
+
363
+ var _iteratorNormalCompletion4 = true;
364
+ var _didIteratorError4 = false;
365
+ var _iteratorError4 = undefined;
366
+
367
+ try {
368
+ for (var _iterator4 = categoryKeys[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
369
+ var categoryKey = _step4.value;
370
+ var _iteratorNormalCompletion6 = true;
371
+ var _didIteratorError6 = false;
372
+ var _iteratorError6 = undefined;
373
+
374
+ try {
375
+ for (var _iterator6 = datumKeys[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
376
+ var datumKey = _step6.value;
377
+
378
+ var aggregator = pivotData.getAggregator(categoryKey, datumKey, aggregation.key);
379
+ var val = parseFloat(aggregator.value());
380
+ if (isFinite(val) && val !== null) {
381
+ values.push(val);
382
+ labels.push(combineCategoryLabels(categoryKey, datumKey));
383
+ }
384
+ }
385
+ } catch (err) {
386
+ _didIteratorError6 = true;
387
+ _iteratorError6 = err;
388
+ } finally {
389
+ try {
390
+ if (!_iteratorNormalCompletion6 && _iterator6.return) {
391
+ _iterator6.return();
392
+ }
393
+ } finally {
394
+ if (_didIteratorError6) {
395
+ throw _iteratorError6;
396
+ }
397
+ }
398
+ }
399
+ }
400
+ } catch (err) {
401
+ _didIteratorError4 = true;
402
+ _iteratorError4 = err;
403
+ } finally {
404
+ try {
405
+ if (!_iteratorNormalCompletion4 && _iterator4.return) {
406
+ _iterator4.return();
407
+ }
408
+ } finally {
409
+ if (_didIteratorError4) {
410
+ throw _iteratorError4;
411
+ }
412
+ }
413
+ }
414
+
415
+ var textValues = [];
416
+ var _iteratorNormalCompletion5 = true;
417
+ var _didIteratorError5 = false;
418
+ var _iteratorError5 = undefined;
419
+
420
+ try {
421
+ for (var _iterator5 = categoryKeys[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
422
+ var _categoryKey = _step5.value;
423
+ var _iteratorNormalCompletion7 = true;
424
+ var _didIteratorError7 = false;
425
+ var _iteratorError7 = undefined;
426
+
427
+ try {
428
+ for (var _iterator7 = datumKeys[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
429
+ var _datumKey = _step7.value;
430
+
431
+ var _aggregator = pivotData.getAggregator(_categoryKey, _datumKey, aggregation.key);
432
+
433
+ var finalFormattedValue = (0, _TableRenderers.applyCellFormatting)(_aggregator.value(), cellFormatting, _aggregator.format.bind(_aggregator), aggregation.aggregatorName);
434
+
435
+ textValues.push(finalFormattedValue);
436
+ }
437
+ } catch (err) {
438
+ _didIteratorError7 = true;
439
+ _iteratorError7 = err;
440
+ } finally {
441
+ try {
442
+ if (!_iteratorNormalCompletion7 && _iterator7.return) {
443
+ _iterator7.return();
444
+ }
445
+ } finally {
446
+ if (_didIteratorError7) {
447
+ throw _iteratorError7;
448
+ }
449
+ }
450
+ }
451
+ }
452
+ } catch (err) {
453
+ _didIteratorError5 = true;
454
+ _iteratorError5 = err;
455
+ } finally {
456
+ try {
457
+ if (!_iteratorNormalCompletion5 && _iterator5.return) {
458
+ _iterator5.return();
459
+ }
460
+ } finally {
461
+ if (_didIteratorError5) {
462
+ throw _iteratorError5;
463
+ }
464
+ }
465
+ }
466
+
467
+ var trace = {
468
+ name: aggregation.label || aggregation.key,
469
+ values: values.length > 0 ? values : [0],
470
+ labels: labels.length > 0 ? labels : ['No Data'],
471
+ text: textValues.length > 0 ? textValues : ['No Data'],
472
+ title: {
473
+ text: aggregation.label || aggregation.key
474
+ },
475
+ hovertemplate: '<b>%{label}</b><br>' + (aggregation.label || aggregation.key) + '<br><b>%{text}</b><extra></extra>'
476
+ };
477
+
478
+ var mergedTrace = Object.assign({}, traceOptions, trace);
479
+ mergedTrace.textinfo = 'text';
480
+ mergedTrace.textposition = 'inside';
481
+
482
+ return mergedTrace;
483
+ }
484
+
485
+ /**
486
+ * Creates traces for charts showing category-level data
487
+ */
488
+ function createCategoryDataTraces(pivotData, aggregations, categoryKeys, datumKeys, groupIndex, traceOptions, plotlyOptions) {
489
+ var traces = [];
490
+
491
+ aggregations.forEach(function (aggregation) {
492
+ var _collectAggregationDa = collectAggregationData(pivotData, categoryKeys, datumKeys, aggregation.key),
493
+ values = _collectAggregationDa.values,
494
+ labels = _collectAggregationDa.labels;
495
+
496
+ // Get formatted text values for display
497
+
498
+
499
+ var textValues = [];
500
+ var _iteratorNormalCompletion8 = true;
501
+ var _didIteratorError8 = false;
502
+ var _iteratorError8 = undefined;
503
+
504
+ try {
505
+ for (var _iterator8 = categoryKeys[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
506
+ var categoryKey = _step8.value;
507
+ var _iteratorNormalCompletion9 = true;
508
+ var _didIteratorError9 = false;
509
+ var _iteratorError9 = undefined;
510
+
511
+ try {
512
+ for (var _iterator9 = datumKeys[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
513
+ var datumKey = _step9.value;
514
+
515
+ var aggregator = pivotData.getAggregator(categoryKey, datumKey, aggregation.key);
516
+ var finalFormattedValue = (0, _TableRenderers.applyCellFormatting)(aggregator.value(), plotlyOptions && plotlyOptions.cellFormatting, aggregator.format.bind(aggregator), aggregation.aggregatorName);
517
+ textValues.push(finalFormattedValue);
518
+ }
519
+ } catch (err) {
520
+ _didIteratorError9 = true;
521
+ _iteratorError9 = err;
522
+ } finally {
523
+ try {
524
+ if (!_iteratorNormalCompletion9 && _iterator9.return) {
525
+ _iterator9.return();
526
+ }
527
+ } finally {
528
+ if (_didIteratorError9) {
529
+ throw _iteratorError9;
530
+ }
531
+ }
532
+ }
533
+ }
534
+ } catch (err) {
535
+ _didIteratorError8 = true;
536
+ _iteratorError8 = err;
537
+ } finally {
538
+ try {
539
+ if (!_iteratorNormalCompletion8 && _iterator8.return) {
540
+ _iterator8.return();
541
+ }
542
+ } finally {
543
+ if (_didIteratorError8) {
544
+ throw _iteratorError8;
545
+ }
546
+ }
547
+ }
548
+
549
+ var trace = {
550
+ name: aggregation.label || aggregation.key,
551
+ xaxis: 'x' + (groupIndex + 1),
552
+ yaxis: 'y' + (groupIndex + 1),
553
+ x: labels,
554
+ y: values,
555
+ text: textValues,
556
+ hovertemplate: '<b>%{x}</b><br>' + (aggregation.label || aggregation.key) + '<br><b>%{text}</b><extra></extra>'
557
+ };
558
+
559
+ if (plotlyOptions && plotlyOptions.displayText) {
560
+
561
+ if (traceOptions.type === 'bar') {
562
+ trace.textposition = traceOptions.orientation === 'h' ? 'middle right' : 'outside';
563
+ traceOptions.mode = 'text';
564
+ } else if (traceOptions.mode && traceOptions.mode.includes('lines')) {
565
+ trace.textposition = 'top';
566
+ traceOptions.mode = 'lines+markers+text';
567
+ } else if (traceOptions.mode && traceOptions.mode.includes('markers')) {
568
+ trace.textposition = 'top center';
569
+ traceOptions.mode = 'markers+text';
570
+ } else {
571
+ trace.textposition = 'top center';
572
+ traceOptions.mode = 'text';
573
+ }
574
+ }
575
+
576
+ traces.push(Object.assign(trace, traceOptions));
577
+ });
578
+
579
+ return traces;
580
+ }
581
+
582
+ /**
583
+ * Creates axis configuration for a subplot group
584
+ */
585
+ function createGroupedSubplotAxes(groupIndex, aggregations, rowsTitle, colsTitle) {
586
+ var _ref;
587
+
588
+ var showXAxisTitle = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
589
+
590
+ var primaryAgg = aggregations[0];
591
+ var aggName = primaryAgg.aggregatorName;
592
+ var xAxisTitle = showXAxisTitle ? buildAxisTitle(rowsTitle, colsTitle) : null;
593
+
594
+ return _ref = {}, _defineProperty(_ref, 'xaxis' + (groupIndex + 1), {
595
+ title: xAxisTitle,
596
+ showticklabels: false,
597
+ automargin: true
598
+ }), _defineProperty(_ref, 'yaxis' + (groupIndex + 1), {
599
+ title: aggName,
600
+ automargin: true
601
+ }), _ref;
602
+ }
603
+
604
+ function makeGroupedRenderer(PlotlyComponent) {
605
+ var traceOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
606
+ var layoutOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
607
+
608
+ var Renderer = function (_React$PureComponent2) {
609
+ _inherits(Renderer, _React$PureComponent2);
610
+
611
+ function Renderer() {
612
+ _classCallCheck(this, Renderer);
613
+
614
+ return _possibleConstructorReturn(this, (Renderer.__proto__ || Object.getPrototypeOf(Renderer)).apply(this, arguments));
615
+ }
616
+
617
+ _createClass(Renderer, [{
618
+ key: 'render',
619
+ value: function render() {
620
+ var _this4 = this;
621
+
622
+ var pivotData = new _Utilities.PivotData(this.props);
623
+ var renderingStrategy = getChartRenderingStrategy(traceOptions);
624
+
625
+ // For pie charts, treat each aggregation as a separate subplot
626
+ if (renderingStrategy === 'pie-totals') {
627
+ var allAggregations = pivotData.getAggregations();
628
+
629
+ if (allAggregations.length === 0) {
630
+ return _react2.default.createElement(
631
+ 'div',
632
+ null,
633
+ 'No aggregations to display'
634
+ );
635
+ }
636
+
637
+ var _rowKeys = pivotData.getRowKeys();
638
+ var _colKeys = pivotData.getColKeys();
639
+ var _categoryKeys = ensureNonEmptyKeys(_rowKeys);
640
+ var _datumKeys = ensureNonEmptyKeys(_colKeys);
641
+
642
+ var _data = [];
643
+ var columns = Math.ceil(Math.sqrt(allAggregations.length));
644
+ var _rows = Math.ceil(allAggregations.length / columns);
645
+ var _dimensions = getChartDimensions(_rows);
646
+
647
+ var _layout = {
648
+ title: 'Aggregations',
649
+ grid: { rows: _rows, columns: columns, pattern: 'independent' },
650
+ width: _dimensions.width,
651
+ height: _dimensions.height,
652
+ showlegend: true,
653
+ hovermode: 'closest'
654
+ };
655
+
656
+ // Create a separate subplot for each aggregation
657
+ allAggregations.forEach(function (aggregation, index) {
658
+ var trace = createPieCategoryTrace(pivotData, aggregation, _categoryKeys, _datumKeys, index, traceOptions, _this4.props.plotlyOptions && _this4.props.plotlyOptions.cellFormatting);
659
+
660
+ trace.domain = {
661
+ row: Math.floor(index / columns),
662
+ column: index % columns
663
+ };
664
+
665
+ _data.push(trace);
666
+ });
667
+
668
+ return _react2.default.createElement(PlotlyComponent, {
669
+ data: _data,
670
+ layout: Object.assign(_layout, layoutOptions, this.props.plotlyOptions),
671
+ config: this.props.plotlyConfig,
672
+ onUpdate: this.props.onRendererUpdate
673
+ });
674
+ }
675
+
676
+ // For non-pie charts, group by aggregation type
677
+ var groupedAggregations = pivotData.groupAggregationsByType();
678
+ var groupNames = Object.keys(groupedAggregations);
679
+
680
+ if (groupNames.length === 0) {
681
+ return _react2.default.createElement(
682
+ 'div',
683
+ null,
684
+ 'No aggregations to display'
685
+ );
686
+ }
687
+
688
+ var rows = groupNames.length;
689
+
690
+ var data = [];
691
+ var dimensions = getChartDimensions(rows);
692
+ var layout = {
693
+ title: 'Grouped Aggregations by Type',
694
+ grid: { rows: rows, columns: 1, pattern: 'independent' },
695
+ width: dimensions.width,
696
+ height: dimensions.height,
697
+ hovermode: 'closest'
698
+ };
699
+
700
+ var rowKeys = pivotData.getRowKeys();
701
+ var colKeys = pivotData.getColKeys();
702
+ var categoryKeys = ensureNonEmptyKeys(rowKeys);
703
+ var datumKeys = ensureNonEmptyKeys(colKeys);
704
+
705
+ groupNames.forEach(function (groupName, groupIndex) {
706
+ var aggregations = groupedAggregations[groupName];
707
+
708
+ var traces = createCategoryDataTraces(pivotData, aggregations, categoryKeys, datumKeys, groupIndex, traceOptions, _this4.props.plotlyOptions);
709
+ data.push.apply(data, _toConsumableArray(traces));
710
+
711
+ Object.assign(layout, createGroupedSubplotAxes(groupIndex, aggregations, _this4.props.rows.join('-'), _this4.props.cols.join('-'), false));
712
+ });
713
+
714
+ return _react2.default.createElement(PlotlyComponent, {
715
+ data: data,
716
+ layout: Object.assign(layout, layoutOptions, this.props.plotlyOptions),
717
+ config: this.props.plotlyConfig,
718
+ onUpdate: this.props.onRendererUpdate
719
+ });
720
+ }
721
+ }]);
722
+
723
+ return Renderer;
724
+ }(_react2.default.PureComponent);
725
+
726
+ var rendererProps = createRendererProps();
727
+ Renderer.defaultProps = rendererProps.defaultProps;
728
+ Renderer.propTypes = rendererProps.propTypes;
729
+
730
+ return Renderer;
731
+ }
732
+
733
+ function makeScatterRenderer(PlotlyComponent) {
734
+ var Renderer = function (_React$PureComponent3) {
735
+ _inherits(Renderer, _React$PureComponent3);
736
+
737
+ function Renderer() {
738
+ _classCallCheck(this, Renderer);
739
+
740
+ return _possibleConstructorReturn(this, (Renderer.__proto__ || Object.getPrototypeOf(Renderer)).apply(this, arguments));
741
+ }
742
+
743
+ _createClass(Renderer, [{
744
+ key: 'render',
745
+ value: function render() {
746
+ var pivotData = new _Utilities.PivotData(this.props);
747
+ var rowKeys = ensureNonEmptyKeys(pivotData.getRowKeys());
748
+ var colKeys = ensureNonEmptyKeys(pivotData.getColKeys());
749
+
750
+ var data = {
751
+ x: [],
752
+ y: [],
753
+ text: [],
754
+ type: 'scatter',
755
+ mode: 'markers+text',
756
+ textposition: 'middle right',
757
+ hovertemplate: '<b>%{x}</b><br>%{y}<br><b>%{text}</b><extra></extra>'
758
+ };
759
+
760
+ // Use forEach instead of map since we're not returning values
761
+ rowKeys.forEach(function (rowKey) {
762
+ colKeys.forEach(function (colKey) {
763
+ var aggregator = pivotData.getAggregator(rowKey, colKey);
764
+ var v = aggregator.value();
765
+ if (v !== null) {
766
+ data.x.push(colKey.join('-'));
767
+ data.y.push(rowKey.join('-'));
768
+ data.text.push(aggregator.format(v));
769
+ }
770
+ });
771
+ });
772
+
773
+ var dimensions = getChartDimensions();
774
+ var layout = {
775
+ title: this.props.rows.join('-') + ' vs ' + this.props.cols.join('-'),
776
+ hovermode: 'closest',
777
+ xaxis: { title: this.props.cols.join('-'), automargin: true },
778
+ yaxis: { title: this.props.rows.join('-'), automargin: true },
779
+ width: dimensions.width,
780
+ height: dimensions.height
781
+ };
782
+
783
+ return _react2.default.createElement(PlotlyComponent, {
784
+ data: [data],
785
+ layout: Object.assign(layout, this.props.plotlyOptions),
786
+ config: this.props.plotlyConfig,
787
+ onUpdate: this.props.onRendererUpdate
788
+ });
789
+ }
790
+ }]);
791
+
792
+ return Renderer;
793
+ }(_react2.default.PureComponent);
794
+
795
+ var rendererProps = createRendererProps();
796
+ Renderer.defaultProps = rendererProps.defaultProps;
797
+ Renderer.propTypes = rendererProps.propTypes;
798
+
799
+ return Renderer;
800
+ }
801
+
802
+ function createPlotlyRenderers(PlotlyComponent) {
803
+ return {
804
+ 'Grouped Column Chart': makeRenderer(PlotlyComponent, { type: 'bar' }, { barmode: 'group' }),
805
+ 'Stacked Column Chart': makeRenderer(PlotlyComponent, { type: 'bar' }, { barmode: 'relative' }),
806
+ 'Grouped Bar Chart': makeRenderer(PlotlyComponent, { type: 'bar', orientation: 'h' }, { barmode: 'group' }, true),
807
+ 'Stacked Bar Chart': makeRenderer(PlotlyComponent, { type: 'bar', orientation: 'h' }, { barmode: 'relative' }, true),
808
+ 'Line Chart': makeRenderer(PlotlyComponent),
809
+ 'Dot Chart': makeRenderer(PlotlyComponent, { mode: 'markers' }, {}, true),
810
+ 'Area Chart': makeRenderer(PlotlyComponent, { stackgroup: 1 }),
811
+ 'Scatter Chart': makeScatterRenderer(PlotlyComponent),
812
+ 'Multiple Pie Chart': makeRenderer(PlotlyComponent, { type: 'pie', scalegroup: 1, hoverinfo: 'label+value', textinfo: 'none' }, {}, true),
813
+ 'Grouped Bars by Type': makeGroupedRenderer(PlotlyComponent, { type: 'bar', orientation: 'h' }, { barmode: 'group' }),
814
+ 'Grouped Columns by Type': makeGroupedRenderer(PlotlyComponent, { type: 'bar' }, { barmode: 'group' }),
815
+ 'Grouped Lines by Type': makeGroupedRenderer(PlotlyComponent, { mode: 'lines+markers' }),
816
+ 'Grouped Areas by Type': makeGroupedRenderer(PlotlyComponent, { stackgroup: 1 }),
817
+ 'Grouped Scatters by Type': makeGroupedRenderer(PlotlyComponent, { mode: 'markers' }),
818
+ 'Grouped Pies by Type': makeGroupedRenderer(PlotlyComponent, { type: 'pie' })
819
+ };
820
+ }
821
+ module.exports = exports['default'];
822
+ //# sourceMappingURL=PlotlyRenderers.js.map