selection

This commit is contained in:
2025-11-01 20:28:00 +01:00
parent 9559a1b5e2
commit f6ceff5444
3 changed files with 493 additions and 297 deletions
+128
View File
@@ -0,0 +1,128 @@
import { useCallback, useEffect, useRef, useState } from 'react';
export const useDetailPanel = ({
documentLookup,
orderedSelectedDocuments,
selectionOrder,
documentsViewMode,
getRowId,
isDocumentRowKey,
}) => {
const [detailPanelOpen, setDetailPanelOpen] = useState(false);
const [detailPanelDocIds, setDetailPanelDocIds] = useState([]);
const [detailPanelDocs, setDetailPanelDocs] = useState([]);
const lastScrolledDetailDocRef = useRef(null);
useEffect(() => {
if (!orderedSelectedDocuments.length) {
setDetailPanelDocIds((prev) => (prev.length ? [] : prev));
return;
}
const nextIds = orderedSelectedDocuments
.map((doc) => doc?.id)
.filter((id) => typeof id === 'string' || typeof id === 'number');
setDetailPanelDocIds((prev) => {
if (prev.length === nextIds.length && prev.every((id, index) => id === nextIds[index])) {
return prev;
}
return nextIds;
});
}, [orderedSelectedDocuments]);
useEffect(() => {
if (!detailPanelDocIds.length) {
setDetailPanelDocs((prev) => (prev.length ? [] : prev));
return;
}
setDetailPanelDocs((prevDocs) => {
const prevMap = new Map((prevDocs || []).map((doc) => [doc.id, doc]));
const next = detailPanelDocIds
.map((id) => documentLookup.get(id) || prevMap.get(id) || null)
.filter(Boolean);
if (next.length === prevDocs.length && next.every((doc, index) => doc === prevDocs[index])) {
return prevDocs;
}
return next;
});
}, [detailPanelDocIds, documentLookup]);
useEffect(() => {
if (!detailPanelOpen) {
lastScrolledDetailDocRef.current = null;
return;
}
if (!orderedSelectedDocuments.length) {
lastScrolledDetailDocRef.current = null;
return;
}
let lastSelectedId = null;
for (let index = selectionOrder.length - 1; index >= 0; index -= 1) {
const key = selectionOrder[index];
if (isDocumentRowKey(key)) {
lastSelectedId = getRowId(key);
if (lastSelectedId) {
break;
}
}
}
if (!lastSelectedId && orderedSelectedDocuments.length) {
const fallbackDoc = orderedSelectedDocuments[orderedSelectedDocuments.length - 1];
lastSelectedId = fallbackDoc?.id || null;
}
if (!lastSelectedId || lastScrolledDetailDocRef.current === lastSelectedId) {
return;
}
if (typeof document === 'undefined') {
return;
}
const targetElement =
document.getElementById(`document-row-${lastSelectedId}`)
|| document.getElementById(`document-card-${lastSelectedId}`);
if (!targetElement) {
return;
}
lastScrolledDetailDocRef.current = lastSelectedId;
requestAnimationFrame(() => {
targetElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
});
}, [
detailPanelOpen,
orderedSelectedDocuments,
selectionOrder,
documentsViewMode,
getRowId,
isDocumentRowKey,
]);
const detailPanelSelectedDocuments = detailPanelDocs;
const openDetailPanel = useCallback(() => {
setDetailPanelOpen(true);
}, []);
const closeDetailPanel = useCallback(() => {
setDetailPanelOpen(false);
}, []);
return {
detailPanelOpen,
detailPanelSelectedDocuments,
openDetailPanel,
closeDetailPanel,
setDetailPanelOpen,
};
};
export default useDetailPanel;