From bff0fd4a7287c6236d80bf5d9c627b393e9d73fa Mon Sep 17 00:00:00 2001 From: johanrd Date: Mon, 25 Aug 2025 17:17:46 +0200 Subject: [PATCH 1/6] adding table setting Fixed table layout for simpler calculations in fixed-table layouts With fixed table layout you can set `tableLayout: fixed` for a simpler calculation of column widths where the resize handle only resizes the column that is being resized. --- .../public/docs/2-plugins/column-resizing.md | 124 ++++++++++++++++++ table/src/plugins/column-resizing/plugin.ts | 38 ++++++ .../column-resizing/fixed-layout-test.gts | 85 ++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 test-app/tests/plugins/column-resizing/fixed-layout-test.gts diff --git a/docs-app/public/docs/2-plugins/column-resizing.md b/docs-app/public/docs/2-plugins/column-resizing.md index c3d5f724..976d6469 100644 --- a/docs-app/public/docs/2-plugins/column-resizing.md +++ b/docs-app/public/docs/2-plugins/column-resizing.md @@ -151,6 +151,130 @@ table = headlessTable(this, { See the API Documentation [here][api-docs] for the full list of options and descriptions. +#### Fixed table layout + +With fixed table layout you can set `tableLayout: fixed` for a simpler calculation of column widths where the resize handle only resizes the column that is being resized. + +```js +table = headlessTable(this, { + columns: () => [ + /* ... */ + ], + plugins: [ColumnResizing.with(() => ({ tableLayout: "fixed" }))], +}); +``` + + + ### Preferences The width will be stored in preferences, per column. diff --git a/table/src/plugins/column-resizing/plugin.ts b/table/src/plugins/column-resizing/plugin.ts index b4945bcc..e7d21b58 100644 --- a/table/src/plugins/column-resizing/plugin.ts +++ b/table/src/plugins/column-resizing/plugin.ts @@ -67,6 +67,17 @@ export interface TableOptions { * Valid values are 'left' or 'right' */ handlePosition?: string; + + /** + * Specify the table layout strategy for column resizing. + * + * - 'auto': Uses complex redistribution logic where resizing one column + * affects neighboring columns (default, preserves existing behavior) + * - 'fixed': Simple per-column resizing suitable for CSS table-layout: fixed + * + * default: 'auto' + */ + tableLayout?: 'auto' | 'fixed'; } interface Signature { @@ -378,6 +389,33 @@ export class TableMeta { resizeColumn(column: Column, delta: number) { if (delta === 0) return; + const tableLayout = this.options?.tableLayout ?? 'auto'; + + if (tableLayout === 'fixed') { + this.#resizeColumnFixed(column, delta); + } else { + this.#resizeColumnAuto(column, delta); + } + } + + /** + * Simple column resizing for table-layout: fixed + * Only affects the target column and respects minimum width + */ + #resizeColumnFixed(column: Column, delta: number) { + const columnMeta = meta.forColumn(column, ColumnResizing); + const newWidth = columnMeta.width + delta; + + if (newWidth >= columnMeta.minWidth) { + columnMeta.width = newWidth; + } + } + + /** + * Complex column resizing with redistribution logic + * Preserves existing behavior for table-layout: auto + */ + #resizeColumnAuto(column: Column, delta: number) { /** * When the delta is negative, we are dragging to the next * when positive, we are dragging to the right diff --git a/test-app/tests/plugins/column-resizing/fixed-layout-test.gts b/test-app/tests/plugins/column-resizing/fixed-layout-test.gts new file mode 100644 index 00000000..dd84f11f --- /dev/null +++ b/test-app/tests/plugins/column-resizing/fixed-layout-test.gts @@ -0,0 +1,85 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { htmlSafe } from "@ember/template"; +import { render } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "ember-qunit"; +import { setOwner } from "@ember/owner"; + +import { headlessTable, type ColumnConfig } from "@universal-ember/table"; +import { + ColumnResizing, + resizeHandle, +} from "@universal-ember/table/plugins/column-resizing"; +import { createHelpers } from "@universal-ember/table/test-support"; + +import { TestStyles, getColumns, assertChanges, width } from "./utils.gts"; + +module("Plugins | resizing | fixed layout", function (hooks) { + setupRenderingTest(hooks); + + let ctx: Context; + let { dragLeft, dragRight } = createHelpers({ + resizeHandle: "[data-handle]", + }); + + hooks.beforeEach(function () { + ctx = new Context(); + setOwner(ctx, this.owner); + }); + + class Context { + @tracked containerWidth = 1000; + + columns: ColumnConfig[] = [ + { name: "A", key: "A" }, + { name: "B", key: "B" }, + { name: "C", key: "C" }, + { name: "D", key: "D" }, + ]; + + table = headlessTable(this, { + columns: () => this.columns, + data: () => [] as unknown[], + plugins: [ColumnResizing.with(() => ({ tableLayout: "fixed" }))], + }); + } + + class FixedLayoutTestComponent extends Component<{ ctx: Context }> { + get table() { + return this.args.ctx.table; + } + + get modifiers() { + return this.table.modifiers; + } + + get testContainerStyle() { + return htmlSafe(`width: ${this.args.ctx.containerWidth}px`); + } + + + } +}); From d68c9800b090b851ce74f657974bf38d04894649 Mon Sep 17 00:00:00 2001 From: johanrd Date: Mon, 25 Aug 2025 17:19:31 +0200 Subject: [PATCH 2/6] add set widths to docs app example of table-layout: fixed --- .../tests/plugins/column-resizing/fixed-layout-test.gts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test-app/tests/plugins/column-resizing/fixed-layout-test.gts b/test-app/tests/plugins/column-resizing/fixed-layout-test.gts index dd84f11f..0718c718 100644 --- a/test-app/tests/plugins/column-resizing/fixed-layout-test.gts +++ b/test-app/tests/plugins/column-resizing/fixed-layout-test.gts @@ -32,10 +32,10 @@ module("Plugins | resizing | fixed layout", function (hooks) { @tracked containerWidth = 1000; columns: ColumnConfig[] = [ - { name: "A", key: "A" }, - { name: "B", key: "B" }, - { name: "C", key: "C" }, - { name: "D", key: "D" }, + { name: "A", key: "A", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))],}, + { name: "B", key: "B", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))] }, + { name: "C", key: "C", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))] }, + { name: "D", key: "D", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))] }, ]; table = headlessTable(this, { From 106a7c41592006c694e3ff75e03d51424b9b715a Mon Sep 17 00:00:00 2001 From: johanrd Date: Mon, 25 Aug 2025 17:25:45 +0200 Subject: [PATCH 3/6] lint:fix --- .../column-resizing/fixed-layout-test.gts | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/test-app/tests/plugins/column-resizing/fixed-layout-test.gts b/test-app/tests/plugins/column-resizing/fixed-layout-test.gts index 0718c718..8a28271c 100644 --- a/test-app/tests/plugins/column-resizing/fixed-layout-test.gts +++ b/test-app/tests/plugins/column-resizing/fixed-layout-test.gts @@ -32,10 +32,26 @@ module("Plugins | resizing | fixed layout", function (hooks) { @tracked containerWidth = 1000; columns: ColumnConfig[] = [ - { name: "A", key: "A", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))],}, - { name: "B", key: "B", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))] }, - { name: "C", key: "C", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))] }, - { name: "D", key: "D", pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))] }, + { + name: "A", + key: "A", + pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))], + }, + { + name: "B", + key: "B", + pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))], + }, + { + name: "C", + key: "C", + pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))], + }, + { + name: "D", + key: "D", + pluginOptions: [ColumnResizing.forColumn(() => ({ minWidth: 128 }))], + }, ]; table = headlessTable(this, { From a266205cbfa8b6e9796954f145825a61a9d9b29c Mon Sep 17 00:00:00 2001 From: johanrd Date: Mon, 25 Aug 2025 17:34:20 +0200 Subject: [PATCH 4/6] fix types --- table/src/plugins/column-resizing/plugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/table/src/plugins/column-resizing/plugin.ts b/table/src/plugins/column-resizing/plugin.ts index 2f8b4d4f..5c6a5bab 100644 --- a/table/src/plugins/column-resizing/plugin.ts +++ b/table/src/plugins/column-resizing/plugin.ts @@ -402,7 +402,7 @@ export class TableMeta { * Simple column resizing for table-layout: fixed * Only affects the target column and respects minimum width */ - #resizeColumnFixed(column: Column, delta: number) { + #resizeColumnFixed(column: Column, delta: number) { const columnMeta = meta.forColumn(column, ColumnResizing); const newWidth = columnMeta.width + delta; @@ -415,7 +415,7 @@ export class TableMeta { * Complex column resizing with redistribution logic * Preserves existing behavior for table-layout: auto */ - #resizeColumnAuto(column: Column, delta: number) { + #resizeColumnAuto(column: Column, delta: number) { /** * When the delta is negative, we are dragging to the next * when positive, we are dragging to the right From f07bd5ced5b4e2dd64433471b9ba5c4b1804056d Mon Sep 17 00:00:00 2001 From: johanrd Date: Mon, 25 Aug 2025 17:45:28 +0200 Subject: [PATCH 5/6] 'fix' for dumb ts --- table/src/plugins/column-resizing/plugin.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/table/src/plugins/column-resizing/plugin.ts b/table/src/plugins/column-resizing/plugin.ts index 5c6a5bab..30522e8c 100644 --- a/table/src/plugins/column-resizing/plugin.ts +++ b/table/src/plugins/column-resizing/plugin.ts @@ -75,9 +75,11 @@ export interface TableOptions { * affects neighboring columns (default, preserves existing behavior) * - 'fixed': Simple per-column resizing suitable for CSS table-layout: fixed * + * Valid values are 'auto' or 'fixed' + * * default: 'auto' */ - tableLayout?: 'auto' | 'fixed'; + tableLayout?: string; } interface Signature { From 3a5be20735f2a236629385ed8bdebee7327cb08a Mon Sep 17 00:00:00 2001 From: johanrd Date: Mon, 25 Aug 2025 17:46:08 +0200 Subject: [PATCH 6/6] lint:fix --- table/src/plugins/column-resizing/plugin.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/table/src/plugins/column-resizing/plugin.ts b/table/src/plugins/column-resizing/plugin.ts index 30522e8c..45b7e791 100644 --- a/table/src/plugins/column-resizing/plugin.ts +++ b/table/src/plugins/column-resizing/plugin.ts @@ -404,7 +404,10 @@ export class TableMeta { * Simple column resizing for table-layout: fixed * Only affects the target column and respects minimum width */ - #resizeColumnFixed(column: Column, delta: number) { + #resizeColumnFixed( + column: Column, + delta: number, + ) { const columnMeta = meta.forColumn(column, ColumnResizing); const newWidth = columnMeta.width + delta; @@ -417,7 +420,10 @@ export class TableMeta { * Complex column resizing with redistribution logic * Preserves existing behavior for table-layout: auto */ - #resizeColumnAuto(column: Column, delta: number) { + #resizeColumnAuto( + column: Column, + delta: number, + ) { /** * When the delta is negative, we are dragging to the next * when positive, we are dragging to the right