Something went wrong. Try again.
A local-first note taking app
Something went wrong. Try again.
TSX
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485import type { DocumentSlotState } from '../documents/useDocumentSlot';import { resolveDocumentLink } from '../documents/resolveDocumentLink';import type { OpenDocRequest } from '../workspaces/workspace';import { DocumentPane } from './DocumentPane';import type { EditorMode } from './types';
const DEFAULT_EMPTY_HINT = 'Select a file from the sidebar to open it here.';
type DocumentSlotViewProps = { state: DocumentSlotState; className?: string; placeholder?: string; emptyHint?: string; /** Rendering mode for the open editor; defaults to `edit`. */ mode?: EditorMode; /** * Open a document (by provider + entry). When provided, internal-link clicks * in the editor are resolved against the open document and routed here — so a * workspace gets file-to-file navigation just by forwarding its open handler. */ onOpenEntry?: (request: OpenDocRequest) => void;};
function SlotPlaceholder({ message }: { message: string }) { return ( <div className="border-border text-foreground/60 flex h-full min-h-0 w-full items-center justify-center rounded-md border border-dashed p-5 text-center text-sm"> {message} </div> );}
/** * Renders a document slot's empty, loading, error, or open states. * Workspaces compose this inside their layout chrome. */export function DocumentSlotView({ state, className, placeholder = 'Start writing…', emptyHint = DEFAULT_EMPTY_HINT, mode, onOpenEntry,}: DocumentSlotViewProps) { if (state.kind === 'empty') { return <SlotPlaceholder message={emptyHint} />; } if (state.kind === 'loading') { return <SlotPlaceholder message={`Opening ${state.request.title}…`} />; } if (state.kind === 'error') { return ( <SlotPlaceholder message={`Could not open ${state.request.title}: ${state.message}`} /> ); } // Resolve internal-link targets against this document, then route to the // workspace's open handler. Kept here (not in each workspace) so every // workspace gets file-to-file navigation for free. const { request, handle } = state; const onOpenLink = onOpenEntry ? (target: string) => onOpenEntry( resolveDocumentLink( { providerId: request.providerId, path: handle.id }, target, ), ) : undefined; return ( // Key by document id so switching tabs to a different document remounts a // fresh editor instead of reusing one bound to the previous document. The // shared editor view binds its content on mount only, so without this a // tab switch can leave the previous file's content showing. <DocumentPane key={handle.id} handle={handle} placeholder={placeholder} className={className} mode={mode} onOpenLink={onOpenLink} /> );}