UNPKG

@deephaven/js-plugin-simple-pivot

Version:
1,411 lines 137 kB
"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