From 61cafb44a61adcd719b38b2aaaa6bb7e06ac298c Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Wed, 28 Oct 2026 21:17:15 +0400 Subject: [PATCH] =?UTF-8?q?perf(table):=20=D0=BF=D0=BE=D0=BC=D0=BE=D1=89?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=B8=20columnSizingInfo=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B5=D1=82=D0=B0=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=88=D0=B8=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Haiku 5.5 --- .../RealtimeTable/utils/columnResizeInfo.js | 17 ++++++++ .../utils/columnResizeInfo.test.js | 40 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 web/src/components/RealtimeTable/utils/columnResizeInfo.js create mode 100644 web/src/components/RealtimeTable/utils/columnResizeInfo.test.js diff --git a/web/src/components/RealtimeTable/utils/columnResizeInfo.js b/web/src/components/RealtimeTable/utils/columnResizeInfo.js new file mode 100644 index 0000000..d948b3b --- /dev/null +++ b/web/src/components/RealtimeTable/utils/columnResizeInfo.js @@ -0,0 +1,17 @@ +// columnSizingInfo для MRT/TanStack при собственном перетаскивании ширины (TableHead/ColumnResizer). +// Пока isResizingColumn !== false, MRT 3.2.1 не пересоздаёт колонки и замораживает тело таблицы +// (openspec/changes/aurora-1839-cell-memo/design.md, «Контекст» п. 3–4, D3). + +export const DEFAULT_COLUMN_SIZING_INFO = { + startOffset: null, + startSize: null, + deltaOffset: null, + deltaPercentage: null, + isResizingColumn: false, + columnSizingStart: [], +}; + +export const startColumnResize = (columnId) => (old) => ({ ...old, isResizingColumn: columnId }); + +// Идемпотентно: конец перетаскивания приходит из mouseup, blur окна и размонтирования. +export const endColumnResize = (old) => (old.isResizingColumn === false ? old : { ...old, isResizingColumn: false }); diff --git a/web/src/components/RealtimeTable/utils/columnResizeInfo.test.js b/web/src/components/RealtimeTable/utils/columnResizeInfo.test.js new file mode 100644 index 0000000..3e271cc --- /dev/null +++ b/web/src/components/RealtimeTable/utils/columnResizeInfo.test.js @@ -0,0 +1,40 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { createTable, getCoreRowModel } from '@tanstack/table-core'; +import { DEFAULT_COLUMN_SIZING_INFO, endColumnResize, startColumnResize } from './columnResizeInfo.js'; + +test('значение по умолчанию совпадает с table-core', () => { + const table = createTable({ data: [], columns: [{ accessorKey: 'a' }], state: {}, getCoreRowModel: getCoreRowModel() }); + assert.deepEqual(DEFAULT_COLUMN_SIZING_INFO, table.initialState.columnSizingInfo); +}); + +test('startColumnResize ставит id колонки и не трогает остальные поля', () => { + const next = startColumnResize('data.q1')(DEFAULT_COLUMN_SIZING_INFO); + assert.equal(next.isResizingColumn, 'data.q1'); + assert.deepEqual({ ...next, isResizingColumn: false }, DEFAULT_COLUMN_SIZING_INFO); + assert.equal(DEFAULT_COLUMN_SIZING_INFO.isResizingColumn, false); +}); + +test('endColumnResize снимает флаг, повторный вызов возвращает тот же объект', () => { + const ended = endColumnResize(startColumnResize('a')(DEFAULT_COLUMN_SIZING_INFO)); + assert.equal(ended.isResizingColumn, false); + assert.equal(endColumnResize(ended), ended); + assert.equal(endColumnResize(DEFAULT_COLUMN_SIZING_INFO), DEFAULT_COLUMN_SIZING_INFO); +}); + +test('table.setColumnSizingInfo проводит флаг через управляемое состояние', () => { + let info = DEFAULT_COLUMN_SIZING_INFO; + const table = createTable({ + data: [{ a: 1 }], + columns: [{ accessorKey: 'a' }], + state: { columnSizingInfo: info }, + onColumnSizingInfoChange: (updater) => { + info = typeof updater === 'function' ? updater(info) : updater; + }, + getCoreRowModel: getCoreRowModel(), + }); + table.setColumnSizingInfo(startColumnResize('a')); + assert.equal(info.isResizingColumn, 'a'); + table.setColumnSizingInfo(endColumnResize); + assert.equal(info.isResizingColumn, false); +});