MCPcopy Create free account
hub / github.com/ZenNotes/zennotes / handler

Function handler

packages/app-core/src/components/VimNav.tsx:297–1014  ·  view source on GitHub ↗
(e: KeyboardEvent)

Source from the content-addressed store, hash-verified

295 useEffect(() => {
296 if (!vimMode) return
297 const handler = (e: KeyboardEvent): void => {
298 const state = useStore.getState()
299 const overrides = state.keymapOverrides
300 const leaderToken = getSequenceTokens(overrides, 'vim.leaderPrefix')[0] ?? 'Space'
301 const panePrefixToken = getSequenceTokens(overrides, 'vim.panePrefix')[0] ?? 'Ctrl+W'
302
303 // Skip when modals / overlays are open
304 if (
305 state.searchOpen ||
306 state.vaultTextSearchOpen ||
307 state.settingsOpen ||
308 state.commandPaletteOpen ||
309 state.bufferPaletteOpen
310 ) return
311 if (
312 document.querySelector('[data-ctx-menu]') ||
313 document.querySelector('[data-prompt-modal]') ||
314 document.querySelector('[data-confirm-modal]')
315 ) return
316
317 // Hint mode — handled entirely by HintOverlay's own listener
318 if (hintRef.current) return
319
320 // `e.target` is only an HTMLElement for real DOM-dispatched events.
321 // Synthetic events fired at `window`/`document` (e.g. programmatic
322 // shortcuts) have a non-Element target, so narrow with `instanceof`
323 // before touching Element-only methods like `.closest()`.
324 const target = e.target instanceof HTMLElement ? e.target : null
325 const tag = target?.tagName
326 // Never steal keys from normal text-entry fields such as the
327 // inline note title, prompt inputs, or textarea-based controls.
328 if (tag === 'INPUT' || tag === 'TEXTAREA') return
329 // The selection format toolbar handles its own keyboard navigation
330 // (arrows / Enter / Esc) once focused — yield to it entirely.
331 if (target?.closest('[data-selection-toolbar]')) return
332 // The home view owns its own roving-focus navigation (↑/↓/j/k/Enter), but
333 // it does not handle the leader key — so the leader (and any pending leader
334 // sequence) must fall through to VimNav, or Space-as-leader is swallowed
335 // while the home view is focused (no note open). (#273)
336 if (
337 shouldYieldToHomeNav(
338 target,
339 sequenceTokenFromEvent(e) === leaderToken,
340 !!leaderPending.current
341 )
342 ) {
343 return
344 }
345 // The database/table view runs its own vim-style motion grid; yield to it
346 // so sidebar/note-list navigation doesn't steal j/k/h/l etc. — EXCEPT the
347 // pane prefix (Ctrl+W) and its pending direction key, so the grid can hand
348 // off to pane/tab navigation (Ctrl+W k → tabs) like every other surface.
349 if (
350 target?.closest('[data-zen-db-grid]') &&
351 !ctrlWPending.current &&
352 sequenceTokenFromEvent(e) !== panePrefixToken
353 ) {
354 return

Callers

nothing calls this directly

Calls 15

getSequenceTokensFunction · 0.90
shouldYieldToHomeNavFunction · 0.90
sequenceTokenFromEventFunction · 0.90
isEditorFocusedFunction · 0.90
matchesShortcutBindingFunction · 0.90
toggleWrapFunction · 0.90
wrapLinkFunction · 0.90
matchesSequenceTokenFunction · 0.90
isEditorInsertModeFunction · 0.90
advanceSequenceFunction · 0.90
getKeymapBindingFunction · 0.90
navigateActiveBufferFunction · 0.90

Tested by

no test coverage detected