From a0866afe054b1564e6d3a1f7223d17718f286a20 Mon Sep 17 00:00:00 2001 From: Jonathan Meyer <26874831+atmgrifter00@users.noreply.github.com> Date: Wed, 12 Apr 2023 17:14:57 -0500 Subject: [PATCH 01/48] Working changes. --- .../src/table-column/base/template.ts | 5 +- packages/nimble-components/src/table/index.ts | 185 ++++++++++++++++++ .../src/table/models/table-layout-helper.ts | 23 +++ .../nimble-components/src/table/styles.ts | 41 +++- .../nimble-components/src/table/template.ts | 31 +-- 5 files changed, 271 insertions(+), 14 deletions(-) diff --git a/packages/nimble-components/src/table-column/base/template.ts b/packages/nimble-components/src/table-column/base/template.ts index 8d144d2484..87118f4ba9 100644 --- a/packages/nimble-components/src/table-column/base/template.ts +++ b/packages/nimble-components/src/table-column/base/template.ts @@ -1,8 +1,9 @@ import { html } from '@microsoft/fast-element'; +import type { TableColumn } from '.'; -export const template = html` +export const template = html` diff --git a/packages/nimble-components/src/table/index.ts b/packages/nimble-components/src/table/index.ts index aa04510c33..a84e6605ed 100644 --- a/packages/nimble-components/src/table/index.ts +++ b/packages/nimble-components/src/table/index.ts @@ -116,6 +116,12 @@ export class Table< @observable public canRenderRows = true; + /** + * @internal + */ + @observable + public isColumnBeingSized = false; + /** * @internal */ @@ -142,6 +148,11 @@ export class Table< */ public readonly rowContainer!: HTMLElement; + /** + * @internal + */ + public readonly rowHeader!: Element; + /** * @internal */ @@ -160,6 +171,9 @@ export class Table< private columnNotifiers: Notifier[] = []; private isInitialized = false; private readonly collapsedRows = new Set(); + private activeColumnDivider?: number; + private currentRowWidth?: number; + private gridSizedColumns?: TableColumn[]; public constructor() { super(); @@ -320,6 +334,16 @@ export class Table< } } + public onDividerMouseDown(columnIndex: number): void { + this.activeColumnDivider = columnIndex; + this.currentRowWidth = this.rowHeader.getBoundingClientRect().width - this.virtualizer.headerContainerMarginRight; + this.flagNonActiveColumnDividers(columnIndex); + this.setColumnsToFixedSize(); + this.isColumnBeingSized = true; + document.addEventListener('mousemove', this.onDividerMouseMove); + document.addEventListener('mouseup', this.onDividerMouseUp); + } + public handleGroupRowExpanded(rowIndex: number, event: Event): void { this.toggleGroupExpanded(rowIndex); event.stopPropagation(); @@ -438,6 +462,167 @@ export class Table< void this.updateColumnsFromChildItems(); } + private readonly onDividerMouseMove = (event: Event): void => { + const mouseEvent = event as MouseEvent; + let deltaX = mouseEvent.movementX > 0 + ? Math.floor(mouseEvent.movementX) + : Math.ceil(mouseEvent.movementX); + deltaX = this.pinColumnSizeDelta(this.activeColumnDivider!, deltaX); + const canSizeLeft = this.canSizeLeft(this.activeColumnDivider!); + const canSizeRight = this.canSizeRight(this.activeColumnDivider! + 1); + if ((canSizeRight && deltaX > 0) || deltaX < 0) { + this.performCascadeSizeLeft(this.activeColumnDivider!, deltaX); + } + if ((canSizeLeft && deltaX < 0) || deltaX > 0) { + this.performCascadeSizeRight(this.activeColumnDivider!, deltaX); + } + }; + + private pinColumnSizeDelta(activeColumnIndex: number, delta: number): number { + let availableSpace = 0; + let currentIndex = activeColumnIndex; + if (delta > 0) { // size right + while (currentIndex + 1 < this.columns.length) { + const column = this.columns[currentIndex + 1]; + availableSpace += Math.floor(column!.currentPixelWidth!) - column!.internalMinPixelWidth; + currentIndex += 1; + } + } else if (delta < 0) { // size left + while (currentIndex >= 0) { + const column = this.columns[currentIndex]; + availableSpace += Math.floor(column!.currentPixelWidth!) - column!.internalMinPixelWidth; + currentIndex -= 1; + } + } + + return delta > 0 + ? Math.min(delta, availableSpace) + : Math.max(delta, -availableSpace); + } + + private canSizeLeft(activeColumnIndex: number): boolean { + let currentIndex = activeColumnIndex; + while (currentIndex >= 0) { + const column = this.columns[currentIndex]; + if (Math.floor(column!.currentPixelWidth!) > column!.internalMinPixelWidth) { + return true; + } + currentIndex -= 1; + } + + return false; + } + + private canSizeRight(activeColumnIndex: number): boolean { + let currentIndex = activeColumnIndex; + while (currentIndex < this.columns.length) { + const column = this.columns[currentIndex]; + if (Math.floor(column!.currentPixelWidth!) > column!.internalMinPixelWidth) { + return true; + } + currentIndex += 1; + } + + return false; + } + + private performCascadeSizeLeft(activeColumnIndex: number, delta: number): void { + let currentDelta = delta; + const leftColumn = this.columns[activeColumnIndex]; + const allowedDelta = delta < 0 + ? Math.min(Math.floor(leftColumn!.currentPixelWidth! - leftColumn!.internalMinPixelWidth), Math.abs(currentDelta)) + : delta; + const actualDelta = currentDelta < 0 ? -allowedDelta : allowedDelta; + leftColumn!.currentPixelWidth! += actualDelta; + + if (Math.ceil(allowedDelta) < Math.abs(currentDelta) && activeColumnIndex > 0 && delta < 0) { + currentDelta += allowedDelta; + this.performCascadeSizeLeft(activeColumnIndex - 1, currentDelta); + } + } + + private performCascadeSizeRight(activeColumnIndex: number, delta: number): void { + let currentDelta = delta; + const rightColumn = this.columns[activeColumnIndex + 1]; + const allowedDelta = delta > 0 + ? Math.min(Math.floor(rightColumn!.currentPixelWidth! - rightColumn!.internalMinPixelWidth), Math.abs(currentDelta)) + : delta; + const actualDelta = allowedDelta < 0 + ? Math.ceil(allowedDelta) + : Math.floor(allowedDelta); + rightColumn!.currentPixelWidth! -= actualDelta; + + if (actualDelta < Math.abs(currentDelta) && activeColumnIndex < this.columns.length - 2 && delta > 0) { + currentDelta -= allowedDelta; + this.performCascadeSizeRight(activeColumnIndex + 1, currentDelta); + } + } + + private readonly onDividerMouseUp = (): void => { + document.removeEventListener('mousemove', this.onDividerMouseMove); + document.removeEventListener('mouseup', this.onDividerMouseUp); + this.unflagNonActiveColumnDividers(); + this.resetGridSizedColumns(); + this.isColumnBeingSized = false; + }; + + private flagNonActiveColumnDividers(activeColumnIndex: number): void { + const firstDividerIndex = activeColumnIndex > 0 ? activeColumnIndex * 2 - 1 : 0; + const secondDividerIndex = activeColumnIndex < this.columns.length - 1 + ? firstDividerIndex + 1 + : firstDividerIndex; + const dividers = this.shadowRoot!.querySelectorAll('.column-divider'); + Array.from(dividers).forEach((divider, i) => { + if (i < firstDividerIndex || i > secondDividerIndex) { + divider.setAttribute('not-active', 'true'); + } + }); + } + + private unflagNonActiveColumnDividers(): void { + const dividers = this.shadowRoot!.querySelectorAll('.column-divider'); + Array.from(dividers).forEach(divider => { + divider.removeAttribute('not-active'); + }); + } + + private cacheGridSizedColumns(): void { + this.gridSizedColumns = []; + for (const column of this.columns) { + if (column.currentPixelWidth === undefined) { + this.gridSizedColumns.push(column); + } + } + } + + private setColumnsToFixedSize(): void { + this.cacheGridSizedColumns(); + const totalMagnitude = TableLayoutHelper.getTotalColumnMagnitude(this.columns); + const totalFixedSize = TableLayoutHelper.getTotalColumnFixedWidth(this.columns); + let accumulatedTotalSize = 0; + for (const column of this.columns) { + if (column.currentPixelWidth === undefined) { + column.currentPixelWidth = Math.max((column.currentFractionalWidth / totalMagnitude) * (this.currentRowWidth! - totalFixedSize), column.internalMinPixelWidth); + accumulatedTotalSize += column.currentPixelWidth; + if (accumulatedTotalSize > this.currentRowWidth!) { + column.currentPixelWidth -= (accumulatedTotalSize - this.currentRowWidth!); + } + } + } + } + + private resetGridSizedColumns(): void { + if (!this.gridSizedColumns) { + return; + } + + const largestColumnFixedSize = Math.max(...this.gridSizedColumns.map(column => column.currentPixelWidth!)!); + for (const column of this.gridSizedColumns) { + column.currentFractionalWidth = column.currentPixelWidth! / largestColumnFixedSize; + column.currentPixelWidth = undefined; + } + } + private async updateColumnsFromChildItems(): Promise { const definedElements = this.childItems.map(async item => (item.matches(':not(:defined)') ? customElements.whenDefined(item.localName) diff --git a/packages/nimble-components/src/table/models/table-layout-helper.ts b/packages/nimble-components/src/table/models/table-layout-helper.ts index 7b43074113..e466c80c01 100644 --- a/packages/nimble-components/src/table/models/table-layout-helper.ts +++ b/packages/nimble-components/src/table/models/table-layout-helper.ts @@ -25,4 +25,27 @@ export class TableLayoutHelper { }, '') ?? '' ); } + + public static getColumnPixelWidth(gridSize: number, columns: TableColumn[], rowWidth: number): number { + let totalMagnitude = 0; + for (const col of columns) { + if (col.currentPixelWidth === undefined) { + totalMagnitude += col.currentFractionalWidth; + } + } + + return (gridSize / totalMagnitude) * rowWidth; + } + + public static getTotalColumnMagnitude(columns: TableColumn[]): number { + return columns.reduce((accumulator: number, currentValue) => { + return accumulator + (currentValue.currentPixelWidth === undefined ? currentValue.currentFractionalWidth : 0); + }, 0); + } + + public static getTotalColumnFixedWidth(columns: TableColumn[]): number { + return columns.reduce((accumulator: number, currentValue) => { + return accumulator + (currentValue.currentPixelWidth !== undefined ? currentValue.currentPixelWidth : 0); + }, 0); + } } diff --git a/packages/nimble-components/src/table/styles.ts b/packages/nimble-components/src/table/styles.ts index 338df70950..e3aa272bd1 100644 --- a/packages/nimble-components/src/table/styles.ts +++ b/packages/nimble-components/src/table/styles.ts @@ -5,6 +5,8 @@ import { applicationBackgroundColor, bodyFont, bodyFontColor, + popupBorderColor, + controlSlimHeight, fillHoverColor, fillHoverSelectedColor, fillSelectedColor @@ -27,6 +29,7 @@ export const styles = css` width: 100%; font: ${bodyFont}; color: ${bodyFontColor}; + cursor: var(--ni-private-table-cursor-override); } .table-viewport { @@ -50,7 +53,7 @@ export const styles = css` top: var(--ni-private-table-row-container-top); } - .header-container { + .header-row-container { position: sticky; top: 0; } @@ -65,12 +68,48 @@ export const styles = css` left: var(--ni-private-table-scroll-x); } + .header-container { + display: flex; + align-items: center; + position: relative; + } + + .header-container:hover .column-divider:not([not-active]).left, + .header-container:hover .column-divider:not([not-active]).right { + display: block; + } + .header-scrollbar-spacer { width: var(--ni-private-table-header-scrollbar-spacer-width); } .header { flex: 1; + overflow: hidden; + } + + .column-divider { + border-left: 2px solid ${popupBorderColor}; + display: none; + height: ${controlSlimHeight}; + cursor: col-resize; + position: absolute; + } + + .left { + left: -1px; + } + + .right { + left: calc(100% - 1px); + } + + .column-divider.left-limit { + cursor: e-resize; + } + + .column-divider.right-limit { + cursor: w-resize; } .row { diff --git a/packages/nimble-components/src/table/template.ts b/packages/nimble-components/src/table/template.ts index f1ffb949b4..bd81d210bb 100644 --- a/packages/nimble-components/src/table/template.ts +++ b/packages/nimble-components/src/table/template.ts @@ -27,21 +27,30 @@ export const template = html` --ni-private-table-header-scrollbar-spacer-width: ${x => x.virtualizer.headerContainerMarginRight}px; --ni-private-table-scroll-height: ${x => x.virtualizer.allRowsHeight}px; --ni-private-table-row-container-top: ${x => x.virtualizer.rowContainerYOffset}px; - --ni-private-table-row-grid-columns: ${x => x.rowGridColumns ?? ''} + --ni-private-table-row-grid-columns: ${x => x.rowGridColumns ?? ''}; + --ni-private-table-cursor-override: ${x => (x.isColumnBeingSized ? 'col-resize' : 'default')}; "> -
-
+
+
${repeat(x => x.columns, html` ${when(x => !x.columnHidden, html` - <${tableHeaderTag} - class="header" - sort-direction="${x => (typeof x.sortIndex === 'number' ? x.sortDirection : TableColumnSortDirection.none)}" - ?first-sorted-column="${(x, c) => x === c.parent.firstSortedColumn}" - > - - +
+ ${when((_, c) => c.index > 0, html` +
+ `)} + <${tableHeaderTag} + class="header" + sort-direction="${x => (typeof x.sortIndex === 'number' ? x.sortDirection : TableColumnSortDirection.none)}" + ?first-sorted-column="${(x, c) => x === c.parent.firstSortedColumn}" + > + + + ${when((_, c) => c.index < (c.parent as Table).columns.length - 1, html` +
+ `)} +
`)} - `)} + `, { positioning: true })}
From ba081ee8f270bfbcfa71f36afeba97a1a107ad47 Mon Sep 17 00:00:00 2001 From: Jonathan Meyer <26874831+atmgrifter00@users.noreply.github.com> Date: Wed, 12 Apr 2023 17:46:35 -0500 Subject: [PATCH 02/48] Minor fixes. --- packages/nimble-components/src/table/index.ts | 49 +++++++++++-------- .../nimble-components/src/table/styles.ts | 5 +- .../nimble-components/src/table/template.ts | 4 +- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/packages/nimble-components/src/table/index.ts b/packages/nimble-components/src/table/index.ts index a84e6605ed..942d6cb348 100644 --- a/packages/nimble-components/src/table/index.ts +++ b/packages/nimble-components/src/table/index.ts @@ -334,14 +334,14 @@ export class Table< } } - public onDividerMouseDown(columnIndex: number): void { + public onRightDividerMouseDown(columnIndex: number): void { this.activeColumnDivider = columnIndex; - this.currentRowWidth = this.rowHeader.getBoundingClientRect().width - this.virtualizer.headerContainerMarginRight; - this.flagNonActiveColumnDividers(columnIndex); - this.setColumnsToFixedSize(); - this.isColumnBeingSized = true; - document.addEventListener('mousemove', this.onDividerMouseMove); - document.addEventListener('mouseup', this.onDividerMouseUp); + this.onDividerMouseDown(columnIndex); + } + + public onLeftDividerMouseDown(columnIndex: number): void { + this.activeColumnDivider = columnIndex - 1; + this.onDividerMouseDown(columnIndex); } public handleGroupRowExpanded(rowIndex: number, event: Event): void { @@ -462,6 +462,15 @@ export class Table< void this.updateColumnsFromChildItems(); } + private onDividerMouseDown(columnIndex: number): void { + this.currentRowWidth = this.rowHeader.getBoundingClientRect().width - this.virtualizer.headerContainerMarginRight; + this.flagActiveColumnDividers(columnIndex); + this.setColumnsToFixedSize(); + this.isColumnBeingSized = true; + document.addEventListener('mousemove', this.onDividerMouseMove); + document.addEventListener('mouseup', this.onDividerMouseUp); + } + private readonly onDividerMouseMove = (event: Event): void => { const mouseEvent = event as MouseEvent; let deltaX = mouseEvent.movementX > 0 @@ -478,6 +487,14 @@ export class Table< } }; + private readonly onDividerMouseUp = (): void => { + document.removeEventListener('mousemove', this.onDividerMouseMove); + document.removeEventListener('mouseup', this.onDividerMouseUp); + this.unflagActiveColumnDividers(); + this.resetGridSizedColumns(); + this.isColumnBeingSized = false; + }; + private pinColumnSizeDelta(activeColumnIndex: number, delta: number): number { let availableSpace = 0; let currentIndex = activeColumnIndex; @@ -558,31 +575,23 @@ export class Table< } } - private readonly onDividerMouseUp = (): void => { - document.removeEventListener('mousemove', this.onDividerMouseMove); - document.removeEventListener('mouseup', this.onDividerMouseUp); - this.unflagNonActiveColumnDividers(); - this.resetGridSizedColumns(); - this.isColumnBeingSized = false; - }; - - private flagNonActiveColumnDividers(activeColumnIndex: number): void { + private flagActiveColumnDividers(activeColumnIndex: number): void { const firstDividerIndex = activeColumnIndex > 0 ? activeColumnIndex * 2 - 1 : 0; const secondDividerIndex = activeColumnIndex < this.columns.length - 1 ? firstDividerIndex + 1 : firstDividerIndex; const dividers = this.shadowRoot!.querySelectorAll('.column-divider'); Array.from(dividers).forEach((divider, i) => { - if (i < firstDividerIndex || i > secondDividerIndex) { - divider.setAttribute('not-active', 'true'); + if (i >= firstDividerIndex && i <= secondDividerIndex) { + divider.setAttribute('active', 'true'); } }); } - private unflagNonActiveColumnDividers(): void { + private unflagActiveColumnDividers(): void { const dividers = this.shadowRoot!.querySelectorAll('.column-divider'); Array.from(dividers).forEach(divider => { - divider.removeAttribute('not-active'); + divider.removeAttribute('active'); }); } diff --git a/packages/nimble-components/src/table/styles.ts b/packages/nimble-components/src/table/styles.ts index e3aa272bd1..86e55d012c 100644 --- a/packages/nimble-components/src/table/styles.ts +++ b/packages/nimble-components/src/table/styles.ts @@ -74,9 +74,10 @@ export const styles = css` position: relative; } - .header-container:hover .column-divider:not([not-active]).left, - .header-container:hover .column-divider:not([not-active]).right { + .header-container:hover .column-divider, + .header-container .column-divider[active] { display: block; + z-index: 1; } .header-scrollbar-spacer { diff --git a/packages/nimble-components/src/table/template.ts b/packages/nimble-components/src/table/template.ts index bd81d210bb..166ed6490e 100644 --- a/packages/nimble-components/src/table/template.ts +++ b/packages/nimble-components/src/table/template.ts @@ -36,7 +36,7 @@ export const template = html
` ${when(x => !x.columnHidden, html`
${when((_, c) => c.index > 0, html` -
+
`)} <${tableHeaderTag} class="header" @@ -46,7 +46,7 @@ export const template = html
` ${when((_, c) => c.index < (c.parent as Table).columns.length - 1, html` -
+
`)} `)} From bd11f9fe560392fec85de9a2eef2181ec32e9952 Mon Sep 17 00:00:00 2001 From: Jonathan Meyer <26874831+atmgrifter00@users.noreply.github.com> Date: Thu, 13 Apr 2023 13:22:24 -0500 Subject: [PATCH 03/48] Refactor to manager class. --- packages/nimble-components/src/table/index.ts | 186 +------------- .../src/table/models/table-layout-helper.ts | 51 ---- .../src/table/models/table-layout-manager.ts | 240 ++++++++++++++++++ .../nimble-components/src/table/styles.ts | 17 +- 4 files changed, 256 insertions(+), 238 deletions(-) delete mode 100644 packages/nimble-components/src/table/models/table-layout-helper.ts create mode 100644 packages/nimble-components/src/table/models/table-layout-manager.ts diff --git a/packages/nimble-components/src/table/index.ts b/packages/nimble-components/src/table/index.ts index 942d6cb348..863a039230 100644 --- a/packages/nimble-components/src/table/index.ts +++ b/packages/nimble-components/src/table/index.ts @@ -41,7 +41,7 @@ import { import { Virtualizer } from './models/virtualizer'; import { getTanStackSortingFunction } from './models/sort-operations'; import { UpdateTracker } from './models/update-tracker'; -import { TableLayoutHelper } from './models/table-layout-helper'; +import { TableLayoutManager } from './models/table-layout-manager'; import type { TableRow } from './components/row'; declare global { @@ -168,12 +168,10 @@ export class Table< private options: TanStackTableOptionsResolved; private readonly tableValidator = new TableValidator(); private readonly updateTracker = new UpdateTracker(this); + private readonly tableLayoutManager = new TableLayoutManager(this); private columnNotifiers: Notifier[] = []; private isInitialized = false; private readonly collapsedRows = new Set(); - private activeColumnDivider?: number; - private currentRowWidth?: number; - private gridSizedColumns?: TableColumn[]; public constructor() { super(); @@ -335,13 +333,11 @@ export class Table< } public onRightDividerMouseDown(columnIndex: number): void { - this.activeColumnDivider = columnIndex; - this.onDividerMouseDown(columnIndex); + this.tableLayoutManager.beginColumnInteractiveSize(columnIndex, columnIndex); } public onLeftDividerMouseDown(columnIndex: number): void { - this.activeColumnDivider = columnIndex - 1; - this.onDividerMouseDown(columnIndex); + this.tableLayoutManager.beginColumnInteractiveSize(columnIndex, columnIndex - 1); } public handleGroupRowExpanded(rowIndex: number, event: Event): void { @@ -462,176 +458,6 @@ export class Table< void this.updateColumnsFromChildItems(); } - private onDividerMouseDown(columnIndex: number): void { - this.currentRowWidth = this.rowHeader.getBoundingClientRect().width - this.virtualizer.headerContainerMarginRight; - this.flagActiveColumnDividers(columnIndex); - this.setColumnsToFixedSize(); - this.isColumnBeingSized = true; - document.addEventListener('mousemove', this.onDividerMouseMove); - document.addEventListener('mouseup', this.onDividerMouseUp); - } - - private readonly onDividerMouseMove = (event: Event): void => { - const mouseEvent = event as MouseEvent; - let deltaX = mouseEvent.movementX > 0 - ? Math.floor(mouseEvent.movementX) - : Math.ceil(mouseEvent.movementX); - deltaX = this.pinColumnSizeDelta(this.activeColumnDivider!, deltaX); - const canSizeLeft = this.canSizeLeft(this.activeColumnDivider!); - const canSizeRight = this.canSizeRight(this.activeColumnDivider! + 1); - if ((canSizeRight && deltaX > 0) || deltaX < 0) { - this.performCascadeSizeLeft(this.activeColumnDivider!, deltaX); - } - if ((canSizeLeft && deltaX < 0) || deltaX > 0) { - this.performCascadeSizeRight(this.activeColumnDivider!, deltaX); - } - }; - - private readonly onDividerMouseUp = (): void => { - document.removeEventListener('mousemove', this.onDividerMouseMove); - document.removeEventListener('mouseup', this.onDividerMouseUp); - this.unflagActiveColumnDividers(); - this.resetGridSizedColumns(); - this.isColumnBeingSized = false; - }; - - private pinColumnSizeDelta(activeColumnIndex: number, delta: number): number { - let availableSpace = 0; - let currentIndex = activeColumnIndex; - if (delta > 0) { // size right - while (currentIndex + 1 < this.columns.length) { - const column = this.columns[currentIndex + 1]; - availableSpace += Math.floor(column!.currentPixelWidth!) - column!.internalMinPixelWidth; - currentIndex += 1; - } - } else if (delta < 0) { // size left - while (currentIndex >= 0) { - const column = this.columns[currentIndex]; - availableSpace += Math.floor(column!.currentPixelWidth!) - column!.internalMinPixelWidth; - currentIndex -= 1; - } - } - - return delta > 0 - ? Math.min(delta, availableSpace) - : Math.max(delta, -availableSpace); - } - - private canSizeLeft(activeColumnIndex: number): boolean { - let currentIndex = activeColumnIndex; - while (currentIndex >= 0) { - const column = this.columns[currentIndex]; - if (Math.floor(column!.currentPixelWidth!) > column!.internalMinPixelWidth) { - return true; - } - currentIndex -= 1; - } - - return false; - } - - private canSizeRight(activeColumnIndex: number): boolean { - let currentIndex = activeColumnIndex; - while (currentIndex < this.columns.length) { - const column = this.columns[currentIndex]; - if (Math.floor(column!.currentPixelWidth!) > column!.internalMinPixelWidth) { - return true; - } - currentIndex += 1; - } - - return false; - } - - private performCascadeSizeLeft(activeColumnIndex: number, delta: number): void { - let currentDelta = delta; - const leftColumn = this.columns[activeColumnIndex]; - const allowedDelta = delta < 0 - ? Math.min(Math.floor(leftColumn!.currentPixelWidth! - leftColumn!.internalMinPixelWidth), Math.abs(currentDelta)) - : delta; - const actualDelta = currentDelta < 0 ? -allowedDelta : allowedDelta; - leftColumn!.currentPixelWidth! += actualDelta; - - if (Math.ceil(allowedDelta) < Math.abs(currentDelta) && activeColumnIndex > 0 && delta < 0) { - currentDelta += allowedDelta; - this.performCascadeSizeLeft(activeColumnIndex - 1, currentDelta); - } - } - - private performCascadeSizeRight(activeColumnIndex: number, delta: number): void { - let currentDelta = delta; - const rightColumn = this.columns[activeColumnIndex + 1]; - const allowedDelta = delta > 0 - ? Math.min(Math.floor(rightColumn!.currentPixelWidth! - rightColumn!.internalMinPixelWidth), Math.abs(currentDelta)) - : delta; - const actualDelta = allowedDelta < 0 - ? Math.ceil(allowedDelta) - : Math.floor(allowedDelta); - rightColumn!.currentPixelWidth! -= actualDelta; - - if (actualDelta < Math.abs(currentDelta) && activeColumnIndex < this.columns.length - 2 && delta > 0) { - currentDelta -= allowedDelta; - this.performCascadeSizeRight(activeColumnIndex + 1, currentDelta); - } - } - - private flagActiveColumnDividers(activeColumnIndex: number): void { - const firstDividerIndex = activeColumnIndex > 0 ? activeColumnIndex * 2 - 1 : 0; - const secondDividerIndex = activeColumnIndex < this.columns.length - 1 - ? firstDividerIndex + 1 - : firstDividerIndex; - const dividers = this.shadowRoot!.querySelectorAll('.column-divider'); - Array.from(dividers).forEach((divider, i) => { - if (i >= firstDividerIndex && i <= secondDividerIndex) { - divider.setAttribute('active', 'true'); - } - }); - } - - private unflagActiveColumnDividers(): void { - const dividers = this.shadowRoot!.querySelectorAll('.column-divider'); - Array.from(dividers).forEach(divider => { - divider.removeAttribute('active'); - }); - } - - private cacheGridSizedColumns(): void { - this.gridSizedColumns = []; - for (const column of this.columns) { - if (column.currentPixelWidth === undefined) { - this.gridSizedColumns.push(column); - } - } - } - - private setColumnsToFixedSize(): void { - this.cacheGridSizedColumns(); - const totalMagnitude = TableLayoutHelper.getTotalColumnMagnitude(this.columns); - const totalFixedSize = TableLayoutHelper.getTotalColumnFixedWidth(this.columns); - let accumulatedTotalSize = 0; - for (const column of this.columns) { - if (column.currentPixelWidth === undefined) { - column.currentPixelWidth = Math.max((column.currentFractionalWidth / totalMagnitude) * (this.currentRowWidth! - totalFixedSize), column.internalMinPixelWidth); - accumulatedTotalSize += column.currentPixelWidth; - if (accumulatedTotalSize > this.currentRowWidth!) { - column.currentPixelWidth -= (accumulatedTotalSize - this.currentRowWidth!); - } - } - } - } - - private resetGridSizedColumns(): void { - if (!this.gridSizedColumns) { - return; - } - - const largestColumnFixedSize = Math.max(...this.gridSizedColumns.map(column => column.currentPixelWidth!)!); - for (const column of this.gridSizedColumns) { - column.currentFractionalWidth = column.currentPixelWidth! / largestColumnFixedSize; - column.currentPixelWidth = undefined; - } - } - private async updateColumnsFromChildItems(): Promise { const definedElements = this.childItems.map(async item => (item.matches(':not(:defined)') ? customElements.whenDefined(item.localName) @@ -684,9 +510,7 @@ export class Table< } private updateRowGridColumns(): void { - this.rowGridColumns = TableLayoutHelper.getGridTemplateColumns( - this.columns - ); + this.rowGridColumns = this.tableLayoutManager.getGridTemplateColumns(); } private validate(): void { diff --git a/packages/nimble-components/src/table/models/table-layout-helper.ts b/packages/nimble-components/src/table/models/table-layout-helper.ts deleted file mode 100644 index e466c80c01..0000000000 --- a/packages/nimble-components/src/table/models/table-layout-helper.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { TableColumn } from '../../table-column/base'; - -/** - * This class provides helper methods for managing the layout of cells within - * a Table. - */ -export class TableLayoutHelper { - public static getGridTemplateColumns(columns: TableColumn[]): string { - return ( - columns - ?.filter(column => !column.columnHidden) - .reduce((accumulator: string, currentValue) => { - const gap = accumulator === '' ? '' : ' '; - const minPixelWidth = currentValue.internalMinPixelWidth; - if (currentValue.currentPixelWidth) { - const pixelWidth = currentValue.currentPixelWidth; - const gridPixelWidth = pixelWidth > minPixelWidth - ? pixelWidth - : minPixelWidth; - return `${accumulator}${gap}${gridPixelWidth}px`; - } - - const fractionalWidth = currentValue.currentFractionalWidth; - return `${accumulator}${gap}minmax(${minPixelWidth}px, ${fractionalWidth}fr)`; - }, '') ?? '' - ); - } - - public static getColumnPixelWidth(gridSize: number, columns: TableColumn[], rowWidth: number): number { - let totalMagnitude = 0; - for (const col of columns) { - if (col.currentPixelWidth === undefined) { - totalMagnitude += col.currentFractionalWidth; - } - } - - return (gridSize / totalMagnitude) * rowWidth; - } - - public static getTotalColumnMagnitude(columns: TableColumn[]): number { - return columns.reduce((accumulator: number, currentValue) => { - return accumulator + (currentValue.currentPixelWidth === undefined ? currentValue.currentFractionalWidth : 0); - }, 0); - } - - public static getTotalColumnFixedWidth(columns: TableColumn[]): number { - return columns.reduce((accumulator: number, currentValue) => { - return accumulator + (currentValue.currentPixelWidth !== undefined ? currentValue.currentPixelWidth : 0); - }, 0); - } -} diff --git a/packages/nimble-components/src/table/models/table-layout-manager.ts b/packages/nimble-components/src/table/models/table-layout-manager.ts new file mode 100644 index 0000000000..d84767f80b --- /dev/null +++ b/packages/nimble-components/src/table/models/table-layout-manager.ts @@ -0,0 +1,240 @@ +import type { Table } from '..'; +import type { TableColumn } from '../../table-column/base'; +import type { TableRecord } from '../types'; + +/** + * This class manages the layout of columns within a Table. + */ +export class TableLayoutManager { + private readonly table: Table; + private activeColumnDivider?: number; + private gridSizedColumns?: TableColumn[]; + private currentRowWidth?: number; + + public constructor(table: Table) { + this.table = table; + } + + public getGridTemplateColumns(): string { + return ( + this.table.columns + ?.filter(column => !column.columnHidden) + .reduce((accumulator: string, currentValue) => { + const gap = accumulator === '' ? '' : ' '; + const minPixelWidth = currentValue.internalMinPixelWidth; + if (currentValue.currentPixelWidth) { + const pixelWidth = currentValue.currentPixelWidth; + const gridPixelWidth = pixelWidth > minPixelWidth + ? pixelWidth + : minPixelWidth; + return `${accumulator}${gap}${gridPixelWidth}px`; + } + + const fractionalWidth = currentValue.currentFractionalWidth; + return `${accumulator}${gap}minmax(${minPixelWidth}px, ${fractionalWidth}fr)`; + }, '') ?? '' + ); + } + + /** + * Sets up state related to interactively sizing a column. + * @param columnIndex The column index currently being hovered over + * @param activeColumnDivider The divider that was clicked on (columnIndex - 1 for left divider, columnIndex for right) + */ + public beginColumnInteractiveSize(columnIndex: number, activeColumnDivider: number): void { + this.activeColumnDivider = activeColumnDivider; + this.currentRowWidth = this.table.rowHeader.getBoundingClientRect().width - this.table.virtualizer.headerContainerMarginRight; + this.flagActiveColumnDividers(columnIndex); + this.setColumnsToFixedSize(); + this.table.isColumnBeingSized = true; + document.addEventListener('mousemove', this.onDividerMouseMove); + document.addEventListener('mouseup', this.onDividerMouseUp); + } + + private readonly onDividerMouseMove = (event: Event): void => { + const mouseEvent = event as MouseEvent; + let deltaX = mouseEvent.movementX > 0 + ? Math.floor(mouseEvent.movementX) + : Math.ceil(mouseEvent.movementX); + deltaX = this.pinColumnSizeDelta(this.activeColumnDivider!, deltaX); + const canSizeLeft = this.canSizeLeft(this.activeColumnDivider!); + const canSizeRight = this.canSizeRight(this.activeColumnDivider! + 1); + if ((canSizeRight && deltaX > 0) || deltaX < 0) { + this.performCascadeSizeLeft(this.activeColumnDivider!, deltaX); + } + if ((canSizeLeft && deltaX < 0) || deltaX > 0) { + this.performCascadeSizeRight(this.activeColumnDivider!, deltaX); + } + }; + + private readonly onDividerMouseUp = (): void => { + document.removeEventListener('mousemove', this.onDividerMouseMove); + document.removeEventListener('mouseup', this.onDividerMouseUp); + this.unflagActiveColumnDividers(); + this.resetGridSizedColumns(); + this.table.isColumnBeingSized = false; + }; + + private getColumnPixelWidth(gridSize: number, rowWidth: number): number { + let totalMagnitude = 0; + for (const col of this.table.columns) { + if (col.currentPixelWidth === undefined) { + totalMagnitude += col.currentFractionalWidth; + } + } + + return (gridSize / totalMagnitude) * rowWidth; + } + + private getTotalColumnMagnitude(): number { + return this.table.columns.reduce((accumulator: number, currentValue) => { + return accumulator + (currentValue.currentPixelWidth === undefined ? currentValue.currentFractionalWidth : 0); + }, 0); + } + + private getTotalColumnFixedWidth(): number { + return this.table.columns.reduce((accumulator: number, currentValue) => { + return accumulator + (currentValue.currentPixelWidth !== undefined ? currentValue.currentPixelWidth : 0); + }, 0); + } + + private setColumnsToFixedSize(): void { + this.cacheGridSizedColumns(); + const totalMagnitude = this.getTotalColumnMagnitude(); + const totalFixedSize = this.getTotalColumnFixedWidth(); + let accumulatedTotalSize = 0; + for (const column of this.table.columns) { + if (column.currentPixelWidth === undefined) { + column.currentPixelWidth = Math.max((column.currentFractionalWidth / totalMagnitude) * (this.currentRowWidth! - totalFixedSize), column.internalMinPixelWidth); + accumulatedTotalSize += column.currentPixelWidth; + if (accumulatedTotalSize > this.currentRowWidth!) { + column.currentPixelWidth -= (accumulatedTotalSize - this.currentRowWidth!); + } + } + } + } + + private pinColumnSizeDelta(activeColumnIndex: number, delta: number): number { + let availableSpace = 0; + let currentIndex = activeColumnIndex; + if (delta > 0) { // size right + while (currentIndex + 1 < this.table.columns.length) { + const column = this.table.columns[currentIndex + 1]; + availableSpace += Math.floor(column!.currentPixelWidth!) - column!.internalMinPixelWidth; + currentIndex += 1; + } + } else if (delta < 0) { // size left + while (currentIndex >= 0) { + const column = this.table.columns[currentIndex]; + availableSpace += Math.floor(column!.currentPixelWidth!) - column!.internalMinPixelWidth; + currentIndex -= 1; + } + } + + return delta > 0 + ? Math.min(delta, availableSpace) + : Math.max(delta, -availableSpace); + } + + private canSizeLeft(activeColumnIndex: number): boolean { + let currentIndex = activeColumnIndex; + while (currentIndex >= 0) { + const column = this.table.columns[currentIndex]; + if (Math.floor(column!.currentPixelWidth!) > column!.internalMinPixelWidth) { + return true; + } + currentIndex -= 1; + } + + return false; + } + + private canSizeRight(activeColumnIndex: number): boolean { + let currentIndex = activeColumnIndex; + while (currentIndex < this.table.columns.length) { + const column = this.table.columns[currentIndex]; + if (Math.floor(column!.currentPixelWidth!) > column!.internalMinPixelWidth) { + return true; + } + currentIndex += 1; + } + + return false; + } + + private performCascadeSizeLeft(activeColumnIndex: number, delta: number): void { + let currentDelta = delta; + const leftColumn = this.table.columns[activeColumnIndex]; + const allowedDelta = delta < 0 + ? Math.min(Math.floor(leftColumn!.currentPixelWidth! - leftColumn!.internalMinPixelWidth), Math.abs(currentDelta)) + : delta; + const actualDelta = currentDelta < 0 ? -allowedDelta : allowedDelta; + leftColumn!.currentPixelWidth! += actualDelta; + + if (Math.ceil(allowedDelta) < Math.abs(currentDelta) && activeColumnIndex > 0 && delta < 0) { + currentDelta += allowedDelta; + this.performCascadeSizeLeft(activeColumnIndex - 1, currentDelta); + } + } + + private performCascadeSizeRight(activeColumnIndex: number, delta: number): void { + let currentDelta = delta; + const rightColumn = this.table.columns[activeColumnIndex + 1]; + const allowedDelta = delta > 0 + ? Math.min(Math.floor(rightColumn!.currentPixelWidth! - rightColumn!.internalMinPixelWidth), Math.abs(currentDelta)) + : delta; + const actualDelta = allowedDelta < 0 + ? Math.ceil(allowedDelta) + : Math.floor(allowedDelta); + rightColumn!.currentPixelWidth! -= actualDelta; + + if (actualDelta < Math.abs(currentDelta) && activeColumnIndex < this.table.columns.length - 2 && delta > 0) { + currentDelta -= allowedDelta; + this.performCascadeSizeRight(activeColumnIndex + 1, currentDelta); + } + } + + private flagActiveColumnDividers(activeColumnIndex: number): void { + const firstDividerIndex = activeColumnIndex > 0 ? activeColumnIndex * 2 - 1 : 0; + const secondDividerIndex = activeColumnIndex < this.table.columns.length - 1 + ? firstDividerIndex + 1 + : firstDividerIndex; + const dividers = this.table.shadowRoot!.querySelectorAll('.column-divider'); + Array.from(dividers).forEach((divider, i) => { + if (i < firstDividerIndex || i > secondDividerIndex) { + divider.setAttribute('not-active', 'true'); + } else { + divider.setAttribute('active', 'true'); + } + }); + } + + private unflagActiveColumnDividers(): void { + const dividers = this.table.shadowRoot!.querySelectorAll('.column-divider'); + Array.from(dividers).forEach(divider => { + divider.removeAttribute('not-active'); + divider.removeAttribute('active'); + }); + } + + private cacheGridSizedColumns(): void { + this.gridSizedColumns = []; + for (const column of this.table.columns) { + if (column.currentPixelWidth === undefined) { + this.gridSizedColumns.push(column); + } + } + } + + private resetGridSizedColumns(): void { + if (!this.gridSizedColumns) { + return; + } + + const largestColumnFixedSize = Math.max(...this.gridSizedColumns.map(column => column.currentPixelWidth!)!); + for (const column of this.gridSizedColumns) { + column.currentFractionalWidth = column.currentPixelWidth! / largestColumnFixedSize; + column.currentPixelWidth = undefined; + } + } +} diff --git a/packages/nimble-components/src/table/styles.ts b/packages/nimble-components/src/table/styles.ts index 86e55d012c..a3a55b061e 100644 --- a/packages/nimble-components/src/table/styles.ts +++ b/packages/nimble-components/src/table/styles.ts @@ -74,12 +74,6 @@ export const styles = css` position: relative; } - .header-container:hover .column-divider, - .header-container .column-divider[active] { - display: block; - z-index: 1; - } - .header-scrollbar-spacer { width: var(--ni-private-table-header-scrollbar-spacer-width); } @@ -97,6 +91,11 @@ export const styles = css` position: absolute; } + .column-divider[active] { + display: block; + z-index: 1; + } + .left { left: -1px; } @@ -105,6 +104,12 @@ export const styles = css` left: calc(100% - 1px); } + .header-container:hover .column-divider:not([not-active]).left, + .header-container:hover .column-divider:not([not-active]).right { + display: block; + z-index: 1; + } + .column-divider.left-limit { cursor: e-resize; } From 6284818ea862caa13e91f2e6f7b1ab7577b17d17 Mon Sep 17 00:00:00 2001 From: Jonathan Meyer <26874831+atmgrifter00@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:00:01 -0500 Subject: [PATCH 04/48] Removed unused method. --- .../src/table/models/table-layout-manager.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/nimble-components/src/table/models/table-layout-manager.ts b/packages/nimble-components/src/table/models/table-layout-manager.ts index b072f6e0ee..60e1c28741 100644 --- a/packages/nimble-components/src/table/models/table-layout-manager.ts +++ b/packages/nimble-components/src/table/models/table-layout-manager.ts @@ -76,17 +76,6 @@ export class TableLayoutManager { this.table.isColumnBeingSized = false; }; - private getColumnPixelWidth(gridSize: number, rowWidth: number): number { - let totalMagnitude = 0; - for (const col of this.table.columns) { - if (col.columnInternals.currentPixelWidth === undefined) { - totalMagnitude += col.columnInternals.currentFractionalWidth; - } - } - - return (gridSize / totalMagnitude) * rowWidth; - } - private getTotalColumnMagnitude(): number { return this.table.columns.reduce((accumulator: number, currentValue) => { return accumulator + (currentValue.columnInternals.currentPixelWidth === undefined From 7fa5820803ae38a5a8d5175c62c15de051bf22d9 Mon Sep 17 00:00:00 2001 From: Jonathan Meyer <26874831+atmgrifter00@users.noreply.github.com> Date: Fri, 14 Apr 2023 08:53:42 -0500 Subject: [PATCH 05/48] Not working well --- packages/nimble-components/src/table/index.ts | 6 ++ .../src/table/models/table-layout-manager.ts | 55 +++++++++++-------- .../nimble-components/src/table/styles.ts | 47 ++++++++-------- .../nimble-components/src/table/template.ts | 9 +-- 4 files changed, 68 insertions(+), 49 deletions(-) diff --git a/packages/nimble-components/src/table/index.ts b/packages/nimble-components/src/table/index.ts index cd7897ffd7..72f22430f8 100644 --- a/packages/nimble-components/src/table/index.ts +++ b/packages/nimble-components/src/table/index.ts @@ -165,6 +165,12 @@ export class Table< @observable public firstSortedColumn?: TableColumn; + /** + * @internal + */ + @observable + public tableWidthFactor = 1; + private readonly table: TanStackTable; private options: TanStackTableOptionsResolved; private readonly tableValidator = new TableValidator(); diff --git a/packages/nimble-components/src/table/models/table-layout-manager.ts b/packages/nimble-components/src/table/models/table-layout-manager.ts index 60e1c28741..95ef2dfc3e 100644 --- a/packages/nimble-components/src/table/models/table-layout-manager.ts +++ b/packages/nimble-components/src/table/models/table-layout-manager.ts @@ -10,6 +10,8 @@ export class TableLayoutManager { private activeColumnDivider?: number; private gridSizedColumns?: TableColumn[]; private currentRowWidth?: number; + private initialTablePixelWidth?: number; + private initialColumnTotalWidth?: number; public constructor(table: Table) { this.table = table; @@ -47,6 +49,8 @@ export class TableLayoutManager { this.currentRowWidth = this.table.rowHeader.getBoundingClientRect().width - this.table.virtualizer.headerContainerMarginRight; this.flagActiveColumnDividers(columnIndex); this.setColumnsToFixedSize(); + this.initialTablePixelWidth = this.table.getBoundingClientRect().width * this.table.tableWidthFactor; + this.initialColumnTotalWidth = this.getTotalColumnFixedWidth(); this.table.isColumnBeingSized = true; document.addEventListener('mousemove', this.onDividerMouseMove); document.addEventListener('mouseup', this.onDividerMouseUp); @@ -54,18 +58,19 @@ export class TableLayoutManager { private readonly onDividerMouseMove = (event: Event): void => { const mouseEvent = event as MouseEvent; - let deltaX = mouseEvent.movementX > 0 + const deltaX = mouseEvent.movementX > 0 ? Math.floor(mouseEvent.movementX) : Math.ceil(mouseEvent.movementX); - deltaX = this.pinColumnSizeDelta(this.activeColumnDivider!, deltaX); - const canSizeLeft = this.canSizeLeft(this.activeColumnDivider!); - const canSizeRight = this.canSizeRight(this.activeColumnDivider! + 1); - if ((canSizeRight && deltaX > 0) || deltaX < 0) { + // deltaX = this.pinColumnSizeDelta(this.activeColumnDivider!, deltaX); + // const canSizeLeft = this.canSizeLeft(this.activeColumnDivider!); + // const canSizeRight = this.canSizeRight(this.activeColumnDivider! + 1); + if (this.canSizeLeft(this.activeColumnDivider!)) { this.performCascadeSizeLeft(this.activeColumnDivider!, deltaX); } - if ((canSizeLeft && deltaX < 0) || deltaX > 0) { + if (this.activeColumnDivider! < this.table.columns.length - 1) { this.performCascadeSizeRight(this.activeColumnDivider!, deltaX); } + this.table.tableWidthFactor = this.getCurrentTotalTableWidth() / this.table.getBoundingClientRect().width; }; private readonly onDividerMouseUp = (): void => { @@ -92,6 +97,10 @@ export class TableLayoutManager { }, 0); } + private getCurrentTotalTableWidth(): number { + return this.initialTablePixelWidth! + (this.getTotalColumnFixedWidth() - this.initialColumnTotalWidth!); + } + private setColumnsToFixedSize(): void { this.cacheGridSizedColumns(); const totalMagnitude = this.getTotalColumnMagnitude(); @@ -131,13 +140,13 @@ export class TableLayoutManager { } private canSizeLeft(activeColumnIndex: number): boolean { - let currentIndex = activeColumnIndex; - while (currentIndex >= 0) { - const column = this.table.columns[currentIndex]; - if (Math.floor(column!.columnInternals.currentPixelWidth!) > column!.columnInternals.minPixelWidth) { - return true; - } - currentIndex -= 1; + if (activeColumnIndex === this.table.columns.length - 1 && this.getCurrentTotalTableWidth() > this.initialTablePixelWidth!) { + return false; + } + + const column = this.table.columns[activeColumnIndex]; + if (Math.floor(column!.columnInternals.currentPixelWidth!) > column!.columnInternals.minPixelWidth) { + return true; } return false; @@ -157,7 +166,7 @@ export class TableLayoutManager { } private performCascadeSizeLeft(activeColumnIndex: number, delta: number): void { - let currentDelta = delta; + const currentDelta = delta; const leftColumn = this.table.columns[activeColumnIndex]; const allowedDelta = delta < 0 ? Math.min(Math.floor(leftColumn!.columnInternals.currentPixelWidth! - leftColumn!.columnInternals.minPixelWidth), Math.abs(currentDelta)) @@ -165,14 +174,14 @@ export class TableLayoutManager { const actualDelta = currentDelta < 0 ? -allowedDelta : allowedDelta; leftColumn!.columnInternals.currentPixelWidth! += actualDelta; - if (Math.ceil(allowedDelta) < Math.abs(currentDelta) && activeColumnIndex > 0 && delta < 0) { - currentDelta += allowedDelta; - this.performCascadeSizeLeft(activeColumnIndex - 1, currentDelta); - } + // if (Math.ceil(allowedDelta) < Math.abs(currentDelta) && activeColumnIndex > 0 && delta < 0) { + // currentDelta += allowedDelta; + // this.performCascadeSizeLeft(activeColumnIndex - 1, currentDelta); + // } } private performCascadeSizeRight(activeColumnIndex: number, delta: number): void { - let currentDelta = delta; + const currentDelta = delta; const rightColumn = this.table.columns[activeColumnIndex + 1]; const allowedDelta = delta > 0 ? Math.min(Math.floor(rightColumn!.columnInternals.currentPixelWidth! - rightColumn!.columnInternals.minPixelWidth), Math.abs(currentDelta)) @@ -182,10 +191,10 @@ export class TableLayoutManager { : Math.floor(allowedDelta); rightColumn!.columnInternals.currentPixelWidth! -= actualDelta; - if (actualDelta < Math.abs(currentDelta) && activeColumnIndex < this.table.columns.length - 2 && delta > 0) { - currentDelta -= allowedDelta; - this.performCascadeSizeRight(activeColumnIndex + 1, currentDelta); - } + // if (actualDelta < Math.abs(currentDelta) && activeColumnIndex < this.table.columns.length - 2 && delta > 0) { + // currentDelta -= allowedDelta; + // this.performCascadeSizeRight(activeColumnIndex + 1, currentDelta); + // } } private flagActiveColumnDividers(activeColumnIndex: number): void { diff --git a/packages/nimble-components/src/table/styles.ts b/packages/nimble-components/src/table/styles.ts index a3a55b061e..2ac1d72471 100644 --- a/packages/nimble-components/src/table/styles.ts +++ b/packages/nimble-components/src/table/styles.ts @@ -23,7 +23,7 @@ export const styles = css` } .table-container { - overflow: hidden; + overflow: auto; display: flex; flex-direction: column; width: 100%; @@ -32,30 +32,10 @@ export const styles = css` cursor: var(--ni-private-table-cursor-override); } - .table-viewport { - overflow: auto; - display: block; - height: 100%; - position: relative; - } - - .table-scroll { - pointer-events: none; - position: absolute; - top: 0px; - width: 100%; - height: var(--ni-private-table-scroll-height); - } - - .table-row-container { - width: 100%; - position: relative; - top: var(--ni-private-table-row-container-top); - } - .header-row-container { position: sticky; top: 0; + width: var(--ni-private-table-total-width); } .header-row { @@ -118,6 +98,29 @@ export const styles = css` cursor: w-resize; } + .table-viewport { + overflow-y: auto; + display: block; + height: 100%; + position: relative; + width: var(--ni-private-table-total-width); + overflow-x: hidden; + } + + .table-scroll { + pointer-events: none; + position: absolute; + top: 0px; + width: 100%; + height: var(--ni-private-table-scroll-height); + } + + .table-row-container { + width: 100%; + position: relative; + top: var(--ni-private-table-row-container-top); + } + .row { background: ${applicationBackgroundColor}; position: relative; diff --git a/packages/nimble-components/src/table/template.ts b/packages/nimble-components/src/table/template.ts index 166ed6490e..85f0e222a8 100644 --- a/packages/nimble-components/src/table/template.ts +++ b/packages/nimble-components/src/table/template.ts @@ -21,7 +21,9 @@ import { tableGroupRowTag } from './components/group-row'; // prettier-ignore export const template = html
` -