Changeset 0.37.9 (#221)
This commit is contained in:
194
src/js/sw/components/notes-pane/index.js
Normal file
194
src/js/sw/components/notes-pane/index.js
Normal file
@@ -0,0 +1,194 @@
|
||||
// ==========================================
|
||||
// NotesPane Kit — Default Assembly
|
||||
// ==========================================
|
||||
// Wires useNotes + all sub-components into the standard
|
||||
// notes experience. Surfaces that need a different
|
||||
// layout import individual pieces instead.
|
||||
//
|
||||
// Usage:
|
||||
// import { NotesPane } from './components/notes-pane/index.js';
|
||||
// html`<${NotesPane} handleRef=${ref} standalone=${true} />`
|
||||
//
|
||||
// Re-exports all pieces for kit consumers:
|
||||
// import { useNotes, NoteList, NoteEditor, ... } from './components/notes-pane/index.js';
|
||||
|
||||
import { useNotes } from './use-notes.js';
|
||||
import { NoteList } from './note-list.js';
|
||||
import { NoteListItem } from './note-list-item.js';
|
||||
import { NoteEditor } from './note-editor.js';
|
||||
import { NoteReader } from './note-reader.js';
|
||||
import { QuickSwitcher, saveRecentNote } from './quick-switcher.js';
|
||||
import { SaveToNoteDialog } from './save-to-note.js';
|
||||
import { renderNoteMarkdown, attachWikilinkHandlers, resolveTransclusions, extractHeadings } from './markdown.js';
|
||||
|
||||
const { useState, useRef, useEffect, useCallback } = window.hooks;
|
||||
const html = window.html;
|
||||
|
||||
/**
|
||||
* Default NotesPane assembly.
|
||||
*
|
||||
* @param {{
|
||||
* initialFolder?: string,
|
||||
* initialNoteId?: string,
|
||||
* standalone?: boolean,
|
||||
* onNoteChange?: (note: object|null) => void,
|
||||
* handleRef?: { current: any },
|
||||
* className?: string,
|
||||
* }} props
|
||||
*/
|
||||
export function NotesPane(props) {
|
||||
const {
|
||||
initialFolder,
|
||||
initialNoteId,
|
||||
standalone = true,
|
||||
onNoteChange,
|
||||
handleRef,
|
||||
className,
|
||||
} = props;
|
||||
|
||||
const notes = useNotes({
|
||||
initialFolder,
|
||||
initialNoteId,
|
||||
onNoteChange,
|
||||
standalone,
|
||||
enableGraph: true,
|
||||
enableQuickSwitcher: true,
|
||||
});
|
||||
|
||||
// ── Lazy-load graph component ───────────
|
||||
const [GraphComp, setGraphComp] = useState(null);
|
||||
useEffect(() => {
|
||||
if (notes.view === 'graph' && !GraphComp) {
|
||||
import('./note-graph.js').then(m => setGraphComp(() => m.NoteGraph));
|
||||
}
|
||||
}, [notes.view, GraphComp]);
|
||||
|
||||
const graphHandleRef = useRef(null);
|
||||
|
||||
// ── Graph data loading ──────────────────
|
||||
useEffect(() => {
|
||||
if (notes.view === 'graph' && !notes.graphData) {
|
||||
notes.loadGraph();
|
||||
}
|
||||
}, [notes.view]);
|
||||
|
||||
// ── Expose imperative handle ────────────
|
||||
useEffect(() => {
|
||||
if (handleRef) {
|
||||
handleRef.current = {
|
||||
getView() { return notes.view; },
|
||||
setView(v) { notes.setView(v); },
|
||||
openNote(id) { saveRecentNote({ id, title: '' }); notes.openNote(id); },
|
||||
newNote() { notes.newNote(); },
|
||||
openDailyNote() { notes.openDailyNote(); },
|
||||
refreshList() { notes.refreshList(); },
|
||||
getEditingId() { return notes.editingId; },
|
||||
openQuickSwitcher() { notes.setQuickSwitcherOpen(true); },
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// ── Quick switcher create-new handler ───
|
||||
const onQuickSwitcherCreate = useCallback((title) => {
|
||||
notes.newNote();
|
||||
// The editor will open blank — we can't pre-fill via state here
|
||||
// but the title will be empty for the user to type
|
||||
}, [notes.newNote]);
|
||||
|
||||
// ── View routing ────────────────────────
|
||||
const renderView = () => {
|
||||
switch (notes.view) {
|
||||
case 'list':
|
||||
return html`
|
||||
<${NoteList}
|
||||
notes=${notes.notes} loading=${notes.loading}
|
||||
hasMore=${notes.hasMore} loadMore=${notes.loadMore}
|
||||
folders=${notes.folders} folder=${notes.folder} setFolder=${notes.setFolder}
|
||||
sort=${notes.sort} setSort=${notes.setSort}
|
||||
searchQuery=${notes.searchQuery} setSearchQuery=${notes.setSearchQuery}
|
||||
tagFilter=${notes.tagFilter} setTagFilter=${notes.setTagFilter}
|
||||
selectMode=${notes.selectMode} selectedIds=${notes.selectedIds}
|
||||
enterSelectMode=${notes.enterSelectMode} exitSelectMode=${notes.exitSelectMode}
|
||||
toggleSelect=${notes.toggleSelect} toggleSelectAll=${notes.toggleSelectAll}
|
||||
bulkDelete=${notes.bulkDelete}
|
||||
onNoteClick=${(id) => { saveRecentNote({ id, title: '' }); notes.openNote(id); }}
|
||||
onNewNote=${notes.newNote}
|
||||
onDailyNote=${notes.openDailyNote}
|
||||
onGraphClick=${() => notes.setView('graph')}
|
||||
pinnedIds=${notes.pinnedIds} togglePin=${notes.togglePin} />`;
|
||||
|
||||
case 'editor':
|
||||
return html`
|
||||
<${NoteEditor}
|
||||
currentNote=${notes.currentNote}
|
||||
editingId=${notes.editingId}
|
||||
folders=${notes.folders}
|
||||
onSave=${notes.saveNote}
|
||||
onCancel=${() => {
|
||||
if (notes.currentNote) {
|
||||
notes.setEditorMode('read');
|
||||
notes.setView('reader');
|
||||
} else {
|
||||
notes.setView('list');
|
||||
notes.refreshList();
|
||||
}
|
||||
}}
|
||||
onDelete=${notes.deleteNote} />`;
|
||||
|
||||
case 'reader':
|
||||
return html`
|
||||
<${NoteReader}
|
||||
note=${notes.currentNote}
|
||||
backlinks=${notes.backlinks}
|
||||
onEdit=${() => {
|
||||
notes.setEditorMode('edit');
|
||||
notes.setView('editor');
|
||||
}}
|
||||
onDelete=${notes.deleteNote}
|
||||
onCopy=${notes.copyNote}
|
||||
onNavigateLink=${notes.navigateToLink}
|
||||
onBack=${() => { notes.setView('list'); notes.refreshList(); }}
|
||||
isDailyNote=${notes.isDailyNote}
|
||||
onDailyPrev=${() => notes.navigateDaily(-1)}
|
||||
onDailyNext=${() => notes.navigateDaily(1)} />`;
|
||||
|
||||
case 'graph':
|
||||
if (!GraphComp) {
|
||||
return html`<div class="sw-notes-pane__loading">Loading graph\u2026</div>`;
|
||||
}
|
||||
return html`
|
||||
<${GraphComp}
|
||||
data=${notes.graphData}
|
||||
onNodeClick=${(id) => { notes.openNote(id); }}
|
||||
onGhostClick=${(title) => { notes.navigateToLink(title); }}
|
||||
onBack=${() => notes.setView('list')}
|
||||
handleRef=${graphHandleRef} />`;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return html`
|
||||
<div class=${'sw-notes-pane' + (className ? ' ' + className : '')}>
|
||||
${renderView()}
|
||||
|
||||
<${QuickSwitcher}
|
||||
open=${notes.quickSwitcherOpen}
|
||||
onClose=${() => notes.setQuickSwitcherOpen(false)}
|
||||
onSelect=${(id) => notes.openNote(id)}
|
||||
onCreateNew=${onQuickSwitcherCreate} />
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// ── Kit re-exports ─────────────────────────
|
||||
export { useNotes } from './use-notes.js';
|
||||
export { NoteList } from './note-list.js';
|
||||
export { NoteListItem } from './note-list-item.js';
|
||||
export { NoteEditor } from './note-editor.js';
|
||||
export { NoteReader } from './note-reader.js';
|
||||
export { NoteGraph } from './note-graph.js';
|
||||
export { QuickSwitcher, saveRecentNote } from './quick-switcher.js';
|
||||
export { SaveToNoteDialog } from './save-to-note.js';
|
||||
export { renderNoteMarkdown, attachWikilinkHandlers, resolveTransclusions, extractHeadings } from './markdown.js';
|
||||
Reference in New Issue
Block a user