({
aria-hidden="true"
className="border-b border-gray-200"
role="cell"
+ style={{ gridColumn: '-3 / -2' }}
/>
)}
Date: Mon, 5 Oct 2026 19:48:56 -0500
Subject: [PATCH 20/20] fix(forms): cleanup
---
.../lib/components/FormCells/FormTable.tsx | 36 ++++++++++++++-----
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx b/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx
index 116e78e2980..3b00190ad93 100644
--- a/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx
+++ b/specifyweb/frontend/js_src/lib/components/FormCells/FormTable.tsx
@@ -146,7 +146,7 @@ function fitSubviewColumnWidths(
);
const totalWidth = preferredWidths.reduce((total, width) => total + width, 0);
if (totalWidth <= availableWidth) return preferredWidths;
- if (availableWidth <= 0) return minimumWidths;
+ if (minimumTotal === 0) return minimumWidths;
if (availableWidth <= minimumTotal)
return minimumWidths.map(
(width) => (width * availableWidth) / minimumTotal
@@ -443,10 +443,14 @@ export function FormTable({
});
return (): void => cancelAnimationFrame(frame);
}, [collapsedViewDefinition, isCollapsed, unsortedResources]);
+ const resizeCleanupRef = React.useRef<(() => void) | undefined>(undefined);
+ React.useEffect(() => (): void => resizeCleanupRef.current?.(), []);
const resizeColumn = React.useCallback(
(columnIndex: number, event: React.PointerEvent): void => {
event.preventDefault();
event.stopPropagation();
+ resizeCleanupRef.current?.();
+ resizeCleanupRef.current = undefined;
const tableElement = scrollerRef.current;
if (tableElement === null) return;
const header = tableElement.querySelector(
@@ -480,15 +484,21 @@ export function FormTable({
};
const handleUp = (upEvent: PointerEvent): void => {
if (upEvent.pointerId !== pointerId) return;
- if (frame !== undefined) cancelAnimationFrame(frame);
+ cleanup();
updateWidth(latestX);
+ };
+ const cleanup = (): void => {
+ if (frame !== undefined) cancelAnimationFrame(frame);
globalThis.removeEventListener('pointermove', handleMove);
globalThis.removeEventListener('pointerup', handleUp);
globalThis.removeEventListener('pointercancel', handleUp);
+ if (resizeCleanupRef.current === cleanup)
+ resizeCleanupRef.current = undefined;
};
globalThis.addEventListener('pointermove', handleMove);
globalThis.addEventListener('pointerup', handleUp);
globalThis.addEventListener('pointercancel', handleUp);
+ resizeCleanupRef.current = cleanup;
},
[columnWidths]
);
@@ -525,12 +535,17 @@ export function FormTable({
(total, width) => total + width,
0
);
- const customFixedWidth = flexibleSubGridColumnWidth
- ? 0
- : tracks.reduce(
- (total, { width }) => total + (typeof width === 'number' ? width : 0),
- 0
- );
+ const customFixedWidth = tracks.reduce(
+ (total, { cellIndex, width }) =>
+ total +
+ (typeof width !== 'number'
+ ? 0
+ : flexibleSubGridColumnWidth
+ ? (contentColumnWidths[cellIndex] ?? minSubviewColumnWidth) /
+ (cells[cellIndex]?.colSpan ?? 1)
+ : width),
+ 0
+ );
const minimumWidths = autoColumns.map(({ cellIndex }) => {
const definition = cells[cellIndex];
const fieldName =
@@ -547,7 +562,10 @@ export function FormTable({
});
const widths = fitSubviewColumnWidths(
autoColumns.map(({ width }) => width),
- tableWidth - tableChromeWidth - fixedWidth - customFixedWidth,
+ Math.max(
+ 0,
+ tableWidth - tableChromeWidth - fixedWidth - customFixedWidth
+ ),
minimumWidths
);
const cellColumns = cells.reduce((total, cell) => total + cell.colSpan, 0);