@serenity-is/sleekgrid
Version:
A modern Data Grid / Spreadsheet component
1,392 lines (1,384 loc) • 158 kB
JavaScript
var Slick = Slick || {};
Slick._ = (() => {
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/grid/index.ts
var grid_exports = {};
__export(grid_exports, {
BasicLayout: () => BasicLayout,
Grid: () => Grid,
gridDefaults: () => gridDefaults
});
// global-externals:_
var { addClass, applyFormatterResultToCellNode, basicRegexSanitizer, columnDefaults, convertCompatFormatter, ensureUniqueColumnIds, escapeHtml, defaultColumnFormat, disableSelection, EventEmitter, EventData, GlobalEditorLock, initializeColumns, H, keyCode, NonDataRow, parsePx, preClickClassName, CellRange, removeClass, RowCell, spacerDiv, titleize } = Slick;
// src/grid/gridoptions.ts
var gridDefaults = {
addNewRowCssClass: "new-row",
alwaysAllowHorizontalScroll: false,
alwaysShowVerticalScroll: false,
asyncEditorLoadDelay: 100,
asyncEditorLoading: false,
asyncPostCleanupDelay: 40,
asyncPostRenderDelay: -1,
autoEdit: true,
autoHeight: false,
cellFlashingCssClass: "flashing",
dataItemColumnValueExtractor: null,
defaultColumnWidth: 80,
defaultFormat: defaultColumnFormat,
editable: false,
editorFactory: null,
editorLock: GlobalEditorLock,
enableAddRow: false,
enableAsyncPostRender: false,
enableAsyncPostRenderCleanup: false,
enableCellNavigation: true,
enableColumnReorder: true,
enableTabKeyNavigation: true,
enableTextSelectionOnCells: false,
explicitInitialization: false,
footerRowHeight: 30,
forceFitColumns: false,
forceSyncScrolling: false,
forceSyncScrollInterval: 250,
formatterFactory: null,
fullWidthRows: false,
groupingPanel: false,
groupingPanelHeight: 30,
headerRowHeight: 30,
leaveSpaceForNewRows: false,
minBuffer: 3,
multiColumnSort: false,
multiSelect: true,
renderAllCells: false,
rowHeight: 30,
selectedCellCssClass: "selected",
showCellSelection: true,
showColumnHeader: true,
showFooterRow: false,
showGroupingPanel: true,
showHeaderRow: false,
showTopPanel: false,
suppressActiveCellChangeOnEdit: false,
topPanelHeight: 30,
useLegacyUI: false,
useCssVars: false
};
// src/grid/basiclayout.ts
var BasicLayout = function() {
var host;
var canvasWidth;
var headersWidth;
var canvas;
var headerCols;
var headerRowCols;
var headerRowSpacer;
var footerRowCols;
var footerRowSpacer;
var topPanel;
var viewport;
function init(hostGrid) {
host = hostGrid;
const spacerW = calcCanvasWidth() + host.getScrollDims().width + "px";
const options = host.getOptions();
const uisd = options.useLegacyUI ? " ui-state-default" : "";
headerCols = H("div", { class: "slick-header-columns", style: (options.rtl ? "right" : "left") + ":-1000px" });
var headerColsS = H("div", { class: "slick-header" + uisd, style: !options.showColumnHeader && "display: none" }, headerCols);
updateHeadersWidth();
headerRowCols = H("div", { class: "slick-headerrow-columns" });
headerRowSpacer = spacerDiv(spacerW);
var headerRow = H("div", { class: "slick-headerrow" + uisd, style: !options.showHeaderRow && "display: none" }, headerRowCols, headerRowSpacer);
topPanel = H("div", { class: "slick-top-panel", style: "width: 10000px" });
var topPanelS = H("div", { class: "slick-top-panel-scroller" + uisd, style: !options.showTopPanel && "display: none" }, topPanel);
canvas = H("div", { class: "grid-canvas", tabIndex: "0", hideFocus: "" });
viewport = H("div", { class: "slick-viewport", tabIndex: "0", hideFocus: "" }, canvas);
footerRowCols = H("div", { class: "slick-footerrow-columns" });
footerRowSpacer = spacerDiv(spacerW);
var footerRow = H("div", { class: "slick-footerrow" + uisd, style: !options.showFooterRow && "display: none" }, footerRowCols, footerRowSpacer);
host.getContainerNode().append(headerColsS, headerRow, topPanelS, viewport, footerRow);
}
function appendCachedRow(_, rowNode) {
rowNode && canvas.appendChild(rowNode);
}
function applyColumnWidths() {
var x = 0, w, rule, cols = host.getColumns(), opts = host.getOptions(), rtl = opts.rtl;
if (opts.useCssVars) {
var styles = host.getContainerNode().style;
for (var i = 0; i < cols.length; i++) {
w = cols[i].width;
var prop = "--l" + i;
var oldVal = styles.getPropertyValue(prop);
var newVal = x + "px";
if (oldVal !== newVal)
styles.setProperty(prop, newVal);
prop = "--r" + i;
oldVal = styles.getPropertyValue(prop);
newVal = canvasWidth - x - w + "px";
if (oldVal !== newVal)
styles.setProperty(prop, newVal);
x += w;
}
} else {
for (var i = 0; i < cols.length; i++) {
w = cols[i].width;
rule = host.getColumnCssRules(i);
rule[rtl ? "right" : "left"].style[rtl ? "right" : "left"] = x + "px";
rule[rtl ? "left" : "right"].style[rtl ? "left" : "right"] = canvasWidth - x - w + "px";
x += w;
}
}
}
function bindAncestorScrollEvents() {
var elem = canvas;
while ((elem = elem.parentNode) != document.body && elem != null) {
if (elem == viewport || elem.scrollWidth != elem.clientWidth || elem.scrollHeight != elem.clientHeight) {
host.bindAncestorScroll(elem);
}
}
}
function calcCanvasWidth() {
var cols = host.getColumns(), i = cols.length;
var rowWidth = 0;
while (i--) {
rowWidth += cols[i].width;
}
return host.getOptions().fullWidthRows ? Math.max(
rowWidth,
host.getAvailableWidth()
) : rowWidth;
}
function updateHeadersWidth() {
headersWidth = 0;
var scrollWidth = host.getScrollDims().width;
var cols = host.getColumns();
for (var i = 0, ii = cols.length; i < ii; i++) {
headersWidth += cols[i].width;
}
headersWidth += scrollWidth;
headersWidth = Math.max(headersWidth, host.getViewportInfo().width) + 1e3;
headerCols.style.width = headersWidth + "px";
}
const destroy = () => {
host = null;
};
function getCanvasNodeFor() {
return canvas;
}
function getCanvasNodes() {
return [canvas];
}
function getCanvasWidth() {
return canvasWidth;
}
function getHeaderCols() {
return [headerCols];
}
function getHeaderColumn(cell) {
return headerCols.children.item(cell);
}
function getHeaderRowCols() {
return [headerRowCols];
}
function getHeaderRowColumn(cell) {
return headerRowCols.childNodes.item(cell);
}
function getHeaderRowColsFor() {
return headerRowCols;
}
function getFooterRowColumn(cell) {
return footerRowCols.childNodes.item(cell);
}
function getFooterRowColsFor() {
return footerRowCols;
}
function getHeaderColsFor() {
return headerCols;
}
function getFooterRowCols() {
return [footerRowCols];
}
function getRowFromCellNode(cellNode) {
return host.getRowFromNode(cellNode.parentElement);
}
function getTopPanelFor() {
return topPanel;
}
function getTopPanelNodes() {
return [topPanel];
}
function getViewportNodeFor() {
return viewport;
}
function getViewportNodes() {
return [viewport];
}
function handleScrollH() {
headerCols.parentElement.scrollLeft = host.getScrollLeft();
topPanel.parentElement.scrollLeft = host.getScrollLeft();
headerRowCols.parentElement.scrollLeft = host.getScrollLeft();
footerRowCols.parentElement.scrollLeft = host.getScrollLeft();
}
function noop() {
}
function realScrollHeightChange() {
canvas.style.height = host.getViewportInfo().realScrollHeight + "px";
}
function reorderViewColumns(viewCols) {
return viewCols;
}
function returnFalse() {
return false;
}
function setOverflow() {
var alwaysVS = host.getOptions().alwaysShowVerticalScroll;
viewport.style.overflowX = "auto";
viewport.style.overflowY = alwaysVS ? "scroll" : host.getOptions().autoHeight ? "hidden" : "auto";
}
function updateCanvasWidth() {
var oldCanvasWidth = canvasWidth;
canvasWidth = calcCanvasWidth();
var scrollWidth = host.getScrollDims().width;
const vpi = host.getViewportInfo();
var canvasWidthPx = canvasWidth + "px";
canvas.style.width = canvasWidthPx;
headerRowCols.style.width = canvasWidthPx;
footerRowCols.style.width = canvasWidthPx;
updateHeadersWidth();
vpi.hasHScroll = canvasWidth > host.getViewportInfo().width - scrollWidth;
var spacerWidthPx = canvasWidth + (vpi.hasVScroll ? scrollWidth : 0) + "px";
headerRowSpacer.style.width = spacerWidthPx;
footerRowSpacer.style.width = spacerWidthPx;
return canvasWidth != oldCanvasWidth;
}
const resizeCanvas = () => {
var vs = host.getViewportInfo();
var _paneTopH = vs.height + vs.topPanelHeight + vs.headerRowHeight + vs.footerRowHeight;
const options = host.getOptions();
if (options.autoHeight) {
host.getContainerNode().style.height = _paneTopH + vs.groupingPanelHeight + parsePx(getComputedStyle(headerCols.parentElement).height) + "px";
viewport.style.height = "";
} else
viewport.style.height = vs.height + "px";
};
function returnZero() {
return 0;
}
var intf = {
afterHeaderColumnDrag: noop,
afterRenderRows: noop,
afterSetOptions: noop,
appendCachedRow,
applyColumnWidths,
beforeCleanupAndRenderCells: noop,
bindAncestorScrollEvents,
calcCanvasWidth,
updateHeadersWidth,
isFrozenRow: returnFalse,
destroy,
getCanvasNodeFor,
getCanvasNodes,
getCanvasWidth,
getFooterRowCols,
getFooterRowColsFor,
getFooterRowColumn,
getHeaderCols,
getHeaderColsFor,
getHeaderColumn,
getHeaderRowCols,
getHeaderRowColsFor,
getHeaderRowColumn,
getRowFromCellNode,
getFrozenCols: returnZero,
getFrozenRowOffset: returnZero,
getFrozenRows: returnZero,
getScrollCanvasY: getCanvasNodeFor,
getScrollContainerX: getViewportNodeFor,
getScrollContainerY: getViewportNodeFor,
getTopPanelFor,
getTopPanelNodes,
getViewportNodeFor,
getViewportNodes,
handleScrollH,
handleScrollV: noop,
init,
layoutName: "basic",
realScrollHeightChange,
reorderViewColumns,
resizeCanvas,
setOverflow,
setPaneVisibility: noop,
setScroller: noop,
updateCanvasWidth
};
return intf;
};
// src/grid/cellnavigator.ts
var CellNavigator = class {
constructor(h) {
this.host = h;
}
findFirstFocusableCell(row) {
var cell = 0;
var cols = this.host.getColumnCount();
while (cell < cols) {
if (this.host.canCellBeActive(row, cell)) {
return cell;
}
cell += this.host.getColspan(row, cell);
}
return null;
}
findLastFocusableCell(row) {
var cell = 0;
var lastFocusableCell = null;
var cols = this.host.getColumnCount();
while (cell < cols) {
if (this.host.canCellBeActive(row, cell)) {
lastFocusableCell = cell;
}
cell += this.host.getColspan(row, cell);
}
return lastFocusableCell;
}
gotoRight(row, cell) {
var cols = this.host.getColumnCount();
if (cell >= cols) {
return null;
}
do {
cell += this.host.getColspan(row, cell);
} while (cell < cols && !this.host.canCellBeActive(row, cell));
if (cell < cols) {
return {
row,
cell,
posX: cell
};
}
return null;
}
gotoLeft(row, cell) {
if (cell <= 0) {
return null;
}
var firstFocusableCell = this.findFirstFocusableCell(row);
if (firstFocusableCell === null || firstFocusableCell >= cell) {
return null;
}
var prev = {
row,
cell: firstFocusableCell,
posX: firstFocusableCell
};
var pos;
while (true) {
pos = this.gotoRight(prev.row, prev.cell);
if (!pos) {
return null;
}
if (pos.cell >= cell) {
return prev;
}
prev = pos;
}
}
gotoDown(row, cell, posX) {
var prevCell;
var rowCount = this.host.getRowCount();
while (true) {
if (++row >= rowCount) {
return null;
}
prevCell = cell = 0;
while (cell <= posX) {
prevCell = cell;
cell += this.host.getColspan(row, cell);
}
if (this.host.canCellBeActive(row, prevCell)) {
return {
row,
cell: prevCell,
posX
};
}
}
}
gotoUp(row, cell, posX) {
var prevCell;
while (true) {
if (--row < 0) {
return null;
}
prevCell = cell = 0;
while (cell <= posX) {
prevCell = cell;
cell += this.host.getColspan(row, cell);
}
if (this.host.canCellBeActive(row, prevCell)) {
return {
row,
cell: prevCell,
posX
};
}
}
}
gotoNext(row, cell, posX) {
if (row == null && cell == null) {
row = cell = posX = 0;
if (this.host.canCellBeActive(row, cell)) {
return {
row,
cell,
posX: cell
};
}
}
var pos = this.gotoRight(row, cell);
if (pos) {
return pos;
}
var firstFocusableCell = null;
var dataLengthIncludingAddNew = this.host.getRowCount();
while (++row < dataLengthIncludingAddNew) {
firstFocusableCell = this.findFirstFocusableCell(row);
if (firstFocusableCell != null) {
return {
row,
cell: firstFocusableCell,
posX: firstFocusableCell
};
}
}
return null;
}
gotoPrev(row, cell, posX) {
var cols = this.host.getColumnCount();
if (row == null && cell == null) {
row = this.host.getRowCount() - 1;
cell = posX = cols - 1;
if (this.host.canCellBeActive(row, cell)) {
return {
row,
cell,
posX: cell
};
}
}
var pos;
var lastSelectableCell;
while (!pos) {
pos = this.gotoLeft(row, cell);
if (pos) {
break;
}
if (--row < 0) {
return null;
}
cell = 0;
lastSelectableCell = this.findLastFocusableCell(row);
if (lastSelectableCell != null) {
pos = {
row,
cell: lastSelectableCell,
posX: lastSelectableCell
};
}
}
return pos;
}
gotoRowStart(row) {
var newCell = this.findFirstFocusableCell(row);
if (newCell === null)
return null;
return {
row,
cell: newCell,
posX: newCell
};
}
gotoRowEnd(row) {
var newCell = this.findLastFocusableCell(row);
if (newCell === null)
return null;
return {
row,
cell: newCell,
posX: newCell
};
}
/**
* @param {string} dir Navigation direction.
* @return {boolean} Whether navigation resulted in a change of active cell.
*/
navigate(dir, activeRow, activeCell, activePosX) {
var tabbingDirections = {
up: -1,
down: 1,
prev: -1,
next: 1,
home: -1,
end: 1
};
const rtl = this.host.isRTL();
tabbingDirections[rtl ? "right" : "left"] = -1;
tabbingDirections[rtl ? "left" : "right"] = 1;
this.host.setTabbingDirection(tabbingDirections[dir]);
var stepFunctions = {
up: this.gotoUp,
down: this.gotoDown,
prev: this.gotoPrev,
next: this.gotoNext,
home: this.gotoRowStart,
end: this.gotoRowEnd
};
stepFunctions[rtl ? "right" : "left"] = this.gotoLeft;
stepFunctions[rtl ? "left" : "right"] = this.gotoRight;
var stepFn = stepFunctions[dir].bind(this);
return stepFn(activeRow, activeCell, activePosX);
}
};
// src/grid/draggable.ts
function windowScrollPosition() {
var _a, _b, _c, _d;
return {
left: (_b = (_a = window.scrollX) != null ? _a : document.documentElement.scrollLeft) != null ? _b : 0,
top: (_d = (_c = window.scrollY) != null ? _c : document.documentElement.scrollTop) != null ? _d : 0
};
}
function Draggable(options) {
let { containerElement } = options;
const { onDragInit, onDragStart, onDrag, onDragEnd, preventDragFromKeys } = options;
let element;
let startX;
let startY;
let deltaX;
let deltaY;
let dragStarted;
if (!containerElement) {
containerElement = document.body;
}
let originaldd = {
dragSource: containerElement,
dragHandle: null
};
function init() {
if (containerElement) {
containerElement.addEventListener("mousedown", userPressed);
containerElement.addEventListener("touchstart", userPressed, { passive: true });
}
}
function executeDragCallbackWhenDefined(callback, evt, dd) {
if (typeof callback === "function") {
return callback(evt, dd);
}
}
function destroy() {
if (containerElement) {
containerElement.removeEventListener("mousedown", userPressed);
containerElement.removeEventListener("touchstart", userPressed);
}
}
function preventDrag(event) {
let eventPrevented = false;
if (preventDragFromKeys) {
preventDragFromKeys.forEach((key) => {
if (event[key]) {
eventPrevented = true;
}
});
}
return eventPrevented;
}
function userPressed(event) {
var _a, _b;
if (!preventDrag(event)) {
element = event.target;
const targetEvent = (_b = (_a = event == null ? void 0 : event.touches) == null ? void 0 : _a[0]) != null ? _b : event;
const { target } = targetEvent;
if (!options.allowDragFrom || (options.allowDragFrom && element.matches(options.allowDragFrom) || options.allowDragFromClosest && element.closest(options.allowDragFromClosest))) {
originaldd.dragHandle = element;
const winScrollPos = windowScrollPosition();
startX = winScrollPos.left + targetEvent.clientX;
startY = winScrollPos.top + targetEvent.clientY;
deltaX = targetEvent.clientX - targetEvent.clientX;
deltaY = targetEvent.clientY - targetEvent.clientY;
originaldd = Object.assign(originaldd, { deltaX, deltaY, startX, startY, target });
const result = executeDragCallbackWhenDefined(onDragInit, event, originaldd);
if (result !== false) {
document.body.addEventListener("mousemove", userMoved);
document.body.addEventListener("touchmove", userMoved, { passive: true });
document.body.addEventListener("mouseup", userReleased);
document.body.addEventListener("touchend", userReleased, { passive: true });
document.body.addEventListener("touchcancel", userReleased, { passive: true });
}
}
}
}
function userMoved(event) {
var _a, _b;
if (!preventDrag(event)) {
const targetEvent = (_b = (_a = event == null ? void 0 : event.touches) == null ? void 0 : _a[0]) != null ? _b : event;
deltaX = targetEvent.clientX - startX;
deltaY = targetEvent.clientY - startY;
const { target } = targetEvent;
if (!dragStarted) {
originaldd = Object.assign(originaldd, { deltaX, deltaY, startX, startY, target });
executeDragCallbackWhenDefined(onDragStart, event, originaldd);
dragStarted = true;
}
originaldd = Object.assign(originaldd, { deltaX, deltaY, startX, startY, target });
executeDragCallbackWhenDefined(onDrag, event, originaldd);
}
}
function userReleased(event) {
document.body.removeEventListener("mousemove", userMoved);
document.body.removeEventListener("touchmove", userMoved);
document.body.removeEventListener("mouseup", userReleased);
document.body.removeEventListener("touchend", userReleased);
document.body.removeEventListener("touchcancel", userReleased);
if (dragStarted) {
const { target } = event;
originaldd = Object.assign(originaldd, { target });
executeDragCallbackWhenDefined(onDragEnd, event, originaldd);
dragStarted = false;
}
}
init();
return { destroy };
}
// src/grid/internal.ts
var maxSupportedCssHeight;
var scrollbarDimensions;
function absBox(elem) {
var box = {
top: elem.offsetTop,
left: elem.offsetLeft,
bottom: 0,
right: 0,
width: elem.offsetWidth,
height: elem.offsetHeight,
visible: true
};
box.bottom = box.top + box.height;
box.right = box.left + box.width;
var offsetParent = elem.offsetParent;
while ((elem = elem.parentNode) != document.body && elem != null) {
if (box.visible && elem.scrollHeight != elem.offsetHeight && getComputedStyle(elem).overflowY !== "visible") {
box.visible = box.bottom > elem.scrollTop && box.top < elem.scrollTop + elem.clientHeight;
}
if (box.visible && elem.scrollWidth != elem.offsetWidth && getComputedStyle(elem).overflowX != "visible") {
box.visible = box.right > elem.scrollLeft && box.left < elem.scrollLeft + elem.clientWidth;
}
box.left -= elem.scrollLeft;
box.top -= elem.scrollTop;
if (elem === offsetParent) {
box.left += elem.offsetLeft;
box.top += elem.offsetTop;
offsetParent = elem.offsetParent;
}
box.bottom = box.top + box.height;
box.right = box.left + box.width;
}
return box;
}
function autosizeColumns(cols, availWidth, absoluteColMinWidth) {
var i, c, widths = [], shrinkLeeway = 0, total = 0, prevTotal;
for (i = 0; i < cols.length; i++) {
c = cols[i];
widths.push(c.width);
total += c.width;
if (c.resizable) {
shrinkLeeway += c.width - Math.max(c.minWidth, absoluteColMinWidth);
}
}
prevTotal = total;
while (total > availWidth && shrinkLeeway) {
var shrinkProportion = (total - availWidth) / shrinkLeeway;
for (i = 0; i < cols.length && total > availWidth; i++) {
c = cols[i];
var width = widths[i];
if (!c.resizable || width <= c.minWidth || width <= absoluteColMinWidth) {
continue;
}
var absMinWidth = Math.max(c.minWidth, absoluteColMinWidth);
var shrinkSize = Math.floor(shrinkProportion * (width - absMinWidth)) || 1;
shrinkSize = Math.min(shrinkSize, width - absMinWidth);
total -= shrinkSize;
shrinkLeeway -= shrinkSize;
widths[i] -= shrinkSize;
}
if (prevTotal <= total) {
break;
}
prevTotal = total;
}
prevTotal = total;
while (total < availWidth) {
var growProportion = availWidth / total;
for (i = 0; i < cols.length && total < availWidth; i++) {
c = cols[i];
var currentWidth = widths[i];
var growSize;
if (!c.resizable || c.maxWidth <= currentWidth) {
growSize = 0;
} else {
growSize = Math.min(Math.floor(growProportion * currentWidth) - currentWidth, c.maxWidth - currentWidth || 1e6) || 1;
}
total += growSize;
widths[i] += total <= availWidth ? growSize : 0;
}
if (prevTotal >= total) {
break;
}
prevTotal = total;
}
var reRender = false;
for (i = 0; i < cols.length; i++) {
if (cols[i].rerenderOnResize && cols[i].width != widths[i]) {
reRender = true;
}
cols[i].width = widths[i];
}
return reRender;
}
function getMaxSupportedCssHeight(recalc) {
if (!recalc && maxSupportedCssHeight != null)
return maxSupportedCssHeight;
return maxSupportedCssHeight = navigator.userAgent.toLowerCase().match(/gecko\//) ? 4e6 : 32e6;
}
function getScrollBarDimensions(recalc) {
if (!scrollbarDimensions || recalc) {
var c = document.body.appendChild(H("div", {
style: "position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow: scroll;border:0"
}));
scrollbarDimensions = {
width: Math.round(c.offsetWidth - c.clientWidth),
height: Math.round(c.offsetWidth - c.clientHeight)
};
c.remove();
}
return scrollbarDimensions;
}
function simpleArrayEquals(arr1, arr2) {
if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length !== arr2.length)
return false;
arr1 = arr1.slice().sort();
arr2 = arr2.slice().sort();
for (var i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i])
return false;
}
return true;
}
function sortToDesiredOrderAndKeepRest(columns, idOrder) {
if (idOrder.length == 0)
return columns;
var orderById = {}, colIdxById = {}, result = [];
for (var i = 0; i < idOrder.length; i++)
orderById[idOrder[i]] = i;
for (i = 0; i < columns.length; i++)
colIdxById[columns[i].id] = i;
function takeFrom(i2) {
for (var j = i2; j < columns.length; j++) {
var c2 = columns[j];
if (i2 != j && orderById[c2.id] != null)
break;
result.push(c2);
colIdxById[c2.id] = null;
}
}
if (orderById[columns[0].id] == null)
takeFrom(0);
for (var id of idOrder) {
i = colIdxById[id];
if (i != null)
takeFrom(i);
}
for (i = 0; i < columns.length; i++) {
var c = columns[i];
if (colIdxById[c.id] != null) {
result.push(c);
colIdxById[c.id] = null;
}
}
return result;
}
function calcMinMaxPageXOnDragStart(cols, colIdx, pageX, forceFit, absoluteColMinWidth) {
var shrinkLeewayOnRight = null, stretchLeewayOnRight = null, j, c;
if (forceFit) {
shrinkLeewayOnRight = 0;
stretchLeewayOnRight = 0;
for (j = colIdx + 1; j < cols.length; j++) {
c = cols[j];
if (c.resizable) {
if (stretchLeewayOnRight != null) {
if (c.maxWidth) {
stretchLeewayOnRight += c.maxWidth - c.previousWidth;
} else {
stretchLeewayOnRight = null;
}
}
shrinkLeewayOnRight += c.previousWidth - Math.max(c.minWidth || 0, absoluteColMinWidth);
}
}
}
var shrinkLeewayOnLeft = 0, stretchLeewayOnLeft = 0;
for (j = 0; j <= colIdx; j++) {
c = cols[j];
if (c.resizable) {
if (stretchLeewayOnLeft != null) {
if (c.maxWidth) {
stretchLeewayOnLeft += c.maxWidth - c.previousWidth;
} else {
stretchLeewayOnLeft = null;
}
}
shrinkLeewayOnLeft += c.previousWidth - Math.max(c.minWidth || 0, absoluteColMinWidth);
}
}
if (shrinkLeewayOnRight === null) {
shrinkLeewayOnRight = 1e5;
}
if (shrinkLeewayOnLeft === null) {
shrinkLeewayOnLeft = 1e5;
}
if (stretchLeewayOnRight === null) {
stretchLeewayOnRight = 1e5;
}
if (stretchLeewayOnLeft === null) {
stretchLeewayOnLeft = 1e5;
}
return {
maxPageX: pageX + Math.min(shrinkLeewayOnRight, stretchLeewayOnLeft),
minPageX: pageX - Math.min(shrinkLeewayOnLeft, stretchLeewayOnRight)
};
}
function shrinkOrStretchColumn(cols, colIdx, d, forceFit, absoluteColMinWidth) {
var c, j, x, actualMinWidth;
if (d < 0) {
x = d;
for (j = colIdx; j >= 0; j--) {
c = cols[j];
if (c.resizable) {
actualMinWidth = Math.max(c.minWidth || 0, absoluteColMinWidth);
if (x && c.previousWidth + x < actualMinWidth) {
x += c.previousWidth - actualMinWidth;
c.width = actualMinWidth;
} else {
c.width = c.previousWidth + x;
x = 0;
}
}
}
if (forceFit) {
x = -d;
for (j = colIdx + 1; j < cols.length; j++) {
c = cols[j];
if (c.resizable) {
if (x && c.maxWidth && c.maxWidth - c.previousWidth < x) {
x -= c.maxWidth - c.previousWidth;
c.width = c.maxWidth;
} else {
c.width = c.previousWidth + x;
x = 0;
}
}
}
}
} else {
x = d;
for (j = colIdx; j >= 0; j--) {
c = cols[j];
if (c.resizable) {
if (x && c.maxWidth && c.maxWidth - c.previousWidth < x) {
x -= c.maxWidth - c.previousWidth;
c.width = c.maxWidth;
} else {
c.width = c.previousWidth + x;
x = 0;
}
}
}
if (forceFit) {
x = -d;
for (j = colIdx + 1; j < cols.length; j++) {
c = cols[j];
if (c.resizable) {
actualMinWidth = Math.max(c.minWidth || 0, absoluteColMinWidth);
if (x && c.previousWidth + x < actualMinWidth) {
x += c.previousWidth - actualMinWidth;
c.width = actualMinWidth;
} else {
c.width = c.previousWidth + x;
x = 0;
}
}
}
}
}
}
function addUiStateHover() {
this == null ? void 0 : this.classList.add("ui-state-hover");
}
function removeUiStateHover() {
this == null ? void 0 : this.classList.remove("ui-state-hover");
}
function getVBoxDelta(el) {
if (!el)
return 0;
var style = getComputedStyle(el);
if (style.boxSizing === "border-box")
return 0;
var p = ["border-top-width", "border-bottom-width", "padding-top", "padding-bottom"];
var delta = 0;
for (var val of p)
delta += parsePx(style.getPropertyValue(val)) || 0;
return delta;
}
function getInnerWidth(el) {
var _a;
var style = getComputedStyle(el);
var width = (_a = parsePx(style.width)) != null ? _a : 0;
if (style.boxSizing != "border-box")
return Math.max(0, width);
var p = ["border-left-width", "border-right-width", "padding-left", "padding-right"];
for (var val of p)
width -= parsePx(style.getPropertyValue(val)) || 0;
return Math.max(width, 0);
}
// src/grid/grid.ts
var Grid = class _Grid {
constructor(container, data, columns, options) {
this._cellCssClasses = {};
this._cellHeightDiff = 0;
this._cellWidthDiff = 0;
this._colLeft = [];
this._colRight = [];
this._headerColumnWidthDiff = 0;
this._ignoreScrollUntil = 0;
this._page = 0;
this._pageOffset = 0;
this._pagingActive = false;
this._pagingIsLastPage = false;
this._plugins = [];
this._postProcessCleanupQueue = [];
this._postProcessedRows = {};
this._postProcessGroupId = 0;
this._rowsCache = {};
this._scrollLeft = 0;
this._scrollLeftPrev = 0;
this._scrollLeftRendered = 0;
this._scrollTop = 0;
this._scrollTopPrev = 0;
this._scrollTopRendered = 0;
this._selectedRows = [];
this._sortColumns = [];
this._tabbingDirection = 1;
this._uid = "sleekgrid_" + Math.round(1e6 * Math.random());
this._viewportInfo = {};
this._vScrollDir = 1;
this._boundAncestorScroll = [];
this.onActiveCellChanged = new EventEmitter();
this.onActiveCellPositionChanged = new EventEmitter();
this.onAddNewRow = new EventEmitter();
this.onBeforeCellEditorDestroy = new EventEmitter();
this.onBeforeDestroy = new EventEmitter();
this.onBeforeEditCell = new EventEmitter();
this.onBeforeFooterRowCellDestroy = new EventEmitter();
this.onBeforeHeaderCellDestroy = new EventEmitter();
this.onBeforeHeaderRowCellDestroy = new EventEmitter();
this.onCellChange = new EventEmitter();
this.onCellCssStylesChanged = new EventEmitter();
this.onClick = new EventEmitter();
this.onColumnsReordered = new EventEmitter();
this.onColumnsResized = new EventEmitter();
this.onCompositeEditorChange = new EventEmitter();
this.onContextMenu = new EventEmitter();
this.onDblClick = new EventEmitter();
this.onDrag = new EventEmitter();
this.onDragEnd = new EventEmitter();
this.onDragInit = new EventEmitter();
this.onDragStart = new EventEmitter();
this.onFooterRowCellRendered = new EventEmitter();
this.onHeaderCellRendered = new EventEmitter();
this.onHeaderClick = new EventEmitter();
this.onHeaderContextMenu = new EventEmitter();
this.onHeaderMouseEnter = new EventEmitter();
this.onHeaderMouseLeave = new EventEmitter();
this.onHeaderRowCellRendered = new EventEmitter();
this.onKeyDown = new EventEmitter();
this.onMouseEnter = new EventEmitter();
this.onMouseLeave = new EventEmitter();
this.onScroll = new EventEmitter();
this.onSelectedRowsChanged = new EventEmitter();
this.onSort = new EventEmitter();
this.onValidationError = new EventEmitter();
this.onViewportChanged = new EventEmitter();
this.handleSelectedRangesChanged = (e, ranges) => {
var previousSelectedRows = this._selectedRows.slice(0);
this._selectedRows = [];
var hash = {}, cols = this._cols;
for (var i = 0; i < ranges.length; i++) {
for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
if (!hash[j]) {
this._selectedRows.push(j);
hash[j] = {};
}
for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
if (this.canCellBeSelected(j, k)) {
hash[j][cols[k].id] = this._options.selectedCellCssClass;
}
}
}
}
this.setCellCssStyles(this._options.selectedCellCssClass, hash);
if (!simpleArrayEquals(previousSelectedRows, this._selectedRows)) {
var caller = e && e.detail && e.detail.caller || "click";
var newSelectedAdditions = this._selectedRows.filter((i2) => previousSelectedRows.indexOf(i2) < 0);
var newSelectedDeletions = previousSelectedRows.filter((i2) => this._selectedRows.indexOf(i2) < 0);
this.trigger(this.onSelectedRowsChanged, {
rows: this.getSelectedRows(),
previousSelectedRows,
caller,
changedSelectedRows: newSelectedAdditions,
changedUnselectedRows: newSelectedDeletions
}, e);
}
this._selectedRows = [];
hash = {}, cols = this._cols;
for (var i = 0; i < ranges.length; i++) {
for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
if (!hash[j]) {
this._selectedRows.push(j);
hash[j] = {};
}
for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
if (this.canCellBeSelected(j, k)) {
hash[j][cols[k].id] = this._options.selectedCellCssClass;
}
}
}
}
};
this.viewOnRowCountChanged = () => {
this.updateRowCount();
this.render();
};
this.viewOnRowsChanged = (_, args) => {
this.invalidateRows(args.rows);
this.render();
this.updateGrandTotals();
};
this.viewOnDataChanged = () => {
this.invalidate();
this.render();
};
this.resizeCanvas = () => {
if (!this._initialized) {
return;
}
this.calcViewportSize();
this._layout.resizeCanvas();
if (!this._scrollDims || !this._scrollDims.width) {
this._scrollDims = getScrollBarDimensions(true);
}
if (this._options.forceFitColumns) {
this.autosizeColumns();
}
this.updateRowCount();
this.handleScroll();
this._scrollLeftRendered = -1;
this.render();
};
this.render = () => {
if (!this._initialized) {
return;
}
var visible = this.getVisibleRange();
var rendered = this.getRenderedRange();
this.cleanupRows(rendered);
if (this._scrollLeftRendered != this._scrollLeft) {
this._layout.beforeCleanupAndRenderCells(rendered);
this.cleanUpAndRenderCells(rendered);
}
this.renderRows(rendered);
this._layout.afterRenderRows(rendered);
this._postProcessFromRow = visible.top;
this._postProcessToRow = Math.min(this.getDataLengthIncludingAddNew() - 1, visible.bottom);
this.startPostProcessing();
this._scrollTopRendered = this._scrollTop;
this._scrollLeftRendered = this._scrollLeft;
this._lastRenderTime = (/* @__PURE__ */ new Date()).getTime();
this._hRender = null;
};
this.handleHeaderRowScroll = (e) => {
if (this._ignoreScrollUntil >= (/* @__PURE__ */ new Date()).getTime())
return;
var scrollLeft = e.target.scrollLeft;
if (scrollLeft != this._layout.getScrollContainerX().scrollLeft) {
this._layout.getScrollContainerX().scrollLeft = scrollLeft;
}
};
this.handleFooterRowScroll = (e) => {
if (this._ignoreScrollUntil >= (/* @__PURE__ */ new Date()).getTime())
return;
var scrollLeft = e.target.scrollLeft;
if (scrollLeft != this._layout.getScrollContainerX().scrollLeft) {
this._layout.getScrollContainerX().scrollLeft = scrollLeft;
}
};
this.asyncPostProcessRows = () => {
var dataLength = this.getDataLength();
var cols = this._cols;
while (this._postProcessFromRow <= this._postProcessToRow) {
var row = this._vScrollDir >= 0 ? this._postProcessFromRow++ : this._postProcessToRow--;
var cacheEntry = this._rowsCache[row];
if (!cacheEntry || row >= dataLength) {
continue;
}
if (!this._postProcessedRows[row]) {
this._postProcessedRows[row] = {};
}
this.ensureCellNodesInRowsCache(row);
for (var x in cacheEntry.cellNodesByColumnIdx) {
var columnIdx = parseInt(x, 10);
var m = cols[columnIdx];
var processedStatus = this._postProcessedRows[row][columnIdx];
if (processedStatus !== "R") {
if (m.asyncPostRender || m.asyncPostRenderCleanup) {
var node = cacheEntry.cellNodesByColumnIdx[columnIdx];
if (node) {
m.asyncPostRender && m.asyncPostRender(node, row, this.getDataItem(row), m, processedStatus === "C");
}
}
this._postProcessedRows[row][columnIdx] = "R";
}
}
if (this._options.asyncPostRenderDelay >= 0) {
this._hPostRender = setTimeout(this.asyncPostProcessRows, this._options.asyncPostRenderDelay);
return;
}
}
};
this.handleActiveCellPositionChange = () => {
if (!this._activeCellNode) {
return;
}
this.trigger(this.onActiveCellPositionChanged, {});
if (this._currentEditor) {
var cellBox = this.getActiveCellPosition();
if (this._currentEditor.show && this._currentEditor.hide) {
if (!cellBox.visible) {
this._currentEditor.hide();
} else {
this._currentEditor.show();
}
}
if (this._currentEditor.position) {
this._currentEditor.position(cellBox);
}
}
};
var _a, _b, _c, _d;
this._data = data;
this._colDefaults = Object.assign({}, columnDefaults);
this._options = options = Object.assign({}, gridDefaults, options);
options.jQuery = this._jQuery = options.jQuery === void 0 ? typeof jQuery !== "undefined" ? jQuery : void 0 : options.jQuery;
options.sanitizer = options.sanitizer === void 0 ? typeof DOMPurify !== "undefined" && typeof DOMPurify.sanitize == "function" ? DOMPurify.sanitize : basicRegexSanitizer : options.sanitizer;
if (this._jQuery && container instanceof this._jQuery)
this._container = container[0];
else if (container instanceof Element)
this._container = container;
else if (typeof container === "string")
this._container = document.querySelector(container);
else if (container.length)
container = container[0];
if (this._container == null) {
throw new Error("SleekGrid requires a valid container, " + container + " does not exist in the DOM.");
}
this._container.classList.add("slick-container");
this._emptyNode = (_a = options.emptyNode) != null ? _a : this._jQuery ? function(node) {
this(node).empty();
}.bind(this._jQuery) : function(node) {
node.innerHTML = "";
};
this._removeNode = (_b = options.removeNode) != null ? _b : this._jQuery ? function(node) {
this(node).remove();
}.bind(this._jQuery) : function(node) {
node.remove();
};
if (options == null ? void 0 : options.createPreHeaderPanel) {
if (options.groupingPanel == null)
options.groupingPanel = true;
if (options.groupingPanelHeight == null && options.preHeaderPanelHeight != null)
options.groupingPanelHeight = options.preHeaderPanelHeight;
if (options.showGroupingPanel == null && options.showPreHeaderPanel != null)
options.showGroupingPanel = options.showPreHeaderPanel;
}
this._options.rtl = (_c = this._options.rtl) != null ? _c : document.body.classList.contains("rtl") || typeof getComputedStyle != "undefined" && getComputedStyle(this._container).direction == "rtl";
if (this._options.rtl)
this._container.classList.add("rtl");
else
this._container.classList.add("ltr");
this.validateAndEnforceOptions();
this._colDefaults.width = options.defaultColumnWidth;
this._editController = {
"commitCurrentEdit": this.commitCurrentEdit.bind(this),
"cancelCurrentEdit": this.cancelCurrentEdit.bind(this)
};
if (this._jQuery)
this._jQuery(this._container).empty();
else
this._container.innerHTML = "";
this._container.style.overflow = "hidden";
this._container.style.outline = "0";
this._container.classList.add(this._uid);
if (this._options.useLegacyUI)
this._container.classList.add("ui-widget");
if (!/relative|absolute|fixed/.test(getComputedStyle(this._container).position)) {
this._container.style.position = "relative";
}
this._container.appendChild(this._focusSink1 = H("div", {
class: "slick-focus-sink",
hideFocus: "",
style: "position:fixed;width:0!important;height:0!important;top:0;left:0;outline:0!important;",
tabIndex: "0"
}));
this._layout = (_d = options.layoutEngine) != null ? _d : new BasicLayout();
this.setInitialCols(columns);
this._scrollDims = getScrollBarDimensions();
if (options.groupingPanel) {
this.createGroupingPanel();
}
this._layout.init({
cleanUpAndRenderCells: this.cleanUpAndRenderCells.bind(this),
bindAncestorScroll: this.bindAncestorScroll.bind(this),
getAvailableWidth: this.getAvailableWidth.bind(this),
getCellFromPoint: this.getCellFromPoint.bind(this),
getColumnCssRules: this.getColumnCssRules.bind(this),
getColumns: this.getColumns.bind(this),
getContainerNode: this.getContainerNode.bind(this),
getDataLength: this.getDataLength.bind(this),
getOptions: this.getOptions.bind(this),
getRowFromNode: this.getRowFromNode.bind(this),
getScrollDims: this.getScrollBarDimensions.bind(this),
getScrollLeft: () => this._scrollLeft,
getScrollTop: () => this._scrollTop,
getViewportInfo: () => this._viewportInfo,
renderRows: this.renderRows.bind(this)
});
this._container.append(this._focusSink2 = this._focusSink1.cloneNode());
if (options.viewportClass)
this.getViewports().forEach((vp) => addClass(vp, options.viewportClass));
if (!options.explicitInitialization) {
this.init();
}
this.bindToData();
}
createGroupingPanel() {
if (this._groupingPanel || !this._focusSink1)
return;
this._focusSink1.insertAdjacentElement("afterend", this._groupingPanel = H("div", {
class: "slick-grouping-panel",
style: !this._options.showGroupingPanel ? "display: none" : null
}));
if (this._options.createPreHeaderPanel) {
this._groupingPanel.appendChild(H("div", { class: "slick-preheader-panel" }));
}
}
bindAncestorScroll(elem) {
if (this._jQuery)
this._jQuery(elem).on("scroll", this.handleActiveCellPositionChange);
else
elem.addEventListener("scroll", this.handleActiveCellPositionChange);
this._boundAncestorScroll.push(elem);
}
init() {
if (this._initialized)
return;
this._initialized = true;
this.calcViewportSize();
this.measureCellPaddingAndBorder();
var viewports = this.getViewports();
if (this._jQuery && !this._options.enableTextSelectionOnCells) {
this._jQuery(viewports).on("selectstart.ui", () => {
return this._jQuery(this).is("input,textarea");
});
}
this._layout.setPaneVisibility();
this._layout.setScroller();
this.setOverflow();
this.updateViewColLeftRight();
this.createColumnHeaders();
this.createColumnFooters();
this.setupColumnSort();
this.createCssRules();
this.resizeCanvas();
this._layout.bindAncestorScrollEvents();
const onEvent = (el, type, listener) => {
if (this._jQuery)
this._jQuery(el).on(type, listener);
else
el.addEventListener(type, listener);
};
onEvent(this._container, "resize", this.resizeCanvas);
viewports.forEach((vp) => {
var scrollTicking = false;
onEvent(vp, "scroll", (e) => {
if (!scrollTicking) {
scrollTicking = true;
window.requestAnimationFrame(() => {
this.handleScroll();
scrollTicking = false;
});
}
});
});
if (this._jQuery && this._jQuery.fn.mousewheel && (this.hasFrozenColumns() || this.hasFrozenRows())) {
this._jQuery(viewports).on("mousewheel", this.handleMouseWheel.bind(this));
}
this._layout.getHeaderCols().forEach((hs) => {
disableSelection(hs);
onEvent(hs, "contextmenu", this.handleHeaderContextMenu.bind(this));
onEvent(hs, "click", this.handleHeaderClick.bind(this));
if (this._jQuery) {
this._jQuery(hs).on("mouseenter", ".slick-header-column", this.handleHeaderMouseEnter.bind(this)).on("mouseleave", ".slick-header-column", this.handleHeaderMouseLeave.bind(this));
} else {
hs.addEventListener("mouseenter", (e) => e.target.closest(".slick-header-column") && this.handleHeaderMouseEnter(e));
hs.addEventListener("mouseleave", (e) => e.target.closest(".slick-header-column") && this.handleHeaderMouseLeave(e));
}
});
this._layout.getHeaderRowCols().forEach((el) => {
onEvent(el.parentElement, "scroll", this.handleHeaderRowScroll);
});
this._layout.getFooterRowCols().forEach((el) => {
onEvent(el.parentElement, "scroll", this.handleFooterRowScroll);
});
[this._focusSink1, this._focusSink2].forEach((fs) => onEvent(fs, "keydown", this.handleKeyDown.bind(this)));
var canvases = Array.from(this.getCanvases());
canvases.forEach((canvas) => {
onEvent(canvas, "keydown", this.handleKeyDown.bind(this));
onEvent(canvas, "click", this.handleClick.bind(this));
onEvent(canvas, "dblclick", this.handleDblClick.bind(this));
onEvent(canvas, "contextmenu", this.handleContextMenu.bind(this));
});
if (this._jQuery && this._jQuery.fn.drag) {
this._jQuery(canvases).on("draginit", this.handleDragInit.bind(this)).on("dragstart", { distance: 3 }, this.handleDragStart.bind(this)).on("drag", this.handleDrag.bind(this)).on("dragend", this.handleDragEnd.bind(this));
} else {
t