Andrey Epifancev e0e460b6c2 fix(table): ресайз завершается при потерянном mouseup; тест-характеристики table-core; комментарии
- ColumnResizer: handleMouseMove завершает перетаскивание, если левая кнопка не зажата
- cellMemoReset.test: убран дубль теста columnSizing, добавлены характеристики закрепления второй колонки и скрытия закреплённой
- комментарии к columnFilters (триггер React.memo(TableHead)) и ссылки на архивную спеку

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 21:49:03 +04:00

27 lines
2.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Ключ явного сброса мемоизации ячеек MRT (memoMode: 'cells') в таблице листа.
// Обоснование и контракт: openspec/changes/aurora-1839-cell-memo/ (design.md D1, D2; specs/sheet-table; после архивации — openspec/specs/sheet-table/spec.md).
// Новое состояние, которое меняет определения колонок или стили закрепления, добавляется сюда и в cellMemoReset.test.js.
const getPinnedSide = (ids, columnVisibility, columnSizing) =>
(ids ?? []).filter((id) => columnVisibility?.[id] !== false).map((id) => [id, columnSizing?.[id] ?? null]);
// left закреплённой колонки — сумма ширин закреплённых левее, поэтому в ключ входят только
// видимые закреплённые колонки и их ширины. Незакреплённые колонки меняют ширину через CSS-переменные MRT.
export const getPinnedLayoutKey = ({ columnPinning, columnVisibility, columnSizing }) =>
JSON.stringify([
getPinnedSide(columnPinning?.left, columnVisibility, columnSizing),
getPinnedSide(columnPinning?.right, columnVisibility, columnSizing),
]);
// Порядок фильтров в массиве не важен: пары сортируются по id. Значение диапазона — массив [min, max].
export const getFilterResetKey = ({ globalFilter, columnFilters }) => {
const filters = (columnFilters ?? []).map(({ id, value }) => [String(id), value ?? null]).sort(([a], [b]) => a.localeCompare(b));
return JSON.stringify([globalFilter ?? '', filters]);
};
export const getCellMemoResetKey = (state) => JSON.stringify([getPinnedLayoutKey(state), getFilterResetKey(state)]);
// Пока ширину тянут, ключ раскладки строится по ширинам на момент нажатия мыши:
// сброс по ширине закреплённой колонки происходит один раз, по отпусканию (design.md, решение 3).
export const pickSettledSizing = ({ previous, current, isResizing }) => (isResizing ? previous : current);