React keymap 绑定 (OpenTUI)

本页涵盖 @opentui/keymap/react

这些绑定用于 OpenTUI React 应用。它们使用来自 @opentui/keymap/opentui 的预创建 Keymap<Renderable, KeyEvent>;它们不包装浏览器 React 应用中使用的 DOM/HTML 适配器。

如果您尚未阅读共享模型,请从 Keymap 概览开始。关于 keymap 构建,请参阅 Keymap 宿主

React 提供的功能

  • KeymapProvider — 现有 OpenTUI keymap 的 React 上下文提供者
  • useKeymap() — 从上下文返回当前的 OpenTUI keymap
  • useBindings(createLayer, deps?) — 为组件生命周期注册一个 keymap 层
  • useActiveKeys(options?) — 派生的活跃按键列表
  • usePendingSequence() — 派生的待处理序列
  • reactiveMatcherFromStore(subscribe, getSnapshot, predicate?) — 将外部 store 适配为 ReactiveMatcher

基本用法

/** @jsxImportSource @opentui/react */

import { createCliRenderer } from "@opentui/core"
import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui"
import { KeymapProvider, useBindings } from "@opentui/keymap/react"
import { createRoot } from "@opentui/react"

const renderer = await createCliRenderer()
const keymap = createDefaultOpenTuiKeymap(renderer)

function App() {
  useBindings(
    () => ({
      commands: [
        {
          name: "quit",
          run() {
            renderer.destroy()
          },
        },
      ],
      bindings: [{ key: "q", cmd: "quit" }],
    }),
    [],
  )

  return <text>Press q to quit</text>
}

createRoot(renderer).render(
  <KeymapProvider keymap={keymap}>
    <App />
  </KeymapProvider>,
)

Provider

属性类型必需描述
keymapKeymap<Renderable, KeyEvent>OpenTUI keymap 实例
childrenReactNode后代 React 树

钩子

钩子描述
useKeymap()返回当前 keymap,如果缺少 provider 则抛出异常
useBindings(createLayer, deps?)使用 deps 对层工厂进行记忆化,注册层,并在卸载时释放
useActiveKeys(options?)在批量 keymap 状态变更时重新渲染,返回 getActiveKeys(...)
usePendingSequence()在批量 keymap 状态变更时重新渲染,返回 getPendingSequence()
reactiveMatcherFromStore(...)从任何 subscribe/getSnapshot store 构建 ReactiveMatcher

useBindings

useBindings() 注册一个类似层的对象。返回的层可以包含 priorityenabledbindingscommands 和任何自定义插件字段。

React 使用 useMemo(createLayer, deps)createLayer 进行记忆化。如果您省略 deps,钩子在挂载后会将层工厂视为静态的,因为默认值是 []。如果层形状依赖于 props 或 React 状态,请将这些值包含在 deps 中。

React 特定的层形状:

形状描述
全局层省略 targetRef
局部 focus-within设置 targetRef 并省略 targetMode
局部精确焦点层设置 targetReftargetMode: "focus"
  • targetRef 存在且 targetMode 被省略时,使用 focus-within
  • 如果 targetRef.currentnull,注册会等待 ref 解析。
  • 传递局部 targetMode 而不传 targetRef 会抛出异常。
  • deps 控制层工厂何时被重新求值。
  • 局部层跟随 targetRef.current,因此它们可以等待 ref 挂载,并在该 ref 后来指向不同的可渲染对象时重新定位。

useActiveKeys()usePendingSequence()

const activeKeys = useActiveKeys({ includeMetadata: true })
const pendingSequence = usePendingSequence()

将这些钩子用于命令面板、按键提示 UI、leader 提示和状态栏。

reactiveMatcherFromStore()

当插件字段期望 ReactiveMatcher 时使用此方法,例如附带的 enabled 字段:

const matcher = useMemo(
  () => reactiveMatcherFromStore(store.subscribe, store.getSnapshot, (mode) => mode === "normal"),
  [store],
)

useBindings(
  () => ({
    enabled: matcher,
    bindings: [{ key: "x", cmd: "delete-line" }],
  }),
  [matcher],
)

示例:packages/react/examples/keymap.tsx