@universal-ember/table 3.1.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/declarations/-private/column.d.ts.map +1 -1
- package/declarations/-private/interfaces/table.d.ts +13 -0
- package/declarations/-private/interfaces/table.d.ts.map +1 -1
- package/declarations/plugins/column-reordering/plugin.d.ts +43 -2
- package/declarations/plugins/column-reordering/plugin.d.ts.map +1 -1
- package/declarations/plugins/column-resizing/plugin.d.ts.map +1 -1
- package/dist/-private/column.js +4 -4
- package/dist/-private/column.js.map +1 -1
- package/dist/plugins/column-reordering/plugin.js +138 -57
- package/dist/plugins/column-reordering/plugin.js.map +1 -1
- package/dist/plugins/column-resizing/plugin.js +8 -1
- package/dist/plugins/column-resizing/plugin.js.map +1 -1
- package/package.json +1 -1
- package/src/-private/column.ts +5 -1
- package/src/-private/interfaces/table.ts +14 -0
- package/src/plugins/column-reordering/plugin.ts +206 -73
- package/src/plugins/column-resizing/plugin.ts +8 -1
|
@@ -156,7 +156,9 @@ let ColumnMeta = (_class = class ColumnMeta {
|
|
|
156
156
|
* Otherwise the table will infinitely resize itself
|
|
157
157
|
*/
|
|
158
158
|
function distributeDelta(delta, visibleColumns) {
|
|
159
|
-
|
|
159
|
+
// Use a tolerance threshold to prevent infinite resize loops from subpixel rounding
|
|
160
|
+
// at different zoom levels. Treat deltas smaller than 0.5px as zero.
|
|
161
|
+
if (Math.abs(delta) < 0.5) return;
|
|
160
162
|
const metas = visibleColumns.map(column => meta.forColumn(column, ColumnResizing));
|
|
161
163
|
const resizableMetas = metas.filter(meta => meta.isResizable && (delta < 0 ? meta.canShrink : true));
|
|
162
164
|
const columnDelta = delta / resizableMetas.length;
|
|
@@ -217,6 +219,11 @@ let TableMeta = (_class2 = (_TableMeta_brand = /*#__PURE__*/new WeakSet(), class
|
|
|
217
219
|
}
|
|
218
220
|
onTableResize(entry) {
|
|
219
221
|
assert('scroll container element must be an HTMLElement', entry.target instanceof HTMLElement);
|
|
222
|
+
|
|
223
|
+
// For fixed layout, columns have explicit widths and should not be auto-redistributed
|
|
224
|
+
if (this.options?.tableLayout === 'fixed') {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
220
227
|
this.scrollContainerWidth = getAccurateClientWidth(entry.target);
|
|
221
228
|
this.scrollContainerHeight = getAccurateClientHeight(entry.target);
|
|
222
229
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../../../src/plugins/column-resizing/plugin.ts"],"sourcesContent":["import { cached, tracked } from '@glimmer/tracking';\nimport { assert } from '@ember/debug';\nimport { isDestroyed, isDestroying } from '@ember/destroyable';\nimport { action } from '@ember/object';\n\nimport { preferences } from '../../plugins/index.ts';\n\nimport { BasePlugin, columns, meta, options } from '../-private/base.ts';\nimport { applyStyles } from '../-private/utils.ts';\nimport {\n getAccurateClientHeight,\n getAccurateClientWidth,\n totalGapOf,\n} from './utils.ts';\n\nimport type { ColumnApi, PluginPreferences } from '../../plugins/index.ts';\nimport type { Column, Table } from '../../index.ts';\n\ninterface ColumnResizePreferences extends PluginPreferences {\n columns: {\n [columnKey: string]: {\n width?: number;\n };\n };\n}\n\ndeclare module '@universal-ember/table/plugins' {\n interface Registry {\n ColumnResizing?: ColumnResizePreferences;\n }\n}\n\nexport interface ColumnOptions {\n /**\n * Force a starting width\n * This may not be less than the minWidth\n */\n width?: number;\n /**\n * Default: 128px\n */\n minWidth?: number;\n /**\n * Flip if the column is resizable or not.\n * The default is whatever the table's plugin option is set to\n * (and then yet again true, if not set at all)\n */\n isResizable?: boolean;\n}\n\nexport interface TableOptions {\n /**\n * Toggle whether the table is able to be resized at all\n *\n * default :true\n */\n enabled?: boolean;\n\n /**\n * By default, each column's \"handle\" position is on the\n * left-hand side of the column.\n *\n * If, for style-reasons, you want to move it to the right,\n * this option should reflect that so that the calculations can be\n * updated to match the expected behavior of which column(s) grow/shrink\n *\n * Valid values are 'left' or 'right'\n */\n handlePosition?: string;\n\n /**\n * Specify the table layout strategy for column resizing.\n *\n * - 'auto': Uses complex redistribution logic where resizing one column\n * affects neighboring columns (default, preserves existing behavior)\n * - 'fixed': Simple per-column resizing suitable for CSS table-layout: fixed\n *\n * Valid values are 'auto' or 'fixed'\n *\n * default: 'auto'\n */\n tableLayout?: string;\n}\n\ninterface Signature {\n Meta: {\n Column: ColumnMeta;\n Table: TableMeta;\n };\n Options: {\n Plugin: TableOptions;\n Column: ColumnOptions;\n };\n}\n\n/**\n * One instance of a plugin exists per table\n * but a plugin can have a \"Meta\" for each column\n */\nexport class ColumnResizing extends BasePlugin<Signature> {\n name = 'column-resizing';\n static features = ['columnWidth'];\n\n meta = {\n column: ColumnMeta,\n table: TableMeta,\n };\n\n headerCellModifier = (element: HTMLElement, { column }: ColumnApi) => {\n const columnMeta = meta.forColumn(column, ColumnResizing);\n\n element.setAttribute('data-test-is-resizable', `${columnMeta.isResizable}`);\n\n applyStyles(element, columnMeta.style);\n };\n\n /**\n * This is what ends up calling resize when the browser changes\n * (assuming that the containing element's styles stretch to fill the space)\n *\n * Later, when container queries are more broadly supported, we'll want to watch\n * the container instead of the window to prevent unneeded updates (as a window can change\n * size without the container changing size)\n */\n containerModifier = resizeObserver;\n\n reset() {\n preferences.forAllColumns(this.table, ColumnResizing).delete('width');\n }\n}\n\nconst DEFAULT_COLUMN_OPTIONS = {\n minWidth: 128,\n};\n\nconst ALLOWED_COLUMN_OPTIONS = ['minWidth', 'width', 'isResizable'];\n\n/**\n * @private\n *\n * Contains resizable information for a particular column\n */\nexport class ColumnMeta {\n constructor(private column: Column) {}\n\n @tracked _width?: number;\n @tracked isResizing = false;\n\n get tableMeta() {\n return meta.forTable(this.column.table, ColumnResizing);\n }\n\n @cached\n get options() {\n const columnOptions = options.forColumn(this.column, ColumnResizing);\n const filteredOptions = Object.entries(columnOptions || {}).reduce(\n (result, [k, v]) => {\n if (ALLOWED_COLUMN_OPTIONS.includes(k)) {\n result[k] = v;\n }\n\n return result;\n },\n {} as Record<string, unknown>,\n ) as ColumnOptions;\n\n return {\n ...DEFAULT_COLUMN_OPTIONS,\n ...filteredOptions,\n };\n }\n\n get key() {\n return this.column.key;\n }\n\n get minWidth() {\n return this.options.minWidth;\n }\n\n get initialWidth() {\n const savedWidth = preferences\n .forColumn(this.column, ColumnResizing)\n .get('width');\n\n if (!savedWidth) {\n return this.options.width;\n }\n\n if (typeof savedWidth !== 'string') {\n assert(\n 'saved width must be a number or string',\n typeof savedWidth === 'number',\n );\n return savedWidth;\n }\n\n return parseInt(savedWidth, 10);\n }\n\n get canShrink() {\n return this.width && this.width > this.minWidth;\n }\n\n get roomToShrink() {\n return this.width ? this.width - this.minWidth : 0;\n }\n\n get isResizable() {\n return this.options.isResizable ?? this.tableMeta.isResizable;\n }\n\n get hasResizeHandle() {\n const previous = columns.previous(this.column);\n\n if (!previous) return false;\n\n return (\n this.isResizable && meta.forColumn(previous, ColumnResizing).isResizable\n );\n }\n\n get width() {\n let width = this._width ?? this.initialWidth;\n\n if (!width) {\n const { defaultColumnWidth } = this.tableMeta;\n\n width = defaultColumnWidth\n ? Math.max(defaultColumnWidth, this.minWidth)\n : this.minWidth;\n }\n\n return width;\n }\n\n set width(value) {\n this._width = value;\n }\n\n get style() {\n const styles: Partial<Pick<CSSStyleDeclaration, 'width' | 'minWidth'>> = {};\n\n if (this.width) styles.width = `${this.width}px`;\n if (this.minWidth) styles.minWidth = `${this.minWidth}px`;\n\n return styles;\n }\n\n @action\n resize(delta: number) {\n this.tableMeta.resizeColumn(this.column, delta);\n }\n\n @action\n save() {\n this.tableMeta.saveColWidths(this.tableMeta.visibleColumnMetas);\n }\n}\n\n/**\n * @private\n *\n * individual column width must exclude:\n * - padding\n * - margin\n * - gap (partial)\n * - any other positioning offsets\n *\n * Otherwise the table will infinitely resize itself\n */\nfunction distributeDelta(delta: number, visibleColumns: Column[]) {\n if (delta === 0) return;\n\n const metas = visibleColumns.map((column) =>\n meta.forColumn(column, ColumnResizing),\n );\n\n const resizableMetas = metas.filter(\n (meta) => meta.isResizable && (delta < 0 ? meta.canShrink : true),\n );\n\n const columnDelta = delta / resizableMetas.length;\n\n for (const meta of resizableMetas) {\n assert('cannot resize a column that does not have a width', meta.width);\n meta.width = Math.max(meta.width + columnDelta, meta.minWidth);\n }\n}\n\n/**\n * @private\n *\n * Contains resizable and width information regarding the table as a whole\n */\nexport class TableMeta {\n constructor(private table: Table) {}\n\n @tracked scrollContainerHeight?: number;\n @tracked scrollContainerWidth?: number;\n\n get options() {\n return options.forTable(this.table, ColumnResizing);\n }\n\n get isResizable() {\n return this.options?.enabled ?? true;\n }\n\n get defaultColumnWidth() {\n if (!this.scrollContainerWidth) return;\n\n return (\n (this.scrollContainerWidth - this.totalInitialColumnWidths) /\n this.columnsWithoutInitialWidth.length\n );\n }\n\n get #availableColumns() {\n return columns.for(this.table, ColumnResizing);\n }\n\n get visibleColumnMetas() {\n return this.#availableColumns.map((column) =>\n meta.forColumn(column, ColumnResizing),\n );\n }\n\n get totalInitialColumnWidths() {\n return this.visibleColumnMetas.reduce(\n (acc, meta) => (acc += meta.initialWidth ?? 0),\n 0,\n );\n }\n\n get columnsWithoutInitialWidth() {\n return this.visibleColumnMetas.filter((meta) => !meta.initialWidth);\n }\n\n get totalVisibleColumnsWidth() {\n return this.visibleColumnMetas.reduce(\n (acc, column) => (acc += column.width ?? 0),\n 0,\n );\n }\n\n @action\n saveColWidths(visibleColumnMetas: ColumnMeta[]) {\n const tablePrefs = this.table.preferences;\n\n for (const column of visibleColumnMetas) {\n const existing = tablePrefs.storage.forPlugin('ColumnResizing');\n const columnPrefs = existing.forColumn(column.key);\n\n columnPrefs.set('width', column.width.toString());\n }\n\n tablePrefs.persist();\n }\n\n @action\n reset() {\n if (!this.scrollContainerWidth) return;\n\n for (const column of this.visibleColumnMetas) {\n column._width = undefined;\n }\n }\n\n @action\n onTableResize(entry: ResizeObserverEntry) {\n assert(\n 'scroll container element must be an HTMLElement',\n entry.target instanceof HTMLElement,\n );\n\n this.scrollContainerWidth = getAccurateClientWidth(entry.target);\n this.scrollContainerHeight = getAccurateClientHeight(entry.target);\n\n // TODO: extract this to card-list and remove it from the plugin\n // card-list will provide its own column-resizing plugin\n // by sub-classing this one, and defining its own way of calculating the \"diff\"\n const totalGap = totalGapOf(entry.target.querySelector('[role=\"row\"]'));\n const diff =\n this.scrollContainerWidth - this.totalVisibleColumnsWidth - totalGap;\n\n distributeDelta(diff, this.#availableColumns);\n }\n\n @action\n resizeColumn<DataType = unknown>(column: Column<DataType>, delta: number) {\n if (delta === 0) return;\n\n const tableLayout = this.options?.tableLayout ?? 'auto';\n\n if (tableLayout === 'fixed') {\n this.#resizeColumnFixed(column, delta);\n } else {\n this.#resizeColumnAuto(column, delta);\n }\n }\n\n /**\n * Simple column resizing for table-layout: fixed\n * Only affects the target column and respects minimum width\n */\n #resizeColumnFixed<DataType = unknown>(\n column: Column<DataType>,\n delta: number,\n ) {\n const columnMeta = meta.forColumn(column, ColumnResizing);\n const newWidth = columnMeta.width + delta;\n\n if (newWidth >= columnMeta.minWidth) {\n columnMeta.width = newWidth;\n }\n }\n\n /**\n * Complex column resizing with redistribution logic\n * Preserves existing behavior for table-layout: auto\n */\n #resizeColumnAuto<DataType = unknown>(\n column: Column<DataType>,\n delta: number,\n ) {\n /**\n * When the delta is negative, we are dragging to the next\n * when positive, we are dragging to the right\n * when dragging to the right, we want to grow the column\n * when dragging to the left, we grow the \"next\" column,\n * which shrinks the column we're dragging\n *\n * This assumes the resize handle for any column is on the right-hand\n * side of the column header\n *\n * If the resize handle were on the left-hand side of the column header\n * we'd want the column.next to be column.previous\n *\n * This is CSS dependent, and can be configured in plugin\n * options\n */\n const isDraggingRight = delta > 0;\n const position = this.options?.handlePosition ?? 'left';\n\n let growingColumn: Column<DataType> | null | undefined;\n\n if (position === 'right') {\n growingColumn = isDraggingRight ? columns.next(column) : column;\n } else {\n growingColumn = isDraggingRight ? columns.previous(column) : column;\n }\n\n if (!growingColumn) return;\n\n const growingColumnMeta = meta.forColumn(growingColumn, ColumnResizing);\n\n assert(\n 'cannot resize a column that does not have a width',\n growingColumnMeta.width,\n );\n\n const shrinkableColumns =\n delta > 0\n ? columns.after(growingColumn)\n : columns.before(growingColumn).reverse();\n\n const shrinkableColumnsMetas = shrinkableColumns\n .map((column) => meta.forColumn(column, ColumnResizing))\n .filter((meta) => meta.canShrink);\n\n let remainder = Math.abs(delta);\n\n while (shrinkableColumnsMetas.length > 0) {\n const shrinkingColumnMeta = shrinkableColumnsMetas.shift();\n\n assert(\n 'cannot resize a column that does not have a width',\n shrinkingColumnMeta?.width,\n );\n\n const actualDelta = Math.min(remainder, shrinkingColumnMeta.roomToShrink);\n\n growingColumnMeta.width += actualDelta;\n shrinkingColumnMeta.width -= actualDelta;\n remainder -= actualDelta;\n }\n }\n}\n\n/**\n * @private\n * included in the same file as the plugin due to circular dependency\n *\n * This goes on the containing element\n *\n * @example\n * ```hbs\n * <div {{resizeObserver @table}}>\n * <table>\n * ```\n */\nfunction resizeObserver(element: HTMLElement, table: Table) {\n const observer = getObserver(element, table);\n\n observer.observe(element);\n\n return () => {\n observer.unobserve(element);\n };\n}\n\nconst CACHE = new WeakMap<HTMLElement, ResizeObserver>();\n\n/**\n * This is technically \"inefficient\" as you don't want too many resize\n * observers on a page, but tables are so big, that I don't see too many use cases\n * where you'd have 10+ tables on a page\n */\nfunction getObserver(element: HTMLElement, table: Table): ResizeObserver {\n let existing = CACHE.get(element);\n\n if (existing) return existing;\n\n existing = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n if (isDestroyed(table) || isDestroying(table)) {\n return;\n }\n\n for (const entry of entries) {\n meta.forTable(table, ColumnResizing).onTableResize(entry);\n }\n });\n\n return existing;\n}\n"],"names":["ColumnResizing","BasePlugin","constructor","args","_defineProperty","column","ColumnMeta","table","TableMeta","element","columnMeta","meta","forColumn","setAttribute","isResizable","applyStyles","style","resizeObserver","reset","preferences","forAllColumns","delete","DEFAULT_COLUMN_OPTIONS","minWidth","ALLOWED_COLUMN_OPTIONS","_class","_initializerDefineProperty","_descriptor","_descriptor2","tableMeta","forTable","options","columnOptions","filteredOptions","Object","entries","reduce","result","k","v","includes","key","initialWidth","savedWidth","get","width","assert","parseInt","canShrink","roomToShrink","hasResizeHandle","previous","columns","_width","defaultColumnWidth","Math","max","value","styles","resize","delta","resizeColumn","save","saveColWidths","visibleColumnMetas","_applyDecoratedDescriptor","prototype","tracked","configurable","enumerable","writable","initializer","cached","getOwnPropertyDescriptor","action","distributeDelta","visibleColumns","metas","map","resizableMetas","filter","columnDelta","length","_class2","_TableMeta_brand","WeakSet","_classPrivateMethodInitSpec","_descriptor3","_descriptor4","enabled","scrollContainerWidth","totalInitialColumnWidths","columnsWithoutInitialWidth","_classPrivateGetter","_get_availableColumns","acc","totalVisibleColumnsWidth","tablePrefs","existing","storage","forPlugin","columnPrefs","set","toString","persist","undefined","onTableResize","entry","target","HTMLElement","getAccurateClientWidth","scrollContainerHeight","getAccurateClientHeight","totalGap","totalGapOf","querySelector","diff","tableLayout","_assertClassBrand","_resizeColumnFixed","call","_resizeColumnAuto","_this","for","newWidth","isDraggingRight","position","handlePosition","growingColumn","next","growingColumnMeta","shrinkableColumns","after","before","reverse","shrinkableColumnsMetas","remainder","abs","shrinkingColumnMeta","shift","actualDelta","min","observer","getObserver","observe","unobserve","CACHE","WeakMap","ResizeObserver","isDestroyed","isDestroying"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../../src/plugins/column-resizing/plugin.ts"],"sourcesContent":["import { cached, tracked } from '@glimmer/tracking';\nimport { assert } from '@ember/debug';\nimport { isDestroyed, isDestroying } from '@ember/destroyable';\nimport { action } from '@ember/object';\n\nimport { preferences } from '../../plugins/index.ts';\n\nimport { BasePlugin, columns, meta, options } from '../-private/base.ts';\nimport { applyStyles } from '../-private/utils.ts';\nimport {\n getAccurateClientHeight,\n getAccurateClientWidth,\n totalGapOf,\n} from './utils.ts';\n\nimport type { ColumnApi, PluginPreferences } from '../../plugins/index.ts';\nimport type { Column, Table } from '../../index.ts';\n\ninterface ColumnResizePreferences extends PluginPreferences {\n columns: {\n [columnKey: string]: {\n width?: number;\n };\n };\n}\n\ndeclare module '@universal-ember/table/plugins' {\n interface Registry {\n ColumnResizing?: ColumnResizePreferences;\n }\n}\n\nexport interface ColumnOptions {\n /**\n * Force a starting width\n * This may not be less than the minWidth\n */\n width?: number;\n /**\n * Default: 128px\n */\n minWidth?: number;\n /**\n * Flip if the column is resizable or not.\n * The default is whatever the table's plugin option is set to\n * (and then yet again true, if not set at all)\n */\n isResizable?: boolean;\n}\n\nexport interface TableOptions {\n /**\n * Toggle whether the table is able to be resized at all\n *\n * default :true\n */\n enabled?: boolean;\n\n /**\n * By default, each column's \"handle\" position is on the\n * left-hand side of the column.\n *\n * If, for style-reasons, you want to move it to the right,\n * this option should reflect that so that the calculations can be\n * updated to match the expected behavior of which column(s) grow/shrink\n *\n * Valid values are 'left' or 'right'\n */\n handlePosition?: string;\n\n /**\n * Specify the table layout strategy for column resizing.\n *\n * - 'auto': Uses complex redistribution logic where resizing one column\n * affects neighboring columns (default, preserves existing behavior)\n * - 'fixed': Simple per-column resizing suitable for CSS table-layout: fixed\n *\n * Valid values are 'auto' or 'fixed'\n *\n * default: 'auto'\n */\n tableLayout?: string;\n}\n\ninterface Signature {\n Meta: {\n Column: ColumnMeta;\n Table: TableMeta;\n };\n Options: {\n Plugin: TableOptions;\n Column: ColumnOptions;\n };\n}\n\n/**\n * One instance of a plugin exists per table\n * but a plugin can have a \"Meta\" for each column\n */\nexport class ColumnResizing extends BasePlugin<Signature> {\n name = 'column-resizing';\n static features = ['columnWidth'];\n\n meta = {\n column: ColumnMeta,\n table: TableMeta,\n };\n\n headerCellModifier = (element: HTMLElement, { column }: ColumnApi) => {\n const columnMeta = meta.forColumn(column, ColumnResizing);\n\n element.setAttribute('data-test-is-resizable', `${columnMeta.isResizable}`);\n\n applyStyles(element, columnMeta.style);\n };\n\n /**\n * This is what ends up calling resize when the browser changes\n * (assuming that the containing element's styles stretch to fill the space)\n *\n * Later, when container queries are more broadly supported, we'll want to watch\n * the container instead of the window to prevent unneeded updates (as a window can change\n * size without the container changing size)\n */\n containerModifier = resizeObserver;\n\n reset() {\n preferences.forAllColumns(this.table, ColumnResizing).delete('width');\n }\n}\n\nconst DEFAULT_COLUMN_OPTIONS = {\n minWidth: 128,\n};\n\nconst ALLOWED_COLUMN_OPTIONS = ['minWidth', 'width', 'isResizable'];\n\n/**\n * @private\n *\n * Contains resizable information for a particular column\n */\nexport class ColumnMeta {\n constructor(private column: Column) {}\n\n @tracked _width?: number;\n @tracked isResizing = false;\n\n get tableMeta() {\n return meta.forTable(this.column.table, ColumnResizing);\n }\n\n @cached\n get options() {\n const columnOptions = options.forColumn(this.column, ColumnResizing);\n const filteredOptions = Object.entries(columnOptions || {}).reduce(\n (result, [k, v]) => {\n if (ALLOWED_COLUMN_OPTIONS.includes(k)) {\n result[k] = v;\n }\n\n return result;\n },\n {} as Record<string, unknown>,\n ) as ColumnOptions;\n\n return {\n ...DEFAULT_COLUMN_OPTIONS,\n ...filteredOptions,\n };\n }\n\n get key() {\n return this.column.key;\n }\n\n get minWidth() {\n return this.options.minWidth;\n }\n\n get initialWidth() {\n const savedWidth = preferences\n .forColumn(this.column, ColumnResizing)\n .get('width');\n\n if (!savedWidth) {\n return this.options.width;\n }\n\n if (typeof savedWidth !== 'string') {\n assert(\n 'saved width must be a number or string',\n typeof savedWidth === 'number',\n );\n return savedWidth;\n }\n\n return parseInt(savedWidth, 10);\n }\n\n get canShrink() {\n return this.width && this.width > this.minWidth;\n }\n\n get roomToShrink() {\n return this.width ? this.width - this.minWidth : 0;\n }\n\n get isResizable() {\n return this.options.isResizable ?? this.tableMeta.isResizable;\n }\n\n get hasResizeHandle() {\n const previous = columns.previous(this.column);\n\n if (!previous) return false;\n\n return (\n this.isResizable && meta.forColumn(previous, ColumnResizing).isResizable\n );\n }\n\n get width() {\n let width = this._width ?? this.initialWidth;\n\n if (!width) {\n const { defaultColumnWidth } = this.tableMeta;\n\n width = defaultColumnWidth\n ? Math.max(defaultColumnWidth, this.minWidth)\n : this.minWidth;\n }\n\n return width;\n }\n\n set width(value) {\n this._width = value;\n }\n\n get style() {\n const styles: Partial<Pick<CSSStyleDeclaration, 'width' | 'minWidth'>> = {};\n\n if (this.width) styles.width = `${this.width}px`;\n if (this.minWidth) styles.minWidth = `${this.minWidth}px`;\n\n return styles;\n }\n\n @action\n resize(delta: number) {\n this.tableMeta.resizeColumn(this.column, delta);\n }\n\n @action\n save() {\n this.tableMeta.saveColWidths(this.tableMeta.visibleColumnMetas);\n }\n}\n\n/**\n * @private\n *\n * individual column width must exclude:\n * - padding\n * - margin\n * - gap (partial)\n * - any other positioning offsets\n *\n * Otherwise the table will infinitely resize itself\n */\nfunction distributeDelta(delta: number, visibleColumns: Column[]) {\n // Use a tolerance threshold to prevent infinite resize loops from subpixel rounding\n // at different zoom levels. Treat deltas smaller than 0.5px as zero.\n if (Math.abs(delta) < 0.5) return;\n\n const metas = visibleColumns.map((column) =>\n meta.forColumn(column, ColumnResizing),\n );\n\n const resizableMetas = metas.filter(\n (meta) => meta.isResizable && (delta < 0 ? meta.canShrink : true),\n );\n\n const columnDelta = delta / resizableMetas.length;\n\n for (const meta of resizableMetas) {\n assert('cannot resize a column that does not have a width', meta.width);\n meta.width = Math.max(meta.width + columnDelta, meta.minWidth);\n }\n}\n\n/**\n * @private\n *\n * Contains resizable and width information regarding the table as a whole\n */\nexport class TableMeta {\n constructor(private table: Table) {}\n\n @tracked scrollContainerHeight?: number;\n @tracked scrollContainerWidth?: number;\n\n get options() {\n return options.forTable(this.table, ColumnResizing);\n }\n\n get isResizable() {\n return this.options?.enabled ?? true;\n }\n\n get defaultColumnWidth() {\n if (!this.scrollContainerWidth) return;\n\n return (\n (this.scrollContainerWidth - this.totalInitialColumnWidths) /\n this.columnsWithoutInitialWidth.length\n );\n }\n\n get #availableColumns() {\n return columns.for(this.table, ColumnResizing);\n }\n\n get visibleColumnMetas() {\n return this.#availableColumns.map((column) =>\n meta.forColumn(column, ColumnResizing),\n );\n }\n\n get totalInitialColumnWidths() {\n return this.visibleColumnMetas.reduce(\n (acc, meta) => (acc += meta.initialWidth ?? 0),\n 0,\n );\n }\n\n get columnsWithoutInitialWidth() {\n return this.visibleColumnMetas.filter((meta) => !meta.initialWidth);\n }\n\n get totalVisibleColumnsWidth() {\n return this.visibleColumnMetas.reduce(\n (acc, column) => (acc += column.width ?? 0),\n 0,\n );\n }\n\n @action\n saveColWidths(visibleColumnMetas: ColumnMeta[]) {\n const tablePrefs = this.table.preferences;\n\n for (const column of visibleColumnMetas) {\n const existing = tablePrefs.storage.forPlugin('ColumnResizing');\n const columnPrefs = existing.forColumn(column.key);\n\n columnPrefs.set('width', column.width.toString());\n }\n\n tablePrefs.persist();\n }\n\n @action\n reset() {\n if (!this.scrollContainerWidth) return;\n\n for (const column of this.visibleColumnMetas) {\n column._width = undefined;\n }\n }\n\n @action\n onTableResize(entry: ResizeObserverEntry) {\n assert(\n 'scroll container element must be an HTMLElement',\n entry.target instanceof HTMLElement,\n );\n\n // For fixed layout, columns have explicit widths and should not be auto-redistributed\n if (this.options?.tableLayout === 'fixed') {\n return;\n }\n\n this.scrollContainerWidth = getAccurateClientWidth(entry.target);\n this.scrollContainerHeight = getAccurateClientHeight(entry.target);\n\n // TODO: extract this to card-list and remove it from the plugin\n // card-list will provide its own column-resizing plugin\n // by sub-classing this one, and defining its own way of calculating the \"diff\"\n const totalGap = totalGapOf(entry.target.querySelector('[role=\"row\"]'));\n const diff =\n this.scrollContainerWidth - this.totalVisibleColumnsWidth - totalGap;\n\n distributeDelta(diff, this.#availableColumns);\n }\n\n @action\n resizeColumn<DataType = unknown>(column: Column<DataType>, delta: number) {\n if (delta === 0) return;\n\n const tableLayout = this.options?.tableLayout ?? 'auto';\n\n if (tableLayout === 'fixed') {\n this.#resizeColumnFixed(column, delta);\n } else {\n this.#resizeColumnAuto(column, delta);\n }\n }\n\n /**\n * Simple column resizing for table-layout: fixed\n * Only affects the target column and respects minimum width\n */\n #resizeColumnFixed<DataType = unknown>(\n column: Column<DataType>,\n delta: number,\n ) {\n const columnMeta = meta.forColumn(column, ColumnResizing);\n const newWidth = columnMeta.width + delta;\n\n if (newWidth >= columnMeta.minWidth) {\n columnMeta.width = newWidth;\n }\n }\n\n /**\n * Complex column resizing with redistribution logic\n * Preserves existing behavior for table-layout: auto\n */\n #resizeColumnAuto<DataType = unknown>(\n column: Column<DataType>,\n delta: number,\n ) {\n /**\n * When the delta is negative, we are dragging to the next\n * when positive, we are dragging to the right\n * when dragging to the right, we want to grow the column\n * when dragging to the left, we grow the \"next\" column,\n * which shrinks the column we're dragging\n *\n * This assumes the resize handle for any column is on the right-hand\n * side of the column header\n *\n * If the resize handle were on the left-hand side of the column header\n * we'd want the column.next to be column.previous\n *\n * This is CSS dependent, and can be configured in plugin\n * options\n */\n const isDraggingRight = delta > 0;\n const position = this.options?.handlePosition ?? 'left';\n\n let growingColumn: Column<DataType> | null | undefined;\n\n if (position === 'right') {\n growingColumn = isDraggingRight ? columns.next(column) : column;\n } else {\n growingColumn = isDraggingRight ? columns.previous(column) : column;\n }\n\n if (!growingColumn) return;\n\n const growingColumnMeta = meta.forColumn(growingColumn, ColumnResizing);\n\n assert(\n 'cannot resize a column that does not have a width',\n growingColumnMeta.width,\n );\n\n const shrinkableColumns =\n delta > 0\n ? columns.after(growingColumn)\n : columns.before(growingColumn).reverse();\n\n const shrinkableColumnsMetas = shrinkableColumns\n .map((column) => meta.forColumn(column, ColumnResizing))\n .filter((meta) => meta.canShrink);\n\n let remainder = Math.abs(delta);\n\n while (shrinkableColumnsMetas.length > 0) {\n const shrinkingColumnMeta = shrinkableColumnsMetas.shift();\n\n assert(\n 'cannot resize a column that does not have a width',\n shrinkingColumnMeta?.width,\n );\n\n const actualDelta = Math.min(remainder, shrinkingColumnMeta.roomToShrink);\n\n growingColumnMeta.width += actualDelta;\n shrinkingColumnMeta.width -= actualDelta;\n remainder -= actualDelta;\n }\n }\n}\n\n/**\n * @private\n * included in the same file as the plugin due to circular dependency\n *\n * This goes on the containing element\n *\n * @example\n * ```hbs\n * <div {{resizeObserver @table}}>\n * <table>\n * ```\n */\nfunction resizeObserver(element: HTMLElement, table: Table) {\n const observer = getObserver(element, table);\n\n observer.observe(element);\n\n return () => {\n observer.unobserve(element);\n };\n}\n\nconst CACHE = new WeakMap<HTMLElement, ResizeObserver>();\n\n/**\n * This is technically \"inefficient\" as you don't want too many resize\n * observers on a page, but tables are so big, that I don't see too many use cases\n * where you'd have 10+ tables on a page\n */\nfunction getObserver(element: HTMLElement, table: Table): ResizeObserver {\n let existing = CACHE.get(element);\n\n if (existing) return existing;\n\n existing = new ResizeObserver((entries: ResizeObserverEntry[]) => {\n if (isDestroyed(table) || isDestroying(table)) {\n return;\n }\n\n for (const entry of entries) {\n meta.forTable(table, ColumnResizing).onTableResize(entry);\n }\n });\n\n return existing;\n}\n"],"names":["ColumnResizing","BasePlugin","constructor","args","_defineProperty","column","ColumnMeta","table","TableMeta","element","columnMeta","meta","forColumn","setAttribute","isResizable","applyStyles","style","resizeObserver","reset","preferences","forAllColumns","delete","DEFAULT_COLUMN_OPTIONS","minWidth","ALLOWED_COLUMN_OPTIONS","_class","_initializerDefineProperty","_descriptor","_descriptor2","tableMeta","forTable","options","columnOptions","filteredOptions","Object","entries","reduce","result","k","v","includes","key","initialWidth","savedWidth","get","width","assert","parseInt","canShrink","roomToShrink","hasResizeHandle","previous","columns","_width","defaultColumnWidth","Math","max","value","styles","resize","delta","resizeColumn","save","saveColWidths","visibleColumnMetas","_applyDecoratedDescriptor","prototype","tracked","configurable","enumerable","writable","initializer","cached","getOwnPropertyDescriptor","action","distributeDelta","visibleColumns","abs","metas","map","resizableMetas","filter","columnDelta","length","_class2","_TableMeta_brand","WeakSet","_classPrivateMethodInitSpec","_descriptor3","_descriptor4","enabled","scrollContainerWidth","totalInitialColumnWidths","columnsWithoutInitialWidth","_classPrivateGetter","_get_availableColumns","acc","totalVisibleColumnsWidth","tablePrefs","existing","storage","forPlugin","columnPrefs","set","toString","persist","undefined","onTableResize","entry","target","HTMLElement","tableLayout","getAccurateClientWidth","scrollContainerHeight","getAccurateClientHeight","totalGap","totalGapOf","querySelector","diff","_assertClassBrand","_resizeColumnFixed","call","_resizeColumnAuto","_this","for","newWidth","isDraggingRight","position","handlePosition","growingColumn","next","growingColumnMeta","shrinkableColumns","after","before","reverse","shrinkableColumnsMetas","remainder","shrinkingColumnMeta","shift","actualDelta","min","observer","getObserver","observe","unobserve","CACHE","WeakMap","ResizeObserver","isDestroyed","isDestroying"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/-private/column.ts
CHANGED
|
@@ -57,7 +57,11 @@ export class Column<T = unknown> {
|
|
|
57
57
|
|
|
58
58
|
@action
|
|
59
59
|
getOptionsForRow(row: Row<T>) {
|
|
60
|
-
const
|
|
60
|
+
const configuredDefault = this.table.config.defaultCellValue;
|
|
61
|
+
const defaults = {
|
|
62
|
+
[DEFAULT_VALUE_KEY]:
|
|
63
|
+
configuredDefault !== undefined ? configuredDefault : DEFAULT_VALUE,
|
|
64
|
+
};
|
|
61
65
|
|
|
62
66
|
return {
|
|
63
67
|
...defaults,
|
|
@@ -90,6 +90,20 @@ export interface TableConfig<DataType> {
|
|
|
90
90
|
meta?: TableMeta;
|
|
91
91
|
pagination?: Pagination;
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Default value to display in cells when the data is empty/missing.
|
|
95
|
+
* If not specified, defaults to '--'.
|
|
96
|
+
*
|
|
97
|
+
* Can be overridden per-column via the column's options.defaultValue.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```js
|
|
101
|
+
* defaultCellValue: '' // show empty string instead of '--'
|
|
102
|
+
* defaultCellValue: 'N/A' // show 'N/A'
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
defaultCellValue?: string;
|
|
106
|
+
|
|
93
107
|
/**
|
|
94
108
|
* Foundational to tables is how to store settings within them.
|
|
95
109
|
* The `key` is meant to identify a particular kind of table. For example, if
|
|
@@ -62,6 +62,7 @@ export class ColumnMeta {
|
|
|
62
62
|
return this.#tableMeta.getPosition(this.column);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// Swaps this column with the column in the new position
|
|
65
66
|
set position(value: number) {
|
|
66
67
|
this.#tableMeta.setPosition(this.column, value);
|
|
67
68
|
}
|
|
@@ -113,7 +114,8 @@ export class TableMeta {
|
|
|
113
114
|
*/
|
|
114
115
|
@tracked
|
|
115
116
|
columnOrder = new ColumnOrder({
|
|
116
|
-
columns: () => this.
|
|
117
|
+
columns: () => this.allColumns,
|
|
118
|
+
visibleColumns: () => this.visibleColumns,
|
|
117
119
|
save: this.save,
|
|
118
120
|
existingOrder: this.read(),
|
|
119
121
|
});
|
|
@@ -152,7 +154,8 @@ export class TableMeta {
|
|
|
152
154
|
reset() {
|
|
153
155
|
preferences.forTable(this.table, ColumnReordering).delete('order');
|
|
154
156
|
this.columnOrder = new ColumnOrder({
|
|
155
|
-
columns: () => this.
|
|
157
|
+
columns: () => this.allColumns,
|
|
158
|
+
visibleColumns: () => this.visibleColumns,
|
|
156
159
|
save: this.save,
|
|
157
160
|
});
|
|
158
161
|
}
|
|
@@ -186,15 +189,27 @@ export class TableMeta {
|
|
|
186
189
|
}
|
|
187
190
|
|
|
188
191
|
get columns() {
|
|
189
|
-
return this.columnOrder.orderedColumns
|
|
192
|
+
return this.columnOrder.orderedColumns.filter(
|
|
193
|
+
(column) => this.visibleColumns[column.key],
|
|
194
|
+
);
|
|
190
195
|
}
|
|
191
196
|
|
|
192
197
|
/**
|
|
193
198
|
* @private
|
|
194
199
|
* This isn't our data to expose, but it is useful to alias
|
|
195
200
|
*/
|
|
196
|
-
private get
|
|
197
|
-
return columns
|
|
201
|
+
private get visibleColumns() {
|
|
202
|
+
return columns
|
|
203
|
+
.for(this.table, ColumnReordering)
|
|
204
|
+
.reduce<Record<string, boolean>>((acc, column) => {
|
|
205
|
+
acc[column.key] = true;
|
|
206
|
+
|
|
207
|
+
return acc;
|
|
208
|
+
}, {});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private get allColumns() {
|
|
212
|
+
return this.table.columns.values();
|
|
198
213
|
}
|
|
199
214
|
}
|
|
200
215
|
|
|
@@ -210,14 +225,73 @@ export class ColumnOrder {
|
|
|
210
225
|
|
|
211
226
|
constructor(
|
|
212
227
|
private args: {
|
|
228
|
+
/**
|
|
229
|
+
* All columns to track in the ordering.
|
|
230
|
+
*
|
|
231
|
+
* Backwards compatible usage (without ColumnVisibility):
|
|
232
|
+
* - Pass only the columns you want to display
|
|
233
|
+
* - All columns are treated as visible
|
|
234
|
+
*
|
|
235
|
+
* New usage (with ColumnVisibility):
|
|
236
|
+
* - Pass ALL columns (including hidden ones)
|
|
237
|
+
* - Provide `visibleColumns` to indicate which are visible
|
|
238
|
+
* - Hidden columns maintain their position when toggled
|
|
239
|
+
*/
|
|
213
240
|
columns: () => Column[];
|
|
241
|
+
/**
|
|
242
|
+
* Optional: Record of which columns are currently visible.
|
|
243
|
+
* When provided, moveLeft/moveRight will skip over hidden columns.
|
|
244
|
+
* When omitted, all columns from `columns` are treated as visible (backwards compatible).
|
|
245
|
+
*
|
|
246
|
+
* Example when using ColumnVisibility:
|
|
247
|
+
* ```ts
|
|
248
|
+
* visibleColumns: () => columns.reduce((acc, col) => {
|
|
249
|
+
* acc[col.key] = meta(col).ColumnVisibility?.isVisible !== false;
|
|
250
|
+
* return acc;
|
|
251
|
+
* }, {})
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
visibleColumns?: () => Record<string, boolean>;
|
|
255
|
+
/**
|
|
256
|
+
* Optional: Callback to persist the column order (e.g., to localStorage).
|
|
257
|
+
*/
|
|
214
258
|
save?: (order: Map<string, number>) => void;
|
|
259
|
+
/**
|
|
260
|
+
* Optional: Previously saved column order to restore.
|
|
261
|
+
*/
|
|
215
262
|
existingOrder?: Map<string, number>;
|
|
216
263
|
},
|
|
217
264
|
) {
|
|
265
|
+
let allColumns = this.args.columns();
|
|
266
|
+
|
|
218
267
|
if (args.existingOrder) {
|
|
219
|
-
|
|
268
|
+
let newOrder = new Map(args.existingOrder.entries());
|
|
269
|
+
|
|
270
|
+
addMissingColumnsToMap(allColumns, newOrder);
|
|
271
|
+
removeExtraColumnsFromMap(allColumns, newOrder);
|
|
272
|
+
this.map = new TrackedMap(newOrder);
|
|
273
|
+
} else {
|
|
274
|
+
this.map = new TrackedMap(allColumns.map((column, i) => [column.key, i]));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @private
|
|
280
|
+
* Helper to get visible columns, defaulting to all columns if not specified
|
|
281
|
+
*/
|
|
282
|
+
private getVisibleColumns(): Record<string, boolean> {
|
|
283
|
+
if (this.args.visibleColumns) {
|
|
284
|
+
return this.args.visibleColumns();
|
|
220
285
|
}
|
|
286
|
+
|
|
287
|
+
// Default: all columns are visible
|
|
288
|
+
return this.args.columns().reduce(
|
|
289
|
+
(acc, col) => {
|
|
290
|
+
acc[col.key] = true;
|
|
291
|
+
return acc;
|
|
292
|
+
},
|
|
293
|
+
{} as Record<string, boolean>,
|
|
294
|
+
);
|
|
221
295
|
}
|
|
222
296
|
|
|
223
297
|
/**
|
|
@@ -230,15 +304,32 @@ export class ColumnOrder {
|
|
|
230
304
|
@action
|
|
231
305
|
moveLeft(key: string) {
|
|
232
306
|
const orderedColumns = this.orderedColumns;
|
|
307
|
+
if (this.map.get(key) === 0) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
233
310
|
|
|
234
311
|
let found = false;
|
|
235
|
-
let nextColumn: { key: string } | undefined;
|
|
236
312
|
|
|
237
313
|
for (const column of orderedColumns.reverse()) {
|
|
238
314
|
if (found) {
|
|
239
|
-
|
|
315
|
+
// Shift moved column left
|
|
316
|
+
let currentPosition = this.map.get(key);
|
|
240
317
|
|
|
241
|
-
|
|
318
|
+
assert('current key must exist in map', currentPosition !== undefined);
|
|
319
|
+
this.map.set(key, currentPosition - 1);
|
|
320
|
+
|
|
321
|
+
// Shift displayed column right
|
|
322
|
+
let displayedColumnPosition = this.map.get(column.key);
|
|
323
|
+
|
|
324
|
+
assert(
|
|
325
|
+
'displaced key must exist in map',
|
|
326
|
+
displayedColumnPosition !== undefined,
|
|
327
|
+
);
|
|
328
|
+
this.map.set(column.key, displayedColumnPosition + 1);
|
|
329
|
+
|
|
330
|
+
if (this.getVisibleColumns()[column.key]) {
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
242
333
|
}
|
|
243
334
|
|
|
244
335
|
if (column.key === key) {
|
|
@@ -246,14 +337,15 @@ export class ColumnOrder {
|
|
|
246
337
|
}
|
|
247
338
|
}
|
|
248
339
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const nextPosition = this.get(nextColumn.key);
|
|
252
|
-
|
|
253
|
-
this.swapWith(key, nextPosition);
|
|
340
|
+
this.args.save?.(this.map);
|
|
254
341
|
}
|
|
255
342
|
|
|
256
343
|
setAll = (map: Map<string, number>) => {
|
|
344
|
+
let allColumns = this.args.columns();
|
|
345
|
+
|
|
346
|
+
addMissingColumnsToMap(allColumns, map);
|
|
347
|
+
removeExtraColumnsFromMap(allColumns, map);
|
|
348
|
+
|
|
257
349
|
this.map.clear();
|
|
258
350
|
|
|
259
351
|
for (const [key, value] of map.entries()) {
|
|
@@ -273,15 +365,28 @@ export class ColumnOrder {
|
|
|
273
365
|
@action
|
|
274
366
|
moveRight(key: string) {
|
|
275
367
|
const orderedColumns = this.orderedColumns;
|
|
276
|
-
|
|
277
368
|
let found = false;
|
|
278
|
-
let nextColumn: { key: string } | undefined;
|
|
279
369
|
|
|
280
370
|
for (const column of orderedColumns) {
|
|
281
371
|
if (found) {
|
|
282
|
-
|
|
372
|
+
// Shift moved column right
|
|
373
|
+
let currentPosition = this.map.get(key);
|
|
283
374
|
|
|
284
|
-
|
|
375
|
+
assert('current key must exist in map', currentPosition !== undefined);
|
|
376
|
+
this.map.set(key, currentPosition + 1);
|
|
377
|
+
|
|
378
|
+
// Shift displaced column left
|
|
379
|
+
let displayedColumnPosition = this.map.get(column.key);
|
|
380
|
+
|
|
381
|
+
assert(
|
|
382
|
+
'displaced key must exist in map',
|
|
383
|
+
displayedColumnPosition !== undefined,
|
|
384
|
+
);
|
|
385
|
+
this.map.set(column.key, displayedColumnPosition - 1);
|
|
386
|
+
|
|
387
|
+
if (this.getVisibleColumns()[column.key]) {
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
285
390
|
}
|
|
286
391
|
|
|
287
392
|
if (column.key === key) {
|
|
@@ -289,11 +394,7 @@ export class ColumnOrder {
|
|
|
289
394
|
}
|
|
290
395
|
}
|
|
291
396
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const nextPosition = this.get(nextColumn.key);
|
|
295
|
-
|
|
296
|
-
this.swapWith(key, nextPosition);
|
|
397
|
+
this.args.save?.(this.map);
|
|
297
398
|
}
|
|
298
399
|
|
|
299
400
|
/**
|
|
@@ -322,11 +423,8 @@ export class ColumnOrder {
|
|
|
322
423
|
[...this.orderedMap.entries()]
|
|
323
424
|
.map((entry) => entry.join(' => '))
|
|
324
425
|
.join(', ') +
|
|
325
|
-
` and the
|
|
326
|
-
this.
|
|
327
|
-
.columns()
|
|
328
|
-
.map((column) => column.key)
|
|
329
|
-
.join(', ') +
|
|
426
|
+
` and the visibleColumns are: ` +
|
|
427
|
+
Object.keys(this.getVisibleColumns()).join(', ') +
|
|
330
428
|
` and current "map" (${this.map.size}) is: ` +
|
|
331
429
|
[...this.map.entries()].map((entry) => entry.join(' => ')).join(', '),
|
|
332
430
|
undefined !== currentPosition,
|
|
@@ -399,21 +497,20 @@ export class ColumnOrder {
|
|
|
399
497
|
|
|
400
498
|
@cached
|
|
401
499
|
get orderedColumns(): Column[] {
|
|
402
|
-
const
|
|
403
|
-
const
|
|
500
|
+
const allColumns = this.args.columns();
|
|
501
|
+
const columnsByKey = allColumns.reduce(
|
|
404
502
|
(keyMap, column) => {
|
|
405
503
|
keyMap[column.key] = column;
|
|
406
|
-
|
|
407
504
|
return keyMap;
|
|
408
505
|
},
|
|
409
506
|
{} as Record<string, Column>,
|
|
410
507
|
);
|
|
411
|
-
const mergedOrder = orderOf(
|
|
508
|
+
const mergedOrder = orderOf(allColumns, this.map);
|
|
412
509
|
|
|
413
|
-
const result: Column[] = Array.from({ length:
|
|
510
|
+
const result: Column[] = Array.from({ length: allColumns.length });
|
|
414
511
|
|
|
415
512
|
for (const [key, position] of mergedOrder.entries()) {
|
|
416
|
-
const column =
|
|
513
|
+
const column = columnsByKey[key];
|
|
417
514
|
|
|
418
515
|
assert(`Could not find column for pair: ${key} @ @{position}`, column);
|
|
419
516
|
result[position] = column;
|
|
@@ -421,13 +518,13 @@ export class ColumnOrder {
|
|
|
421
518
|
|
|
422
519
|
assert(
|
|
423
520
|
`Generated orderedColumns' length (${result.filter(Boolean).length}) ` +
|
|
424
|
-
`does not match the length of
|
|
521
|
+
`does not match the length of all columns (${allColumns.length}). ` +
|
|
425
522
|
`orderedColumns: ${result
|
|
426
523
|
.filter(Boolean)
|
|
427
524
|
.map((c) => c.key)
|
|
428
525
|
.join(', ')} -- ` +
|
|
429
|
-
`
|
|
430
|
-
result.filter(Boolean).length ===
|
|
526
|
+
`all columns: ${allColumns.map((c) => c.key).join(', ')}`,
|
|
527
|
+
result.filter(Boolean).length === allColumns.length,
|
|
431
528
|
);
|
|
432
529
|
|
|
433
530
|
return result.filter(Boolean);
|
|
@@ -438,55 +535,91 @@ export class ColumnOrder {
|
|
|
438
535
|
* @private
|
|
439
536
|
*
|
|
440
537
|
* Utility for helping determine the percieved order of a set of columns
|
|
441
|
-
* given the original (default) ordering, and then user-configurations
|
|
538
|
+
* given the original (default) ordering, and then user-configurations.
|
|
539
|
+
*
|
|
540
|
+
* This function adds missing columns but preserves extra columns in the map
|
|
541
|
+
* (they might be hidden, not deleted).
|
|
442
542
|
*/
|
|
443
543
|
export function orderOf(
|
|
444
544
|
columns: { key: string }[],
|
|
445
545
|
currentOrder: Map<string, number>,
|
|
446
546
|
): Map<string, number> {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
547
|
+
// Create a copy to avoid mutating the input
|
|
548
|
+
let workingOrder = new Map(currentOrder);
|
|
549
|
+
|
|
550
|
+
// Add any missing columns to the end
|
|
551
|
+
addMissingColumnsToMap(columns, workingOrder);
|
|
552
|
+
|
|
553
|
+
// DON'T remove extra columns - they might be hidden columns, not deleted ones
|
|
554
|
+
// The ColumnOrder constructor handles removal of truly deleted columns
|
|
555
|
+
|
|
556
|
+
// Ensure positions are consecutive and zero based
|
|
557
|
+
let inOrder = Array.from(workingOrder.entries()).sort(
|
|
558
|
+
([_keyA, positionA], [_keyB, positionB]) => positionA - positionB,
|
|
452
559
|
);
|
|
453
560
|
|
|
454
|
-
|
|
455
|
-
* O(n * log(n)) ?
|
|
456
|
-
*/
|
|
457
|
-
for (let i = 0; i < Math.max(columns.length, current.size); i++) {
|
|
458
|
-
const orderedKey = current.get(i);
|
|
561
|
+
let orderedColumns = new Map<string, number>();
|
|
459
562
|
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
* If the currentOrder specifies columns not presently available,
|
|
463
|
-
* ignore them
|
|
464
|
-
*/
|
|
465
|
-
if (availableSet.has(orderedKey)) {
|
|
466
|
-
result.set(orderedKey, i);
|
|
467
|
-
continue;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
563
|
+
let position = 0;
|
|
470
564
|
|
|
471
|
-
|
|
565
|
+
for (let [key] of inOrder) {
|
|
566
|
+
orderedColumns.set(key, position++);
|
|
567
|
+
}
|
|
472
568
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
continue;
|
|
476
|
-
}
|
|
569
|
+
return orderedColumns;
|
|
570
|
+
}
|
|
477
571
|
|
|
478
|
-
|
|
572
|
+
/**
|
|
573
|
+
* @private
|
|
574
|
+
*
|
|
575
|
+
* Utility to add any missing columns to the position map. By calling this whenever
|
|
576
|
+
* data is passed in to the system we can simplify the code within the system because
|
|
577
|
+
* we know we are dealing with a full set of positions.
|
|
578
|
+
*
|
|
579
|
+
* @param columns - A list of all columns available to the table
|
|
580
|
+
* @param map - A Map of `key` to position (as a zero based integer)
|
|
581
|
+
*/
|
|
582
|
+
function addMissingColumnsToMap(
|
|
583
|
+
columns: { key: string }[],
|
|
584
|
+
map: Map<string, number>,
|
|
585
|
+
): void {
|
|
586
|
+
if (map.size < columns.length) {
|
|
587
|
+
let maxAssignedColumn = Math.max(...map.values());
|
|
588
|
+
|
|
589
|
+
for (let column of columns) {
|
|
590
|
+
if (map.get(column.key) === undefined) {
|
|
591
|
+
map.set(column.key, ++maxAssignedColumn);
|
|
592
|
+
}
|
|
479
593
|
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
480
596
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
597
|
+
/**
|
|
598
|
+
* @private
|
|
599
|
+
*
|
|
600
|
+
* Utility to remove any extra columns from the position map. By calling this whenever
|
|
601
|
+
* data is passed in to the system we can simplify the code within the system because
|
|
602
|
+
* we know we are dealing with a full set of positions.
|
|
603
|
+
*
|
|
604
|
+
* @param columns - A list of all columns available to the table
|
|
605
|
+
* @param map - A Map of `key` to position (as a zero based integer)
|
|
606
|
+
*/
|
|
607
|
+
function removeExtraColumnsFromMap(
|
|
608
|
+
columns: { key: string }[],
|
|
609
|
+
map: Map<string, number>,
|
|
610
|
+
): void {
|
|
611
|
+
let columnsLookup = columns.reduce(
|
|
612
|
+
function (acc, { key }) {
|
|
613
|
+
acc[key] = true;
|
|
487
614
|
|
|
488
|
-
|
|
489
|
-
|
|
615
|
+
return acc;
|
|
616
|
+
},
|
|
617
|
+
{} as Record<string, boolean>,
|
|
618
|
+
);
|
|
490
619
|
|
|
491
|
-
|
|
620
|
+
for (let key of map.keys()) {
|
|
621
|
+
if (!columnsLookup[key]) {
|
|
622
|
+
map.delete(key);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
492
625
|
}
|
|
@@ -270,7 +270,9 @@ export class ColumnMeta {
|
|
|
270
270
|
* Otherwise the table will infinitely resize itself
|
|
271
271
|
*/
|
|
272
272
|
function distributeDelta(delta: number, visibleColumns: Column[]) {
|
|
273
|
-
|
|
273
|
+
// Use a tolerance threshold to prevent infinite resize loops from subpixel rounding
|
|
274
|
+
// at different zoom levels. Treat deltas smaller than 0.5px as zero.
|
|
275
|
+
if (Math.abs(delta) < 0.5) return;
|
|
274
276
|
|
|
275
277
|
const metas = visibleColumns.map((column) =>
|
|
276
278
|
meta.forColumn(column, ColumnResizing),
|
|
@@ -374,6 +376,11 @@ export class TableMeta {
|
|
|
374
376
|
entry.target instanceof HTMLElement,
|
|
375
377
|
);
|
|
376
378
|
|
|
379
|
+
// For fixed layout, columns have explicit widths and should not be auto-redistributed
|
|
380
|
+
if (this.options?.tableLayout === 'fixed') {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
377
384
|
this.scrollContainerWidth = getAccurateClientWidth(entry.target);
|
|
378
385
|
this.scrollContainerHeight = getAccurateClientHeight(entry.target);
|
|
379
386
|
|