feat: auto-focus editor with H1 title selected on new note creation

When a new note is created (Cmd+N or via command palette), the editor
immediately focuses and selects all text in the H1 title block, so the
user can start typing the note name right away without clicking.

- signalFocusEditor now accepts { selectTitle?: boolean } and passes it
  in the laputa:focus-editor event detail
- handleCreateNoteImmediate dispatches with selectTitle: true
- useEditorFocus reads selectTitle from event and calls selectFirstHeading
- selectFirstHeading walks the ProseMirror document to find the first
  heading node and uses TipTap's chain().setTextSelection() to select it
- Opening existing notes is unaffected (selectTitle defaults to false)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Test
2026-03-02 18:31:53 +01:00
parent 3c27403f86
commit f04dfdbd37
3 changed files with 126 additions and 11 deletions

View File

@@ -241,8 +241,10 @@ function navigateWikilink(entries: VaultEntry[], target: string, selectNote: (e:
}
/** Dispatch focus-editor event with perf timing marker. */
function signalFocusEditor(): void {
window.dispatchEvent(new CustomEvent('laputa:focus-editor', { detail: { t0: performance.now() } }))
function signalFocusEditor(opts?: { selectTitle?: boolean }): void {
window.dispatchEvent(new CustomEvent('laputa:focus-editor', {
detail: { t0: performance.now(), selectTitle: opts?.selectTitle ?? false },
}))
}
interface PersistCallbacks {
@@ -372,7 +374,7 @@ export function useNoteActions(config: NoteActionsConfig) {
addEntryWithMock(resolved.entry, resolved.content, addEntry)
config.trackUnsaved?.(resolved.entry.path)
config.markContentPending?.(resolved.entry.path, resolved.content)
signalFocusEditor()
signalFocusEditor({ selectTitle: true })
setTimeout(() => pendingNamesRef.current.delete(title), 500)
}, [entries, openTabWithContent, addEntry, config.trackUnsaved, config.markContentPending]) // eslint-disable-line react-hooks/exhaustive-deps -- config callbacks are stable