feat: add keyboard navigation for document views, externalize document preview handling, and include physics model documentation.

This commit is contained in:
2025-11-27 01:06:31 +01:00
parent 3588fde3a2
commit 9ba581f64e
6 changed files with 306 additions and 392 deletions
+49 -3
View File
@@ -1,5 +1,7 @@
import React from 'react';
import React, { useEffect, useCallback } from 'react';
import { useDocumentViewLogic, DocumentViewLogic } from './hooks/useDocumentViewLogic';
import { useDocumentsNavigation } from './hooks/useDocumentsNavigation';
import { useWorkspaceSelectionContext } from '../app/WorkspaceSelectionContext';
import DocumentsListRow from './components/DocumentsListRow';
import DocumentsGridCard from './components/DocumentsGridCard';
import DocumentsListContainer from './components/DocumentsListContainer';
@@ -19,15 +21,59 @@ const AbstractDocumentsView = <CProps extends { clearSelection: () => void; chil
containerProps,
...props
}: AbstractDocumentsViewProps<CProps>) => {
const { entries, onDocumentRename, onFolderRename } = props;
const { entries, onDocumentRename, onFolderRename, onFolderSelect, onPreview, scrollRef, viewId } = props;
const viewLogic = useDocumentViewLogic({
onDocumentRename,
onFolderRename,
});
const { handleKeyDown, handleFocus } = useDocumentsNavigation({
entries,
onFolderSelect,
onPreview,
});
const { clearSelection } = viewLogic;
useEffect(() => {
if (scrollRef?.current) {
scrollRef.current.scrollTop = 0;
}
}, [scrollRef, viewId]);
const { focusedEntryKey } = useWorkspaceSelectionContext();
const ensureFocusedEntryVisible = useCallback(() => {
if (!focusedEntryKey) return;
const container = scrollRef?.current;
if (!container) return;
let selector = null;
if (focusedEntryKey.startsWith('document:')) {
selector = `#document-${focusedEntryKey.slice('document:'.length)}`;
} else if (focusedEntryKey.startsWith('folder:')) {
selector = `#folder-${focusedEntryKey.slice('folder:'.length)}`;
}
if (!selector) {
return;
}
const entry = container.querySelector(selector) as HTMLElement;
if (!entry || !container.contains(entry)) {
return;
}
entry.scrollIntoView({ block: 'nearest' });
}, [focusedEntryKey, scrollRef]);
useEffect(() => {
ensureFocusedEntryVisible();
}, [ensureFocusedEntryVisible]);
return (
<ContainerComponent clearSelection={clearSelection} {...(containerProps as any)}>
<ContainerComponent
clearSelection={clearSelection}
onKeyDown={handleKeyDown}
onFocus={handleFocus}
tabIndex={0}
{...(containerProps as any)}
>
{entries.map((entry) => (
<ItemComponent
key={entry.key}