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 keymapuseBindings(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
| 属性 | 类型 | 必需 | 描述 |
|---|---|---|---|
keymap | Keymap<Renderable, KeyEvent> | 是 | OpenTUI keymap 实例 |
children | ReactNode | 否 | 后代 React 树 |
钩子
| 钩子 | 描述 |
|---|---|
useKeymap() | 返回当前 keymap,如果缺少 provider 则抛出异常 |
useBindings(createLayer, deps?) | 使用 deps 对层工厂进行记忆化,注册层,并在卸载时释放 |
useActiveKeys(options?) | 在批量 keymap 状态变更时重新渲染,返回 getActiveKeys(...) |
usePendingSequence() | 在批量 keymap 状态变更时重新渲染,返回 getPendingSequence() |
reactiveMatcherFromStore(...) | 从任何 subscribe/getSnapshot store 构建 ReactiveMatcher |
useBindings
useBindings() 注册一个类似层的对象。返回的层可以包含 priority、enabled、bindings、commands 和任何自定义插件字段。
React 使用 useMemo(createLayer, deps) 对 createLayer 进行记忆化。如果您省略 deps,钩子在挂载后会将层工厂视为静态的,因为默认值是 []。如果层形状依赖于 props 或 React 状态,请将这些值包含在 deps 中。
React 特定的层形状:
| 形状 | 描述 |
|---|---|
| 全局层 | 省略 targetRef |
局部 focus-within 层 | 设置 targetRef 并省略 targetMode |
| 局部精确焦点层 | 设置 targetRef 和 targetMode: "focus" |
- 当
targetRef存在且targetMode被省略时,使用focus-within。 - 如果
targetRef.current为null,注册会等待 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