import { NileGrid } from './nile-grid'; import { takeFromRight, giveToRight, totalReducibleRight } from './nile-grid.width'; import { applyColumnsTemplate } from './nile-grid.layout'; /** * @param minColumnWidth Minimum allowed column width * @param resizeStart Guide line element (start) * @param resizeEnd Guide line element (end) * @param col Active column index * @param scrollHeight Height to apply to guides * @param columnWidths Current column widths * @returns void */ export const resizeLinesHandler = ( minColumnWidth: number, resizeStart: HTMLElement, resizeEnd: HTMLElement, col: number, scrollHeight: number, columnWidths: number[], ) => { resizeStart.style.display = 'block'; resizeEnd.style.display = 'block'; resizeStart.style.height = scrollHeight + 'px'; resizeEnd.style.height = scrollHeight + 'px'; const floor = minColumnWidth; const safe = (n: number) => Math.max(0, Math.round(n || 0)); const sum = (arr: number[], endExclusive: number) => safe(arr.slice(0, Math.max(0, endExclusive)).reduce((a, b) => a + (b || 0), 0)); const totalGridWidth = safe(columnWidths.reduce((a, b) => a + (b || 0), 0)); const baseLeft = sum(columnWidths, col); const appliedColWidth = safe(Math.max(floor, columnWidths[col] ?? floor)); let handleLeft = baseLeft + appliedColWidth; const minEdge = baseLeft + floor; const maxEdge = totalGridWidth; handleLeft = Math.min(Math.max(handleLeft, minEdge), maxEdge); handleLeft = Math.max(handleLeft, 20); resizeStart.style.left = `${handleLeft - 6}px`; resizeEnd.style.left = `${handleLeft - 2}px`; }; /** * @param targetWidth New computed width in pixels * @param min Minimum allowed width * @param max Maximum allowed width * @returns Adjusted column width */ export function computeNewWidth(opts: { target: HTMLElement; col: number; widthPx: number; floor: number; columnWidths: number[]; }) { const { target, col, widthPx, floor, columnWidths } = opts; // move this outside - getAttribute const hasSpan = !!target.getAttribute('colspan') && parseInt(target.getAttribute('colspan')!, 10) > 1; const prevW = columnWidths[col] ?? floor; const newWraw = hasSpan ? widthPx - (columnWidths[col - 1] ?? 0) : widthPx; const newW = Math.max(floor, Math.round(Number.isFinite(newWraw) ? newWraw : prevW)); return { prevW, newW, delta0: newW - prevW }; } /** * @param columnWidths Current widths array * @param containerWidth Container total width */ export function resizeNoScroll({ grid, col, prevW, newW, floor }: { grid: NileGrid; col: number; prevW: number; newW: number; floor: number; }) { if (grid.lockedWidthColumns?.[col]) return; let delta = newW - prevW; if (delta > 0) { const rightReducible = totalReducibleRight(grid.columnWidths, col + 1, floor, grid.lockedWidthColumns); if (rightReducible <= 0) return; delta = Math.min(delta, rightReducible); grid.columnWidths[col] = prevW + delta; takeFromRight(grid.columnWidths, col + 1, delta, floor, grid.lockedWidthColumns); } else { const newColW = Math.max(floor, newW); const actualShrink = prevW - newColW; grid.columnWidths[col] = newColW; giveToRight(grid.columnWidths, col + 1, actualShrink); } } /** * @param columnWidths Current widths * @param containerWidth Container width */ export function resizeWithScroll(opts: { grid: NileGrid; col: number; newW: number; }) { const { grid, col, newW } = opts; if (grid.lockedWidthColumns?.[col]) return; grid.columnWidths[col] = newW; } /** * @param el Target element within grid * @returns Scrollbar width compensation value */ export function getScrollbarComp(el: HTMLElement) { const scroller = el.closest('nile-grid') as HTMLElement | null; return scroller ? scroller.offsetWidth - scroller.clientWidth : 0; } /** * @param nileGrid The parent grid * @param columnWidths New column width array */ export function applyAfterResize(grid: any, col: number) { resizeLinesHandler( grid.minColumnWidth, grid.resizeStart, grid.resizeEnd, col, grid.scrollHeight, grid.columnWidths ); applyColumnsTemplate(grid, grid.columnWidths); } export function updateResizeGuides(grid: NileGrid, col: number) { resizeLinesHandler( grid.minColumnWidth, grid.resizeStart, grid.resizeEnd, col, grid.scrollHeight, grid.columnWidths ); }