UNPKG

@serenity-is/sleekgrid

Version:

A modern Data Grid / Spreadsheet component

1,392 lines (1,384 loc) 158 kB
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