github vadimdemedes/ink v7.0.0

5 hours ago

Breaking

  • Require Node.js 22 19b5316
  • Require React 19.2+ cfaebbb
    • Ink now uses useEffectEvent internally to avoid re-subscribing input handlers on every render
  • Pressing Backspace now correctly sets key.backspace instead of key.delete (#634) 321a2e8
    • Most terminals send the same byte for Backspace as the Delete key, which caused Ink to misreport it. If you were checking key.delete to handle backspace, switch to key.backspace
  • key.meta is no longer set to true when Escape is pressed e195912
    • Previously a backward-compat shim made plain Escape set both key.escape and key.meta. Now only key.escape is true. key.meta is reserved for actual Alt/Meta modifier combinations

New

  • Add usePaste hook for handling clipboard paste events fbbeb23
    • Automatically enables bracketed paste mode so pasted text arrives as a single string, never misinterpreted as individual key presses by useInput
  • Add useWindowSize hook 7047795
    • Returns {columns, rows} and re-renders automatically on terminal resize
  • Add useBoxMetrics hook for measuring box dimensions at runtime (#433) 88731d1
  • Add useAnimation hook for built-in animation support (#142) ada019c
    • Provides a frame counter that increments at a configurable interval, with pause/resume support and automatic cleanup on unmount
  • Add alternateScreen option to render() (#263) 5a60eb9
    • Renders into the terminal's alternate screen buffer (like vim or less), restoring the previous terminal content on exit
  • Add interactive option to render() (#888) 02490f6
    • Override automatic interactive-mode detection for environments where the built-in heuristic doesn't fit
  • Add activeId to useFocusManager() (#661) eb2f470
    • Returns the ID of the currently focused component, or undefined if nothing is focused
  • Add borderBackgroundColor (and per-side variants) to <Box> (#906) d3c6d14
    • Set a background color on borders independently from the box content background
  • Add wrap="hard" to <Text> (#925) 2b1e3a6
    • Fills each line to the full column width, breaking words mid-word as needed
  • Add maxWidth and maxHeight props to <Box> (#713) 9291794
  • Add aspectRatio, alignContent, position="static", and top/right/bottom/left layout props to <Box> c2f4b86
  • Kitty keyboard protocol: query all terminals in auto mode instead of a hardcoded allowlist (#895) 3e672b5

Fixes

  • Fix incremental rendering for trailing newline (#910) c32da0b
  • Fix useInput crash on unmapped key codes (#902) 969a4f1
  • Fix CJK text truncation exceeding <Box> width b5f3e3a
  • Fix splitting wide characters (emoji, CJK) when overlapping writes occur (#930) 06d53f4
  • Fix dangling staticNode reference (#905) 0dc4dfa

Migration guide

key.backspace vs key.delete

// Before — physical backspace was reported as key.delete
useInput((input, key) => {
  if (key.delete) { /* was catching physical backspace key */ }
});

// After
useInput((input, key) => {
  if (key.backspace) { /* physical backspace key (0x7F) */ }
  if (key.delete)    { /* actual Delete key (e.g. Fn+Backspace) */ }
});

key.meta no longer set on plain Escape

// Before — key.meta was true for both Escape AND Alt+key
useInput((input, key) => {
  if (key.meta) { /* fired on plain Escape too */ }
});

// After — check key.escape explicitly for the Escape key
useInput((input, key) => {
  if (key.escape) { /* plain Escape */ }
  if (key.meta)   { /* Alt/Meta combos only */ }
});

v6.8.0...v7.0.0

Don't miss a new ink release

NewReleases is sending notifications on new releases.