#50

fix(@wterm/dom): support IME composition (Japanese/Chinese/Korean input)

Opensakaritoruwants to merge intofrom

Summary

Adds IME (Input Method Editor) composition support to @wterm/dom, fixing three independent issues that broke Japanese / Chinese / Korean text entry:

  1. Garbled first keystroke — the IME's initial keydown (which fires with keyCode === 229 before compositionstart) was forwarded to the PTY as a raw character, so commits like `こんにちは` produced `kこんにちは`.
  2. Off-screen composition preview — uncommitted IME text rendered into the textarea, but the textarea was positioned at `left: -9999px`, so users couldn't see what they were typing.
  3. Misanchored overlay in TUI mode — TUI apps that hide the cursor (`\x1b[?25l`, e.g. Claude Code, vim, less) drop the `.term-cursor` element, so the composition overlay had no anchor and snapped to `(0,0)`.

Changes

Three atomic commits, all scoped to `packages/@wterm/dom/src/input.ts` and its tests:

  • `fix: bail keydown handler during IME composition` — early-return when `composing`, `isComposing`, or `keyCode === 229`
  • `feat: render uncommitted IME text via composition overlay` — adds a `term-composition` span that mirrors the xterm.js compositionView pattern; textarea is repositioned to the cursor (still visually transparent) so the IME's native popup anchors correctly
  • `fix: keep IME overlay anchored when TUI hides the cursor` — falls back to `bridge.getCursor()` + `.term-row[N]` + measured char width when `.term-cursor` is absent; coalesces `MutationObserver` fires through `requestAnimationFrame` to avoid layout thrashing during fast streams

No API surface change. No new dependencies. No other packages touched.

Test plan

  • `pnpm --filter @wterm/dom test` — 79 tests pass (11 new IME tests across keydown gating, overlay lifecycle, and TUI-mode fallback)
  • `pnpm test` (turbo, full monorepo) — 12/12 tasks pass; React/Vue wrappers unaffected
  • `pnpm exec tsc --noEmit` — clean
  • `pnpm exec prettier --check` — clean
  • Manual: typed `こんにちは` in a Next.js + `@wterm/dom` app running Claude Code in PTY; composition preview visible inline at the prompt, commits arrive once on confirm, cursor stays anchored when the TUI hides the cursor

Notes

  • Docs updates skipped: IME support is a behavior fix with no public API / option / theme change. Happy to add a line to a changelog or docs page if maintainers prefer.
  • An unrelated rendering glitch (DEC SCS `\x1b(0` → box-drawing characters) was observed during testing of TUI apps but is not part of this PR — looks like a separate codepath in the parser.

Activity

4
vercel[bot]6mo ago

@sakaritoru is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.