#50
fix(@wterm/dom): support IME composition (Japanese/Chinese/Korean input)
Summary
Adds IME (Input Method Editor) composition support to @wterm/dom, fixing three independent issues that broke Japanese / Chinese / Korean text entry:
- Garbled first keystroke — the IME's initial
keydown(which fires withkeyCode === 229beforecompositionstart) was forwarded to the PTY as a raw character, so commits like `こんにちは` produced `kこんにちは`. - 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.
- 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.
@sakaritoru is attempting to deploy a commit to the Vercel Labs Team on Vercel.
A member of the Team first needs to authorize it.