@deephaven/iris-grid 1.21.1 → 1.22.1-alpha-pivot-builder.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.
Files changed (57) hide show
  1. package/README.md +284 -1
  2. package/dist/AdvancedFilterCreator.css +42 -0
  3. package/dist/AdvancedFilterCreator.css.map +1 -1
  4. package/dist/AdvancedFilterCreator.d.ts +2 -0
  5. package/dist/AdvancedFilterCreator.d.ts.map +1 -1
  6. package/dist/AdvancedFilterCreator.js +13 -3
  7. package/dist/AdvancedFilterCreator.js.map +1 -1
  8. package/dist/CommonTypes.d.ts +62 -2
  9. package/dist/CommonTypes.d.ts.map +1 -1
  10. package/dist/CommonTypes.js.map +1 -1
  11. package/dist/IrisGrid.d.ts +89 -3
  12. package/dist/IrisGrid.d.ts.map +1 -1
  13. package/dist/IrisGrid.js +294 -91
  14. package/dist/IrisGrid.js.map +1 -1
  15. package/dist/IrisGridModel.d.ts +30 -1
  16. package/dist/IrisGridModel.d.ts.map +1 -1
  17. package/dist/IrisGridModel.js +36 -1
  18. package/dist/IrisGridModel.js.map +1 -1
  19. package/dist/IrisGridModelWidgetProps.d.ts +26 -0
  20. package/dist/IrisGridModelWidgetProps.d.ts.map +1 -0
  21. package/dist/IrisGridModelWidgetProps.js +2 -0
  22. package/dist/IrisGridModelWidgetProps.js.map +1 -0
  23. package/dist/IrisGridProxyModel.d.ts.map +1 -1
  24. package/dist/IrisGridProxyModel.js +34 -2
  25. package/dist/IrisGridProxyModel.js.map +1 -1
  26. package/dist/IrisGridTextCellRenderer.d.ts.map +1 -1
  27. package/dist/IrisGridTextCellRenderer.js +1 -1
  28. package/dist/IrisGridTextCellRenderer.js.map +1 -1
  29. package/dist/IrisGridUtils.d.ts +25 -2
  30. package/dist/IrisGridUtils.d.ts.map +1 -1
  31. package/dist/IrisGridUtils.js +99 -42
  32. package/dist/IrisGridUtils.js.map +1 -1
  33. package/dist/LazyIrisGrid.d.ts +1 -1
  34. package/dist/RemoteComponentModules.d.ts +12 -0
  35. package/dist/RemoteComponentModules.d.ts.map +1 -0
  36. package/dist/RemoteComponentModules.js +16 -0
  37. package/dist/RemoteComponentModules.js.map +1 -0
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +2 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/sidebar/IrisGridTableOptionsWidgetProps.d.ts +22 -0
  43. package/dist/sidebar/IrisGridTableOptionsWidgetProps.d.ts.map +1 -0
  44. package/dist/sidebar/IrisGridTableOptionsWidgetProps.js +2 -0
  45. package/dist/sidebar/IrisGridTableOptionsWidgetProps.js.map +1 -0
  46. package/dist/sidebar/OptionType.d.ts +8 -0
  47. package/dist/sidebar/OptionType.d.ts.map +1 -1
  48. package/dist/sidebar/OptionType.js +7 -0
  49. package/dist/sidebar/OptionType.js.map +1 -1
  50. package/dist/sidebar/PluginTableOptionsErrorBoundary.d.ts +30 -0
  51. package/dist/sidebar/PluginTableOptionsErrorBoundary.d.ts.map +1 -0
  52. package/dist/sidebar/PluginTableOptionsErrorBoundary.js +60 -0
  53. package/dist/sidebar/PluginTableOptionsErrorBoundary.js.map +1 -0
  54. package/dist/sidebar/index.d.ts +3 -2
  55. package/dist/sidebar/index.d.ts.map +1 -1
  56. package/dist/sidebar/index.js.map +1 -1
  57. package/package.json +16 -16
package/dist/IrisGrid.js CHANGED
@@ -42,6 +42,7 @@ import IrisGridModel from "./IrisGridModel.js";
42
42
  import { isPartitionedGridModel } from "./PartitionedGridModel.js";
43
43
  import IrisGridPartitionSelector from "./IrisGridPartitionSelector.js";
44
44
  import SelectDistinctBuilder from "./sidebar/SelectDistinctBuilder.js";
45
+ import PluginTableOptionsErrorBoundary from "./sidebar/PluginTableOptionsErrorBoundary.js";
45
46
  import AdvancedSettingsType from "./sidebar/AdvancedSettingsType.js";
46
47
  import AdvancedSettingsMenu from "./sidebar/AdvancedSettingsMenu.js";
47
48
  import SHORTCUTS from "./IrisGridShortcuts.js";
@@ -49,7 +50,6 @@ import ConditionalFormattingMenu from "./sidebar/conditional-formatting/Conditio
49
50
  import ConditionalFormatEditor from "./sidebar/conditional-formatting/ConditionalFormatEditor.js";
50
51
  import IrisGridCellOverflowModal from "./IrisGridCellOverflowModal.js";
51
52
  import GotoRow from "./GotoRow.js";
52
- import AggregationOperation from "./sidebar/aggregations/AggregationOperation.js";
53
53
  import { IrisGridThemeContext } from "./IrisGridThemeProvider.js";
54
54
  import { isMissingPartitionError } from "./MissingPartitionError.js";
55
55
  import { NoPastePermissionModal } from "./NoPastePermissionModal.js";
@@ -80,6 +80,17 @@ function isEmptyConfig(_ref) {
80
80
  } = _ref;
81
81
  return advancedFilters.size === 0 && aggregationSettings.aggregations.length === 0 && customColumns.length === 0 && quickFilters.size === 0 && !reverse && rollupConfig == null && searchFilter == null && selectDistinctColumns.length === 0 && sorts.length === 0;
82
82
  }
83
+
84
+ /**
85
+ * The subset of `IrisGridProps` that overrides how the grid presents its
86
+ * model: theme, canvas renderer, extra mouse handlers, and the metric
87
+ * calculator factory. Hosts that render `<IrisGrid>` on behalf of a plugin
88
+ * (e.g. `GridWidgetPlugin`) accept this as a single passthrough bag so they
89
+ * don't need to know each view concern by name, and plugins build it from
90
+ * their own hooks. Kept as a `Pick` (not `Partial<IrisGridProps>`) so it can
91
+ * never clobber structural props like `model` or `ref`.
92
+ */
93
+
83
94
  class IrisGrid extends Component {
84
95
  constructor(props) {
85
96
  var _model$layoutHints, _model$columns$0$name, _model$columns$;
@@ -117,12 +128,22 @@ class IrisGrid extends Component {
117
128
  _defineProperty(this, "tableUtils", void 0);
118
129
  _defineProperty(this, "keyHandlers", void 0);
119
130
  _defineProperty(this, "mouseHandlers", void 0);
131
+ /**
132
+ * The metric calculator factory most recently used to instantiate the
133
+ * calculator currently stored in state. Used by `maybeRebuildMetricCalculator`
134
+ * (called from `componentDidUpdate` when the `getMetricCalculator` prop
135
+ * changes) to detect when a different factory is supplied and rebuild.
136
+ */
137
+ _defineProperty(this, "lastMetricCalculatorFactory", void 0);
120
138
  _defineProperty(this, "slideTransitionRef", /*#__PURE__*/React.createRef());
121
139
  _defineProperty(this, "bottomTransitionRef", /*#__PURE__*/React.createRef());
122
140
  _defineProperty(this, "getAdvancedMenuOpenedHandler", memoize(column => this.handleAdvancedMenuOpened.bind(this, column), {
123
141
  max: 100
124
142
  }));
125
- _defineProperty(this, "getCachedAdvancedFilterMenuActions", memoize((model, column, advancedFilterOptions, sortDirection, formatter) => /*#__PURE__*/_jsx(AdvancedFilterCreator, {
143
+ _defineProperty(this, "getAdvancedMenuToggleMaximizeHandler", memoize(column => this.handleAdvancedFilterToggleMaximize.bind(this, column), {
144
+ max: 100
145
+ }));
146
+ _defineProperty(this, "getCachedAdvancedFilterMenuActions", memoize((model, column, advancedFilterOptions, sortDirection, formatter, isMaximized, onToggleMaximize) => /*#__PURE__*/_jsx(AdvancedFilterCreator, {
126
147
  model: model,
127
148
  column: column,
128
149
  onFilterChange: this.handleAdvancedFilterChange,
@@ -131,7 +152,9 @@ class IrisGrid extends Component {
131
152
  options: advancedFilterOptions,
132
153
  sortDirection: sortDirection,
133
154
  formatter: formatter,
134
- tableUtils: this.tableUtils
155
+ tableUtils: this.tableUtils,
156
+ isMaximized: isMaximized,
157
+ onToggleMaximize: onToggleMaximize
135
158
  }), {
136
159
  max: 50
137
160
  }));
@@ -141,63 +164,72 @@ class IrisGrid extends Component {
141
164
  optionItems.push({
142
165
  type: OptionType.CHART_BUILDER,
143
166
  title: 'Chart Builder',
144
- icon: dhGraphLineUp
167
+ icon: dhGraphLineUp,
168
+ order: 100
145
169
  });
146
170
  }
147
171
  if (isOrganizeColumnsAvailable) {
148
172
  optionItems.push({
149
173
  type: OptionType.VISIBILITY_ORDERING_BUILDER,
150
174
  title: 'Organize Columns',
151
- icon: dhEye
175
+ icon: dhEye,
176
+ order: 200
152
177
  });
153
178
  }
154
179
  if (isFormatColumnsAvailable) {
155
180
  optionItems.push({
156
181
  type: OptionType.CONDITIONAL_FORMATTING,
157
182
  title: 'Conditional Formatting',
158
- icon: vsEdit
183
+ icon: vsEdit,
184
+ order: 300
159
185
  });
160
186
  }
161
187
  if (isCustomColumnsAvailable) {
162
188
  optionItems.push({
163
189
  type: OptionType.CUSTOM_COLUMN_BUILDER,
164
190
  title: 'Custom Columns',
165
- icon: vsSplitHorizontal
191
+ icon: vsSplitHorizontal,
192
+ order: 400
166
193
  });
167
194
  }
168
195
  if (isRollupAvailable) {
169
196
  optionItems.push({
170
197
  type: OptionType.ROLLUP_ROWS,
171
198
  title: 'Rollup Rows',
172
- icon: dhTriangleDownSquare
199
+ icon: dhTriangleDownSquare,
200
+ order: 500
173
201
  });
174
202
  }
175
203
  if (isTotalsAvailable) {
176
204
  optionItems.push({
177
205
  type: OptionType.AGGREGATIONS,
178
206
  title: 'Aggregate Columns',
179
- icon: vsSymbolOperator
207
+ icon: vsSymbolOperator,
208
+ order: 600
180
209
  });
181
210
  }
182
211
  if (isSelectDistinctAvailable) {
183
212
  optionItems.push({
184
213
  type: OptionType.SELECT_DISTINCT,
185
214
  title: 'Select Distinct Values',
186
- icon: vsRuby
215
+ icon: vsRuby,
216
+ order: 700
187
217
  });
188
218
  }
189
219
  if (isExportAvailable && canDownloadCsv) {
190
220
  optionItems.push({
191
221
  type: OptionType.TABLE_EXPORTER,
192
222
  title: 'Download CSV',
193
- icon: vsCloudDownload
223
+ icon: vsCloudDownload,
224
+ order: 800
194
225
  });
195
226
  }
196
227
  if (hasAdvancedSettings) {
197
228
  optionItems.push({
198
229
  type: OptionType.ADVANCED_SETTINGS,
199
230
  title: 'Advanced Settings',
200
- icon: vsTools
231
+ icon: vsTools,
232
+ order: 900
201
233
  });
202
234
  }
203
235
  optionItems.push({
@@ -206,7 +238,8 @@ class IrisGrid extends Component {
206
238
  subtitle: toggleFilterBarAction.shortcut.getDisplayText(),
207
239
  icon: vsFilter,
208
240
  isOn: isFilterBarShown,
209
- onChange: toggleFilterBarAction.action
241
+ onChange: toggleFilterBarAction.action,
242
+ order: 1000
210
243
  });
211
244
  if (canToggleSearch) {
212
245
  optionItems.push({
@@ -215,7 +248,8 @@ class IrisGrid extends Component {
215
248
  subtitle: toggleSearchBarAction.shortcut.getDisplayText(),
216
249
  icon: vsSearch,
217
250
  isOn: showSearchBar,
218
- onChange: toggleSearchBarAction.action
251
+ onChange: toggleSearchBarAction.action,
252
+ order: 1100
219
253
  });
220
254
  }
221
255
  optionItems.push({
@@ -224,48 +258,80 @@ class IrisGrid extends Component {
224
258
  subtitle: toggleGotoRowAction.shortcut.getDisplayText(),
225
259
  icon: vsReply,
226
260
  isOn: showGotoRow,
227
- onChange: toggleGotoRowAction.action
261
+ onChange: toggleGotoRowAction.action,
262
+ order: 1200
228
263
  });
229
264
  return Object.freeze(optionItems);
230
265
  }, {
231
266
  max: 1
232
267
  }));
268
+ /**
269
+ * Apply the `transformTableOptions` transform (if any) to the
270
+ * default option list.
271
+ * Catches exceptions so a buggy plugin can't break the grid,
272
+ * and warns about duplicate `type` collisions.
273
+ */
274
+ _defineProperty(this, "getCachedTransformedOptionItems", memoize((items, transformTableOptions) => {
275
+ if (transformTableOptions == null) {
276
+ return items;
277
+ }
278
+ var transformedItems;
279
+ try {
280
+ transformedItems = transformTableOptions(items);
281
+ } catch (err) {
282
+ log.error('transformTableOptions threw an error; falling back to defaults.', err);
283
+ return items;
284
+ }
285
+ // Stably sort by ascending `order`. Items without an `order` sink to
286
+ // the end of the menu (default `Infinity`), while items with an `order`
287
+ // are positioned by their weight. Decorate-sort-undecorate guarantees
288
+ // stability regardless of the engine's sort implementation.
289
+ var sortedItems = transformedItems.map((item, index) => ({
290
+ item,
291
+ index
292
+ })).sort((a, b) => {
293
+ var _a$item$order, _b$item$order;
294
+ return ((_a$item$order = a.item.order) !== null && _a$item$order !== void 0 ? _a$item$order : Infinity) - ((_b$item$order = b.item.order) !== null && _b$item$order !== void 0 ? _b$item$order : Infinity) || a.index - b.index;
295
+ }).map(_ref2 => {
296
+ var {
297
+ item
298
+ } = _ref2;
299
+ return item;
300
+ });
301
+ var keys = new Set();
302
+ for (var i = 0; i < sortedItems.length; i += 1) {
303
+ var key = String(sortedItems[i].type);
304
+ if (keys.has(key)) {
305
+ log.warn("transformTableOptions produced duplicate type \"".concat(key, "\"; ") + 'only the first entry will be accessible from the menu.');
306
+ break;
307
+ }
308
+ keys.add(key);
309
+ }
310
+ return Object.freeze(sortedItems);
311
+ }, {
312
+ max: 1
313
+ }));
233
314
  _defineProperty(this, "getCachedHiddenColumns", memoize((metricCalculator, userColumnWidths) => IrisGridUtils.getHiddenColumns(new Map([...metricCalculator.initialColumnWidths, ...userColumnWidths])), {
234
315
  max: 1
235
316
  }));
236
317
  _defineProperty(this, "getAggregationMap", memoize((columns, aggregations) => {
237
318
  var aggregationMap = {};
238
- aggregations.forEach(_ref2 => {
319
+ aggregations.forEach(_ref3 => {
239
320
  var {
240
321
  operation,
241
322
  selected,
242
323
  invert
243
- } = _ref2;
324
+ } = _ref3;
244
325
  aggregationMap[operation] = AggregationUtils.getOperationColumnNames(columns, operation, selected, invert);
245
326
  });
246
327
  return aggregationMap;
247
328
  }, {
248
329
  max: 1
249
330
  }));
250
- _defineProperty(this, "getOperationMap", memoize((columns, aggregations) => {
251
- var operationMap = {};
252
- aggregations.filter(a => !AggregationUtils.isRollupOperation(a.operation)).forEach(_ref3 => {
253
- var {
254
- operation,
255
- selected,
256
- invert
257
- } = _ref3;
258
- AggregationUtils.getOperationColumnNames(columns, operation, selected, invert).forEach(name => {
259
- var _operationMap$name;
260
- var newOperations = [...((_operationMap$name = operationMap[name]) !== null && _operationMap$name !== void 0 ? _operationMap$name : []), operation];
261
- operationMap[name] = Object.freeze(newOperations);
262
- });
263
- });
264
- return operationMap;
265
- }, {
331
+ _defineProperty(this, "getOperationMap", memoize((columns, aggregations) => IrisGridUtils.getOperationMap(columns, aggregations), {
266
332
  max: 1
267
333
  }));
268
- _defineProperty(this, "getOperationOrder", memoize(aggregations => aggregations.map(a => a.operation).filter(o => !AggregationUtils.isRollupOperation(o)), {
334
+ _defineProperty(this, "getOperationOrder", memoize(aggregations => IrisGridUtils.getOperationOrder(aggregations), {
269
335
  max: 1
270
336
  }));
271
337
  _defineProperty(this, "getCachedFormatColumns", memoize((dh, columns, rules) => getFormatColumns(dh, columns, rules), {
@@ -293,28 +359,7 @@ class IrisGrid extends Component {
293
359
  _defineProperty(this, "getModelRollupConfig", memoize((originalColumns, config, aggregationSettings) => IrisGridUtils.getModelRollupConfig(originalColumns, config, aggregationSettings), {
294
360
  max: 1
295
361
  }));
296
- _defineProperty(this, "getModelTotalsConfig", memoize((columns, config, aggregationSettings) => {
297
- var _config$columns$lengt, _config$columns;
298
- if (((_config$columns$lengt = config === null || config === void 0 || (_config$columns = config.columns) === null || _config$columns === void 0 ? void 0 : _config$columns.length) !== null && _config$columns$lengt !== void 0 ? _config$columns$lengt : 0) > 0) {
299
- // If we've got rollups, then aggregations are applied as part of that...
300
- return null;
301
- }
302
-
303
- // Filter out aggregations without any columns actually selected
304
- var aggregations = aggregationSettings.aggregations.filter(agg => agg.selected.length > 0 || agg.invert);
305
- if (aggregations.length === 0) {
306
- // We don't actually have any aggregations set, don't bother
307
- return null;
308
- }
309
- var operationMap = this.getOperationMap(columns, aggregations);
310
- var operationOrder = this.getOperationOrder(aggregations);
311
- return {
312
- operationMap,
313
- operationOrder,
314
- showOnTop: aggregationSettings.showOnTop,
315
- defaultOperation: AggregationOperation.SKIP
316
- };
317
- }, {
362
+ _defineProperty(this, "getModelTotalsConfig", memoize((columns, config, aggregationSettings) => IrisGridUtils.getModelTotalsConfig(columns, config, aggregationSettings), {
318
363
  max: 1
319
364
  }));
320
365
  _defineProperty(this, "getCachedStateOverride", memoize((model, theme, hoverSelectColumn, isFilterBarShown, isSelectingColumn, loadingScrimProgress, quickFilters, advancedFilters, sorts, reverse, rollupConfig, isMenuShown) => ({
@@ -367,7 +412,7 @@ class IrisGrid extends Component {
367
412
  _defineProperty(this, "getCachedKeyHandlers", memoize(keyHandlers => [...keyHandlers, ...this.keyHandlers].sort((a, b) => a.order - b.order), {
368
413
  max: 1
369
414
  }));
370
- _defineProperty(this, "getCachedMouseHandlers", memoize(mouseHandlers => [...mouseHandlers, ...this.mouseHandlers].map(handler => typeof handler === 'function' ? handler(this) : handler), {
415
+ _defineProperty(this, "getCachedMouseHandlers", memoize(mouseHandlersProp => [...mouseHandlersProp, ...this.mouseHandlers].map(handler => typeof handler === 'function' ? handler(this) : handler), {
371
416
  max: 1
372
417
  }));
373
418
  _defineProperty(this, "getCachedRenderer", memoize(rendererProp => rendererProp !== null && rendererProp !== void 0 ? rendererProp : new IrisGridRenderer(), {
@@ -543,6 +588,7 @@ class IrisGrid extends Component {
543
588
  this.handleAdvancedFilterChange = this.handleAdvancedFilterChange.bind(this);
544
589
  this.handleAdvancedFilterSortChange = this.handleAdvancedFilterSortChange.bind(this);
545
590
  this.handleAdvancedFilterDone = this.handleAdvancedFilterDone.bind(this);
591
+ this.handleAdvancedFilterToggleMaximize = this.handleAdvancedFilterToggleMaximize.bind(this);
546
592
  this.handleAdvancedMenuOpened = this.handleAdvancedMenuOpened.bind(this);
547
593
  this.handleGotoRowOpened = this.handleGotoRowOpened.bind(this);
548
594
  this.handleGotoRowClosed = this.handleGotoRowClosed.bind(this);
@@ -565,11 +611,14 @@ class IrisGrid extends Component {
565
611
  this.handleMenuSelect = this.handleMenuSelect.bind(this);
566
612
  this.handleMenuBack = this.handleMenuBack.bind(this);
567
613
  this.handleRequestFailed = this.handleRequestFailed.bind(this);
614
+ this.handlePending = this.handlePending.bind(this);
615
+ this.handlePendingCleared = this.handlePendingCleared.bind(this);
568
616
  this.handleSelectionChanged = this.handleSelectionChanged.bind(this);
569
617
  this.handleMovedColumnsChanged = this.handleMovedColumnsChanged.bind(this);
570
618
  this.handleHeaderGroupsChanged = this.handleHeaderGroupsChanged.bind(this);
571
619
  this.handleUpdate = this.handleUpdate.bind(this);
572
620
  this.handleTableChanged = this.handleTableChanged.bind(this);
621
+ this.handleModelChanged = this.handleModelChanged.bind(this);
573
622
  this.handleTooltipRef = this.handleTooltipRef.bind(this);
574
623
  this.handleViewChanged = this.handleViewChanged.bind(this);
575
624
  this.handleFormatSelection = this.handleFormatSelection.bind(this);
@@ -696,23 +745,27 @@ class IrisGrid extends Component {
696
745
  dh: _dh
697
746
  } = _model;
698
747
  var _keyHandlers = [new CopyCellKeyHandler(this), new ReverseKeyHandler(this), new ClearFilterKeyHandler(this)];
699
- var _mouseHandlers = [new IrisGridCellOverflowMouseHandler(this), new IrisGridRowTreeMouseHandler(this), new IrisGridTokenMouseHandler(this), new IrisGridColumnSelectMouseHandler(this), new IrisGridColumnTooltipMouseHandler(this), new IrisGridSortMouseHandler(this), new IrisGridFilterMouseHandler(this), new IrisGridContextMenuHandler(this, _dh), new IrisGridDataSelectMouseHandler(this), new PendingMouseHandler(this), new IrisGridPartitionedTableMouseHandler(this), ...(canCopy ? [new IrisGridCopyCellMouseHandler(this)] : [])];
748
+ var mouseHandlers = [new IrisGridCellOverflowMouseHandler(this), new IrisGridRowTreeMouseHandler(this), new IrisGridTokenMouseHandler(this), new IrisGridColumnSelectMouseHandler(this), new IrisGridColumnTooltipMouseHandler(this), new IrisGridSortMouseHandler(this), new IrisGridFilterMouseHandler(this), new IrisGridContextMenuHandler(this, _dh), new IrisGridDataSelectMouseHandler(this), new PendingMouseHandler(this), new IrisGridPartitionedTableMouseHandler(this), ...(canCopy ? [new IrisGridCopyCellMouseHandler(this)] : [])];
700
749
  if (canCopy) {
701
750
  _keyHandlers.push(new CopyKeyHandler(this));
702
751
  }
703
752
  var _movedColumns = movedColumnsProp.length > 0 ? movedColumnsProp : _model.initialMovedColumns;
704
753
  var movedRows = movedRowsProp.length > 0 ? movedRowsProp : _model.initialMovedRows;
705
- var _metricCalculator = getMetricCalculator({
754
+ var metricCalculatorFactory = getMetricCalculator;
755
+ var _metricCalculator = metricCalculatorFactory({
706
756
  userColumnWidths: new Map(_userColumnWidths),
707
757
  userColumnWidthsByName: userColumnWidthsByName != null ? new Map(userColumnWidthsByName) : undefined,
708
758
  userRowHeights: new Map(userRowHeights),
709
759
  movedColumns: _movedColumns,
710
760
  initialColumnWidths: new Map(_model === null || _model === void 0 || (_model$layoutHints = _model.layoutHints) === null || _model$layoutHints === void 0 || (_model$layoutHints = _model$layoutHints.hiddenColumns) === null || _model$layoutHints === void 0 ? void 0 : _model$layoutHints.map(name => [_model.getColumnIndexByName(name), 0]))
711
761
  });
762
+ // Remember the factory we used so we can detect a model-driven swap
763
+ // (e.g. pivot-builder's proxy swapping its inner model) on COLUMNS_CHANGED.
764
+ this.lastMetricCalculatorFactory = metricCalculatorFactory;
712
765
  var searchColumns = _selectedSearchColumns !== null && _selectedSearchColumns !== void 0 ? _selectedSearchColumns : [];
713
766
  var _searchFilter = CrossColumnSearch.createSearchFilter(_dh, _searchValue, searchColumns, _model.columns, _invertSearchColumns);
714
767
  this.tableUtils = new TableUtils(_dh);
715
- this.mouseHandlers = _mouseHandlers;
768
+ this.mouseHandlers = mouseHandlers;
716
769
  this.keyHandlers = _keyHandlers;
717
770
  this.state = {
718
771
  isFilterBarShown: _isFilterBarShown,
@@ -729,6 +782,7 @@ class IrisGrid extends Component {
729
782
  quickFilters: _quickFilters ? new Map(_quickFilters) : new Map(),
730
783
  advancedFilters: new Map(_advancedFilters),
731
784
  shownAdvancedFilter: null,
785
+ maximizedAdvancedFilter: null,
732
786
  hoverAdvancedFilter: null,
733
787
  sorts: [],
734
788
  reverse: false,
@@ -816,12 +870,24 @@ class IrisGrid extends Component {
816
870
  settings,
817
871
  model,
818
872
  customFilters,
819
- sorts
873
+ sorts,
874
+ getMetricCalculator
820
875
  } = this.props;
821
876
  if (model !== prevProps.model) {
822
877
  this.stopListening(prevProps.model);
823
878
  this.startListening(model);
824
879
  }
880
+
881
+ // The renderer and mouse handlers flow through memoized getters in
882
+ // render(), so a `renderer` / `mouseHandlers` prop change naturally
883
+ // propagates on the next render. The metric calculator, however, lives in
884
+ // component state, so mirror that path when the `getMetricCalculator` prop
885
+ // changes (e.g. the pivot-builder middleware swapping the pivot factory in
886
+ // or out) so the calculator stays in sync. Moved columns are not touched
887
+ // here — a model swap resets them via `handleModelChanged`.
888
+ if (getMetricCalculator !== prevProps.getMetricCalculator) {
889
+ this.maybeRebuildMetricCalculator();
890
+ }
825
891
  var changedInputFilters = inputFilters !== prevProps.inputFilters ? inputFilters.filter(inputFilter => !prevProps.inputFilters.includes(inputFilter)) : [];
826
892
  if (changedInputFilters.length > 0) {
827
893
  var _advancedSettings$get;
@@ -1757,18 +1823,24 @@ class IrisGrid extends Component {
1757
1823
  startListening(model) {
1758
1824
  model.addEventListener(IrisGridModel.EVENT.UPDATED, this.handleUpdate);
1759
1825
  model.addEventListener(IrisGridModel.EVENT.REQUEST_FAILED, this.handleRequestFailed);
1826
+ model.addEventListener(IrisGridModel.EVENT.PENDING, this.handlePending);
1827
+ model.addEventListener(IrisGridModel.EVENT.PENDING_CLEARED, this.handlePendingCleared);
1760
1828
  model.addEventListener(IrisGridModel.EVENT.COLUMNS_CHANGED, this.handleCustomColumnsChanged);
1761
1829
  model.addEventListener(IrisGridModel.EVENT.PENDING_DATA_UPDATED, this.handlePendingDataUpdated);
1762
1830
  model.addEventListener(IrisGridModel.EVENT.VIEWPORT_UPDATED, this.handleViewportUpdated);
1763
1831
  model.addEventListener(IrisGridModel.EVENT.TABLE_CHANGED, this.handleTableChanged);
1832
+ model.addEventListener(IrisGridModel.EVENT.MODEL_CHANGED, this.handleModelChanged);
1764
1833
  }
1765
1834
  stopListening(model) {
1766
1835
  model.removeEventListener(IrisGridModel.EVENT.UPDATED, this.handleUpdate);
1767
1836
  model.removeEventListener(IrisGridModel.EVENT.REQUEST_FAILED, this.handleRequestFailed);
1837
+ model.removeEventListener(IrisGridModel.EVENT.PENDING, this.handlePending);
1838
+ model.removeEventListener(IrisGridModel.EVENT.PENDING_CLEARED, this.handlePendingCleared);
1768
1839
  model.removeEventListener(IrisGridModel.EVENT.COLUMNS_CHANGED, this.handleCustomColumnsChanged);
1769
1840
  model.removeEventListener(IrisGridModel.EVENT.PENDING_DATA_UPDATED, this.handlePendingDataUpdated);
1770
1841
  model.removeEventListener(IrisGridModel.EVENT.VIEWPORT_UPDATED, this.handleViewportUpdated);
1771
1842
  model.removeEventListener(IrisGridModel.EVENT.TABLE_CHANGED, this.handleTableChanged);
1843
+ model.removeEventListener(IrisGridModel.EVENT.MODEL_CHANGED, this.handleModelChanged);
1772
1844
  }
1773
1845
  focus() {
1774
1846
  var _this$grid3;
@@ -2388,9 +2460,20 @@ class IrisGrid extends Component {
2388
2460
  var _this$grid16;
2389
2461
  (_this$grid16 = this.grid) === null || _this$grid16 === void 0 || _this$grid16.focus();
2390
2462
  }
2463
+ handleAdvancedFilterToggleMaximize(column) {
2464
+ this.setState(_ref13 => {
2465
+ var {
2466
+ maximizedAdvancedFilter
2467
+ } = _ref13;
2468
+ return {
2469
+ maximizedAdvancedFilter: maximizedAdvancedFilter === column ? null : column
2470
+ };
2471
+ });
2472
+ }
2391
2473
  handleAdvancedMenuOpened(column) {
2392
2474
  this.setState({
2393
- shownAdvancedFilter: column
2475
+ shownAdvancedFilter: column,
2476
+ maximizedAdvancedFilter: null
2394
2477
  });
2395
2478
  }
2396
2479
  handleGotoRowOpened() {
@@ -2415,12 +2498,14 @@ class IrisGrid extends Component {
2415
2498
  var _this$filterInputRef2;
2416
2499
  (_this$filterInputRef2 = this.filterInputRef) === null || _this$filterInputRef2 === void 0 || _this$filterInputRef2.current.focus();
2417
2500
  this.setState({
2418
- shownAdvancedFilter: null
2501
+ shownAdvancedFilter: null,
2502
+ maximizedAdvancedFilter: null
2419
2503
  });
2420
2504
  } else {
2421
2505
  this.setState({
2422
2506
  focusedFilterBarColumn: null,
2423
- shownAdvancedFilter: null
2507
+ shownAdvancedFilter: null,
2508
+ maximizedAdvancedFilter: null
2424
2509
  });
2425
2510
  }
2426
2511
  }
@@ -2452,11 +2537,11 @@ class IrisGrid extends Component {
2452
2537
  this.startLoading('Filtering...', {
2453
2538
  resetRanges: true
2454
2539
  });
2455
- this.setState(_ref13 => {
2540
+ this.setState(_ref14 => {
2456
2541
  var {
2457
2542
  focusedFilterBarColumn,
2458
2543
  quickFilters
2459
- } = _ref13;
2544
+ } = _ref14;
2460
2545
  var newQuickFilters = new Map(quickFilters);
2461
2546
  if (focusedFilterBarColumn != null) {
2462
2547
  var modelIndex = this.getModelColumn(focusedFilterBarColumn);
@@ -2518,10 +2603,10 @@ class IrisGrid extends Component {
2518
2603
  model
2519
2604
  } = this.props;
2520
2605
  var column = model.columns[modelIndex];
2521
- this.setState(_ref14 => {
2606
+ this.setState(_ref15 => {
2522
2607
  var {
2523
2608
  columnAlignmentMap = EMPTY_MAP
2524
- } = _ref14;
2609
+ } = _ref15;
2525
2610
  var newColumnAlignmentMap = new Map(columnAlignmentMap);
2526
2611
  if (alignment != null) {
2527
2612
  newColumnAlignmentMap.set(column.name, alignment);
@@ -2546,10 +2631,10 @@ class IrisGrid extends Component {
2546
2631
  });
2547
2632
  }
2548
2633
  handleMenuBack() {
2549
- this.setState(_ref15 => {
2634
+ this.setState(_ref16 => {
2550
2635
  var {
2551
2636
  openOptions
2552
- } = _ref15;
2637
+ } = _ref16;
2553
2638
  var newOptions = [...openOptions];
2554
2639
  newOptions.pop();
2555
2640
  return {
@@ -2558,10 +2643,10 @@ class IrisGrid extends Component {
2558
2643
  });
2559
2644
  }
2560
2645
  handleMenuSelect(option) {
2561
- this.setState(_ref16 => {
2646
+ this.setState(_ref17 => {
2562
2647
  var {
2563
2648
  openOptions
2564
- } = _ref16;
2649
+ } = _ref17;
2565
2650
  return {
2566
2651
  openOptions: [...openOptions, option]
2567
2652
  };
@@ -2599,6 +2684,37 @@ class IrisGrid extends Component {
2599
2684
  onError(new Error("Error displaying table: ".concat(error)));
2600
2685
  }
2601
2686
  }
2687
+
2688
+ /**
2689
+ * Raise the loading scrim in response to a model-driven `PENDING` event. The
2690
+ * model is the start signal, mirroring how `UPDATED`/`COLUMNS_CHANGED` are
2691
+ * already the model-driven stop signal. Idempotent: the first message within
2692
+ * a commit wins (the `loadingScrimStartTime == null` guard collapses multiple
2693
+ * pending operations into a single scrim).
2694
+ */
2695
+ handlePending(event) {
2696
+ var {
2697
+ detail
2698
+ } = event;
2699
+ var {
2700
+ text,
2701
+ options
2702
+ } = detail !== null && detail !== void 0 ? detail : {};
2703
+ if (this.loadingScrimStartTime == null) {
2704
+ this.startLoading(text !== null && text !== void 0 ? text : 'Loading...', _objectSpread({
2705
+ loadingCancelShown: false
2706
+ }, options));
2707
+ }
2708
+ }
2709
+
2710
+ /**
2711
+ * Clear the loading scrim in response to a model-driven `PENDING_CLEARED`
2712
+ * event. Only needed for operations that do not naturally end in
2713
+ * `UPDATED`/`COLUMNS_CHANGED`/`REQUEST_FAILED`.
2714
+ */
2715
+ handlePendingCleared() {
2716
+ this.stopLoading();
2717
+ }
2602
2718
  handleUpdate() {
2603
2719
  var _this$grid18;
2604
2720
  log.debug2('Received model update');
@@ -2636,10 +2752,6 @@ class IrisGrid extends Component {
2636
2752
  var {
2637
2753
  model
2638
2754
  } = this.props;
2639
- // movedColumns reset triggers metricCalculator update in the Grid component
2640
- this.setState({
2641
- movedColumns: model.initialMovedColumns
2642
- });
2643
2755
  // For partitioned tables, we want to rebuild filters on table change to ensure filters are applied to the new partition
2644
2756
  var {
2645
2757
  partitionConfig
@@ -2648,6 +2760,24 @@ class IrisGrid extends Component {
2648
2760
  this.rebuildFilters();
2649
2761
  }
2650
2762
  }
2763
+
2764
+ /**
2765
+ * Handle an inner-model swap on a proxy model (`MODEL_CHANGED`). The previous
2766
+ * model's `movedColumns` reference indices that may not exist in the new
2767
+ * model (e.g. a pivot exposes a different column set), so reset them to the
2768
+ * new model's initial order. The metric calculator is rebuilt separately when
2769
+ * the `getMetricCalculator` prop changes (see `componentDidUpdate`); a calc
2770
+ * whose seed `movedColumns` are now stale self-heals because `getMetrics`
2771
+ * reconciles against the grid's current `movedColumns` at draw time.
2772
+ */
2773
+ handleModelChanged() {
2774
+ var {
2775
+ model
2776
+ } = this.props;
2777
+ this.setState({
2778
+ movedColumns: model.initialMovedColumns
2779
+ });
2780
+ }
2651
2781
  handleViewChanged(metrics) {
2652
2782
  var _this$grid$state, _this$grid19;
2653
2783
  var {
@@ -2876,6 +3006,56 @@ class IrisGrid extends Component {
2876
3006
  this.loadTableState();
2877
3007
  }
2878
3008
  }
3009
+
3010
+ /**
3011
+ * Rebuild the metric calculator when the `getMetricCalculator` prop swaps for
3012
+ * a different factory (e.g. entering or leaving a pivot, where the
3013
+ * pivot-builder middleware flips the prop). The renderer and mouse handlers
3014
+ * are recomputed via their memoized getters on the next render and do not
3015
+ * need explicit handling here.
3016
+ *
3017
+ * User column-widths / row-heights from the previous calculator are not
3018
+ * carried over: a factory swap means the column set has effectively changed,
3019
+ * so the stored sizes wouldn't map to anything meaningful.
3020
+ *
3021
+ * Moved columns are NOT reset here — that is owned by `handleModelChanged`
3022
+ * (the `MODEL_CHANGED` event) so that a plain prop swap against the same
3023
+ * model preserves the user's layout. The new calculator is seeded with the
3024
+ * current moved columns; `getMetrics` reconciles against the grid's live
3025
+ * `movedColumns` at draw time, so a later reset stays consistent.
3026
+ */
3027
+ maybeRebuildMetricCalculator() {
3028
+ var _model$layoutHints4;
3029
+ var {
3030
+ getMetricCalculator
3031
+ } = this.props;
3032
+ var factory = getMetricCalculator;
3033
+ if (factory === this.lastMetricCalculatorFactory) return;
3034
+ var {
3035
+ model
3036
+ } = this.props;
3037
+ var {
3038
+ movedColumns
3039
+ } = this.state;
3040
+ var next = factory({
3041
+ userColumnWidths: new Map(),
3042
+ userRowHeights: new Map(),
3043
+ movedColumns,
3044
+ initialColumnWidths: new Map(model === null || model === void 0 || (_model$layoutHints4 = model.layoutHints) === null || _model$layoutHints4 === void 0 || (_model$layoutHints4 = _model$layoutHints4.hiddenColumns) === null || _model$layoutHints4 === void 0 ? void 0 : _model$layoutHints4.map(name => [model.getColumnIndexByName(name), 0]))
3045
+ });
3046
+ this.lastMetricCalculatorFactory = factory;
3047
+ log.debug('Swapping metric calculator', next);
3048
+ // Also push the new calculator onto the Grid synchronously so any
3049
+ // immediately-following read of `Grid.metricCalculator` (before React has
3050
+ // committed the setState below) uses the new instance against the new
3051
+ // model rather than invoking the old calculator and potentially throwing.
3052
+ if (this.grid != null) {
3053
+ this.grid.metricCalculator = next;
3054
+ }
3055
+ this.setState({
3056
+ metricCalculator: next
3057
+ });
3058
+ }
2879
3059
  handlePendingCommitClicked() {
2880
3060
  return this.commitPending();
2881
3061
  }
@@ -2924,11 +3104,11 @@ class IrisGrid extends Component {
2924
3104
  } = this.state;
2925
3105
  if (!metrics) throw new Error('Metrics not set');
2926
3106
  var allColumns = [...metrics.allColumnWidths.entries()];
2927
- var visibleColumns = allColumns.filter(_ref17 => {
2928
- var [_, width] = _ref17;
3107
+ var visibleColumns = allColumns.filter(_ref18 => {
3108
+ var [_, width] = _ref18;
2929
3109
  return width !== 0;
2930
- }).map(_ref18 => {
2931
- var [modelIndex] = _ref18;
3110
+ }).map(_ref19 => {
3111
+ var [modelIndex] = _ref19;
2932
3112
  return modelIndex;
2933
3113
  });
2934
3114
  var contentWidths = metrics.contentColumnWidths;
@@ -2995,10 +3175,10 @@ class IrisGrid extends Component {
2995
3175
  if (shouldStartLoading) {
2996
3176
  this.startLoading("Aggregating ".concat(aggregation.operation, "..."));
2997
3177
  }
2998
- this.setState(_ref19 => {
3178
+ this.setState(_ref20 => {
2999
3179
  var {
3000
3180
  aggregationSettings
3001
- } = _ref19;
3181
+ } = _ref20;
3002
3182
  return {
3003
3183
  selectedAggregation: aggregation,
3004
3184
  aggregationSettings: _objectSpread(_objectSpread({}, aggregationSettings), {}, {
@@ -3110,10 +3290,10 @@ class IrisGrid extends Component {
3110
3290
  */
3111
3291
  removeEmptyAggregations() {
3112
3292
  log.debug('removeEmptyAggregations');
3113
- this.setState(_ref20 => {
3293
+ this.setState(_ref21 => {
3114
3294
  var {
3115
3295
  aggregationSettings
3116
- } = _ref20;
3296
+ } = _ref21;
3117
3297
  var {
3118
3298
  aggregations
3119
3299
  } = aggregationSettings;
@@ -3652,7 +3832,8 @@ class IrisGrid extends Component {
3652
3832
  advancedSettings,
3653
3833
  onAdvancedSettingsChange,
3654
3834
  canDownloadCsv,
3655
- onCreateChart
3835
+ onCreateChart,
3836
+ transformTableOptions
3656
3837
  } = this.props;
3657
3838
  var {
3658
3839
  metricCalculator,
@@ -3671,6 +3852,7 @@ class IrisGrid extends Component {
3671
3852
  shownColumnTooltip,
3672
3853
  hoverAdvancedFilter,
3673
3854
  shownAdvancedFilter,
3855
+ maximizedAdvancedFilter,
3674
3856
  hoverSelectColumn,
3675
3857
  quickFilters,
3676
3858
  advancedFilters,
@@ -3820,7 +4002,8 @@ class IrisGrid extends Component {
3820
4002
  }),
3821
4003
  onClick: () => {
3822
4004
  _this7.setState({
3823
- shownAdvancedFilter: columnIndex
4005
+ shownAdvancedFilter: columnIndex,
4006
+ maximizedAdvancedFilter: null
3824
4007
  });
3825
4008
  },
3826
4009
  onContextMenu: event => {
@@ -3909,6 +4092,7 @@ class IrisGrid extends Component {
3909
4092
  style: style,
3910
4093
  children: /*#__PURE__*/_jsx(Popper, {
3911
4094
  className: "advanced-filter-menu-popper",
4095
+ isMaximized: shownAdvancedFilter === columnIndex && maximizedAdvancedFilter === columnIndex,
3912
4096
  onEntered: _this7.getAdvancedMenuOpenedHandler(columnIndex),
3913
4097
  onExited: () => {
3914
4098
  _this7.handleAdvancedMenuClosed(columnIndex);
@@ -3919,7 +4103,7 @@ class IrisGrid extends Component {
3919
4103
  options: {
3920
4104
  positionFixed: true
3921
4105
  },
3922
- children: _this7.getCachedAdvancedFilterMenuActions(model, column, advancedFilterOptions, sortDirection, formatter)
4106
+ children: _this7.getCachedAdvancedFilterMenuActions(model, column, advancedFilterOptions, sortDirection, formatter, shownAdvancedFilter === columnIndex && maximizedAdvancedFilter === columnIndex, _this7.getAdvancedMenuToggleMaximizeHandler(columnIndex))
3923
4107
  })
3924
4108
  }, columnIndex);
3925
4109
  advancedFilterMenus.push(element);
@@ -3930,7 +4114,8 @@ class IrisGrid extends Component {
3930
4114
  if (_loop3()) continue;
3931
4115
  }
3932
4116
  }
3933
- var optionItems = this.getCachedOptionItems(onCreateChart !== undefined && model.isChartBuilderAvailable, model.isCustomColumnsAvailable, model.isFormatColumnsAvailable, model.isOrganizeColumnsAvailable, model.isRollupAvailable, model.isTotalsAvailable || isRollup, model.isSelectDistinctAvailable, model.isExportAvailable, this.toggleFilterBarAction, this.toggleSearchBarAction, this.toggleGotoRowAction, isFilterBarShown, showSearchBar, canDownloadCsv, this.isTableSearchAvailable(), isGotoShown, advancedSettings.size > 0);
4117
+ var defaultOptionItems = this.getCachedOptionItems(onCreateChart !== undefined && model.isChartBuilderAvailable, model.isCustomColumnsAvailable, model.isFormatColumnsAvailable, model.isOrganizeColumnsAvailable, model.isRollupAvailable, model.isTotalsAvailable || isRollup, model.isSelectDistinctAvailable, model.isExportAvailable, this.toggleFilterBarAction, this.toggleSearchBarAction, this.toggleGotoRowAction, isFilterBarShown, showSearchBar, canDownloadCsv, this.isTableSearchAvailable(), isGotoShown, advancedSettings.size > 0);
4118
+ var optionItems = this.getCachedTransformedOptionItems(defaultOptionItems, transformTableOptions);
3934
4119
  var hiddenColumns = this.getCachedHiddenColumns(metricCalculator, userColumnWidths);
3935
4120
  var openOptionsStack = openOptions.map(option => {
3936
4121
  switch (option.type) {
@@ -4025,7 +4210,25 @@ class IrisGrid extends Component {
4025
4210
  onChange: onAdvancedSettingsChange
4026
4211
  });
4027
4212
  default:
4028
- throw Error("Unexpected option type ".concat(option.type));
4213
+ {
4214
+ // Plugin-contributed items render their own page via
4215
+ // `configPage`. The page is isolated inside an error
4216
+ // boundary so a throwing plugin doesn't tear down the
4217
+ // entire grid subtree. Built-in items that hit the default
4218
+ // case indicate a programmer error (unhandled enum case).
4219
+ var PluginPage = option.configPage;
4220
+ if (PluginPage == null) {
4221
+ throw Error("Unexpected option type ".concat(option.type));
4222
+ }
4223
+ return /*#__PURE__*/_jsx(PluginTableOptionsErrorBoundary, {
4224
+ itemType: String(option.type),
4225
+ onBack: this.handleMenuBack,
4226
+ children: /*#__PURE__*/_jsx(PluginPage, {
4227
+ model: model,
4228
+ onBack: this.handleMenuBack
4229
+ })
4230
+ }, String(option.type));
4231
+ }
4029
4232
  }
4030
4233
  });
4031
4234
  return /*#__PURE__*/_jsxs("div", {
@@ -4215,7 +4418,7 @@ class IrisGrid extends Component {
4215
4418
  unmountOnExit: true,
4216
4419
  children: /*#__PURE__*/_jsx("div", {
4217
4420
  className: "table-sidebar",
4218
- children: /*#__PURE__*/_jsxs(Stack, {
4421
+ children: /*#__PURE__*/_jsx(Stack, {
4219
4422
  children: [/*#__PURE__*/_jsx(Page, {
4220
4423
  title: "Table Options",
4221
4424
  onClose: this.handleMenuClose,
@@ -4223,7 +4426,7 @@ class IrisGrid extends Component {
4223
4426
  onSelect: i => this.handleMenuSelect(optionItems[i]),
4224
4427
  items: optionItems
4225
4428
  })
4226
- }), openOptionsStack.map((option, i) => /*#__PURE__*/_jsx(Page, {
4429
+ }, "table-options"), ...openOptionsStack.map((option, i) => /*#__PURE__*/_jsx(Page, {
4227
4430
  title: openOptions[i].title,
4228
4431
  onBack: this.handleMenuBack,
4229
4432
  onClose: this.handleMenuClose,