@deephaven/js-plugin-simple-pivot
Version:
Simple Pivot plugin for Deephaven
1,411 lines • 137 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const plugin = require("@deephaven/plugin");
const icons = require("@deephaven/icons");
const React = require("react");
const irisGrid = require("@deephaven/iris-grid");
const jsapiBootstrap = require("@deephaven/jsapi-bootstrap");
const components = require("@deephaven/components");
const Log = require("@deephaven/log");
const jsapiUtils = require("@deephaven/jsapi-utils");
require("react-redux");
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
var jsxRuntimeExports = {};
var jsxRuntime = {
get exports() {
return jsxRuntimeExports;
},
set exports(v) {
jsxRuntimeExports = v;
}
};
var reactJsxRuntime_production_min = {};
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === void 0) {
throw new TypeError("Object.assign cannot be called with null or undefined");
}
return Object(val);
}
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
var test1 = new String("abc");
test1[5] = "de";
if (Object.getOwnPropertyNames(test1)[0] === "5") {
return false;
}
var test2 = {};
for (var i = 0; i < 10; i++) {
test2["_" + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function(n2) {
return test2[n2];
});
if (order2.join("") !== "0123456789") {
return false;
}
var test3 = {};
"abcdefghijklmnopqrst".split("").forEach(function(letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join("") !== "abcdefghijklmnopqrst") {
return false;
}
return true;
} catch (err) {
return false;
}
}
shouldUseNative() ? Object.assign : function(target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
/** @license React v17.0.2
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var f = React, g = 60103;
reactJsxRuntime_production_min.Fragment = 60107;
if ("function" === typeof Symbol && Symbol.for) {
var h = Symbol.for;
g = h("react.element");
reactJsxRuntime_production_min.Fragment = h("react.fragment");
}
var m = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, n = Object.prototype.hasOwnProperty, p = { key: true, ref: true, __self: true, __source: true };
function q(c, a, k) {
var b, d = {}, e = null, l = null;
void 0 !== k && (e = "" + k);
void 0 !== a.key && (e = "" + a.key);
void 0 !== a.ref && (l = a.ref);
for (b in a)
n.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]);
if (c && c.defaultProps)
for (b in a = c.defaultProps, a)
void 0 === d[b] && (d[b] = a[b]);
return { $$typeof: g, type: c, key: e, ref: l, props: d, _owner: m.current };
}
reactJsxRuntime_production_min.jsx = q;
reactJsxRuntime_production_min.jsxs = q;
(function(module2) {
{
module2.exports = reactJsxRuntime_production_min;
}
})(jsxRuntime);
var EMPTY_ARRAY = Object.freeze([]);
function _defineProperty$6(obj, key, value) {
key = _toPropertyKey$6(key);
if (key in obj) {
Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey$6(arg) {
var key = _toPrimitive$6(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
function _toPrimitive$6(input, hint) {
if (typeof input !== "object" || input === null)
return input;
var prim = input[Symbol.toPrimitive];
if (prim !== void 0) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object")
return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
class CanceledPromiseError extends Error {
constructor() {
super(...arguments);
_defineProperty$6(this, "isCanceled", true);
}
}
const CanceledPromiseError$1 = CanceledPromiseError;
class EventShimCustomEvent extends CustomEvent {
// The fields declared are so TS plays nicely w/ event-target-shim and the browser CustomEvent
// They don't actually do anything other than tell TS to not complain that they aren't set in the constructor
// If declare is removed, then the properties are initialized to undefined which breaks this class
// This will be the default for tsc and babel at some point
// https://github.com/babel/babel/issues/12128#issuecomment-702119272
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor(typeArg, eventInitDict) {
super(typeArg, eventInitDict);
}
}
function _defineProperty$5(obj, key, value) {
key = _toPropertyKey$5(key);
if (key in obj) {
Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey$5(arg) {
var key = _toPrimitive$5(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
function _toPrimitive$5(input, hint) {
if (typeof input !== "object" || input === null)
return input;
var prim = input[Symbol.toPrimitive];
if (prim !== void 0) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object")
return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
class TimeoutError extends Error {
constructor() {
super(...arguments);
_defineProperty$5(this, "isTimeout", true);
}
}
const TimeoutError$1 = TimeoutError;
class PromiseUtils {
/**
* Creates a promise that can be canceled by calling the `cancel` function
* Pass an optional `cleanupFunc` to perform actions on the resolved item after promise is cancelled.
* @param promise The item to resolve
* @param cleanup Function to cleanup the resolved item after cancelation. Called after both this promise is cancelled and the wrapped item was resolved (order does not matter).
*/
static makeCancelable(promise, cleanup) {
var hasCanceled = false;
var resolved;
var rejectFn;
var wrappedPromise = new Promise((resolve, reject) => {
rejectFn = reject;
Promise.resolve(promise).then((val) => {
if (hasCanceled) {
if (cleanup) {
cleanup(val);
}
} else {
resolved = val;
resolve(val);
}
}).catch((error) => reject(error));
});
wrappedPromise.cancel = () => {
hasCanceled = true;
rejectFn(new CanceledPromiseError$1());
if (resolved != null && cleanup) {
cleanup(resolved);
}
};
return wrappedPromise;
}
static isCanceled(error) {
return error instanceof CanceledPromiseError$1;
}
static isTimedOut(error) {
return error instanceof TimeoutError$1;
}
/**
* Wrap a callback call in a Promise + setTimeout.
* @param timeoutMs
* @param callback
*/
static withTimeout(timeoutMs, callback) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(callback());
} catch (err) {
reject(err);
}
}, timeoutMs);
});
}
}
function assertNotNull(value) {
var message = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "Value is null or undefined";
if (value == null)
throw new Error(message);
}
function getErrorMessage(error) {
var errorObj = error;
if (error instanceof CustomEvent) {
errorObj = error.detail;
}
var message = "";
if (errorObj instanceof Error) {
message = errorObj.message;
} else if (errorObj != null) {
message = "".concat(errorObj);
}
message = message.trim();
if (message.length > 0) {
return message;
}
return void 0;
}
var safeIsNaN = Number.isNaN || function ponyfill(value) {
return typeof value === "number" && value !== value;
};
function isEqual(first, second) {
if (first === second) {
return true;
}
if (safeIsNaN(first) && safeIsNaN(second)) {
return true;
}
return false;
}
function areInputsEqual(newInputs, lastInputs) {
if (newInputs.length !== lastInputs.length) {
return false;
}
for (var i = 0; i < newInputs.length; i++) {
if (!isEqual(newInputs[i], lastInputs[i])) {
return false;
}
}
return true;
}
function memoizeOne(resultFn, isEqual2) {
if (isEqual2 === void 0) {
isEqual2 = areInputsEqual;
}
var lastThis;
var lastArgs = [];
var lastResult;
var calledOnce = false;
function memoized() {
var newArgs = [];
for (var _i = 0; _i < arguments.length; _i++) {
newArgs[_i] = arguments[_i];
}
if (calledOnce && lastThis === this && isEqual2(newArgs, lastArgs)) {
return lastResult;
}
lastResult = resultFn.apply(this, newArgs);
calledOnce = true;
lastThis = this;
lastArgs = newArgs;
return lastResult;
}
return memoized;
}
function _defineProperty$4(obj, key, value) {
key = _toPropertyKey$4(key);
if (key in obj) {
Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey$4(arg) {
var key = _toPrimitive$4(arg, "string");
return typeof key === "symbol" ? key : String(key);
}
function _toPrimitive$4(input, hint) {
if (typeof input !== "object" || input === null)
return input;
var prim = input[Symbol.toPrimitive];
if (prim !== void 0) {
var res = prim.call(input, hint || "default");
if (typeof res !== "object")
return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
var SELECTION_DIRECTION;
(function(SELECTION_DIRECTION2) {
SELECTION_DIRECTION2["DOWN"] = "DOWN";
SELECTION_DIRECTION2["UP"] = "UP";
SELECTION_DIRECTION2["LEFT"] = "LEFT";
SELECTION_DIRECTION2["RIGHT"] = "RIGHT";
})(SELECTION_DIRECTION || (SELECTION_DIRECTION = {}));
class GridRange {
/**
* Returns a normalized array of indexes ensuring left <= right and top <= bottom
* @param startColumn Start column index
* @param startRow Start row index
* @param endColumn End column index
* @param endRow End row index
* @returns Array containing normalized indexes [left, top, right, bottom]
*/
static normalize(startColumn, startRow, endColumn, endRow) {
var left = startColumn;
var top = startRow;
var right = endColumn;
var bottom = endRow;
if (left != null && right != null && right < left) {
left = right;
right = startColumn;
}
if (top != null && bottom != null && bottom < top) {
top = bottom;
bottom = startRow;
}
return [left, top, right, bottom];
}
/**
* Makes a GridRange ensuring startColumn <= endColumn, startRow <= endRow
* @param startColumn Start column index
* @param startRow Start row index
* @param endColumn End column index
* @param endRow End row index
* @returns Normalized GridRange
*/
static makeNormalized(startColumn, startRow, endColumn, endRow) {
return new GridRange(...GridRange.normalize(startColumn, startRow, endColumn, endRow));
}
/**
* Creates a GridRange representing a single cell
* @param column Column index
* @param row Row index
* @returns GridRange representing the cell
*/
static makeCell(column, row) {
return new GridRange(column, row, column, row);
}
/**
* Creates a GridRange representing an infinite length column
* @param column Column index
* @returns GridRange representing the column
*/
static makeColumn(column) {
return new GridRange(column, null, column, null);
}
/**
* Creates a GridRange representing an infinite length row
* @param row Row index
* @returns GridRange representing the row
*/
static makeRow(row) {
return new GridRange(null, row, null, row);
}
/**
* Returns the minimum value between 2 range indexes or null if at least 1 is null
* @param index1 First grid range index
* @param index2 Second grid range index
* @returns Minimum index or null if either index is null
*/
static minOrNull(index1, index2) {
if (index1 == null || index2 == null) {
return null;
}
return Math.min(index1, index2);
}
/**
* Returns the maximum value between 2 range indexes or null if at least 1 is null
* @param index1 First grid range index
* @param index2 Second grid range index
* @returns Maximum index or null if either index is null
*/
static maxOrNull(index1, index2) {
if (index1 == null || index2 == null) {
return null;
}
return Math.max(index1, index2);
}
/**
* Consolidate the passed in ranges to the minimum set, merging overlapping ranges.
* @param ranges The ranges to consolidate
* @returns Consolidated ranges
*/
static consolidate(ranges) {
var result = ranges.slice();
var wasModified = true;
while (wasModified) {
wasModified = false;
for (var i = 0; i < result.length && !wasModified; i += 1) {
var range = result[i];
for (var j = result.length - 1; j > i; j -= 1) {
var other = result[j];
if (range.contains(other)) {
result.splice(j, 1);
} else if (other.contains(range)) {
wasModified = true;
result[i] = other;
result.splice(j, 1);
break;
} else if (range.startRow === other.startRow && range.endRow === other.endRow) {
if (range.touches(other)) {
var {
startRow,
endRow
} = range;
var startColumn = GridRange.minOrNull(range.startColumn, other.startColumn);
var endColumn = GridRange.maxOrNull(range.endColumn, other.endColumn);
wasModified = true;
result[i] = new GridRange(startColumn, startRow, endColumn, endRow);
result.splice(j, 1);
break;
}
} else if (range.startColumn === other.startColumn && range.endColumn === other.endColumn) {
if (range.touches(other)) {
var {
startColumn: _startColumn,
endColumn: _endColumn
} = range;
var _startRow = GridRange.minOrNull(range.startRow, other.startRow);
var _endRow = GridRange.maxOrNull(range.endRow, other.endRow);
wasModified = true;
result[i] = new GridRange(_startColumn, _startRow, _endColumn, _endRow);
result.splice(j, 1);
break;
}
}
}
}
}
return result;
}
/**
* Checks if the 1-D ranges between 2 index pairs overlap or are continuous.
* For example ranges [0, 1] and [2, 3] are continuous and will return true.
* [0, 1] and [1, 3] overlap and return true.
* [0, 1] and [3, 4] do not overlap and have a gap so this will return false.
* @param start1 Start of 1st range
* @param end1 End of 1st range
* @param start2 Start of 2nd range
* @param end2 End of 2nd range
* @returns True if the ranges overlap or touch, else false
*/
static isAxisRangeTouching(start1, end1, start2, end2) {
if (start1 == null) {
if (end1 == null) {
return true;
}
if (start2 == null) {
return true;
}
return start2 <= end1 + 1;
}
if (end1 == null) {
if (end2 == null) {
return true;
}
return end2 >= start1 - 1;
}
if (start2 == null) {
if (end2 == null) {
return true;
}
return start1 <= end2 + 1;
}
if (end2 == null) {
return end1 >= start2 - 1;
}
if (start2 >= start1 - 1) {
return start2 <= end1 + 1;
}
return end2 >= start1 - 1;
}
/**
* Checks if 2 arrays of ranges are the same ranges
* @param ranges1 First array of ranges
* @param ranges2 Second array of ranges
* @returns True if the arrays contain the same ranges in the same order
*/
static rangeArraysEqual(ranges1, ranges2) {
if (ranges1 === ranges2) {
return true;
}
if (ranges1 == null || ranges2 == null || ranges1.length !== ranges2.length) {
return false;
}
for (var i = 0; i < ranges1.length; i += 1) {
if (!ranges1[i].equals(ranges2[i])) {
return false;
}
}
return true;
}
/**
* Get the intersection (overlapping area) of two ranges
* @param range One range to check for the intersection
* @param otherRange The other range to check for the intersection
* @returns Intersection of the two ranges. If they do not intersect, returns `null`.
*/
static intersection(range, otherRange) {
var _startColumn2, _endColumn2, _startRow2, _endRow2, _endColumn3, _endRow3;
if (range.equals(otherRange)) {
return range;
}
var {
startColumn,
startRow,
endColumn,
endRow
} = range;
startColumn = startColumn != null && otherRange.startColumn != null ? Math.max(startColumn, otherRange.startColumn) : (_startColumn2 = startColumn) !== null && _startColumn2 !== void 0 ? _startColumn2 : otherRange.startColumn;
endColumn = endColumn != null && otherRange.endColumn != null ? Math.min(endColumn, otherRange.endColumn) : (_endColumn2 = endColumn) !== null && _endColumn2 !== void 0 ? _endColumn2 : otherRange.endColumn;
startRow = startRow != null && otherRange.startRow != null ? Math.max(startRow, otherRange.startRow) : (_startRow2 = startRow) !== null && _startRow2 !== void 0 ? _startRow2 : otherRange.startRow;
endRow = endRow != null && otherRange.endRow != null ? Math.min(endRow, otherRange.endRow) : (_endRow2 = endRow) !== null && _endRow2 !== void 0 ? _endRow2 : otherRange.endRow;
if (startColumn != null && startColumn > ((_endColumn3 = endColumn) !== null && _endColumn3 !== void 0 ? _endColumn3 : -1) || startRow != null && startRow > ((_endRow3 = endRow) !== null && _endRow3 !== void 0 ? _endRow3 : -1)) {
return null;
}
return new GridRange(startColumn, startRow, endColumn, endRow);
}
/**
* Subtracts 1 range from another
* @param range The range to be subtracted from
* @param subtractRange The range to subtract from within this range
* @returns The ranges needed to represent the remaining
*/
static subtractFromRange(range, subtractRange) {
var result = [];
var subtract = GridRange.intersection(range, subtractRange);
if (subtract == null) {
return [range];
}
if (subtract.startRow != null && (range.startRow == null || range.startRow < subtract.startRow)) {
result.push(new GridRange(range.startColumn, range.startRow, range.endColumn, subtract.startRow - 1));
}
if (subtract.startColumn != null && (range.startColumn == null || range.startColumn < subtract.startColumn)) {
result.push(new GridRange(range.startColumn, subtract.startRow, subtract.startColumn - 1, subtract.endRow));
}
if (subtract.endColumn != null && (range.endColumn == null || range.endColumn > subtract.endColumn)) {
result.push(new GridRange(subtract.endColumn + 1, subtract.startRow, range.endColumn, subtract.endRow));
}
if (subtract.endRow != null && (range.endRow == null || range.endRow > subtract.endRow)) {
result.push(new GridRange(range.startColumn, subtract.endRow + 1, range.endColumn, range.endRow));
}
return result;
}
/**
* Subtract a range from multiple ranges
* @param ranges The ranges to be subtracted from
* @param subtractRange The range to subtract from within these ranges
* @returns The ranges needed to represent the remaining
*/
static subtractFromRanges(ranges, subtractRange) {
var result = [];
for (var i = 0; i < ranges.length; i += 1) {
result.push(...GridRange.subtractFromRange(ranges[i], subtractRange));
}
return result;
}
/**
* Subtract multiple ranges from multiple ranges
* @param ranges The ranges to be subtracted from
* @param subtractRanges The ranges to subtract from within these ranges
* @returns The ranges needed to represent the remaining
*/
static subtractRangesFromRanges(ranges, subtractRanges) {
var result = [...ranges];
for (var i = 0; i < subtractRanges.length; i += 1) {
result = GridRange.subtractFromRanges(result, subtractRanges[i]);
}
return result;
}
/**
* Test if a given range is bounded (all values are non-null)
* @param range The range to test
* @returns True if this range is bounded, false otherwise
*/
static isBounded(range) {
return range.startRow != null && range.startColumn != null && range.endRow != null && range.endColumn != null;
}
/**
* Converts any GridRange passed in that is a full row or column selection to be bound
* to the `columnCount` and `rowCount` passed in
*
* @param range The range to get the bounded range of
* @param columnCount The number of columns
* @param rowCount The number of rows
* @returns The passed in GridRange with any null values filled in
*/
static boundedRange(range, columnCount, rowCount) {
var _range$startColumn, _range$startRow, _range$endColumn, _range$endRow;
if (GridRange.isBounded(range)) {
return range;
}
return new GridRange((_range$startColumn = range.startColumn) !== null && _range$startColumn !== void 0 ? _range$startColumn : 0, (_range$startRow = range.startRow) !== null && _range$startRow !== void 0 ? _range$startRow : 0, (_range$endColumn = range.endColumn) !== null && _range$endColumn !== void 0 ? _range$endColumn : columnCount - 1, (_range$endRow = range.endRow) !== null && _range$endRow !== void 0 ? _range$endRow : rowCount - 1);
}
/**
* Converts the GridRanges passed in to be bound to the `columnCount` and `rowCount` passed in
*
* @param ranges The ranges to get the bounded ranges of
* @param columnCount The number of columns
* @param rowCount The number of rows
* @returns The passed in GridRange with any null values filled in
*/
static boundedRanges(ranges, columnCount, rowCount) {
return ranges.map((r) => GridRange.boundedRange(r, columnCount, rowCount));
}
/**
* Offsets a GridRange by the specified amount in the x and y directions
*
* @param range The range to offset
* @param columnOffset The number of columns to offset
* @param rowOffset The number of rows to offset
* @returns The new grid range offset from the original
*/
static offset(range, columnOffset, rowOffset) {
return new GridRange(range.startColumn != null ? range.startColumn + columnOffset : null, range.startRow != null ? range.startRow + rowOffset : null, range.endColumn != null ? range.endColumn + columnOffset : null, range.endRow != null ? range.endRow + rowOffset : null);
}
/**
* Get the next cell given the selected ranges and the current cell
* @param ranges The selected bounded ranges within the grid
* @param column The cursor column, or null if none focused
* @param row The cursor row, or null if none focused
* @param direction The direction in which to select next
* @returns The next cell to focus, or null if there should be no more focus
*/
static nextCell(ranges) {
var column = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : null;
var row = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : null;
var direction = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : GridRange.SELECTION_DIRECTION.DOWN;
if (ranges.length === 0) {
return null;
}
var rangeIndex = -1;
if (column != null && row != null) {
rangeIndex = ranges.findIndex((r) => r.containsCell(column, row));
if (rangeIndex >= 0) {
var range = ranges[rangeIndex];
var nextCell = range.nextCell(column, row, direction);
if (nextCell != null) {
return nextCell;
}
}
}
switch (direction) {
case GridRange.SELECTION_DIRECTION.DOWN:
case GridRange.SELECTION_DIRECTION.RIGHT: {
var nextRangeIndex = rangeIndex < ranges.length - 1 ? rangeIndex + 1 : 0;
var nextRange = ranges[nextRangeIndex];
return nextRange.startCell(direction);
}
case GridRange.SELECTION_DIRECTION.LEFT:
case GridRange.SELECTION_DIRECTION.UP: {
var _nextRangeIndex = rangeIndex > 0 ? rangeIndex - 1 : ranges.length - 1;
var _nextRange = ranges[_nextRangeIndex];
return _nextRange.startCell(direction);
}
default:
throw new Error("Invalid direction: ".concat(direction));
}
}
/**
* Count the number of cells in the provided grid ranges
* @param ranges The ranges to count the rows of
* @returns The number of cells in the ranges, or `NaN` if any of the ranges were unbounded
*/
static cellCount(ranges) {
return ranges.reduce((cellCount, range) => {
var _range$endRow2, _range$startRow2, _range$endColumn2, _range$startColumn2;
return cellCount + (((_range$endRow2 = range.endRow) !== null && _range$endRow2 !== void 0 ? _range$endRow2 : NaN) - ((_range$startRow2 = range.startRow) !== null && _range$startRow2 !== void 0 ? _range$startRow2 : NaN) + 1) * (((_range$endColumn2 = range.endColumn) !== null && _range$endColumn2 !== void 0 ? _range$endColumn2 : NaN) - ((_range$startColumn2 = range.startColumn) !== null && _range$startColumn2 !== void 0 ? _range$startColumn2 : NaN) + 1);
}, 0);
}
/**
* Count the number of rows in the provided grid ranges
* @param ranges The ranges to count the rows of
* @returns The number of rows in the ranges, or `NaN` if any of the ranges were unbounded
*/
static rowCount(ranges) {
return ranges.reduce((rowCount, range) => {
var _range$endRow3, _range$startRow3;
return rowCount + ((_range$endRow3 = range.endRow) !== null && _range$endRow3 !== void 0 ? _range$endRow3 : NaN) - ((_range$startRow3 = range.startRow) !== null && _range$startRow3 !== void 0 ? _range$startRow3 : NaN) + 1;
}, 0);
}
/**
* Count the number of columns in the provided grid ranges
* @param ranges The ranges to count the columns of
* @returns The number of columns in the ranges, or `NaN` if any of the ranges were unbounded
*/
static columnCount(ranges) {
return ranges.reduce((columnCount, range) => {
var _range$endColumn3, _range$startColumn3;
return columnCount + ((_range$endColumn3 = range.endColumn) !== null && _range$endColumn3 !== void 0 ? _range$endColumn3 : NaN) - ((_range$startColumn3 = range.startColumn) !== null && _range$startColumn3 !== void 0 ? _range$startColumn3 : NaN) + 1;
}, 0);
}
/**
* Check if the provided ranges contain the provided cell
* @param ranges The ranges to check
* @param column The column index
* @param row The row index
* @returns True if the cell is within the provided ranges, false otherwise.
*/
static containsCell(ranges, column, row) {
for (var i = 0; i < ranges.length; i += 1) {
var range = ranges[i];
if (range.containsCell(column, row)) {
return true;
}
}
return false;
}
/**
* Iterate through each cell in the provided ranges
* @param ranges The ranges to iterate through
* @param {(column: number, row: number, index: number) => void} callback The callback to execute. `index` is the index within that range
* @param {GridRange.SELECTION_DIRECTION} direction The direction to iterate in
*/
static forEachCell(ranges, callback) {
var direction = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : GridRange.SELECTION_DIRECTION.RIGHT;
for (var i = 0; i < ranges.length; i += 1) {
ranges[i].forEach(callback, direction);
}
}
constructor(startColumn, startRow, endColumn, endRow) {
_defineProperty$4(this, "startColumn", void 0);
_defineProperty$4(this, "startRow", void 0);
_defineProperty$4(this, "endColumn", void 0);
_defineProperty$4(this, "endRow", void 0);
this.startColumn = startColumn;
this.startRow = startRow;
this.endColumn = endColumn;
this.endRow = endRow;
}
/**
* Checks if the provided range is equivalent to this range (same start and end column/row indexes)
* @param other Grid range to check against
* @returns True if the ranges cover the same area
*/
equals(other) {
return this.startColumn === other.startColumn && this.startRow === other.startRow && this.endColumn === other.endColumn && this.endRow === other.endRow;
}
/**
* Checks if this GridRange contains another range
* @param other The range to check
* @returns True if this GridRange completely contains `other`
* */
contains(other) {
return (this.startColumn == null || other.startColumn != null && this.startColumn <= other.startColumn) && (this.startRow == null || other.startRow != null && this.startRow <= other.startRow) && (this.endColumn == null || other.endColumn != null && this.endColumn >= other.endColumn) && (this.endRow == null || other.endRow != null && this.endRow >= other.endRow);
}
/**
* Check if the provided cell is in this range
* @param column The column to check
* @param row The row to check
* @returns True if this cell is within this range
*/
containsCell(column, row) {
if (column == null || row == null) {
return false;
}
return (this.startColumn == null || this.startColumn <= column) && (this.endColumn == null || this.endColumn >= column) && (this.startRow == null || this.startRow <= row) && (this.endRow == null || this.endRow >= row);
}
/**
* Check if the provided range touches (or overlaps) this GridRange
* Effectively checks if the 2 ranges could be represented by 1 continuous range
* @param other The range to check
* @returns True if this GridRange touches `other`
* */
touches(other) {
return GridRange.isAxisRangeTouching(this.startRow, this.endRow, other.startRow, other.endRow) && GridRange.isAxisRangeTouching(this.startColumn, this.endColumn, other.startColumn, other.endColumn);
}
/**
* Subtracts a range from this range
* @param other The range to deselect from within this range
* @returns The ranges needed to represent the remaining
*/
subtract(other) {
return GridRange.subtractFromRange(this, other);
}
/**
* Get the first cell in this range. Throws if this range is unbounded.
*
* @param direction The direction to get the starting cell in. Defaults to DOWN
* @returns The first cell in this range in the direction specified
*/
startCell() {
var direction = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : GridRange.SELECTION_DIRECTION.DOWN;
if (!GridRange.isBounded(this)) {
throw new Error("Cannot get the startCell of an unbounded range");
}
switch (direction) {
case GridRange.SELECTION_DIRECTION.DOWN:
case GridRange.SELECTION_DIRECTION.RIGHT:
return {
column: this.startColumn,
row: this.startRow
};
case GridRange.SELECTION_DIRECTION.LEFT:
case GridRange.SELECTION_DIRECTION.UP: {
return {
column: this.endColumn,
row: this.endRow
};
}
default:
throw new Error("Invalid direction: ".concat(direction));
}
}
/**
* Get the next cell in the direction specified. Throws if this range is unbounded.
* If already at the bounds of the range in that direction, wrap to the next column or row
* If at the end of the entire range, return null
* If outside of the range, returns the next cell closest within this range.
*
* @param column The cursor column
* @param row The cursor row
* @param direction The direction to go in
* @returns The next cell in the direction specified, or `null` if at the end of the range
*/
nextCell(column, row, direction) {
if (!GridRange.isBounded(this)) {
throw new Error("Bounded range required");
}
if (column == null || row == null) {
throw new Error("Require a non-null cursor");
}
var {
startColumn,
endColumn,
startRow,
endRow
} = this;
switch (direction) {
case GridRange.SELECTION_DIRECTION.DOWN:
if (row < endRow) {
return {
column,
row: Math.max(row + 1, startRow)
};
}
if (column < endColumn) {
return {
column: Math.max(column + 1, startColumn),
row: startRow
};
}
break;
case GridRange.SELECTION_DIRECTION.UP:
if (row > startRow) {
return {
column,
row: Math.min(row - 1, endRow)
};
}
if (column > startColumn) {
return {
column: Math.min(column - 1, endColumn),
row: endRow
};
}
break;
case GridRange.SELECTION_DIRECTION.RIGHT:
if (column < endColumn) {
return {
column: Math.max(column + 1, startColumn),
row
};
}
if (row < endRow) {
return {
column: startColumn,
row: Math.max(row + 1, startRow)
};
}
break;
case GridRange.SELECTION_DIRECTION.LEFT:
if (column > startColumn) {
return {
column: Math.min(column - 1, endColumn),
row
};
}
if (row > startRow) {
return {
column: endColumn,
row: Math.min(row - 1, endRow)
};
}
break;
default:
throw new Error("Invalid direction: ".concat(direction));
}
return null;
}
/**
* Iterate through each cell in the range
* @param callback Callback to execute. `index` is the index within this range
* @param direction The direction to iterate in
*/
forEach(callback) {
var direction = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : GridRange.SELECTION_DIRECTION.RIGHT;
var i = 0;
var {
column: c,
row: r
} = this.startCell(direction);
while (c != null && r != null) {
var _this$nextCell;
callback(c, r, i);
i += 1;
({
column: c,
row: r
} = (_this$nextCell = this.nextCell(c, r, direction)) !== null && _this$nextCell !== void 0 ? _this$nextCell : {});
}
}
}
_defineProperty$4(GridRange, "SELECTION_DIRECTION", SELECTION_DIRECTION);
var propTypesExports = {};
var propTypes = {
get exports() {
return propTypesExports;
},
set exports(v) {
propTypesExports = v;
}
};
var ReactPropTypesSecret$1 = "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";
var ReactPropTypesSecret_1 = ReactPropTypesSecret$1;
var ReactPropTypesSecret = ReactPropTypesSecret_1;
function emptyFunction() {
}
function emptyFunctionWithReset() {
}
emptyFunctionWithReset.resetWarningCache = emptyFunction;
var factoryWithThrowingShims = function() {
function shim(props, propName, componentName, location, propFullName, secret) {
if (secret === ReactPropTypesSecret) {
return;
}
var err = new Error(
"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types"
);
err.name = "Invariant Violation";
throw err;
}
shim.isRequired = shim;
function getShim() {
return shim;
}
var ReactPropTypes = {
array: shim,
bigint: shim,
bool: shim,
func: shim,
number: shim,
object: shim,
string: shim,
symbol: shim,
any: shim,
arrayOf: getShim,
element: shim,
elementType: shim,
instanceOf: getShim,
node: shim,
objectOf: getShim,
oneOf: getShim,
oneOfType: getShim,
shape: getShim,
exact: getShim,
checkPropTypes: emptyFunctionWithReset,
resetWarningCache: emptyFunction
};
ReactPropTypes.PropTypes = ReactPropTypes;
return ReactPropTypes;
};
{
propTypes.exports = factoryWithThrowingShims();
}
const KEY_TABLE_PIVOT_COLUMN = "__PIVOT_COLUMN";
const PIVOT_COLUMN_PREFIX = "PIVOT_C_";
const TOTALS_COLUMN = "__TOTALS_COLUMN";
function getSimplePivotColumnMap(data, columns, pivotIdColumn) {
const columnMap = [];
const rowIter = data.fullIndex.iterator();
while (rowIter.hasNext()) {
const rowKey = rowIter.next().value;
const value = [];
for (let i = 0; i < columns.length; i += 1) {
value.push(data.getData(rowKey, columns[i]));
}
columnMap.push([
`${PIVOT_COLUMN_PREFIX}${data.getData(rowKey, pivotIdColumn)}`,
value.join(", ")
]);
}
return columnMap;
}
function isColumnMapComplete(columnMap, columns) {
return !columns.some(
(c) => c.name.startsWith(PIVOT_COLUMN_PREFIX) && !columnMap.has(c.name)
);
}
const log$3 = Log.module(
"@deephaven/js-plugin-simple-pivot/IrisGridSimplePivotModel"
);
function makeModel(dh, table, formatter) {
return new irisGrid.IrisGridTableModel(dh, table, formatter);
}
const GRAND_TOTAL_VALUE = "Grand Total";
class IrisGridSimplePivotModel extends irisGrid.IrisGridModel {
constructor(dh, table, keyTable, totalsTable, columnMap, schema, pivotWidget, formatter = new jsapiUtils.Formatter(dh)) {
super(dh);
__publicField(this, "keyTable");
__publicField(this, "keyTableSubscription");
__publicField(this, "columnMap");
__publicField(this, "nextColumnMap");
__publicField(this, "schema");
__publicField(this, "pivotWidget");
__publicField(this, "model");
__publicField(this, "schemaPromise");
__publicField(this, "nextModel");
__publicField(this, "totalsTable");
__publicField(this, "nextTotalsTable");
__publicField(this, "totalsRowMap");
__publicField(this, "_layoutHints");
__publicField(this, "getCachedColumnHeaderGroups", memoizeOne(
(columnMap, schema) => [
new irisGrid.ColumnHeaderGroup({
name: schema.pivotDescription,
children: schema.rowColNames,
depth: 1,
childIndexes: schema.rowColNames.map((_, index) => index)
}),
new irisGrid.ColumnHeaderGroup({
name: schema.columnColNames.join(", "),
children: [...columnMap.keys()],
depth: 1,
childIndexes: [...columnMap.keys()].map((_, index) => index)
})
]
));
__publicField(this, "getCachedMovedColumns", memoizeOne(
(columns, hasTotals) => {
if (!hasTotals) {
return EMPTY_ARRAY;
}
const totalsColumnIndex = columns.findIndex(
(c) => c.name === TOTALS_COLUMN
);
if (totalsColumnIndex === -1) {
log$3.warn("Totals column not found in getCachedMovedColumns");
return EMPTY_ARRAY;
}
const movedColumns = [];
if (totalsColumnIndex < columns.length - 1) {
movedColumns.push({
from: totalsColumnIndex,
to: columns.length - 1
});
}
return movedColumns;
}
));
__publicField(this, "getCachedColumns", memoizeOne(
(columnMap, tableColumns) => tableColumns.map((c) => this.createDisplayColumn(c, columnMap))
));
__publicField(this, "getColumnIndicesByNameMap", memoizeOne(
(columns) => {
const indices = /* @__PURE__ */ new Map();
columns.forEach(({ name }, i) => indices.set(name, i));
return indices;
}
));
this.addEventListener = this.addEventListener.bind(this);
this.removeEventListener = this.removeEventListener.bind(this);
this.dispatchEvent = this.dispatchEvent.bind(this);
this.handleModelEvent = this.handleModelEvent.bind(this);
this.handleKeyTableUpdate = this.handleKeyTableUpdate.bind(this);
this.handleSchemaUpdate = this.handleSchemaUpdate.bind(this);
this.handleTotalsUpdate = this.handleTotalsUpdate.bind(this);
this.model = makeModel(dh, table, formatter);
this.schemaPromise = null;
this.nextModel = null;
this.keyTable = keyTable;
this.keyTableSubscription = null;
this.pivotWidget = pivotWidget;
this.totalsTable = null;
this.nextTotalsTable = null;
this.totalsRowMap = /* @__PURE__ */ new Map();
this.columnMap = new Map(
schema.hasTotals ? [[TOTALS_COLUMN, "Totals"], ...columnMap] : columnMap
);
this.nextColumnMap = null;
this.pivotWidget = pivotWidget;
this.schema = schema;
this._layoutHints = {
backColumns: [TOTALS_COLUMN],
hiddenColumns: [],
frozenColumns: [],
columnGroups: [],
areSavedLayoutsAllowed: false,
frontColumns: [],
searchDisplayMode: this.dh.SearchDisplayMode.SEARCH_DISPLAY_HIDE
};
this.startListeningToKeyTable();
this.startListeningToSchema();
this.setTotalsTable(totalsTable);
return new Proxy(this, {
// We want to use any properties on the proxy model if defined
// If not, then proxy to the underlying model
get(target, prop, receiver) {
var _a;
const proxyHasGetter = ((_a = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(target), prop)) == null ? void 0 : _a.get) != null;
if (proxyHasGetter) {
return Reflect.get(target, prop, receiver);
}
const proxyHasProp = Object.prototype.hasOwnProperty.call(target, prop);
const proxyHasFn = Object.prototype.hasOwnProperty.call(
Object.getPrototypeOf(target),
prop
);
const trueTarget = proxyHasProp || proxyHasFn ? target : target.model;
return Reflect.get(trueTarget, prop);
},
set(target, prop, value) {
var _a;
const proxyHasSetter = ((_a = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(target), prop)) == null ? void 0 : _a.set) != null;
const proxyHasProp = Object.prototype.hasOwnProperty.call(target, prop);
if (proxyHasSetter || proxyHasProp) {
return Reflect.set(target, prop, value, target);
}
return Reflect.set(target.model, prop, value, target.model);
}
});
}
/**
* Add displayName property to the given column
* @param column Column to add displayName to
* @param columnMap Column name map
* @returns Column with the displayName
*/
createDisplayColumn(column, columnMap) {
return new Proxy(column, {
get: (target, prop) => {
if (prop === "displayName") {
return columnMap.get(column.name) ?? column.name;
}
return Reflect.get(target, prop);
}
});
}
get initialColumnHeaderGroups() {
return this.getCachedColumnHeaderGroups(this.columnMap, this.schema);
}
get initialMovedColumns() {
log$3.debug("get initialMovedColumns");
return this.getCachedMovedColumns(
this.model.columns,
this.schema.hasTotals
);
}
get columns() {
return this.getCachedColumns(this.columnMap, this.model.columns);
}
get isChartBuilderAvailable() {
return false;
}
get isFormatColumnsAvailable() {
return false;
}
get isOrganizeColumnsAvailable() {
return false;
}
get isSeekRowAvailable() {
return false;
}
get isSelectDistinctAvailable() {
return false;
}
get isReversible() {
return false;
}
isFilterable(columnIndex) {
return columnIndex < this.schema.rowColNames.length;
}
isColumnSortable(columnIndex) {
return columnIndex < this.schema.rowColNames.length;
}
get isTotalsAvailable() {
return false;
}
get isRollupAvailable() {
return false;
}
get isExportAvailable() {
return false;
}
get isCustomColumnsAvailable() {
return false;
}
get rowCount() {
return this.model.rowCount + (this.schema.hasTotals ? 1 : 0);
}
valueForCell(x, y) {
if (this.schema.hasTotals && y === this.rowCount - 1) {
if (x >= this.schema.rowColNames.length) {
return this.totalsRowMap.get(this.columns[x].name);
}
return x === 0 ? GRAND_TOTAL_VALUE : void 0;
}
return this.model.valueForCell(x, y);
}
textForCell(x, y) {
return this.schema.hasTotals && y === this.rowCount - 1 && x === 0 ? GRAND_TOTAL_VALUE : (
// Pass the context so model.textForCell calls this.valueForCell instead of model.valueForCell
this.model.textForCell.call(this, x, y)
);
}
setTotalsTable(totalsTable) {
log$3.debug("setTotalsTable", totalsTable);
this.stopListeningToTotals();
if (totalsTable == null) {
this.totalsTable = null;
return;
}
this.totalsTable = totalsTable;
this.startListeningToTotals();
this.totalsTable.setViewport(0, 0);
}
startListeningToKeyTable() {
const { dh, keyTable } = this;
log$3.debug("Start Listening to key table");
this.keyTableSubscription = keyTable.subscribe(keyTable.columns);
this.keyTableSubscription.addEventListener(
dh.Table.EVENT_UPDATED,
this.handleKeyTableUpdate
);
}
stopListeningToKeyTable() {
var _a;
log$3.debug("Stop Listening to key table subscription");
(_a = this.keyTableSubscription) == null ? void 0 : _a.close();
this.keyTableSubscription = null;
}
startListeningToSchema() {
const { dh, pivotWidget } = this;
log$3.debug("Start Listening to schema");
pivotWidget.addEventListener(
dh.Widget.EVENT_MESSAGE,
this.handleSchemaUpdate
);
}
stopListeningToSchema() {
const { dh, pivotWidget } = this;
log$3.debug("Stop Listening to schema");
pivotWidget.removeEventListener(
dh.Widget.EVENT_MESSAGE,
this.handleSchemaUpdate
);
}
startListeningToTotals() {
var _a;
log$3.debug("Start Listening to totals table");
(_a = this.totalsTable) == null ? void 0 : _a.addEventListener(
this.dh.Table.EVENT_UPDATED,
this.handleTotalsUpdate
);
}
stopListeningToTotals() {
var _a;
log$3.debug("Stop Listening to totals table");
(_a = this.totalsTable) == null ? void 0 : _a.removeEventListener(
this.dh.Table.EVENT_UPDATED,
this.handleTotalsUpdate
);
}
handleKeyTableUpdate(e) {
log$3.debug("Key table updated");
const pivotIdColumn = this.keyTable.findColumn(KEY_TABLE_PIVOT_COLUMN);
const columns = this.keyTable.columns.filter(
(c) => c.name !== KEY_TABLE_PIVOT_COLUMN
);
const keyColumns = getSimplePivotColumnMap(
e.detail,
columns,
pivotIdColumn
);
if (this.schema.hasTotals) {
keyColumns.push([TOTALS_COLUMN, "Totals"]);
}
const columnMap = new Map(keyColumns);
if (this.nextModel == null) {
if (isColumnMapComplete(columnMap, this.model.columns)) {
log$3.debug2(
"Key table update matches the existing model, update columns"
);
this.columnMap = columnMap;
this.columnHeaderGroups = this.getCachedColumnHeaderGroups(
this.columnMap,
this.schema
);
this.dispatchEvent(
new EventShimCustomEvent(irisGrid.IrisGridModel.EVENT.COLUMNS_CHANGED, {
detail: this.columns
})
);
} else {
log$3.debug2(
"Key table update does not match the existing model, save column map for the next schema update"
);
this.nextColumnMap = columnMap;
}
return;
}
if (isColumnMapComplete(columnMap, this.nextModel.columns)) {
log$3.debug2("Key table update matches the saved model, update the model");
assertNotNull(this.nextTotalsTable);
this.setModel(this.nextModel, columnMap, this.nextTotalsTable);
this.nextModel = null;
this.nextTotalsTable = null;
} else {
log$3.debug2(
"Key table update does not match the saved model, save column map for the next schema update"
);
this.nextColumnMap = columnMap;
}
}
async handleSchemaUpdate(e) {
log$3.debug("Schema updated");
const tables = e.detail.exportedObjects;
const tablePromise = tables[0].fetch();
const totalsTablePromise = tables.length === 2 ? tables[1].fetch() : null;
const pivotTablesPromise = Promise.all([tablePromise, totalsTablePromise]);
this.setNextSchema(pivotTablesPromise);
}
copyTotalsData(data) {
this.totalsRowMap = /* @__PURE__ */ new Map();
data.columns.forEach((column) => {
this.totalsRowMap.set(column.name, data.getData(0, column));
});
}
handleTotalsUpdate(event) {
log$3.debug("handleTotalsUpdate", event.detail);
this.copyTotalsData(event.deta