@deephaven/js-plugin-pivot 0.1.0 → 0.2.1-alpha-pivots.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 (2) hide show
  1. package/dist/index.js +1218 -762
  2. package/package.json +8 -9
package/dist/index.js CHANGED
@@ -10,8 +10,8 @@ const plugin = require("@deephaven/plugin");
10
10
  const icons = require("@deephaven/icons");
11
11
  const React = require("react");
12
12
  const irisGrid = require("@deephaven/iris-grid");
13
- const jsapiBootstrap = require("@deephaven/jsapi-bootstrap");
14
13
  const components = require("@deephaven/components");
14
+ const jsapiBootstrap = require("@deephaven/jsapi-bootstrap");
15
15
  const Log = require("@deephaven/log");
16
16
  const jsapiUtils = require("@deephaven/jsapi-utils");
17
17
  const dashboardCorePlugins = require("@deephaven/dashboard-core-plugins");
@@ -274,6 +274,9 @@ class EventShimCustomEvent extends CustomEvent {
274
274
  super(typeArg, eventInitDict);
275
275
  }
276
276
  }
277
+ function isNotNullOrUndefined(value2) {
278
+ return value2 != null;
279
+ }
277
280
  function assertNotNull(value2) {
278
281
  var message = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "Value is null or undefined";
279
282
  if (value2 == null)
@@ -499,9 +502,6 @@ function isEditableGridModel(model) {
499
502
  function isExpandableGridModel(model) {
500
503
  return (model === null || model === void 0 ? void 0 : model.hasExpandableRows) !== void 0;
501
504
  }
502
- function isExpandableColumnGridModel(model) {
503
- return (model === null || model === void 0 ? void 0 : model.hasExpandableColumns) !== void 0;
504
- }
505
505
  var NAN = 0 / 0;
506
506
  var symbolTag = "[object Symbol]";
507
507
  var reTrim = /^\s+|\s+$/g;
@@ -1693,30 +1693,24 @@ function find(str2, type = null, opts = null) {
1693
1693
  }
1694
1694
  return filtered;
1695
1695
  }
1696
- function _defineProperty$9(obj, key, value2) {
1697
- key = _toPropertyKey$9(key);
1698
- if (key in obj) {
1699
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
1700
- } else {
1701
- obj[key] = value2;
1702
- }
1703
- return obj;
1704
- }
1705
- function _toPropertyKey$9(arg) {
1706
- var key = _toPrimitive$9(arg, "string");
1707
- return typeof key === "symbol" ? key : String(key);
1708
- }
1709
- function _toPrimitive$9(input, hint) {
1710
- if (typeof input !== "object" || input === null)
1711
- return input;
1712
- var prim = input[Symbol.toPrimitive];
1713
- if (prim !== void 0) {
1714
- var res = prim.call(input, hint || "default");
1715
- if (typeof res !== "object")
1716
- return res;
1696
+ function _defineProperty$9(e, r, t) {
1697
+ return (r = _toPropertyKey$9(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
1698
+ }
1699
+ function _toPropertyKey$9(t) {
1700
+ var i = _toPrimitive$9(t, "string");
1701
+ return "symbol" == typeof i ? i : i + "";
1702
+ }
1703
+ function _toPrimitive$9(t, r) {
1704
+ if ("object" != typeof t || !t)
1705
+ return t;
1706
+ var e = t[Symbol.toPrimitive];
1707
+ if (void 0 !== e) {
1708
+ var i = e.call(t, r || "default");
1709
+ if ("object" != typeof i)
1710
+ return i;
1717
1711
  throw new TypeError("@@toPrimitive must return a primitive value.");
1718
1712
  }
1719
- return (hint === "string" ? String : Number)(input);
1713
+ return ("string" === r ? String : Number)(t);
1720
1714
  }
1721
1715
  var SELECTION_DIRECTION;
1722
1716
  (function(SELECTION_DIRECTION2) {
@@ -2352,51 +2346,45 @@ function isAxisRange(range) {
2352
2346
  function isBoundedAxisRange(range) {
2353
2347
  return isAxisRange(range) && range[0] != null && range[1] != null;
2354
2348
  }
2355
- function ownKeys$1(object, enumerableOnly) {
2356
- var keys2 = Object.keys(object);
2349
+ function ownKeys$1(e, r) {
2350
+ var t = Object.keys(e);
2357
2351
  if (Object.getOwnPropertySymbols) {
2358
- var symbols = Object.getOwnPropertySymbols(object);
2359
- enumerableOnly && (symbols = symbols.filter(function(sym) {
2360
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
2361
- })), keys2.push.apply(keys2, symbols);
2362
- }
2363
- return keys2;
2364
- }
2365
- function _objectSpread$1(target) {
2366
- for (var i = 1; i < arguments.length; i++) {
2367
- var source = null != arguments[i] ? arguments[i] : {};
2368
- i % 2 ? ownKeys$1(Object(source), true).forEach(function(key) {
2369
- _defineProperty$8(target, key, source[key]);
2370
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$1(Object(source)).forEach(function(key) {
2371
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
2352
+ var o = Object.getOwnPropertySymbols(e);
2353
+ r && (o = o.filter(function(r2) {
2354
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
2355
+ })), t.push.apply(t, o);
2356
+ }
2357
+ return t;
2358
+ }
2359
+ function _objectSpread$1(e) {
2360
+ for (var r = 1; r < arguments.length; r++) {
2361
+ var t = null != arguments[r] ? arguments[r] : {};
2362
+ r % 2 ? ownKeys$1(Object(t), true).forEach(function(r2) {
2363
+ _defineProperty$8(e, r2, t[r2]);
2364
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1(Object(t)).forEach(function(r2) {
2365
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
2372
2366
  });
2373
2367
  }
2374
- return target;
2368
+ return e;
2375
2369
  }
2376
- function _defineProperty$8(obj, key, value2) {
2377
- key = _toPropertyKey$8(key);
2378
- if (key in obj) {
2379
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
2380
- } else {
2381
- obj[key] = value2;
2382
- }
2383
- return obj;
2384
- }
2385
- function _toPropertyKey$8(arg) {
2386
- var key = _toPrimitive$8(arg, "string");
2387
- return typeof key === "symbol" ? key : String(key);
2388
- }
2389
- function _toPrimitive$8(input, hint) {
2390
- if (typeof input !== "object" || input === null)
2391
- return input;
2392
- var prim = input[Symbol.toPrimitive];
2393
- if (prim !== void 0) {
2394
- var res = prim.call(input, hint || "default");
2395
- if (typeof res !== "object")
2396
- return res;
2370
+ function _defineProperty$8(e, r, t) {
2371
+ return (r = _toPropertyKey$8(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
2372
+ }
2373
+ function _toPropertyKey$8(t) {
2374
+ var i = _toPrimitive$8(t, "string");
2375
+ return "symbol" == typeof i ? i : i + "";
2376
+ }
2377
+ function _toPrimitive$8(t, r) {
2378
+ if ("object" != typeof t || !t)
2379
+ return t;
2380
+ var e = t[Symbol.toPrimitive];
2381
+ if (void 0 !== e) {
2382
+ var i = e.call(t, r || "default");
2383
+ if ("object" != typeof i)
2384
+ return i;
2397
2385
  throw new TypeError("@@toPrimitive must return a primitive value.");
2398
2386
  }
2399
- return (hint === "string" ? String : Number)(input);
2387
+ return ("string" === r ? String : Number)(t);
2400
2388
  }
2401
2389
  class GridUtils {
2402
2390
  // use same constant as chrome source for windows
@@ -2669,15 +2657,35 @@ class GridUtils {
2669
2657
  } = metrics;
2670
2658
  return GridUtils.getNextShownItem(startIndex, modelRows, visibleRows, userRowHeights);
2671
2659
  }
2660
+ /**
2661
+ * Check if a separator exists between a column and the next column at a given depth.
2662
+ * A separator exists if adjacent columns have different header text at the specified depth.
2663
+ *
2664
+ * @param model The grid model
2665
+ * @param depth The header depth to check at
2666
+ * @param columnIndex The current model column index
2667
+ * @param nextColumnIndex The next model column index (undefined for last column)
2668
+ * @returns true if a separator should be shown, false otherwise
2669
+ */
2670
+ static hasColumnSeparatorAtDepth(model, depth, columnIndex, nextColumnIndex) {
2671
+ if (depth == null || columnIndex == null) {
2672
+ return false;
2673
+ }
2674
+ if (nextColumnIndex == null) {
2675
+ return true;
2676
+ }
2677
+ return model.textForColumnHeader(columnIndex, depth) !== model.textForColumnHeader(nextColumnIndex, depth);
2678
+ }
2672
2679
  /**
2673
2680
  * Gets the column index if the x/y coordinates provided are close enough to the separator, otherwise null
2674
2681
  * @param x Mouse x coordinate
2675
2682
  * @param y Mouse y coordinate
2676
2683
  * @param metrics The grid metrics
2677
2684
  * @param theme The grid theme with potential user overrides
2685
+ * @param model The grid model
2678
2686
  * @returns Index of the column separator at the coordinates provided, or null if none match
2679
2687
  */
2680
- static getColumnSeparatorIndex(x, y, metrics, theme) {
2688
+ static getColumnSeparatorIndex(x, y, metrics, theme, model) {
2681
2689
  var {
2682
2690
  rowHeaderWidth,
2683
2691
  columnHeaderHeight,
@@ -2686,7 +2694,8 @@ class GridUtils {
2686
2694
  visibleColumns,
2687
2695
  allColumnXs,
2688
2696
  allColumnWidths,
2689
- columnHeaderMaxDepth
2697
+ columnHeaderMaxDepth,
2698
+ modelColumns
2690
2699
  } = metrics;
2691
2700
  var {
2692
2701
  allowColumnResize,
@@ -2697,6 +2706,7 @@ class GridUtils {
2697
2706
  }
2698
2707
  var gridX = x - rowHeaderWidth;
2699
2708
  var halfSeparatorSize = headerSeparatorHandleSize * 0.5;
2709
+ var depth = GridUtils.getColumnHeaderDepthAtY(y, metrics);
2700
2710
  var isPreviousColumnHidden = false;
2701
2711
  for (var i = floatingColumns.length - 1; i >= 0; i -= 1) {
2702
2712
  var _allColumnXs$get, _allColumnWidths$get;
@@ -2713,7 +2723,7 @@ class GridUtils {
2713
2723
  }
2714
2724
  var minX = midX - halfSeparatorSize;
2715
2725
  var maxX = midX + halfSeparatorSize;
2716
- if (minX <= gridX && gridX <= maxX) {
2726
+ if (minX <= gridX && gridX <= maxX && GridUtils.hasColumnSeparatorAtDepth(model, depth, modelColumns.get(column), modelColumns.get(column + 1))) {
2717
2727
  return column;
2718
2728
  }
2719
2729
  isPreviousColumnHidden = isColumnHidden;
@@ -2738,7 +2748,7 @@ class GridUtils {
2738
2748
  }
2739
2749
  var _minX = _midX - halfSeparatorSize;
2740
2750
  var _maxX = _midX + halfSeparatorSize;
2741
- if (_minX <= gridX && gridX <= _maxX) {
2751
+ if (_minX <= gridX && gridX <= _maxX && GridUtils.hasColumnSeparatorAtDepth(model, depth, modelColumns.get(_column), modelColumns.get(_column + 1))) {
2742
2752
  return _column;
2743
2753
  }
2744
2754
  isPreviousColumnHidden = _isColumnHidden;
@@ -5877,51 +5887,45 @@ var memoizee = function(fn) {
5877
5887
  requireRefCounter();
5878
5888
  return plain(fn, options);
5879
5889
  };
5880
- function ownKeys(object, enumerableOnly) {
5881
- var keys2 = Object.keys(object);
5890
+ function ownKeys(e, r) {
5891
+ var t = Object.keys(e);
5882
5892
  if (Object.getOwnPropertySymbols) {
5883
- var symbols = Object.getOwnPropertySymbols(object);
5884
- enumerableOnly && (symbols = symbols.filter(function(sym) {
5885
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
5886
- })), keys2.push.apply(keys2, symbols);
5887
- }
5888
- return keys2;
5889
- }
5890
- function _objectSpread(target) {
5891
- for (var i = 1; i < arguments.length; i++) {
5892
- var source = null != arguments[i] ? arguments[i] : {};
5893
- i % 2 ? ownKeys(Object(source), true).forEach(function(key) {
5894
- _defineProperty$7(target, key, source[key]);
5895
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function(key) {
5896
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
5893
+ var o = Object.getOwnPropertySymbols(e);
5894
+ r && (o = o.filter(function(r2) {
5895
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
5896
+ })), t.push.apply(t, o);
5897
+ }
5898
+ return t;
5899
+ }
5900
+ function _objectSpread(e) {
5901
+ for (var r = 1; r < arguments.length; r++) {
5902
+ var t = null != arguments[r] ? arguments[r] : {};
5903
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
5904
+ _defineProperty$7(e, r2, t[r2]);
5905
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
5906
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
5897
5907
  });
5898
5908
  }
5899
- return target;
5909
+ return e;
5900
5910
  }
5901
- function _defineProperty$7(obj, key, value2) {
5902
- key = _toPropertyKey$7(key);
5903
- if (key in obj) {
5904
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
5905
- } else {
5906
- obj[key] = value2;
5907
- }
5908
- return obj;
5909
- }
5910
- function _toPropertyKey$7(arg) {
5911
- var key = _toPrimitive$7(arg, "string");
5912
- return typeof key === "symbol" ? key : String(key);
5913
- }
5914
- function _toPrimitive$7(input, hint) {
5915
- if (typeof input !== "object" || input === null)
5916
- return input;
5917
- var prim = input[Symbol.toPrimitive];
5918
- if (prim !== void 0) {
5919
- var res = prim.call(input, hint || "default");
5920
- if (typeof res !== "object")
5921
- return res;
5911
+ function _defineProperty$7(e, r, t) {
5912
+ return (r = _toPropertyKey$7(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
5913
+ }
5914
+ function _toPropertyKey$7(t) {
5915
+ var i = _toPrimitive$7(t, "string");
5916
+ return "symbol" == typeof i ? i : i + "";
5917
+ }
5918
+ function _toPrimitive$7(t, r) {
5919
+ if ("object" != typeof t || !t)
5920
+ return t;
5921
+ var e = t[Symbol.toPrimitive];
5922
+ if (void 0 !== e) {
5923
+ var i = e.call(t, r || "default");
5924
+ if ("object" != typeof i)
5925
+ return i;
5922
5926
  throw new TypeError("@@toPrimitive must return a primitive value.");
5923
5927
  }
5924
- return (hint === "string" ? String : Number)(input);
5928
+ return ("string" === r ? String : Number)(t);
5925
5929
  }
5926
5930
  var memoizeClear = (fn, options) => {
5927
5931
  var isClearingCache = false;
@@ -6966,30 +6970,24 @@ const GridColorUtils = {
6966
6970
  rgbToHex,
6967
6971
  lerpColor
6968
6972
  };
6969
- function _defineProperty$6(obj, key, value2) {
6970
- key = _toPropertyKey$6(key);
6971
- if (key in obj) {
6972
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
6973
- } else {
6974
- obj[key] = value2;
6975
- }
6976
- return obj;
6977
- }
6978
- function _toPropertyKey$6(arg) {
6979
- var key = _toPrimitive$6(arg, "string");
6980
- return typeof key === "symbol" ? key : String(key);
6981
- }
6982
- function _toPrimitive$6(input, hint) {
6983
- if (typeof input !== "object" || input === null)
6984
- return input;
6985
- var prim = input[Symbol.toPrimitive];
6986
- if (prim !== void 0) {
6987
- var res = prim.call(input, hint || "default");
6988
- if (typeof res !== "object")
6989
- return res;
6973
+ function _defineProperty$6(e, r, t) {
6974
+ return (r = _toPropertyKey$6(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
6975
+ }
6976
+ function _toPropertyKey$6(t) {
6977
+ var i = _toPrimitive$6(t, "string");
6978
+ return "symbol" == typeof i ? i : i + "";
6979
+ }
6980
+ function _toPrimitive$6(t, r) {
6981
+ if ("object" != typeof t || !t)
6982
+ return t;
6983
+ var e = t[Symbol.toPrimitive];
6984
+ if (void 0 !== e) {
6985
+ var i = e.call(t, r || "default");
6986
+ if ("object" != typeof i)
6987
+ return i;
6990
6988
  throw new TypeError("@@toPrimitive must return a primitive value.");
6991
6989
  }
6992
- return (hint === "string" ? String : Number)(input);
6990
+ return ("string" === r ? String : Number)(t);
6993
6991
  }
6994
6992
  class GridMouseHandler {
6995
6993
  // What order this mouse handler should trigger in. Smaller numbers trigger first
@@ -7029,30 +7027,24 @@ class GridMouseHandler {
7029
7027
  return false;
7030
7028
  }
7031
7029
  }
7032
- function _defineProperty$5(obj, key, value2) {
7033
- key = _toPropertyKey$5(key);
7034
- if (key in obj) {
7035
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
7036
- } else {
7037
- obj[key] = value2;
7038
- }
7039
- return obj;
7040
- }
7041
- function _toPropertyKey$5(arg) {
7042
- var key = _toPrimitive$5(arg, "string");
7043
- return typeof key === "symbol" ? key : String(key);
7044
- }
7045
- function _toPrimitive$5(input, hint) {
7046
- if (typeof input !== "object" || input === null)
7047
- return input;
7048
- var prim = input[Symbol.toPrimitive];
7049
- if (prim !== void 0) {
7050
- var res = prim.call(input, hint || "default");
7051
- if (typeof res !== "object")
7052
- return res;
7030
+ function _defineProperty$5(e, r, t) {
7031
+ return (r = _toPropertyKey$5(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
7032
+ }
7033
+ function _toPropertyKey$5(t) {
7034
+ var i = _toPrimitive$5(t, "string");
7035
+ return "symbol" == typeof i ? i : i + "";
7036
+ }
7037
+ function _toPrimitive$5(t, r) {
7038
+ if ("object" != typeof t || !t)
7039
+ return t;
7040
+ var e = t[Symbol.toPrimitive];
7041
+ if (void 0 !== e) {
7042
+ var i = e.call(t, r || "default");
7043
+ if ("object" != typeof i)
7044
+ return i;
7053
7045
  throw new TypeError("@@toPrimitive must return a primitive value.");
7054
7046
  }
7055
- return (hint === "string" ? String : Number)(input);
7047
+ return ("string" === r ? String : Number)(t);
7056
7048
  }
7057
7049
  class GridSeparatorMouseHandler extends GridMouseHandler {
7058
7050
  constructor() {
@@ -7260,30 +7252,24 @@ class GridSeparatorMouseHandler extends GridMouseHandler {
7260
7252
  }
7261
7253
  }
7262
7254
  const GridSeparatorMouseHandler$1 = GridSeparatorMouseHandler;
7263
- function _defineProperty$4(obj, key, value2) {
7264
- key = _toPropertyKey$4(key);
7265
- if (key in obj) {
7266
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
7267
- } else {
7268
- obj[key] = value2;
7269
- }
7270
- return obj;
7271
- }
7272
- function _toPropertyKey$4(arg) {
7273
- var key = _toPrimitive$4(arg, "string");
7274
- return typeof key === "symbol" ? key : String(key);
7275
- }
7276
- function _toPrimitive$4(input, hint) {
7277
- if (typeof input !== "object" || input === null)
7278
- return input;
7279
- var prim = input[Symbol.toPrimitive];
7280
- if (prim !== void 0) {
7281
- var res = prim.call(input, hint || "default");
7282
- if (typeof res !== "object")
7283
- return res;
7255
+ function _defineProperty$4(e, r, t) {
7256
+ return (r = _toPropertyKey$4(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
7257
+ }
7258
+ function _toPropertyKey$4(t) {
7259
+ var i = _toPrimitive$4(t, "string");
7260
+ return "symbol" == typeof i ? i : i + "";
7261
+ }
7262
+ function _toPrimitive$4(t, r) {
7263
+ if ("object" != typeof t || !t)
7264
+ return t;
7265
+ var e = t[Symbol.toPrimitive];
7266
+ if (void 0 !== e) {
7267
+ var i = e.call(t, r || "default");
7268
+ if ("object" != typeof i)
7269
+ return i;
7284
7270
  throw new TypeError("@@toPrimitive must return a primitive value.");
7285
7271
  }
7286
- return (hint === "string" ? String : Number)(input);
7272
+ return ("string" === r ? String : Number)(t);
7287
7273
  }
7288
7274
  class GridColumnSeparatorMouseHandler extends GridSeparatorMouseHandler$1 {
7289
7275
  constructor() {
@@ -7311,20 +7297,20 @@ class GridColumnSeparatorMouseHandler extends GridSeparatorMouseHandler$1 {
7311
7297
  var {
7312
7298
  x,
7313
7299
  y,
7314
- columnHeaderDepth
7300
+ columnHeaderDepth: depth
7315
7301
  } = gridPoint;
7316
7302
  var {
7317
7303
  modelColumns
7318
7304
  } = metrics;
7319
- var separatorIndex = GridUtils.getColumnSeparatorIndex(x, y, metrics, theme);
7320
- if (separatorIndex == null || columnHeaderDepth == null || columnHeaderDepth > 0) {
7305
+ var separatorIndex = GridUtils.getColumnSeparatorIndex(x, y, metrics, theme, model);
7306
+ if (separatorIndex == null || depth == null) {
7321
7307
  return null;
7322
7308
  }
7323
7309
  var columnIndex = modelColumns.get(separatorIndex);
7324
7310
  if (columnIndex != null) {
7325
7311
  return {
7326
7312
  index: separatorIndex,
7327
- depth: 0
7313
+ depth
7328
7314
  };
7329
7315
  }
7330
7316
  return null;
@@ -7344,30 +7330,24 @@ class GridColumnSeparatorMouseHandler extends GridSeparatorMouseHandler$1 {
7344
7330
  }
7345
7331
  const GridColumnSeparatorMouseHandler$1 = GridColumnSeparatorMouseHandler;
7346
7332
  var DEFAULT_FONT_WIDTH = 10;
7347
- function _defineProperty$3(obj, key, value2) {
7348
- key = _toPropertyKey$3(key);
7349
- if (key in obj) {
7350
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
7351
- } else {
7352
- obj[key] = value2;
7353
- }
7354
- return obj;
7355
- }
7356
- function _toPropertyKey$3(arg) {
7357
- var key = _toPrimitive$3(arg, "string");
7358
- return typeof key === "symbol" ? key : String(key);
7359
- }
7360
- function _toPrimitive$3(input, hint) {
7361
- if (typeof input !== "object" || input === null)
7362
- return input;
7363
- var prim = input[Symbol.toPrimitive];
7364
- if (prim !== void 0) {
7365
- var res = prim.call(input, hint || "default");
7366
- if (typeof res !== "object")
7367
- return res;
7333
+ function _defineProperty$3(e, r, t) {
7334
+ return (r = _toPropertyKey$3(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
7335
+ }
7336
+ function _toPropertyKey$3(t) {
7337
+ var i = _toPrimitive$3(t, "string");
7338
+ return "symbol" == typeof i ? i : i + "";
7339
+ }
7340
+ function _toPrimitive$3(t, r) {
7341
+ if ("object" != typeof t || !t)
7342
+ return t;
7343
+ var e = t[Symbol.toPrimitive];
7344
+ if (void 0 !== e) {
7345
+ var i = e.call(t, r || "default");
7346
+ if ("object" != typeof i)
7347
+ return i;
7368
7348
  throw new TypeError("@@toPrimitive must return a primitive value.");
7369
7349
  }
7370
- return (hint === "string" ? String : Number)(input);
7350
+ return ("string" === r ? String : Number)(t);
7371
7351
  }
7372
7352
  class CellRenderer {
7373
7353
  constructor() {
@@ -7427,30 +7407,24 @@ const CellRenderer$1 = CellRenderer;
7427
7407
  function isDataBarGridModel(model) {
7428
7408
  return (model === null || model === void 0 ? void 0 : model.dataBarOptionsForCell) !== void 0;
7429
7409
  }
7430
- function _defineProperty$2(obj, key, value2) {
7431
- key = _toPropertyKey$2(key);
7432
- if (key in obj) {
7433
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
7434
- } else {
7435
- obj[key] = value2;
7436
- }
7437
- return obj;
7438
- }
7439
- function _toPropertyKey$2(arg) {
7440
- var key = _toPrimitive$2(arg, "string");
7441
- return typeof key === "symbol" ? key : String(key);
7442
- }
7443
- function _toPrimitive$2(input, hint) {
7444
- if (typeof input !== "object" || input === null)
7445
- return input;
7446
- var prim = input[Symbol.toPrimitive];
7447
- if (prim !== void 0) {
7448
- var res = prim.call(input, hint || "default");
7449
- if (typeof res !== "object")
7450
- return res;
7410
+ function _defineProperty$2(e, r, t) {
7411
+ return (r = _toPropertyKey$2(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
7412
+ }
7413
+ function _toPropertyKey$2(t) {
7414
+ var i = _toPrimitive$2(t, "string");
7415
+ return "symbol" == typeof i ? i : i + "";
7416
+ }
7417
+ function _toPrimitive$2(t, r) {
7418
+ if ("object" != typeof t || !t)
7419
+ return t;
7420
+ var e = t[Symbol.toPrimitive];
7421
+ if (void 0 !== e) {
7422
+ var i = e.call(t, r || "default");
7423
+ if ("object" != typeof i)
7424
+ return i;
7451
7425
  throw new TypeError("@@toPrimitive must return a primitive value.");
7452
7426
  }
7453
- return (hint === "string" ? String : Number)(input);
7427
+ return ("string" === r ? String : Number)(t);
7454
7428
  }
7455
7429
  class DataBarCellRenderer extends CellRenderer$1 {
7456
7430
  constructor() {
@@ -7804,30 +7778,24 @@ _defineProperty$2(DataBarCellRenderer, "getGradient", memoizeClear$1((width, col
7804
7778
  // Stringify the arguments for memoization. Lets the color arrays be different arrays in memory, but still cache hit
7805
7779
  }));
7806
7780
  const DataBarCellRenderer$1 = DataBarCellRenderer;
7807
- function _defineProperty$1(obj, key, value2) {
7808
- key = _toPropertyKey$1(key);
7809
- if (key in obj) {
7810
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
7811
- } else {
7812
- obj[key] = value2;
7813
- }
7814
- return obj;
7815
- }
7816
- function _toPropertyKey$1(arg) {
7817
- var key = _toPrimitive$1(arg, "string");
7818
- return typeof key === "symbol" ? key : String(key);
7819
- }
7820
- function _toPrimitive$1(input, hint) {
7821
- if (typeof input !== "object" || input === null)
7822
- return input;
7823
- var prim = input[Symbol.toPrimitive];
7824
- if (prim !== void 0) {
7825
- var res = prim.call(input, hint || "default");
7826
- if (typeof res !== "object")
7827
- return res;
7781
+ function _defineProperty$1(e, r, t) {
7782
+ return (r = _toPropertyKey$1(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
7783
+ }
7784
+ function _toPropertyKey$1(t) {
7785
+ var i = _toPrimitive$1(t, "string");
7786
+ return "symbol" == typeof i ? i : i + "";
7787
+ }
7788
+ function _toPrimitive$1(t, r) {
7789
+ if ("object" != typeof t || !t)
7790
+ return t;
7791
+ var e = t[Symbol.toPrimitive];
7792
+ if (void 0 !== e) {
7793
+ var i = e.call(t, r || "default");
7794
+ if ("object" != typeof i)
7795
+ return i;
7828
7796
  throw new TypeError("@@toPrimitive must return a primitive value.");
7829
7797
  }
7830
- return (hint === "string" ? String : Number)(input);
7798
+ return ("string" === r ? String : Number)(t);
7831
7799
  }
7832
7800
  class TextCellRenderer extends CellRenderer$1 {
7833
7801
  constructor() {
@@ -8012,30 +7980,24 @@ class TextCellRenderer extends CellRenderer$1 {
8012
7980
  */
8013
7981
  }
8014
7982
  const TextCellRenderer$1 = TextCellRenderer;
8015
- function _defineProperty(obj, key, value2) {
8016
- key = _toPropertyKey(key);
8017
- if (key in obj) {
8018
- Object.defineProperty(obj, key, { value: value2, enumerable: true, configurable: true, writable: true });
8019
- } else {
8020
- obj[key] = value2;
8021
- }
8022
- return obj;
8023
- }
8024
- function _toPropertyKey(arg) {
8025
- var key = _toPrimitive(arg, "string");
8026
- return typeof key === "symbol" ? key : String(key);
8027
- }
8028
- function _toPrimitive(input, hint) {
8029
- if (typeof input !== "object" || input === null)
8030
- return input;
8031
- var prim = input[Symbol.toPrimitive];
8032
- if (prim !== void 0) {
8033
- var res = prim.call(input, hint || "default");
8034
- if (typeof res !== "object")
8035
- return res;
7983
+ function _defineProperty(e, r, t) {
7984
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e;
7985
+ }
7986
+ function _toPropertyKey(t) {
7987
+ var i = _toPrimitive(t, "string");
7988
+ return "symbol" == typeof i ? i : i + "";
7989
+ }
7990
+ function _toPrimitive(t, r) {
7991
+ if ("object" != typeof t || !t)
7992
+ return t;
7993
+ var e = t[Symbol.toPrimitive];
7994
+ if (void 0 !== e) {
7995
+ var i = e.call(t, r || "default");
7996
+ if ("object" != typeof i)
7997
+ return i;
8036
7998
  throw new TypeError("@@toPrimitive must return a primitive value.");
8037
7999
  }
8038
- return (hint === "string" ? String : Number)(input);
8000
+ return ("string" === r ? String : Number)(t);
8039
8001
  }
8040
8002
  class GridRenderer {
8041
8003
  constructor() {
@@ -9023,7 +8985,8 @@ class GridRenderer {
9023
8985
  var columnIndex = startIndex;
9024
8986
  while (columnIndex <= endIndex) {
9025
8987
  var {
9026
- columnCount
8988
+ columnCount,
8989
+ calculatedColumnWidths
9027
8990
  } = metrics;
9028
8991
  var modelColumn = getOrThrow(modelColumns, columnIndex);
9029
8992
  var columnGroupName = model.textForColumnHeader(modelColumn, depth);
@@ -9033,23 +8996,23 @@ class GridRenderer {
9033
8996
  if (columnGroupName != null) {
9034
8997
  var prevColumnIndex = columnIndex - 1;
9035
8998
  while (prevColumnIndex >= 0 && (columnGroupRight - columnGroupLeft < visibleWidth || columnGroupLeft > minX)) {
9036
- var _modelColumns$get, _ref3, _userColumnWidths$get;
8999
+ var _modelColumns$get, _ref3, _ref4, _userColumnWidths$get;
9037
9000
  var prevModelIndex = (_modelColumns$get = modelColumns.get(prevColumnIndex)) !== null && _modelColumns$get !== void 0 ? _modelColumns$get : GridUtils.getModelIndex(prevColumnIndex, movedColumns);
9038
9001
  if (prevModelIndex == null || model.textForColumnHeader(prevModelIndex, depth) !== columnGroupName) {
9039
9002
  break;
9040
9003
  }
9041
- var prevColumnWidth = (_ref3 = (_userColumnWidths$get = userColumnWidths.get(prevModelIndex)) !== null && _userColumnWidths$get !== void 0 ? _userColumnWidths$get : allColumnWidths.get(prevColumnIndex)) !== null && _ref3 !== void 0 ? _ref3 : columnWidth;
9004
+ var prevColumnWidth = (_ref3 = (_ref4 = (_userColumnWidths$get = userColumnWidths.get(prevModelIndex)) !== null && _userColumnWidths$get !== void 0 ? _userColumnWidths$get : allColumnWidths.get(prevColumnIndex)) !== null && _ref4 !== void 0 ? _ref4 : calculatedColumnWidths.get(prevModelIndex)) !== null && _ref3 !== void 0 ? _ref3 : columnWidth;
9042
9005
  columnGroupLeft -= prevColumnWidth;
9043
9006
  prevColumnIndex -= 1;
9044
9007
  }
9045
9008
  var nextColumnIndex = columnIndex + 1;
9046
9009
  while (nextColumnIndex < columnCount && (columnGroupRight - columnGroupLeft < visibleWidth || columnGroupRight < maxX)) {
9047
- var _modelColumns$get2, _ref4, _userColumnWidths$get2;
9010
+ var _modelColumns$get2, _ref5, _userColumnWidths$get2;
9048
9011
  var nextModelIndex = (_modelColumns$get2 = modelColumns.get(nextColumnIndex)) !== null && _modelColumns$get2 !== void 0 ? _modelColumns$get2 : GridUtils.getModelIndex(nextColumnIndex, movedColumns);
9049
9012
  if (model.textForColumnHeader(nextModelIndex, depth) !== columnGroupName) {
9050
9013
  break;
9051
9014
  }
9052
- var nextColumnWidth = (_ref4 = (_userColumnWidths$get2 = userColumnWidths.get(nextModelIndex)) !== null && _userColumnWidths$get2 !== void 0 ? _userColumnWidths$get2 : allColumnWidths.get(nextColumnIndex)) !== null && _ref4 !== void 0 ? _ref4 : columnWidth;
9015
+ var nextColumnWidth = (_ref5 = (_userColumnWidths$get2 = userColumnWidths.get(nextModelIndex)) !== null && _userColumnWidths$get2 !== void 0 ? _userColumnWidths$get2 : allColumnWidths.get(nextColumnIndex)) !== null && _ref5 !== void 0 ? _ref5 : columnWidth;
9053
9016
  columnGroupRight += nextColumnWidth;
9054
9017
  nextColumnIndex += 1;
9055
9018
  }
@@ -9960,6 +9923,16 @@ class PivotColumnHeaderGroup extends irisGrid.ColumnHeaderGroup {
9960
9923
  function isCorePlusDh(dh) {
9961
9924
  return "coreplus" in dh;
9962
9925
  }
9926
+ function getKeyColumnGroups(model) {
9927
+ const keyColumnGroups = [];
9928
+ for (let depth = 0; depth <= model.columnHeaderMaxDepth; depth += 1) {
9929
+ const group = model.getColumnHeaderGroup(0, depth);
9930
+ if (isPivotColumnHeaderGroup(group) && group.isKeyColumnGroup) {
9931
+ keyColumnGroups.push(group);
9932
+ }
9933
+ }
9934
+ return keyColumnGroups;
9935
+ }
9963
9936
  const GRAND_TOTALS_GROUP_NAME = "Grand Total";
9964
9937
  const TOTALS_GROUP_NAME = "Total";
9965
9938
  const ROOT_DEPTH = 2;
@@ -9975,29 +9948,34 @@ function makeColumn({
9975
9948
  type,
9976
9949
  index,
9977
9950
  description,
9951
+ isFilterable = false,
9978
9952
  isSortable = false,
9979
9953
  depth = ROOT_DEPTH,
9980
9954
  hasChildren = false,
9981
- isExpanded = false
9955
+ isExpanded = false,
9956
+ isProxy = false,
9957
+ filter = () => {
9958
+ throw new Error("Filter not implemented for virtual column");
9959
+ },
9960
+ sort = () => {
9961
+ throw new Error("Sort not implemented for virtual column");
9962
+ }
9982
9963
  }) {
9983
9964
  return {
9984
9965
  name,
9985
9966
  displayName,
9986
9967
  type,
9987
9968
  isPartitionColumn: false,
9969
+ isFilterable,
9988
9970
  isSortable,
9989
- isProxy: false,
9971
+ isProxy,
9990
9972
  description,
9991
9973
  index,
9992
9974
  depth,
9993
9975
  hasChildren,
9994
9976
  isExpanded,
9995
- filter: () => {
9996
- throw new Error("Filter not implemented for virtual column");
9997
- },
9998
- sort: () => {
9999
- throw new Error("Sort not implemented for virtual column");
10000
- },
9977
+ filter,
9978
+ sort,
10001
9979
  formatColor: () => {
10002
9980
  throw new Error("Color not implemented for virtual column");
10003
9981
  },
@@ -10030,7 +10008,7 @@ function makeColumnGroupName(keys2, columnSources, depth) {
10030
10008
  function makeValueSourceColumnName(columnName, valueSource) {
10031
10009
  return `${columnName}/${valueSource.name}`;
10032
10010
  }
10033
- function makeExpandableDisplayColumn(snapshotDim, valueSource, originalIndex, offset) {
10011
+ function makeColumnFromSnapshot(snapshotDim, valueSource, originalIndex, offset) {
10034
10012
  const keys2 = snapshotDim.getKeys(originalIndex);
10035
10013
  const depth = snapshotDim.getDepth(originalIndex);
10036
10014
  const hasChildren = snapshotDim.hasChildren(originalIndex);
@@ -10052,7 +10030,7 @@ function makeExpandableDisplayColumn(snapshotDim, valueSource, originalIndex, of
10052
10030
  hasChildren
10053
10031
  });
10054
10032
  }
10055
- function makePlaceholderDisplayColumn(valueSource, originalIndex, offset) {
10033
+ function makePlaceholderColumn(valueSource, originalIndex, offset) {
10056
10034
  return makeColumn({
10057
10035
  name: makePlaceholderColumnName(originalIndex, valueSource),
10058
10036
  displayName: "",
@@ -10063,21 +10041,32 @@ function makePlaceholderDisplayColumn(valueSource, originalIndex, offset) {
10063
10041
  hasChildren: false
10064
10042
  });
10065
10043
  }
10066
- function makeRowSourceColumn(source, index) {
10044
+ function makeColumnFromSource(source, index) {
10067
10045
  const { name, type, isSortable, description } = source;
10068
- return makeColumn({ name, type, index, isSortable, description });
10046
+ const isFilterable = true;
10047
+ return makeColumn({
10048
+ name,
10049
+ type,
10050
+ index,
10051
+ isFilterable,
10052
+ isSortable,
10053
+ description,
10054
+ filter: source.filter.bind(source),
10055
+ sort: source.sort.bind(source)
10056
+ });
10069
10057
  }
10070
10058
  function checkColumnsChanged(prevColumns, newColumns) {
10071
10059
  return prevColumns.length !== newColumns.length || prevColumns.some((col, i) => col.name !== newColumns[i].name);
10072
10060
  }
10073
- function getKeyColumnGroups(columnSources, rowSources) {
10061
+ function makeKeyColumnGroups(columnSources, rowSources, includeGroupColumn) {
10062
+ const groupName = includeGroupColumn ? ["__GROUP__"] : [];
10074
10063
  const groups = columnSources.length === 0 ? [
10075
10064
  new PivotColumnHeaderGroup({
10076
10065
  name: "/",
10077
10066
  displayName: "",
10078
10067
  // For empty row sources we will render a "dead column"
10079
10068
  // or a Groups column, depending on the table settings
10080
- children: rowSources.map((c) => c.name),
10069
+ children: [...groupName, ...rowSources.map((c) => c.name)],
10081
10070
  childIndexes: [],
10082
10071
  isKeyColumnGroup: true,
10083
10072
  depth: 1,
@@ -10087,7 +10076,7 @@ function getKeyColumnGroups(columnSources, rowSources) {
10087
10076
  (source, i) => new PivotColumnHeaderGroup({
10088
10077
  name: source.name,
10089
10078
  displayName: source.name,
10090
- children: i === columnSources.length - 1 ? rowSources.map((c) => c.name) : [columnSources[i + 1].name],
10079
+ children: i === columnSources.length - 1 ? [...groupName, ...rowSources.map((c) => c.name)] : [columnSources[i + 1].name],
10091
10080
  childIndexes: [],
10092
10081
  isKeyColumnGroup: true,
10093
10082
  depth: columnSources.length - i,
@@ -10099,7 +10088,7 @@ function getKeyColumnGroups(columnSources, rowSources) {
10099
10088
  []
10100
10089
  ) : groups;
10101
10090
  }
10102
- function getTotalsColumnGroups(columnSources, valueSources, isRootColumnExpanded) {
10091
+ function makeTotalsColumnGroups(columnSources, valueSources, isRootColumnExpanded) {
10103
10092
  const groupName = pluralize(valueSources.length, GRAND_TOTALS_GROUP_NAME);
10104
10093
  return columnSources.length === 0 ? [
10105
10094
  new PivotColumnHeaderGroup({
@@ -10123,7 +10112,7 @@ function getTotalsColumnGroups(columnSources, valueSources, isRootColumnExpanded
10123
10112
  })
10124
10113
  );
10125
10114
  }
10126
- function getSnapshotColumnGroups(snapshotColumns, columnSources, valueSources, formatValue) {
10115
+ function makeSnapshotColumnGroups(snapshotColumns, columnSources, valueSources, formatValue) {
10127
10116
  const maxDepth = Math.max(columnSources.length, 1);
10128
10117
  const groupMap = /* @__PURE__ */ new Map();
10129
10118
  const groupName = pluralize(valueSources.length, TOTALS_GROUP_NAME);
@@ -10163,27 +10152,41 @@ function getSnapshotColumnGroups(snapshotColumns, columnSources, valueSources, f
10163
10152
  }
10164
10153
  return [...groupMap.values()];
10165
10154
  }
10166
- function getColumnGroups(pivotTable, snapshotColumns, isRootColumnExpanded = true, formatValue = (v, t) => String(v)) {
10155
+ function makeColumnGroups(pivotTable, snapshotColumns, isRootColumnExpanded = true, includeGroupColumn = false, formatValue = (v, t) => String(v)) {
10167
10156
  const virtualColumnGroups = [
10168
- ...getKeyColumnGroups(pivotTable.columnSources, pivotTable.rowSources),
10169
- ...getTotalsColumnGroups(
10157
+ ...makeKeyColumnGroups(
10158
+ pivotTable.columnSources,
10159
+ pivotTable.rowSources,
10160
+ includeGroupColumn
10161
+ ),
10162
+ ...makeTotalsColumnGroups(
10170
10163
  pivotTable.columnSources,
10171
10164
  pivotTable.valueSources,
10172
10165
  isRootColumnExpanded
10173
10166
  )
10174
10167
  ];
10175
- const snapshotColumnGroups = snapshotColumns == null ? [] : getSnapshotColumnGroups(
10168
+ const snapshotColumnGroups = snapshotColumns == null ? [] : makeSnapshotColumnGroups(
10176
10169
  snapshotColumns,
10177
10170
  pivotTable.columnSources,
10178
10171
  pivotTable.valueSources
10179
10172
  );
10180
10173
  return [...virtualColumnGroups, ...snapshotColumnGroups];
10181
10174
  }
10182
- const log$3 = Log.module("@deephaven/js-plugin-pivot/IrisGridPivotModel");
10175
+ const log$4 = Log.module("@deephaven/js-plugin-pivot/IrisGridPivotModel");
10183
10176
  const SET_VIEWPORT_THROTTLE = 150;
10184
10177
  const APPLY_VIEWPORT_THROTTLE = 0;
10185
10178
  const ROW_BUFFER_PAGES = 1;
10186
10179
  const COLUMN_BUFFER_PAGES = 1;
10180
+ const VirtualGroupColumn = Object.freeze(
10181
+ makeColumn({
10182
+ name: "__GROUP__",
10183
+ displayName: "Group",
10184
+ type: "java.lang.String",
10185
+ index: 0,
10186
+ depth: 2,
10187
+ isProxy: true
10188
+ })
10189
+ );
10187
10190
  function isIrisGridPivotModel(model) {
10188
10191
  return typeof model === "object" && model !== null && "pivotTable" in model && "keyColumns" in model && "expandAll" in model && "collapseAll" in model && "hasExpandableRows" in model && "hasExpandableColumns" in model;
10189
10192
  }
@@ -10194,13 +10197,9 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10194
10197
  }
10195
10198
  super(dh);
10196
10199
  __publicField(this, "pivotTable");
10197
- __publicField(this, "keyColumns");
10200
+ __publicField(this, "showExtraGroupCol", true);
10198
10201
  __publicField(this, "_layoutHints");
10199
- __publicField(this, "_columnHeaderGroupMap", /* @__PURE__ */ new Map());
10200
- __publicField(this, "columnHeaderParentMap", /* @__PURE__ */ new Map());
10201
- __publicField(this, "_columnHeaderMaxDepth", null);
10202
- __publicField(this, "_columnHeaderGroups", []);
10203
- __publicField(this, "_isColumnHeaderGroupsInitialized", false);
10202
+ __publicField(this, "_sorts", EMPTY_ARRAY);
10204
10203
  __publicField(this, "viewportData", null);
10205
10204
  __publicField(this, "formattedStringData", []);
10206
10205
  __publicField(this, "snapshotColumns", null);
@@ -10217,73 +10216,80 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10217
10216
  __publicField(this, "dh");
10218
10217
  __publicField(this, "getCachedColumns", memoizeOne(
10219
10218
  (snapshotColumns, virtualColumns, valueSources) => {
10219
+ const columns = [];
10220
+ this.pivotTable.columnSources.forEach((source, col) => {
10221
+ const index = -this.pivotTable.columnSources.length + col;
10222
+ columns[index] = makeColumnFromSource(source, index);
10223
+ });
10224
+ columns.push(...virtualColumns);
10220
10225
  if (snapshotColumns == null) {
10221
- log$3.debug2("getCachedColumns", {
10222
- snapshotColumns,
10223
- valueSources
10224
- });
10225
- return virtualColumns;
10226
+ return columns;
10226
10227
  }
10227
- const columns = [...virtualColumns];
10228
10228
  for (let i = 0; i < snapshotColumns.totalCount; i += 1) {
10229
10229
  const isColumnInViewport = i >= snapshotColumns.offset && i < snapshotColumns.offset + snapshotColumns.count;
10230
10230
  for (let v = 0; v < valueSources.length; v += 1) {
10231
10231
  columns.push(
10232
- isColumnInViewport ? makeExpandableDisplayColumn(
10232
+ isColumnInViewport ? makeColumnFromSnapshot(
10233
10233
  snapshotColumns,
10234
10234
  valueSources[v],
10235
10235
  i,
10236
10236
  virtualColumns.length
10237
- ) : makePlaceholderDisplayColumn(
10238
- valueSources[v],
10239
- i,
10240
- virtualColumns.length
10241
- )
10237
+ ) : makePlaceholderColumn(valueSources[v], i, virtualColumns.length)
10242
10238
  );
10243
10239
  }
10244
10240
  }
10245
- log$3.debug2("getCachedColumns", {
10246
- snapshotColumns,
10247
- valueSources,
10248
- columns: columns.map(({ name }) => name)
10249
- });
10250
10241
  return columns;
10251
10242
  }
10252
10243
  ));
10253
10244
  __publicField(this, "getCachedTotalsColumns", memoizeOne(
10254
- (pivotTable, valueSources) => valueSources.map(
10245
+ (pivotTable, valueSources, groupColumn) => valueSources.map(
10255
10246
  (source, col) => makeColumn({
10256
10247
  name: makeGrandTotalColumnName(source),
10257
10248
  displayName: source.name,
10258
10249
  description: source.description,
10259
10250
  type: source.type,
10260
- index: pivotTable.rowSources.length + col,
10251
+ index: pivotTable.rowSources.length + col + (groupColumn == null ? 0 : 1),
10261
10252
  depth: 2,
10262
10253
  isExpanded: true,
10263
10254
  hasChildren: true
10264
10255
  })
10265
10256
  )
10266
10257
  ));
10258
+ __publicField(this, "getCachedKeyColumns", memoizeOne(
10259
+ (pivotTable, groupColumn) => pivotTable.rowSources.map(
10260
+ (source, index) => makeColumnFromSource(source, index + (groupColumn == null ? 0 : 1))
10261
+ )
10262
+ ));
10267
10263
  __publicField(this, "getCachedVirtualColumns", memoizeOne(
10268
- (keyColumns, totalsColumns) => [...keyColumns, ...totalsColumns]
10264
+ (groupColumn, keyColumns, totalsColumns) => groupColumn ? [groupColumn, ...keyColumns, ...totalsColumns] : [...keyColumns, ...totalsColumns]
10269
10265
  ));
10270
10266
  /**
10271
- * Get the cached column header groups.
10267
+ * Get the cached header groups data, including groups array, max depth, parent map, and group map.
10272
10268
  * Returns groups for the key columns, totals, and the snapshot column in the current viewport.
10273
10269
  * Placeholder columns are not included in the groups.
10274
10270
  */
10275
- __publicField(this, "getCachedColumnHeaderGroups", memoizeOne(
10276
- (snapshotColumns, isRootColumnExpanded, formatValue) => getColumnGroups(
10277
- this.pivotTable,
10278
- snapshotColumns,
10279
- isRootColumnExpanded,
10280
- formatValue
10281
- )
10271
+ __publicField(this, "getCachedParsedColumnHeaderData", memoizeOne(
10272
+ (snapshotColumns, groupColumn, formatter, isRootColumnExpanded) => {
10273
+ const columnGroups = makeColumnGroups(
10274
+ this.pivotTable,
10275
+ snapshotColumns,
10276
+ isRootColumnExpanded,
10277
+ groupColumn != null,
10278
+ (value2, type) => this.getCachedFormattedString(formatter, value2, type, "")
10279
+ );
10280
+ return irisGrid.IrisGridUtils.parseColumnHeaderGroups(
10281
+ this,
10282
+ columnGroups,
10283
+ (args) => new PivotColumnHeaderGroup(args)
10284
+ );
10285
+ }
10282
10286
  ));
10283
10287
  __publicField(this, "getColumnIndicesByNameMap", memoizeOne(
10284
10288
  (columns) => {
10285
10289
  const indices = /* @__PURE__ */ new Map();
10286
- columns.forEach(({ name }, i) => indices.set(name, i));
10290
+ Object.entries(columns).forEach(
10291
+ ([i, { name }]) => indices.set(name, Number(i))
10292
+ );
10287
10293
  return indices;
10288
10294
  }
10289
10295
  ));
@@ -10316,7 +10322,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10316
10322
  return this.dh.RangeSet.ofRange(0, totalColumnCount);
10317
10323
  }
10318
10324
  if (viewportColumns.length === 0) {
10319
- log$3.debug(
10325
+ log$4.debug(
10320
10326
  "Empty viewport columns, returning minimal range",
10321
10327
  viewportColumns
10322
10328
  );
@@ -10339,7 +10345,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10339
10345
  ) ?? 0
10340
10346
  );
10341
10347
  if (minIndex > maxIndex) {
10342
- log$3.warn(
10348
+ log$4.warn(
10343
10349
  "Invalid column range, minIndex > maxIndex",
10344
10350
  viewportColumns,
10345
10351
  minIndex,
@@ -10359,12 +10365,12 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10359
10365
  __publicField(this, "setViewport", lodash_throttle(
10360
10366
  (top, bottom, columns) => {
10361
10367
  if (bottom < top) {
10362
- log$3.error("Invalid viewport", top, bottom);
10368
+ log$4.error("Invalid viewport", top, bottom);
10363
10369
  return;
10364
10370
  }
10365
10371
  const { viewport } = this;
10366
10372
  if (viewport != null && viewport.top === top && viewport.bottom === bottom && viewport.columns === columns) {
10367
- log$3.debug2("Ignoring duplicate viewport", viewport);
10373
+ log$4.debug2("Ignoring duplicate viewport", viewport);
10368
10374
  return;
10369
10375
  }
10370
10376
  this.viewport = {
@@ -10372,7 +10378,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10372
10378
  bottom,
10373
10379
  columns
10374
10380
  };
10375
- log$3.debug2("setViewport", this.viewport);
10381
+ log$4.debug2("setViewport", this.viewport);
10376
10382
  this.applyViewport();
10377
10383
  },
10378
10384
  SET_VIEWPORT_THROTTLE
@@ -10393,7 +10399,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10393
10399
  if (!this.viewport) {
10394
10400
  return;
10395
10401
  }
10396
- log$3.debug2("applyViewport", this.viewport);
10402
+ log$4.debug2("applyViewport", this.viewport);
10397
10403
  const { top, bottom, columns } = this.viewport;
10398
10404
  const [viewportTop, viewportBottom] = this.getCachedViewportRowRange(
10399
10405
  top,
@@ -10415,9 +10421,6 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10415
10421
  this.snapshotValueSources = pivotTable.valueSources;
10416
10422
  this.rowBufferPages = config.rowBufferPages ?? ROW_BUFFER_PAGES;
10417
10423
  this.columnBufferPages = config.columnBufferPages ?? COLUMN_BUFFER_PAGES;
10418
- this.keyColumns = pivotTable.rowSources.map(
10419
- (source, col) => makeRowSourceColumn(source, col)
10420
- );
10421
10424
  this._layoutHints = {
10422
10425
  backColumns: [],
10423
10426
  hiddenColumns: [],
@@ -10430,14 +10433,45 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10430
10433
  };
10431
10434
  }
10432
10435
  get filter() {
10433
- return EMPTY_ARRAY;
10436
+ return this.pivotTable.filter;
10434
10437
  }
10435
- set filter(_) {
10438
+ set filter(filters) {
10439
+ log$4.debug2("Setting filter on pivot table", filters);
10440
+ this.pivotTable.applyFilter(filters);
10441
+ this.applyViewport();
10436
10442
  }
10437
- get sort() {
10438
- return EMPTY_ARRAY;
10443
+ hydratePivotSort(sort) {
10444
+ const sourceIndex = this.getColumnIndexByName(sort.column.name);
10445
+ const source = this.columns[sourceIndex ?? -1];
10446
+ return (source == null ? void 0 : source.sort()[sort.direction === "ASC" ? "asc" : "desc"]()) ?? null;
10439
10447
  }
10440
- set sort(_) {
10448
+ get sort() {
10449
+ return this._sorts ?? EMPTY_ARRAY;
10450
+ }
10451
+ set sort(sorts) {
10452
+ log$4.debug("Setting sorts on pivot table", sorts);
10453
+ this._sorts = sorts;
10454
+ const columnBySorts = [];
10455
+ const rowBySorts = [];
10456
+ sorts.forEach((s) => {
10457
+ const sort = this.hydratePivotSort(s);
10458
+ if (sort == null) {
10459
+ log$4.warn(`Cannot hydrate sort for source: ${s.column.name}`, s);
10460
+ return;
10461
+ }
10462
+ const index = this.getColumnIndexByName(sort.name);
10463
+ if (index == null) {
10464
+ log$4.warn(`Cannot find index for source: ${s.column.name}`, s);
10465
+ return;
10466
+ }
10467
+ if (index < 0) {
10468
+ columnBySorts.push(sort);
10469
+ } else {
10470
+ rowBySorts.push(sort);
10471
+ }
10472
+ });
10473
+ this.pivotTable.applyRowSort(rowBySorts);
10474
+ this.pivotTable.applyColumnSort(columnBySorts);
10441
10475
  }
10442
10476
  get customColumns() {
10443
10477
  return EMPTY_ARRAY;
@@ -10482,68 +10516,69 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10482
10516
  async export() {
10483
10517
  throw new Error("Method not implemented.");
10484
10518
  }
10519
+ get showExtraGroupColumn() {
10520
+ return this.showExtraGroupCol;
10521
+ }
10522
+ set showExtraGroupColumn(showExtraGroupCol) {
10523
+ if (showExtraGroupCol === this.showExtraGroupCol) {
10524
+ return;
10525
+ }
10526
+ this.showExtraGroupCol = showExtraGroupCol;
10527
+ this.dispatchEvent(
10528
+ new EventShimCustomEvent(irisGrid.IrisGridModel.EVENT.COLUMNS_CHANGED, {
10529
+ detail: this.columns
10530
+ })
10531
+ );
10532
+ }
10533
+ get groupColumn() {
10534
+ return this.pivotTable.rowSources.length !== 1 && this.showExtraGroupCol ? VirtualGroupColumn : null;
10535
+ }
10536
+ get keyColumns() {
10537
+ return this.getCachedKeyColumns(this.pivotTable, this.groupColumn);
10538
+ }
10485
10539
  get totalsColumns() {
10486
10540
  return this.getCachedTotalsColumns(
10487
10541
  this.pivotTable,
10488
- this.snapshotValueSources
10542
+ this.snapshotValueSources,
10543
+ this.groupColumn
10489
10544
  );
10490
10545
  }
10491
10546
  get virtualColumns() {
10492
- return this.getCachedVirtualColumns(this.keyColumns, this.totalsColumns);
10547
+ return this.getCachedVirtualColumns(
10548
+ this.groupColumn,
10549
+ this.keyColumns,
10550
+ this.totalsColumns
10551
+ );
10493
10552
  }
10494
- get initialColumnHeaderGroups() {
10495
- const groups = this.getCachedColumnHeaderGroups(
10553
+ getParsedColumnHeaderData() {
10554
+ return this.getCachedParsedColumnHeaderData(
10496
10555
  this.snapshotColumns,
10497
- this.isRootColumnExpanded,
10498
- (value2, type) => (
10499
- // Ignore name based formatting, pass empty column name
10500
- this.getCachedFormattedString(this.formatter, value2, type, "")
10501
- )
10556
+ this.groupColumn,
10557
+ this.formatter,
10558
+ this.isRootColumnExpanded
10502
10559
  );
10503
- log$3.debug2("initialColumnHeaderGroups", groups);
10504
- return groups;
10560
+ }
10561
+ get initialColumnHeaderGroups() {
10562
+ return this.columnHeaderGroups;
10505
10563
  }
10506
10564
  get columnHeaderMaxDepth() {
10507
- return this._columnHeaderMaxDepth ?? 1;
10565
+ const { maxDepth } = this.getParsedColumnHeaderData();
10566
+ return maxDepth;
10508
10567
  }
10509
- set columnHeaderMaxDepth(depth) {
10510
- this._columnHeaderMaxDepth = depth;
10568
+ get columnHeaderParentMap() {
10569
+ const { parentMap } = this.getParsedColumnHeaderData();
10570
+ return parentMap;
10511
10571
  }
10512
10572
  get columnHeaderGroupMap() {
10513
- this.initializeColumnHeaderGroups();
10514
- return this._columnHeaderGroupMap;
10573
+ const { groupMap } = this.getParsedColumnHeaderData();
10574
+ return groupMap;
10515
10575
  }
10516
10576
  get columnHeaderGroups() {
10517
- this.initializeColumnHeaderGroups();
10518
- return this._columnHeaderGroups;
10577
+ const { groups } = this.getParsedColumnHeaderData();
10578
+ return groups;
10519
10579
  }
10520
10580
  set columnHeaderGroups(_groups) {
10521
10581
  }
10522
- setInternalColumnHeaderGroups(groups) {
10523
- if (groups === this._columnHeaderGroups) {
10524
- return;
10525
- }
10526
- const {
10527
- groups: newGroups,
10528
- maxDepth,
10529
- parentMap,
10530
- groupMap
10531
- } = irisGrid.IrisGridUtils.parseColumnHeaderGroups(
10532
- this,
10533
- groups,
10534
- (args) => new PivotColumnHeaderGroup(args)
10535
- );
10536
- this._columnHeaderGroups = newGroups;
10537
- this.columnHeaderMaxDepth = maxDepth;
10538
- this.columnHeaderParentMap = parentMap;
10539
- this._columnHeaderGroupMap = groupMap;
10540
- this._isColumnHeaderGroupsInitialized = true;
10541
- }
10542
- initializeColumnHeaderGroups() {
10543
- if (!this._isColumnHeaderGroupsInitialized) {
10544
- this.setInternalColumnHeaderGroups(this.initialColumnHeaderGroups);
10545
- }
10546
- }
10547
10582
  textForColumnHeader(x, depth = 0) {
10548
10583
  const header = this.columnAtDepth(x, depth);
10549
10584
  if (isPivotColumnHeaderGroup(header)) {
@@ -10602,6 +10637,10 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10602
10637
  get initialMovedColumns() {
10603
10638
  return EMPTY_ARRAY;
10604
10639
  }
10640
+ /**
10641
+ * Get the columns in the pivot model.
10642
+ * Returned array includes column sources with negative indexes.
10643
+ */
10605
10644
  get columns() {
10606
10645
  return this.getCachedColumns(
10607
10646
  this.snapshotColumns,
@@ -10628,10 +10667,12 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10628
10667
  return false;
10629
10668
  }
10630
10669
  isFilterable(columnIndex) {
10631
- return false;
10670
+ var _a;
10671
+ return ((_a = this.columns[columnIndex]) == null ? void 0 : _a.isFilterable) ?? false;
10632
10672
  }
10633
10673
  isColumnSortable(columnIndex) {
10634
- return false;
10674
+ var _a;
10675
+ return ((_a = this.columns[columnIndex]) == null ? void 0 : _a.isSortable) ?? false;
10635
10676
  }
10636
10677
  get isTotalsAvailable() {
10637
10678
  return false;
@@ -10683,7 +10724,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10683
10724
  }
10684
10725
  }
10685
10726
  handleModelEvent(event) {
10686
- log$3.debug2("handleModelEvent", event);
10727
+ log$4.debug2("handleModelEvent", event);
10687
10728
  const { detail, type } = event;
10688
10729
  this.dispatchEvent(new EventShimCustomEvent(type, { detail }));
10689
10730
  }
@@ -10697,10 +10738,10 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10697
10738
  this.formattedStringData = [];
10698
10739
  this.viewportData = this.extractSnapshotData(snapshot);
10699
10740
  this.updatePendingExpandCollapseState();
10700
- this.setInternalColumnHeaderGroups(this.initialColumnHeaderGroups);
10701
- log$3.debug2("Pivot updated", {
10741
+ log$4.debug2("Pivot updated", {
10702
10742
  columns: this.columns,
10703
- snapshot: this.snapshotColumns,
10743
+ snapshot,
10744
+ snapshotColumns: this.snapshotColumns,
10704
10745
  viewport: (_a = this.viewportData) == null ? void 0 : _a.rowTotalCount,
10705
10746
  columnCount: this.columnCount,
10706
10747
  rowCount: this.rowCount
@@ -10712,7 +10753,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10712
10753
  })
10713
10754
  );
10714
10755
  } else {
10715
- log$3.debug2("Pivot columns did not change in the update");
10756
+ log$4.debug2("Pivot columns did not change in the update");
10716
10757
  }
10717
10758
  this.dispatchEvent(new EventShimCustomEvent(irisGrid.IrisGridModel.EVENT.UPDATED));
10718
10759
  }
@@ -10751,10 +10792,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10751
10792
  const keyData = /* @__PURE__ */ new Map();
10752
10793
  const totalsData = /* @__PURE__ */ new Map();
10753
10794
  for (let c = 0; c < keys2.length; c += 1) {
10754
- keyData.set(c, {
10755
- // Only render the value for the deepest level
10756
- value: c === depth - 1 ? keys2[c] : void 0
10757
- });
10795
+ keyData.set(c, { value: keys2[c] });
10758
10796
  }
10759
10797
  for (let v = 0; v < snapshot.valueSources.length; v += 1) {
10760
10798
  totalsData.set(v, {
@@ -10865,7 +10903,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10865
10903
  }
10866
10904
  }
10867
10905
  close() {
10868
- log$3.debug("close");
10906
+ log$4.debug("close");
10869
10907
  this.pivotTable.close();
10870
10908
  }
10871
10909
  get formatter() {
@@ -10957,49 +10995,41 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
10957
10995
  return true;
10958
10996
  }
10959
10997
  expandAllColumns() {
10960
- log$3.debug("expandAllColumns");
10998
+ log$4.debug("expandAllColumns");
10961
10999
  this.setColumnExpanded(this.keyColumns.length, true, true);
10962
11000
  }
10963
11001
  collapseAllColumns() {
10964
- log$3.debug("collapseAllColumns");
11002
+ log$4.debug("collapseAllColumns");
10965
11003
  this.setColumnExpanded(this.keyColumns.length, false, true);
10966
11004
  }
10967
11005
  isColumnExpandable(x, depth) {
10968
- var _a, _b;
10969
- log$3.debug2("isColumnExpandable", {
10970
- x,
10971
- depth,
10972
- name: (_a = this.columns[x]) == null ? void 0 : _a.name,
10973
- v: this.virtualColumns,
10974
- cC: this.columnCount,
10975
- c: this.columns
10976
- });
10977
- if (x >= this.keyColumns.length && x < this.virtualColumns.length) {
11006
+ var _a;
11007
+ if (this.isGrandTotalsColumn(x)) {
10978
11008
  return !this.isRootColumnExpanded || this.columns.length > this.virtualColumns.length;
10979
11009
  }
10980
11010
  if (x < this.keyColumns.length) {
10981
11011
  return false;
10982
11012
  }
10983
- return ((_b = this.columns[x]) == null ? void 0 : _b.hasChildren) ?? false;
11013
+ return ((_a = this.columns[x]) == null ? void 0 : _a.hasChildren) ?? false;
11014
+ }
11015
+ isGrandTotalsColumn(x) {
11016
+ const totalsStartIndex = this.keyColumns.length + (this.groupColumn == null ? 0 : 1);
11017
+ return x >= totalsStartIndex && x < this.virtualColumns.length;
10984
11018
  }
10985
11019
  isColumnExpanded(x) {
10986
11020
  var _a;
10987
- if (x >= this.keyColumns.length && x < this.virtualColumns.length) {
11021
+ if (this.isGrandTotalsColumn(x)) {
10988
11022
  return this.isRootColumnExpanded;
10989
11023
  }
10990
11024
  return ((_a = this.columns[x]) == null ? void 0 : _a.isExpanded) ?? false;
10991
11025
  }
10992
11026
  setColumnExpanded(x, isExpanded, expandDescendants = false) {
10993
- var _a;
10994
- log$3.debug2("[0] setColumnExpanded", {
11027
+ log$4.debug2("setColumnExpanded", {
10995
11028
  x,
10996
11029
  isExpanded,
10997
- name: (_a = this.columns[x]) == null ? void 0 : _a.name,
10998
- v: this.virtualColumns,
10999
- cC: this.columnCount,
11000
- c: this.columns
11030
+ expandDescendants
11001
11031
  });
11002
- if (x >= this.keyColumns.length && x < this.virtualColumns.length) {
11032
+ if (this.isGrandTotalsColumn(x)) {
11003
11033
  this.pivotTable.setRootColumnExpanded(isExpanded, expandDescendants);
11004
11034
  this.isRootColumnExpanded = isExpanded;
11005
11035
  return;
@@ -11065,15 +11095,27 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
11065
11095
  this.formattedStringData[x][y] = text;
11066
11096
  }
11067
11097
  dataForCell(x, y) {
11068
- var _a, _b, _c;
11098
+ var _a, _b, _c, _d, _e, _f;
11069
11099
  const keyCount = this.keyColumns.length;
11070
- if (x < keyCount) {
11071
- return (_a = this.row(y)) == null ? void 0 : _a.keyData.get(x);
11100
+ const groupOffset = this.groupColumn == null ? 0 : 1;
11101
+ if (groupOffset === 1 && x === 0) {
11102
+ const rowDepth = ((_a = this.row(y)) == null ? void 0 : _a.depth) ?? 2;
11103
+ return y === 0 ? (
11104
+ // Empty value for the group cell in the totals row
11105
+ { value: "" }
11106
+ ) : {
11107
+ // Render all key values except the last one in the group column
11108
+ // to match the Rollup UI
11109
+ value: rowDepth < keyCount ? (_c = (_b = this.row(y)) == null ? void 0 : _b.keyData.get(rowDepth - 1)) == null ? void 0 : _c.value : ""
11110
+ };
11111
+ }
11112
+ if (x < keyCount + groupOffset) {
11113
+ return (_d = this.row(y)) == null ? void 0 : _d.keyData.get(x - groupOffset);
11072
11114
  }
11073
11115
  if (x < this.virtualColumns.length) {
11074
- return (_b = this.row(y)) == null ? void 0 : _b.totalsData.get(x - keyCount);
11116
+ return (_e = this.row(y)) == null ? void 0 : _e.totalsData.get(x - keyCount - groupOffset);
11075
11117
  }
11076
- return (_c = this.row(y)) == null ? void 0 : _c.data.get(x - this.virtualColumns.length);
11118
+ return (_f = this.row(y)) == null ? void 0 : _f.data.get(x - this.virtualColumns.length);
11077
11119
  }
11078
11120
  formatForCell(x, y) {
11079
11121
  var _a;
@@ -11116,7 +11158,7 @@ class IrisGridPivotModel extends irisGrid.IrisGridModel {
11116
11158
  this.virtualColumns.length,
11117
11159
  this.snapshotValueSources.length
11118
11160
  );
11119
- log$3.debug2("applyBufferedViewport", {
11161
+ log$4.debug2("applyBufferedViewport", {
11120
11162
  top,
11121
11163
  bottom,
11122
11164
  columns,
@@ -11146,8 +11188,8 @@ function useIrisGridPivotModel(fetch) {
11146
11188
  [model]
11147
11189
  );
11148
11190
  const makeModel = React.useCallback(async () => {
11149
- const pivotWidget = await fetch();
11150
- return new IrisGridPivotModel(dh, pivotWidget);
11191
+ const pivotTable = await fetch();
11192
+ return new IrisGridPivotModel(dh, pivotTable);
11151
11193
  }, [dh, fetch]);
11152
11194
  const reload = React.useCallback(async () => {
11153
11195
  setIsLoading(true);
@@ -11195,6 +11237,22 @@ function useIrisGridPivotModel(fetch) {
11195
11237
  }
11196
11238
  throw new Error("Invalid state");
11197
11239
  }
11240
+ const log$3 = Log.module("@deephaven/js-plugin-pivot/usePivotTableFetch");
11241
+ function usePivotTableFetch(fetch) {
11242
+ const api = jsapiBootstrap.useApi();
11243
+ return React.useCallback(
11244
+ () => fetch().then((widget) => {
11245
+ log$3.debug("Pivot fetch result:", widget);
11246
+ if (!isCorePlusDh(api)) {
11247
+ throw new Error("CorePlus is not available");
11248
+ }
11249
+ const pivotTable = new api.coreplus.pivot.PivotTable(widget);
11250
+ log$3.debug("Created pivot table:", pivotTable);
11251
+ return pivotTable;
11252
+ }),
11253
+ [api, fetch]
11254
+ );
11255
+ }
11198
11256
  class PivotColumnGroupMouseHandler extends GridMouseHandler {
11199
11257
  constructor(irisGrid2) {
11200
11258
  super();
@@ -11238,179 +11296,364 @@ class PivotColumnGroupMouseHandler extends GridMouseHandler {
11238
11296
  onClick(gridPoint, grid, event) {
11239
11297
  const column = this.getColumnGroupFromGridPoint(gridPoint);
11240
11298
  if (column != null && column === this.column && this.isExpandableColumnGroup(column, gridPoint.columnHeaderDepth)) {
11241
- this.irisGrid.toggleExpandColumn(column);
11299
+ this.irisGrid.toggleExpandColumn(
11300
+ column,
11301
+ GridUtils.isModifierKeyDown(event)
11302
+ );
11242
11303
  return true;
11243
11304
  }
11244
11305
  return false;
11245
11306
  }
11246
11307
  }
11247
- function getColumnGroupName(model, modelColumn, depth) {
11248
- var _a;
11249
- return (_a = model.getColumnHeaderGroup(modelColumn, depth ?? 0)) == null ? void 0 : _a.name;
11308
+ function getColumnWidth(column, metrics, themeColumnWidth) {
11309
+ const {
11310
+ firstColumn,
11311
+ allColumnWidths,
11312
+ calculatedColumnWidths,
11313
+ userColumnWidths,
11314
+ treePaddingX
11315
+ } = metrics;
11316
+ const modelColumn = GridUtils.getModelIndex(column, metrics.movedColumns);
11317
+ return userColumnWidths.get(modelColumn) ?? allColumnWidths.get(column) ?? (calculatedColumnWidths.has(modelColumn) ? (calculatedColumnWidths.get(modelColumn) ?? 0) + (column === firstColumn ? treePaddingX : 0) : void 0) ?? themeColumnWidth;
11318
+ }
11319
+ function getColumnHeaderCoordinates(state, group) {
11320
+ const { metrics, theme } = state;
11321
+ const { childIndexes, depth } = group;
11322
+ const firstChildIndex = childIndexes[0];
11323
+ const lastChildIndex = childIndexes[childIndexes.length - 1];
11324
+ if (firstChildIndex == null || lastChildIndex == null) {
11325
+ throw new Error("Group has no child columns");
11326
+ }
11327
+ const { left, right, allColumnXs, allColumnWidths, gridX, gridY } = metrics;
11328
+ const {
11329
+ filterBarHeight,
11330
+ columnHeaderHeight,
11331
+ columnWidth: themeColumnWidth
11332
+ } = theme;
11333
+ const firstVisible = Math.max(left, firstChildIndex);
11334
+ const lastVisible = Math.min(right, lastChildIndex);
11335
+ if (firstVisible > lastChildIndex || lastVisible < firstChildIndex) {
11336
+ return null;
11337
+ }
11338
+ const firstVisibleX = allColumnXs.get(firstVisible);
11339
+ if (firstVisibleX == null) {
11340
+ return null;
11341
+ }
11342
+ let groupX1 = firstVisibleX;
11343
+ for (let i = firstChildIndex; i < firstVisible; i += 1) {
11344
+ groupX1 -= getColumnWidth(i, metrics, themeColumnWidth);
11345
+ }
11346
+ const lastColumnX = allColumnXs.get(lastVisible);
11347
+ const lastColumnWidth = allColumnWidths.get(lastVisible);
11348
+ if (lastColumnX == null || lastColumnWidth == null) {
11349
+ return null;
11350
+ }
11351
+ let groupX2 = lastColumnX + lastColumnWidth;
11352
+ for (let i = lastVisible + 1; i <= lastChildIndex; i += 1) {
11353
+ groupX2 += getColumnWidth(i, metrics, themeColumnWidth);
11354
+ }
11355
+ return {
11356
+ x1: gridX + groupX1,
11357
+ y1: gridY - filterBarHeight - (depth + 1) * columnHeaderHeight,
11358
+ x2: gridX + groupX2,
11359
+ y2: gridY - filterBarHeight - depth * columnHeaderHeight
11360
+ };
11250
11361
  }
11251
- class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11252
- drawColumnHeaders(context, state) {
11253
- const {
11254
- mouseX,
11255
- mouseY,
11256
- theme,
11257
- metrics,
11258
- draggingColumnSeparator,
11259
- isDragging,
11260
- model
11261
- } = state;
11262
- const {
11263
- columnHeaderHeight,
11264
- floatingColumns,
11265
- gridX,
11266
- width,
11267
- visibleColumns,
11268
- allColumnWidths,
11269
- allColumnXs,
11270
- floatingLeftColumnCount,
11271
- floatingLeftWidth,
11272
- floatingRightWidth,
11273
- modelColumns,
11274
- columnHeaderMaxDepth
11275
- } = metrics;
11276
- if (columnHeaderHeight <= 0) {
11277
- return;
11278
- }
11279
- const {
11280
- headerHiddenSeparatorSize,
11281
- headerHiddenSeparatorHoverColor,
11282
- headerSeparatorColor,
11283
- headerSeparatorHoverColor
11284
- } = theme;
11285
- const hiddenSeparatorHeight = columnHeaderHeight * 0.5;
11286
- const hiddenY = columnHeaderHeight * (columnHeaderMaxDepth - 1) + columnHeaderHeight * 0.5 - hiddenSeparatorHeight * 0.5;
11287
- const containsFrozenColumns = floatingLeftColumnCount > 0;
11288
- if (!isExpandableColumnGridModel(model)) {
11289
- throw new Error("Unsupported model type");
11362
+ class IrisGridPivotMetricCalculator extends irisGrid.IrisGridMetricCalculator {
11363
+ constructor() {
11364
+ super(...arguments);
11365
+ // Initialize with null to ensure the first check always triggers reset
11366
+ __publicField(this, "cachedIsFilterBarShown", null);
11367
+ __publicField(this, "getCachedColumnSourceLabelWidth", memoizeOne(
11368
+ (keyColumnGroups, headerHorizontalPadding, maxColumnWidth, state) => {
11369
+ let result = 0;
11370
+ keyColumnGroups.forEach((group) => {
11371
+ const sourceIndex = -group.depth;
11372
+ const width = this.getColumnHeaderGroupWidth(
11373
+ sourceIndex,
11374
+ 0,
11375
+ state,
11376
+ maxColumnWidth
11377
+ );
11378
+ result = Math.max(result, width + headerHorizontalPadding);
11379
+ });
11380
+ return result;
11381
+ }
11382
+ ));
11383
+ }
11384
+ /**
11385
+ * Resets column width caches if filter bar visibility has changed
11386
+ * to adjust for the minimum filter box width.
11387
+ * @param state The current IrisGridPivotMetricState
11388
+ */
11389
+ resetHeaderWidthsIfFilterBarChanged(state) {
11390
+ const { isFilterBarShown } = state;
11391
+ if (this.cachedIsFilterBarShown !== isFilterBarShown) {
11392
+ this.resetCalculatedHeaderGroupWidths();
11290
11393
  }
11291
- context.save();
11292
- this.drawColumnHeadersForRange(
11293
- context,
11394
+ this.cachedIsFilterBarShown = isFilterBarShown;
11395
+ }
11396
+ getColumnHeaderGroupWidth(modelColumn, depth, state, maxColumnWidth) {
11397
+ const baseWidth = super.getColumnHeaderGroupWidth(
11398
+ modelColumn,
11399
+ depth,
11294
11400
  state,
11295
- [visibleColumns[0], visibleColumns[visibleColumns.length - 1]],
11296
- {
11297
- minX: gridX + floatingLeftWidth,
11298
- maxX: width - floatingRightWidth
11299
- }
11401
+ maxColumnWidth
11300
11402
  );
11301
- if (containsFrozenColumns) {
11302
- this.drawColumnHeadersForRange(
11303
- context,
11304
- state,
11305
- [floatingColumns[0], floatingColumns[floatingColumns.length - 1]],
11306
- {
11307
- minX: gridX,
11308
- maxX: gridX + floatingLeftWidth
11309
- }
11310
- );
11403
+ const { isFilterBarShown, model } = state;
11404
+ if (!isFilterBarShown) {
11405
+ return baseWidth;
11311
11406
  }
11312
- if (headerSeparatorColor) {
11313
- context.strokeStyle = headerSeparatorColor;
11314
- const hiddenColumns = [...allColumnWidths.entries()].filter(([_, w]) => w === 0).map(([index]) => index);
11315
- context.beginPath();
11316
- context.fillStyle = headerSeparatorColor;
11317
- for (let i = 0; i < hiddenColumns.length; i += 1) {
11318
- const column = hiddenColumns[i];
11319
- const columnX = getOrThrow(allColumnXs, column);
11320
- const columnWidth = getOrThrow(allColumnWidths, column);
11321
- const minX = gridX + columnX + columnWidth + 0.5 - headerHiddenSeparatorSize * 0.5;
11322
- context.rect(
11323
- minX,
11324
- hiddenY,
11325
- headerHiddenSeparatorSize,
11326
- hiddenSeparatorHeight
11327
- );
11328
- }
11329
- context.fill();
11407
+ const group = model.getColumnHeaderGroup(modelColumn, depth);
11408
+ if (!isPivotColumnHeaderGroup(group) || !group.isKeyColumnGroup) {
11409
+ return baseWidth;
11330
11410
  }
11331
- if (headerSeparatorHoverColor) {
11332
- let { index: highlightedSeparator, depth } = draggingColumnSeparator ?? {};
11333
- if (highlightedSeparator == null && mouseX != null && mouseY != null) {
11334
- const separator = GridColumnSeparatorMouseHandler$1.getColumnSeparator(
11335
- GridUtils.getGridPointFromXY(mouseX, mouseY, metrics),
11336
- metrics,
11337
- model,
11338
- theme
11339
- );
11340
- highlightedSeparator = separator == null ? void 0 : separator.index;
11341
- depth = separator == null ? void 0 : separator.depth;
11342
- }
11343
- let shouldDrawSeparator;
11344
- if (highlightedSeparator == null) {
11345
- shouldDrawSeparator = false;
11346
- } else {
11347
- const columnIndex = modelColumns.get(highlightedSeparator);
11348
- const nextColumnIndex = modelColumns.get(highlightedSeparator + 1);
11349
- if (columnIndex == null || nextColumnIndex == null) {
11350
- shouldDrawSeparator = false;
11351
- } else {
11352
- shouldDrawSeparator = getColumnGroupName(model, columnIndex, depth) !== getColumnGroupName(model, nextColumnIndex, depth);
11353
- }
11411
+ const { theme } = state;
11412
+ const { columnSourceFilterMinWidth } = theme;
11413
+ return baseWidth + columnSourceFilterMinWidth;
11414
+ }
11415
+ /**
11416
+ * Calculate the width needed for the column source labels
11417
+ * @param model The IrisGridPivotModel instance
11418
+ * @param state The current IrisGridPivotMetricState
11419
+ * @returns The calculated width for the column source labels
11420
+ */
11421
+ calculateColumnSourceLabelWidth(model, state) {
11422
+ const { theme } = state;
11423
+ const { headerHorizontalPadding, maxColumnWidth } = theme;
11424
+ const keyColumnGroups = getKeyColumnGroups(model);
11425
+ return this.getCachedColumnSourceLabelWidth(
11426
+ keyColumnGroups,
11427
+ headerHorizontalPadding,
11428
+ maxColumnWidth,
11429
+ state
11430
+ );
11431
+ }
11432
+ /**
11433
+ * Gets the metrics for the current state. This method has to be called before setColumnSize or resetColumnSize.
11434
+ * @param state The current IrisGridPivotMetricState
11435
+ * @returns The metrics for the current state
11436
+ */
11437
+ getMetrics(state) {
11438
+ const { model } = state;
11439
+ if (!isIrisGridPivotModel(model)) {
11440
+ throw new Error("Model is not an IrisGridPivotModel");
11441
+ }
11442
+ const columnSourceLabelWidth = this.calculateColumnSourceLabelWidth(
11443
+ model,
11444
+ state
11445
+ );
11446
+ this.resetHeaderWidthsIfFilterBarChanged(state);
11447
+ return {
11448
+ ...super.getMetrics(state),
11449
+ columnSourceLabelWidth
11450
+ };
11451
+ }
11452
+ /**
11453
+ * Get metrics for positioning the filter bar input field.
11454
+ * @param index The visible index of the column to get the filter box coordinates for
11455
+ * @param state The current IrisGridMetricState
11456
+ * @param metrics The grid metrics
11457
+ * @returns Coordinates for the filter input field, or null if positioning cannot be calculated
11458
+ */
11459
+ // eslint-disable-next-line class-methods-use-this
11460
+ getFilterInputCoordinates(index, state, metrics) {
11461
+ if (index >= 0) {
11462
+ return super.getFilterInputCoordinates(index, state, metrics);
11463
+ }
11464
+ const { model, theme } = state;
11465
+ if (!isIrisGridPivotModel(model)) {
11466
+ return null;
11467
+ }
11468
+ const { gridY, columnSourceLabelWidth } = metrics;
11469
+ const { columnSourceFilterMinWidth, filterBarHeight } = theme;
11470
+ const depth = -index;
11471
+ const keyColumnGroup = model.getColumnHeaderGroup(0, depth);
11472
+ if (keyColumnGroup == null || !isPivotColumnHeaderGroup(keyColumnGroup) || !keyColumnGroup.isKeyColumnGroup) {
11473
+ return null;
11474
+ }
11475
+ const groupCoords = getColumnHeaderCoordinates(
11476
+ { metrics, theme, model },
11477
+ keyColumnGroup
11478
+ );
11479
+ if (groupCoords == null) {
11480
+ return null;
11481
+ }
11482
+ const { x1, x2 } = groupCoords;
11483
+ const columnSourceFilterWidth = Math.max(
11484
+ columnSourceFilterMinWidth,
11485
+ x2 - x1 - columnSourceLabelWidth
11486
+ );
11487
+ const x = x2 - columnSourceFilterWidth;
11488
+ const y = gridY - theme.columnHeaderHeight - (1 - index) * (filterBarHeight ?? 0);
11489
+ return {
11490
+ x,
11491
+ y,
11492
+ width: columnSourceFilterWidth + 1,
11493
+ // cover right border
11494
+ height: (filterBarHeight ?? 0) - 1
11495
+ // remove bottom border
11496
+ };
11497
+ }
11498
+ /**
11499
+ * Calculate the new left index to bring the given column into view.
11500
+ * @param column The column that should be scrolled into view
11501
+ * @param state The current IrisGridMetricState
11502
+ * @param metrics The grid metrics
11503
+ * @returns The left column index to scroll to, or null if no scroll is needed
11504
+ */
11505
+ getScrollLeftForColumn(column, state, metrics) {
11506
+ if (column < 0) {
11507
+ return null;
11508
+ }
11509
+ return super.getScrollLeftForColumn(column, state, metrics);
11510
+ }
11511
+ }
11512
+ function getColumnSourceHeaderFromGridPoint(model, gridPoint) {
11513
+ const { column, row, columnHeaderDepth } = gridPoint;
11514
+ const sourceIndex = columnHeaderDepth != null ? -columnHeaderDepth : null;
11515
+ if (column == null || row !== null || columnHeaderDepth == null) {
11516
+ return null;
11517
+ }
11518
+ const group = model.getColumnHeaderGroup(column, columnHeaderDepth);
11519
+ if (sourceIndex != null && sourceIndex < 0 && isIrisGridPivotModel(model) && isPivotColumnHeaderGroup(group) && group.isKeyColumnGroup) {
11520
+ return sourceIndex;
11521
+ }
11522
+ return null;
11523
+ }
11524
+ function isGridPointInColumnSourceFilterBox(model, gridPoint, metrics, theme) {
11525
+ if (!isIrisGridPivotModel(model)) {
11526
+ return false;
11527
+ }
11528
+ const { column, row, columnHeaderDepth } = gridPoint;
11529
+ if (column == null || row !== null || columnHeaderDepth == null) {
11530
+ return false;
11531
+ }
11532
+ const sourceIndex = getColumnSourceHeaderFromGridPoint(model, gridPoint);
11533
+ if (sourceIndex == null) {
11534
+ return false;
11535
+ }
11536
+ const group = model.getColumnHeaderGroup(column, columnHeaderDepth);
11537
+ if (!isPivotColumnHeaderGroup(group)) {
11538
+ return false;
11539
+ }
11540
+ const coords = getColumnHeaderCoordinates(
11541
+ { metrics, theme, model },
11542
+ group
11543
+ );
11544
+ if (coords == null) {
11545
+ return false;
11546
+ }
11547
+ const { columnSourceFilterMinWidth } = theme;
11548
+ const { columnSourceLabelWidth } = metrics;
11549
+ const { x1, x2 } = coords;
11550
+ const columnSourceFilterWidth = Math.max(
11551
+ x2 - x1 - columnSourceLabelWidth,
11552
+ columnSourceFilterMinWidth
11553
+ );
11554
+ return gridPoint.x > x2 - columnSourceFilterWidth;
11555
+ }
11556
+ const log$2 = Log.module("@deephaven/js-plugin-pivot/PivotSortMouseHandler");
11557
+ class PivotSortMouseHandler extends GridMouseHandler {
11558
+ constructor(irisGrid2) {
11559
+ super();
11560
+ __publicField(this, "columnSource");
11561
+ __publicField(this, "irisGrid");
11562
+ this.columnSource = null;
11563
+ this.irisGrid = irisGrid2;
11564
+ }
11565
+ // We need to remember where the down started, because the canvas element will trigger a click where mouseUp is
11566
+ onDown(gridPoint, grid, event) {
11567
+ const { model } = this.irisGrid.props;
11568
+ assertNotNull(model);
11569
+ this.columnSource = getColumnSourceHeaderFromGridPoint(model, gridPoint);
11570
+ log$2.debug("onDown", gridPoint, this.columnSource);
11571
+ return false;
11572
+ }
11573
+ onClick(gridPoint, grid, event) {
11574
+ const { model } = this.irisGrid.props;
11575
+ assertNotNull(model);
11576
+ const columnSource = getColumnSourceHeaderFromGridPoint(model, gridPoint);
11577
+ if (columnSource != null && columnSource === this.columnSource && model.isColumnSortable(columnSource)) {
11578
+ const addToExisting = components.ContextActionUtils.isModifierKeyDown(event);
11579
+ this.irisGrid.toggleSort(columnSource, addToExisting);
11580
+ return true;
11581
+ }
11582
+ return false;
11583
+ }
11584
+ }
11585
+ function isPivotGridMetrics(metrics) {
11586
+ return metrics.columnSourceLabelWidth !== void 0;
11587
+ }
11588
+ class PivotFilterMouseHandler extends GridMouseHandler {
11589
+ constructor(irisGrid2) {
11590
+ super();
11591
+ __publicField(this, "irisGrid");
11592
+ this.irisGrid = irisGrid2;
11593
+ }
11594
+ onDown(gridPoint) {
11595
+ const { model } = this.irisGrid.props;
11596
+ const { isFilterBarShown, metrics } = this.irisGrid.state;
11597
+ const sourceIndex = getColumnSourceHeaderFromGridPoint(model, gridPoint);
11598
+ if (sourceIndex != null) {
11599
+ assertNotNull(metrics, "Metrics not set");
11600
+ if (!isPivotGridMetrics(metrics)) {
11601
+ throw new Error("PivotGridMetrics required");
11602
+ }
11603
+ const theme = this.irisGrid.getTheme();
11604
+ if (isFilterBarShown && theme.columnHeaderHeight != null && theme.filterBarHeight != null && isGridPointInColumnSourceFilterBox(model, gridPoint, metrics, theme)) {
11605
+ this.irisGrid.focusFilterBar(sourceIndex);
11606
+ return true;
11354
11607
  }
11355
- if (shouldDrawSeparator && highlightedSeparator != null && depth != null && (!isDragging || draggingColumnSeparator != null)) {
11356
- context.strokeStyle = headerSeparatorHoverColor;
11357
- const columnX = getOrThrow(allColumnXs, highlightedSeparator);
11358
- const columnWidth = getOrThrow(allColumnWidths, highlightedSeparator);
11359
- const x = gridX + columnX + columnWidth + 0.5;
11360
- const visibleColumnIndex = visibleColumns.indexOf(highlightedSeparator);
11361
- const nextColumn = visibleColumnIndex < visibleColumns.length - 1 ? visibleColumns[visibleColumnIndex + 1] : null;
11362
- const nextColumnWidth = nextColumn != null ? allColumnWidths.get(nextColumn) : null;
11363
- const isColumnHidden = columnWidth === 0;
11364
- const isNextColumnHidden = nextColumnWidth != null && nextColumnWidth === 0;
11365
- if (isColumnHidden) {
11366
- context.strokeStyle = headerHiddenSeparatorHoverColor;
11367
- context.fillStyle = headerHiddenSeparatorHoverColor;
11368
- context.fillRect(
11369
- x,
11370
- hiddenY,
11371
- headerHiddenSeparatorSize * 0.5,
11372
- hiddenSeparatorHeight
11373
- );
11374
- } else if (isNextColumnHidden) {
11375
- context.fillStyle = headerSeparatorHoverColor;
11376
- context.fillRect(
11377
- x - headerHiddenSeparatorSize * 0.5,
11378
- hiddenY,
11379
- headerHiddenSeparatorSize * 0.5,
11380
- hiddenSeparatorHeight
11381
- );
11382
- }
11383
- context.beginPath();
11384
- context.moveTo(
11385
- x,
11386
- (columnHeaderMaxDepth - depth - 1) * columnHeaderHeight
11387
- );
11388
- context.lineTo(
11389
- x,
11390
- (columnHeaderMaxDepth - depth) * columnHeaderHeight - 1
11391
- );
11392
- context.stroke();
11608
+ }
11609
+ return false;
11610
+ }
11611
+ onClick(gridPoint, grid, event) {
11612
+ const { model } = this.irisGrid.props;
11613
+ const { isFilterBarShown, metrics } = this.irisGrid.state;
11614
+ const sourceIndex = getColumnSourceHeaderFromGridPoint(model, gridPoint);
11615
+ if (sourceIndex != null) {
11616
+ assertNotNull(metrics, "Metrics not set");
11617
+ if (!isPivotGridMetrics(metrics)) {
11618
+ throw new Error("PivotGridMetrics required");
11619
+ }
11620
+ const theme = this.irisGrid.getTheme();
11621
+ if (isFilterBarShown && theme.columnHeaderHeight != null && theme.filterBarHeight != null && isGridPointInColumnSourceFilterBox(model, gridPoint, metrics, theme)) {
11622
+ return true;
11393
11623
  }
11394
11624
  }
11395
- context.restore();
11625
+ return false;
11626
+ }
11627
+ }
11628
+ function usePivotMouseHandlers() {
11629
+ return React.useMemo(
11630
+ () => [
11631
+ (irisGrid2) => new PivotColumnGroupMouseHandler(irisGrid2),
11632
+ // Filter handler should consume events before sort
11633
+ (irisGrid2) => new PivotFilterMouseHandler(irisGrid2),
11634
+ (irisGrid2) => new PivotSortMouseHandler(irisGrid2)
11635
+ ],
11636
+ []
11637
+ );
11638
+ }
11639
+ function getColumnGroupName(model, modelColumn, depth) {
11640
+ var _a;
11641
+ return (_a = model.getColumnHeaderGroup(modelColumn, depth ?? 0)) == null ? void 0 : _a.name;
11642
+ }
11643
+ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11644
+ drawColumnHeaders(context, state) {
11645
+ super.drawColumnHeaders(context, state);
11646
+ this.drawColumnSourceFilters(context, state);
11396
11647
  }
11397
11648
  drawColumnHeadersAtDepth(context, state, range, bounds, depth) {
11398
- const { metrics, model, theme } = state;
11649
+ const { isFilterBarShown, metrics, model, theme } = state;
11399
11650
  if (!isIrisGridPivotModel(model)) {
11400
11651
  throw new Error("Unsupported model type");
11401
11652
  }
11402
- const {
11403
- modelColumns,
11404
- allColumnXs,
11405
- gridX,
11406
- userColumnWidths,
11407
- allColumnWidths,
11408
- movedColumns
11409
- } = metrics;
11410
- const { columnHeaderHeight, columnWidth } = theme;
11653
+ const { modelColumns } = metrics;
11654
+ const { columnHeaderHeight } = theme;
11411
11655
  const { columnHeaderMaxDepth } = model;
11412
11656
  const { minX, maxX } = bounds;
11413
- const visibleWidth = maxX - minX;
11414
11657
  if (columnHeaderMaxDepth === 0) {
11415
11658
  return;
11416
11659
  }
@@ -11430,70 +11673,61 @@ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11430
11673
  if (depth > 0) {
11431
11674
  let columnIndex = startIndex;
11432
11675
  while (columnIndex <= endIndex) {
11433
- const { columnCount } = metrics;
11434
11676
  const modelColumn = getOrThrow(modelColumns, columnIndex);
11435
11677
  const columnGroupColor = model.colorForColumnHeader(
11436
11678
  modelColumn,
11437
11679
  depth,
11438
11680
  theme
11439
11681
  );
11440
- const headerGroup = model.getColumnHeaderGroup(modelColumn, depth ?? 0);
11682
+ const headerGroup = model.getColumnHeaderGroup(modelColumn, depth);
11441
11683
  const isExpandable = isPivotColumnHeaderGroup(headerGroup) && headerGroup.isExpandable;
11442
11684
  const isExpanded = isPivotColumnHeaderGroup(headerGroup) && headerGroup.isExpanded;
11443
- const columnGroupName = getColumnGroupName(model, modelColumn, depth);
11444
- let columnGroupLeft = getOrThrow(allColumnXs, columnIndex) + gridX;
11445
- let columnGroupRight = columnGroupLeft + getOrThrow(allColumnWidths, columnIndex);
11446
- if (columnGroupName != null) {
11447
- let prevColumnIndex = columnIndex - 1;
11448
- while (prevColumnIndex >= 0 && (columnGroupRight - columnGroupLeft < visibleWidth || columnGroupLeft > minX)) {
11449
- const prevModelIndex = modelColumns.get(prevColumnIndex) ?? GridUtils.getModelIndex(prevColumnIndex, movedColumns);
11450
- if (prevModelIndex == null || getColumnGroupName(model, prevModelIndex, depth) !== columnGroupName) {
11451
- break;
11452
- }
11453
- const prevColumnWidth = userColumnWidths.get(prevModelIndex) ?? allColumnWidths.get(prevColumnIndex) ?? columnWidth;
11454
- columnGroupLeft -= prevColumnWidth;
11455
- prevColumnIndex -= 1;
11456
- }
11457
- let nextColumnIndex = columnIndex + 1;
11458
- while (nextColumnIndex < columnCount && (columnGroupRight - columnGroupLeft < visibleWidth || columnGroupRight < maxX)) {
11459
- const nextModelIndex = modelColumns.get(nextColumnIndex) ?? GridUtils.getModelIndex(nextColumnIndex, movedColumns);
11460
- if (getColumnGroupName(model, nextModelIndex, depth) !== columnGroupName) {
11461
- break;
11462
- }
11463
- const nextColumnWidth = userColumnWidths.get(nextModelIndex) ?? allColumnWidths.get(nextColumnIndex) ?? columnWidth;
11464
- columnGroupRight += nextColumnWidth;
11465
- nextColumnIndex += 1;
11466
- }
11467
- columnIndex = nextColumnIndex - 1;
11468
- const isFullWidth = columnGroupRight - columnGroupLeft >= visibleWidth;
11469
- let x = columnGroupLeft;
11470
- if (isFullWidth) {
11471
- if (columnGroupRight < maxX) {
11472
- x = columnGroupRight - visibleWidth;
11473
- } else if (columnGroupLeft < minX) {
11474
- x = minX;
11685
+ const groupName = getColumnGroupName(model, modelColumn, depth);
11686
+ if (groupName != null && isPivotColumnHeaderGroup(headerGroup)) {
11687
+ const coords = getColumnHeaderCoordinates(state, headerGroup);
11688
+ if (coords != null) {
11689
+ const { x1: columnGroupLeft, x2: columnGroupRight } = coords;
11690
+ columnIndex = headerGroup.childIndexes[headerGroup.childIndexes.length - 1];
11691
+ const columnWidth = columnGroupRight - columnGroupLeft;
11692
+ let headerRightPadding;
11693
+ if (isPivotColumnHeaderGroup(headerGroup) && headerGroup.isKeyColumnGroup === true && theme.columnSourceFilterMinWidth != null) {
11694
+ if (isFilterBarShown) {
11695
+ headerRightPadding = Math.max(
11696
+ theme.columnSourceFilterMinWidth,
11697
+ columnWidth - metrics.columnSourceLabelWidth
11698
+ );
11699
+ } else {
11700
+ const { advancedFilters, quickFilters } = state;
11701
+ const { filterBarCollapsedHeight } = theme;
11702
+ if (advancedFilters.size > 0 || quickFilters.size > 0) {
11703
+ headerRightPadding = filterBarCollapsedHeight;
11704
+ }
11705
+ }
11475
11706
  }
11707
+ const sort = jsapiUtils.TableUtils.getSortForColumn(model.sort, groupName);
11708
+ this.drawColumnHeader(
11709
+ context,
11710
+ state,
11711
+ model.textForColumnHeader(modelColumn, depth) ?? "",
11712
+ columnGroupLeft,
11713
+ columnWidth,
11714
+ {
11715
+ backgroundColor: columnGroupColor ?? void 0
11716
+ },
11717
+ bounds,
11718
+ isExpandable,
11719
+ isExpanded,
11720
+ sort,
11721
+ headerRightPadding
11722
+ );
11476
11723
  }
11477
- this.drawColumnHeader(
11478
- context,
11479
- state,
11480
- model.textForColumnHeader(modelColumn, depth) ?? "",
11481
- x,
11482
- Math.min(columnGroupRight - columnGroupLeft, visibleWidth),
11483
- {
11484
- backgroundColor: columnGroupColor ?? void 0
11485
- },
11486
- bounds,
11487
- isExpandable,
11488
- isExpanded
11489
- );
11490
11724
  }
11491
11725
  columnIndex += 1;
11492
11726
  }
11493
11727
  }
11494
11728
  context.restore();
11495
11729
  }
11496
- drawColumnHeader(context, state, columnText, columnX, columnWidth, style, bounds, isExpandable = false, isExpanded = false) {
11730
+ drawColumnHeader(context, state, columnText, columnX, columnWidth, style, bounds, isExpandable = false, isExpanded = false, sort = null, headerRightPadding) {
11497
11731
  if (columnWidth <= 0) {
11498
11732
  return;
11499
11733
  }
@@ -11509,7 +11743,7 @@ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11509
11743
  white
11510
11744
  } = theme;
11511
11745
  const { fontWidthsLower, fontWidthsUpper, width } = metrics;
11512
- const maxWidth = columnWidth - headerHorizontalPadding * 2;
11746
+ const maxLabelWidth = columnWidth - headerHorizontalPadding * 2 - (headerRightPadding ?? 0);
11513
11747
  const {
11514
11748
  backgroundColor = headerBackgroundColor,
11515
11749
  separatorColor = headerSeparatorColor
@@ -11555,7 +11789,7 @@ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11555
11789
  const renderText = this.textCellRenderer.getCachedTruncatedString(
11556
11790
  context,
11557
11791
  columnText,
11558
- maxWidth,
11792
+ maxLabelWidth,
11559
11793
  fontWidthLower,
11560
11794
  fontWidthUpper
11561
11795
  );
@@ -11565,15 +11799,15 @@ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11565
11799
  maxX -= headerHorizontalPadding;
11566
11800
  const treeMarkerPadding = isExpandable ? iconSize : 0;
11567
11801
  const contentLeft = columnX + headerHorizontalPadding;
11568
- const visibleLeft = lodash_clamp(contentLeft, minX, maxX);
11569
- const contentRight = columnX + columnWidth - headerHorizontalPadding;
11570
- const visibleRight = lodash_clamp(contentRight, minX, maxX);
11571
- const visibleWidth = visibleRight - visibleLeft;
11802
+ const contentViewportLeft = lodash_clamp(contentLeft, minX, maxX);
11803
+ const contentRight = columnX + columnWidth - headerHorizontalPadding - (headerRightPadding ?? 0);
11804
+ const contentViewportRight = lodash_clamp(contentRight, minX, maxX);
11805
+ const contentViewportWidth = contentViewportRight - contentViewportLeft;
11572
11806
  const textWidth = this.getCachedHeaderWidth(context, renderText);
11573
11807
  const contentWidth = textWidth + treeMarkerPadding;
11574
11808
  const isBeyondLeft = contentLeft < minX;
11575
11809
  if (isBeyondLeft) {
11576
- if (contentWidth < visibleWidth) {
11810
+ if (contentWidth < contentViewportWidth) {
11577
11811
  x = minX;
11578
11812
  } else {
11579
11813
  x = contentRight - contentWidth;
@@ -11601,6 +11835,15 @@ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11601
11835
  isExpanded
11602
11836
  );
11603
11837
  }
11838
+ this.drawColumnSourceSortIndicator(
11839
+ context,
11840
+ state,
11841
+ sort,
11842
+ columnText,
11843
+ columnX,
11844
+ columnWidth,
11845
+ { minX, maxX }
11846
+ );
11604
11847
  context.restore();
11605
11848
  }
11606
11849
  drawColumnHeaderTreeMarker(context, state, columnX, columnWidth, headerY, headerHeight, treeBox, isExpanded) {
@@ -11628,39 +11871,287 @@ class IrisGridPivotRenderer extends irisGrid.IrisGridRenderer {
11628
11871
  isExpanded
11629
11872
  );
11630
11873
  }
11874
+ drawColumnSourceSortIndicator(context, state, sort, columnText, columnX, columnWidth, bounds) {
11875
+ const { isFilterBarShown, metrics, theme, quickFilters, advancedFilters } = state;
11876
+ const { gridX, columnHeaderHeight, columnSourceLabelWidth } = metrics;
11877
+ const {
11878
+ iconSize: themeIconSize,
11879
+ columnSourceFilterMinWidth,
11880
+ filterBarCollapsedHeight
11881
+ } = theme;
11882
+ const iconSize = Math.round(themeIconSize * 0.75);
11883
+ if (sort == null) {
11884
+ return;
11885
+ }
11886
+ const icon = this.getSortIcon(sort, iconSize);
11887
+ if (!icon) {
11888
+ return;
11889
+ }
11890
+ if (columnSourceFilterMinWidth == null || columnSourceFilterMinWidth <= 0) {
11891
+ return;
11892
+ }
11893
+ const expandedFilterWidth = Math.max(
11894
+ columnWidth - columnSourceLabelWidth,
11895
+ columnSourceFilterMinWidth
11896
+ );
11897
+ const collapsedFilterWidth = advancedFilters.size > 0 || quickFilters.size > 0 ? filterBarCollapsedHeight : 0;
11898
+ const x = gridX + columnX + columnWidth - iconSize - (isFilterBarShown ? expandedFilterWidth : collapsedFilterWidth) - 1;
11899
+ const y = (columnHeaderHeight - iconSize) * 0.5;
11900
+ context.save();
11901
+ context.fillStyle = theme.headerSortBarColor;
11902
+ context.translate(x, y);
11903
+ context.fill(icon);
11904
+ context.restore();
11905
+ }
11906
+ drawColumnSourceFilters(context, state) {
11907
+ const { isFilterBarShown, quickFilters, advancedFilters } = state;
11908
+ if (isFilterBarShown) {
11909
+ this.drawExpandedColumnSourceFilters(context, state);
11910
+ } else if (quickFilters != null && quickFilters.size > 0 || advancedFilters != null && advancedFilters.size > 0) {
11911
+ this.drawCollapsedColumnSourceFilters(context, state);
11912
+ }
11913
+ }
11914
+ drawExpandedColumnSourceFilters(context, state) {
11915
+ const { model, metrics, theme, quickFilters, advancedFilters } = state;
11916
+ const { columnSourceFilterMinWidth } = theme;
11917
+ if (columnSourceFilterMinWidth == null || columnSourceFilterMinWidth <= 0) {
11918
+ return;
11919
+ }
11920
+ const { columnSourceLabelWidth } = metrics;
11921
+ const filterBoxes = getKeyColumnGroups(model).map((group) => {
11922
+ const coords = getColumnHeaderCoordinates(state, group);
11923
+ if (coords == null) {
11924
+ return null;
11925
+ }
11926
+ const { x1, y1, x2, y2 } = coords;
11927
+ const columnSourceFilterWidth = Math.max(
11928
+ x2 - x1 - columnSourceLabelWidth,
11929
+ columnSourceFilterMinWidth
11930
+ );
11931
+ return {
11932
+ depth: group.depth,
11933
+ x1: x2 - columnSourceFilterWidth,
11934
+ y1,
11935
+ x2,
11936
+ y2
11937
+ };
11938
+ }).filter(isNotNullOrUndefined);
11939
+ if (filterBoxes.length === 0) {
11940
+ return;
11941
+ }
11942
+ context.save();
11943
+ context.font = theme.filterBarFont;
11944
+ context.textAlign = "left";
11945
+ if (quickFilters != null && quickFilters.size > 0 || advancedFilters != null && advancedFilters.size > 0) {
11946
+ context.fillStyle = theme.filterBarExpandedActiveBackgroundColor;
11947
+ } else {
11948
+ context.fillStyle = theme.filterBarExpandedBackgroundColor;
11949
+ }
11950
+ context.fillRect(
11951
+ filterBoxes[0].x1,
11952
+ filterBoxes[filterBoxes.length - 1].y1,
11953
+ filterBoxes[0].x2 - filterBoxes[0].x1,
11954
+ filterBoxes[0].y2 - filterBoxes[filterBoxes.length - 1].y1
11955
+ );
11956
+ context.strokeStyle = theme.filterBarSeparatorColor;
11957
+ context.beginPath();
11958
+ filterBoxes.forEach(({ x1, y1, x2, y2 }) => {
11959
+ const w = x2 - x1;
11960
+ const h = y2 - y1;
11961
+ context.rect(x1 + 0.5, y1 + 0.5, w, h - 2);
11962
+ });
11963
+ context.stroke();
11964
+ filterBoxes.forEach(({ x1, x2, depth }) => {
11965
+ this.drawExpandedColumnSourceFilter(context, state, depth, x1, x2 - x1);
11966
+ });
11967
+ context.restore();
11968
+ }
11969
+ drawExpandedColumnSourceFilter(context, state, headerDepth, inputX, inputWidth) {
11970
+ if (inputWidth <= 0) {
11971
+ return;
11972
+ }
11973
+ const { metrics, theme, quickFilters, advancedFilters } = state;
11974
+ const {
11975
+ filterBarHeight,
11976
+ filterBarExpandedActiveCellBackgroundColor,
11977
+ filterBarErrorColor,
11978
+ filterBarHorizontalPadding,
11979
+ headerColor
11980
+ } = theme;
11981
+ const { columnHeaderHeight, gridY } = metrics;
11982
+ const filterIndex = -headerDepth;
11983
+ const quickFilter = quickFilters.get(filterIndex);
11984
+ const advancedFilter = advancedFilters.get(filterIndex);
11985
+ if (quickFilter == null && advancedFilter == null) {
11986
+ return;
11987
+ }
11988
+ let text = null;
11989
+ if (quickFilter != null) {
11990
+ const { text: filterText } = quickFilter;
11991
+ text = filterText;
11992
+ if (text == null || text === "") {
11993
+ text = jsapiUtils.TableUtils.getFilterText(quickFilter.filter);
11994
+ }
11995
+ if (text != null) {
11996
+ const { fontWidthsLower, fontWidthsUpper } = metrics;
11997
+ const fontWidthLower = fontWidthsLower.get(context.font);
11998
+ const fontWidthUpper = fontWidthsUpper.get(context.font);
11999
+ const maxLength = inputWidth - filterBarHorizontalPadding * 2;
12000
+ text = this.textCellRenderer.getCachedTruncatedString(
12001
+ context,
12002
+ text,
12003
+ maxLength,
12004
+ fontWidthLower,
12005
+ fontWidthUpper
12006
+ );
12007
+ }
12008
+ }
12009
+ const inputY = gridY - filterBarHeight - columnHeaderHeight - columnHeaderHeight * headerDepth;
12010
+ const isFilterValid = irisGrid.IrisGridRenderer.isFilterValid(
12011
+ advancedFilter,
12012
+ quickFilter
12013
+ );
12014
+ context.save();
12015
+ if (isFilterValid && filterBarExpandedActiveCellBackgroundColor != null) {
12016
+ context.fillStyle = filterBarExpandedActiveCellBackgroundColor;
12017
+ context.fillRect(
12018
+ inputX + 1,
12019
+ // +1 left border
12020
+ inputY + 1,
12021
+ // +1 top border
12022
+ inputWidth - 1,
12023
+ // -1 right border
12024
+ filterBarHeight - 3
12025
+ // -3 top, bottom border and bottom casing
12026
+ );
12027
+ } else if (filterBarErrorColor != null) {
12028
+ context.fillStyle = filterBarErrorColor;
12029
+ context.lineWidth = 2;
12030
+ context.strokeStyle = filterBarErrorColor;
12031
+ const rectLeft = inputX + 2;
12032
+ const rectTop = inputY + 2;
12033
+ const rectWidth = inputWidth - 3;
12034
+ const rectHeight = filterBarHeight - 5;
12035
+ context.strokeRect(rectLeft, rectTop, rectWidth, rectHeight);
12036
+ }
12037
+ if (text != null && text !== "") {
12038
+ const textX = inputX + filterBarHorizontalPadding;
12039
+ const textY = inputY + filterBarHeight * 0.5 + 1;
12040
+ context.fillStyle = headerColor;
12041
+ context.fillText(text, textX, textY);
12042
+ }
12043
+ context.restore();
12044
+ }
12045
+ drawCollapsedColumnSourceFilters(context, state) {
12046
+ const { metrics, model, theme } = state;
12047
+ const { gridX, gridY, columnHeaderHeight, columnHeaderMaxDepth } = metrics;
12048
+ const { headerSeparatorColor, filterBarCollapsedHeight } = theme;
12049
+ if (filterBarCollapsedHeight <= 0) {
12050
+ return;
12051
+ }
12052
+ const filterBoxes = getKeyColumnGroups(model).map((group) => {
12053
+ const coords = getColumnHeaderCoordinates(state, group);
12054
+ if (coords == null) {
12055
+ return null;
12056
+ }
12057
+ const { x2: x22, y1, y2 } = coords;
12058
+ return {
12059
+ depth: group.depth,
12060
+ x1: x22 - filterBarCollapsedHeight,
12061
+ y1,
12062
+ x2: x22,
12063
+ y2
12064
+ };
12065
+ }).filter(isNotNullOrUndefined);
12066
+ if (filterBoxes.length === 0) {
12067
+ return;
12068
+ }
12069
+ context.save();
12070
+ const { x2 } = filterBoxes[filterBoxes.length - 1];
12071
+ context.fillStyle = headerSeparatorColor;
12072
+ context.fillRect(
12073
+ gridX + x2 - filterBarCollapsedHeight,
12074
+ gridY - columnHeaderHeight * columnHeaderMaxDepth - filterBarCollapsedHeight,
12075
+ filterBarCollapsedHeight,
12076
+ columnHeaderHeight * (columnHeaderMaxDepth - 1)
12077
+ );
12078
+ filterBoxes.forEach(({ x2: columnRight, depth }) => {
12079
+ this.drawCollapsedColumnSourceFilter(context, state, depth, columnRight);
12080
+ });
12081
+ context.restore();
12082
+ }
12083
+ // eslint-disable-next-line class-methods-use-this
12084
+ drawCollapsedColumnSourceFilter(context, state, headerDepth, columnRight) {
12085
+ if (columnRight <= 0) {
12086
+ return;
12087
+ }
12088
+ const { metrics, theme, quickFilters, advancedFilters } = state;
12089
+ const { columnHeaderHeight, gridY } = metrics;
12090
+ const filterIndex = -headerDepth;
12091
+ const quickFilter = quickFilters.get(filterIndex);
12092
+ const advancedFilter = advancedFilters.get(filterIndex);
12093
+ const {
12094
+ filterBarCollapsedHeight,
12095
+ filterBarActiveColor,
12096
+ filterBarActiveBackgroundColor,
12097
+ filterBarErrorColor
12098
+ } = theme;
12099
+ context.save();
12100
+ const isFilterValid = irisGrid.IrisGridRenderer.isFilterValid(
12101
+ advancedFilter,
12102
+ quickFilter
12103
+ );
12104
+ if (filterBarActiveBackgroundColor != null && quickFilter == null && advancedFilter == null) {
12105
+ context.fillStyle = filterBarActiveBackgroundColor;
12106
+ } else if (filterBarActiveColor != null && isFilterValid) {
12107
+ context.fillStyle = filterBarActiveColor;
12108
+ } else if (filterBarErrorColor != null) {
12109
+ context.fillStyle = filterBarErrorColor;
12110
+ }
12111
+ const x = columnRight - filterBarCollapsedHeight + 1;
12112
+ const y = gridY - filterBarCollapsedHeight - columnHeaderHeight - columnHeaderHeight * headerDepth;
12113
+ const rectWidth = filterBarCollapsedHeight - 1;
12114
+ const rectHeight = columnHeaderHeight - 1;
12115
+ context.fillRect(x, y, rectWidth, rectHeight);
12116
+ context.restore();
12117
+ }
11631
12118
  }
11632
- const IrisGridPivotTheme = Object.freeze({
12119
+ function usePivotRenderer() {
12120
+ return React.useMemo(() => new IrisGridPivotRenderer(), []);
12121
+ }
12122
+ const IrisGridPivotThemeColors = Object.freeze({
11633
12123
  columnSourceHeaderBackground: "var(--dh-color-grid-bg)",
11634
12124
  totalsHeaderBackground: "var(--dh-color-grid-bg)"
11635
12125
  });
11636
- const log$2 = Log.module("@deephaven/js-plugin-pivot/PivotWidget");
11637
- function PivotWidget({
11638
- fetch
11639
- }) {
11640
- const dh = jsapiBootstrap.useApi();
11641
- const mouseHandlers = React.useMemo(
11642
- () => [(irisGrid2) => new PivotColumnGroupMouseHandler(irisGrid2)],
11643
- []
11644
- );
11645
- const renderer = React.useMemo(() => new IrisGridPivotRenderer(), []);
12126
+ function getIrisGridPivotTheme() {
12127
+ return Object.freeze({
12128
+ ...components.resolveCssVariablesInRecord(IrisGridPivotThemeColors),
12129
+ columnSourceFilterMinWidth: 120
12130
+ });
12131
+ }
12132
+ const log$1 = Log.module("@deephaven/js-plugin-pivot/usePivotTheme");
12133
+ function usePivotTheme() {
11646
12134
  const theme = components.useTheme();
11647
- const pivotTheme = React.useMemo(() => {
11648
- log$2.debug("Theme changed, updating pivot theme", theme);
11649
- return components.resolveCssVariablesInRecord(IrisGridPivotTheme);
12135
+ return React.useMemo(() => {
12136
+ log$1.debug("Theme changed, updating pivot theme", theme);
12137
+ return getIrisGridPivotTheme();
11650
12138
  }, [theme]);
11651
- const pivotTableFetch = React.useCallback(
11652
- () => fetch().then((result) => {
11653
- log$2.debug("pivotWidget fetch result:", result);
11654
- if (!isCorePlusDh(dh)) {
11655
- throw new Error("CorePlus is not available");
11656
- }
11657
- const pivot = new dh.coreplus.pivot.PivotTable(result);
11658
- log$2.debug("Created pivot table:", pivot);
11659
- return pivot;
11660
- }),
11661
- [dh, fetch]
12139
+ }
12140
+ function usePivotMetricCalculatorFactory() {
12141
+ return React.useMemo(
12142
+ () => (...args) => new IrisGridPivotMetricCalculator(...args),
12143
+ []
11662
12144
  );
11663
- const fetchResult = useIrisGridPivotModel(pivotTableFetch);
12145
+ }
12146
+ function PivotWidget({
12147
+ fetch
12148
+ }) {
12149
+ const pivotFetch = usePivotTableFetch(fetch);
12150
+ const mouseHandlers = usePivotMouseHandlers();
12151
+ const renderer = usePivotRenderer();
12152
+ const pivotTheme = usePivotTheme();
12153
+ const getPivotMetricCalculator = usePivotMetricCalculatorFactory();
12154
+ const fetchResult = useIrisGridPivotModel(pivotFetch);
11664
12155
  if (fetchResult.status === "loading") {
11665
12156
  return /* @__PURE__ */ jsxRuntimeExports.jsx(components.LoadingOverlay, { isLoading: true });
11666
12157
  }
@@ -11680,71 +12171,84 @@ function PivotWidget({
11680
12171
  model,
11681
12172
  mouseHandlers,
11682
12173
  renderer,
11683
- theme: pivotTheme
12174
+ theme: pivotTheme,
12175
+ getMetricCalculator: getPivotMetricCalculator
11684
12176
  }
11685
12177
  );
11686
12178
  }
11687
- const log$1 = Log.module("@deephaven/js-plugin-pivot/useHydratePivotGrid");
11688
- function useHydratePivotGrid(fetch, id, metadata) {
12179
+ const log = Log.module("@deephaven/js-plugin-pivot/useHydratePivotGrid");
12180
+ function useHydratePivotGrid(id, metadata) {
12181
+ assertNotNull(metadata, "Missing Pivot metadata");
12182
+ const objectFetch = jsapiBootstrap.useObjectFetch(metadata);
11689
12183
  const api = jsapiBootstrap.useApi();
11690
12184
  const loadPlugin = dashboardCorePlugins.useLoadTablePlugin();
11691
- const fetchTable = React.useCallback(
11692
- () => fetch().then((result) => {
11693
- log$1.debug("Pivot fetch result:", result);
11694
- if (!isCorePlusDh(api)) {
11695
- throw new Error("CorePlus is not available");
11696
- }
11697
- const pivot = new api.coreplus.pivot.PivotTable(result);
11698
- log$1.debug("Created pivot table:", pivot);
11699
- return pivot;
11700
- }),
11701
- [api, fetch]
11702
- );
11703
- const mouseHandlers = React.useMemo(
11704
- () => [(irisGrid2) => new PivotColumnGroupMouseHandler(irisGrid2)],
11705
- []
11706
- );
11707
- const renderer = React.useMemo(() => new IrisGridPivotRenderer(), []);
11708
- const theme = components.useTheme();
11709
- const pivotTheme = React.useMemo(() => {
11710
- log$1.debug("Theme changed, updating pivot theme", theme);
11711
- return components.resolveCssVariablesInRecord(IrisGridPivotTheme);
11712
- }, [theme]);
11713
- const hydratedProps = React.useMemo(
11714
- () => ({
12185
+ const mouseHandlers = usePivotMouseHandlers();
12186
+ const renderer = usePivotRenderer();
12187
+ const theme = usePivotTheme();
12188
+ const getMetricCalculator = usePivotMetricCalculatorFactory();
12189
+ const { status } = objectFetch;
12190
+ if (status === "loading") {
12191
+ log.debug("Widget is loading");
12192
+ return { status: "loading" };
12193
+ }
12194
+ if (status === "error") {
12195
+ log.debug("Error fetching widget:", objectFetch.error);
12196
+ return {
12197
+ status: "error",
12198
+ error: objectFetch.error
12199
+ };
12200
+ }
12201
+ const { fetch } = objectFetch;
12202
+ return {
12203
+ status: "success",
12204
+ props: {
11715
12205
  loadPlugin,
11716
12206
  localDashboardId: id,
11717
- makeModel: async () => {
11718
- const pivotWidget = await fetchTable();
11719
- return new IrisGridPivotModel(api, pivotWidget);
12207
+ makeModel: async function makeModel() {
12208
+ log.debug("Fetching pivot widget");
12209
+ const widget = await fetch();
12210
+ log.debug("Pivot fetch result:", widget);
12211
+ if (!isCorePlusDh(api)) {
12212
+ throw new Error("CorePlus is not available");
12213
+ }
12214
+ const pivotTable = new api.coreplus.pivot.PivotTable(widget);
12215
+ log.debug("Created pivot table:", pivotTable);
12216
+ return new IrisGridPivotModel(api, pivotTable);
11720
12217
  },
11721
12218
  metadata,
11722
12219
  mouseHandlers,
11723
- renderer
11724
- }),
11725
- [api, fetchTable, id, loadPlugin, metadata, mouseHandlers, renderer]
11726
- );
11727
- const hydratedPropsWithTheme = React.useMemo(
11728
- () => ({ ...hydratedProps, theme: pivotTheme }),
11729
- [hydratedProps, pivotTheme]
11730
- );
11731
- return hydratedPropsWithTheme;
12220
+ renderer,
12221
+ theme,
12222
+ getMetricCalculator
12223
+ }
12224
+ };
11732
12225
  }
11733
12226
  const PivotPanel = React.forwardRef(
12227
+ // Unconnected IrisGridPanel type is not exported from dashboard-core-plugins
11734
12228
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
11735
- (props, ref) => {
11736
- const { localDashboardId, fetch, metadata } = props;
11737
- const hydratedProps = useHydratePivotGrid(
11738
- fetch,
11739
- localDashboardId,
11740
- metadata
11741
- );
12229
+ (panelProps, ref) => {
12230
+ const { localDashboardId, metadata, panelState, ...props } = panelProps;
12231
+ const hydrateResult = useHydratePivotGrid(localDashboardId, metadata);
12232
+ if (hydrateResult.status === "loading") {
12233
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(components.LoadingOverlay, { isLoading: true });
12234
+ }
12235
+ if (hydrateResult.status === "error") {
12236
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
12237
+ components.LoadingOverlay,
12238
+ {
12239
+ errorMessage: getErrorMessage(hydrateResult.error),
12240
+ isLoading: false
12241
+ }
12242
+ );
12243
+ }
12244
+ const { props: hydratedProps } = hydrateResult;
11742
12245
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
11743
12246
  dashboardCorePlugins.IrisGridPanel,
11744
12247
  {
11745
12248
  ref,
11746
12249
  ...props,
11747
- ...hydratedProps
12250
+ ...hydratedProps,
12251
+ panelState
11748
12252
  }
11749
12253
  );
11750
12254
  }
@@ -11759,63 +12263,15 @@ const PivotPlugin = {
11759
12263
  icon: icons.dhTable,
11760
12264
  title: "Pivot Table"
11761
12265
  };
11762
- const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
11763
- let nanoid = (size = 21) => {
11764
- let id = "";
11765
- let bytes = crypto.getRandomValues(new Uint8Array(size |= 0));
11766
- while (size--) {
11767
- id += urlAlphabet[bytes[size] & 63];
11768
- }
11769
- return id;
11770
- };
11771
12266
  const VARIABLE_TYPE = "PivotTable";
11772
- const log = Log.module("@deephaven/js-plugin-pivot/DashboardPlugin");
11773
- function DashboardPlugin({
11774
- id,
11775
- layout,
11776
- registerComponent
11777
- }) {
11778
- const handlePanelOpen = React.useCallback(
11779
- ({
11780
- dragEvent,
11781
- fetch,
11782
- metadata = {},
11783
- panelId = nanoid(),
11784
- widget
11785
- }) => {
11786
- const { name, type } = widget;
11787
- if (type !== VARIABLE_TYPE) {
11788
- return;
11789
- }
11790
- log.info("Panel opened of type", type);
11791
- const config = {
11792
- type: "react-component",
11793
- component: PivotPanel.displayName,
11794
- props: {
11795
- localDashboardId: id,
11796
- id: panelId,
11797
- metadata: {
11798
- ...metadata,
11799
- ...widget
11800
- },
11801
- fetch
11802
- },
11803
- title: name ?? void 0,
11804
- id: panelId
11805
- };
11806
- const { root: root2 } = layout;
11807
- dashboard.LayoutUtils.openComponent({ root: root2, config, dragEvent });
11808
- },
11809
- [id, layout]
11810
- );
11811
- React.useEffect(() => {
11812
- assertNotNull(PivotPanel.displayName);
11813
- const cleanups = [registerComponent(PivotPanel.displayName, PivotPanel)];
11814
- return () => {
11815
- cleanups.forEach((cleanup) => cleanup());
11816
- };
11817
- }, [registerComponent]);
11818
- dashboard.useListener(layout.eventHub, "PanelEvent.OPEN", handlePanelOpen);
12267
+ function DashboardPlugin(dashboardProps) {
12268
+ assertNotNull(PivotPanel.displayName);
12269
+ dashboard.useDashboardPanel({
12270
+ dashboardProps,
12271
+ componentName: PivotPanel.displayName,
12272
+ supportedTypes: VARIABLE_TYPE,
12273
+ component: PivotPanel
12274
+ });
11819
12275
  return null;
11820
12276
  }
11821
12277
  exports.DashboardPlugin = DashboardPlugin;