@elench/testkit 0.1.114 → 0.1.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +33 -8
  2. package/lib/cli/args.mjs +3 -3
  3. package/lib/cli/assistant/app.mjs +4 -2
  4. package/lib/cli/assistant/session.mjs +5 -1
  5. package/lib/cli/assistant/state.mjs +1 -2
  6. package/lib/cli/command-flags.mjs +4 -0
  7. package/lib/cli/commands/db/schema/refresh.mjs +21 -0
  8. package/lib/cli/commands/db/schema/verify.mjs +27 -0
  9. package/lib/cli/components/blocks/run-tree.mjs +7 -2
  10. package/lib/cli/components/hooks/use-element-layout.mjs +63 -0
  11. package/lib/cli/components/hooks/use-spinner-frame.mjs +26 -0
  12. package/lib/cli/entrypoint.mjs +1 -0
  13. package/lib/cli/operations/db/schema/refresh/operation.mjs +56 -0
  14. package/lib/cli/operations/db/{snapshot/capture → schema/verify}/operation.mjs +6 -27
  15. package/lib/cli/operations/run/operation.mjs +1 -0
  16. package/lib/cli/renderers/db-schema/text.mjs +7 -0
  17. package/lib/config/database.mjs +64 -0
  18. package/lib/config-api/index.d.ts +16 -1
  19. package/lib/config-api/index.mjs +31 -16
  20. package/lib/database/fingerprint.mjs +2 -0
  21. package/lib/database/index.mjs +142 -104
  22. package/lib/database/schema-source.mjs +295 -0
  23. package/lib/database/template-steps.mjs +158 -38
  24. package/lib/runner/orchestrator.mjs +4 -3
  25. package/lib/runner/template-steps.mjs +12 -1
  26. package/lib/runner/template.mjs +16 -1
  27. package/node_modules/@alcalzone/ansi-tokenize/README.md +0 -5
  28. package/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.d.ts +8 -0
  29. package/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js +10 -8
  30. package/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js.map +1 -1
  31. package/node_modules/@alcalzone/ansi-tokenize/build/tokenize.d.ts +1 -5
  32. package/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js +9 -45
  33. package/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js.map +1 -1
  34. package/node_modules/@alcalzone/ansi-tokenize/package.json +1 -1
  35. package/node_modules/@elench/next-analysis/package.json +1 -1
  36. package/node_modules/@elench/testkit-bridge/package.json +2 -2
  37. package/node_modules/@elench/testkit-protocol/package.json +1 -1
  38. package/node_modules/@elench/ts-analysis/package.json +1 -1
  39. package/node_modules/cli-boxes/index.d.ts +95 -90
  40. package/node_modules/cli-boxes/index.js +5 -2
  41. package/node_modules/cli-boxes/package.json +6 -13
  42. package/node_modules/cli-boxes/readme.md +15 -3
  43. package/node_modules/cli-truncate/index.d.ts +1 -1
  44. package/node_modules/cli-truncate/package.json +4 -4
  45. package/node_modules/cli-truncate/readme.md +1 -0
  46. package/node_modules/es-toolkit/CHANGELOG.md +801 -0
  47. package/node_modules/es-toolkit/src/compat/_internal/Equals.d.ts +1 -0
  48. package/node_modules/es-toolkit/src/compat/_internal/IsWritable.d.ts +3 -0
  49. package/node_modules/es-toolkit/src/compat/_internal/MutableList.d.ts +4 -0
  50. package/node_modules/es-toolkit/src/compat/_internal/RejectReadonly.d.ts +4 -0
  51. package/node_modules/esprima/ChangeLog +235 -0
  52. package/node_modules/ink/build/apply-styles.js +175 -0
  53. package/node_modules/ink/build/build-layout.js +77 -0
  54. package/node_modules/ink/build/calculate-wrapped-text.js +53 -0
  55. package/node_modules/ink/build/components/App.d.ts +1 -4
  56. package/node_modules/ink/build/components/App.js +22 -142
  57. package/node_modules/ink/build/components/App.js.map +1 -1
  58. package/node_modules/ink/build/components/AppContext.d.ts +3 -23
  59. package/node_modules/ink/build/components/AppContext.js +4 -7
  60. package/node_modules/ink/build/components/AppContext.js.map +1 -1
  61. package/node_modules/ink/build/components/Box.d.ts +3 -16
  62. package/node_modules/ink/build/components/Color.js +62 -0
  63. package/node_modules/ink/build/components/Cursor.d.ts +83 -0
  64. package/node_modules/ink/build/components/Cursor.js +53 -0
  65. package/node_modules/ink/build/components/Cursor.js.map +1 -0
  66. package/node_modules/ink/build/components/ErrorBoundary.d.ts +2 -2
  67. package/node_modules/ink/build/components/ErrorOverview.js +6 -6
  68. package/node_modules/ink/build/components/ErrorOverview.js.map +1 -1
  69. package/node_modules/ink/build/components/Static.js.map +1 -1
  70. package/node_modules/ink/build/components/StdinContext.d.ts +1 -7
  71. package/node_modules/ink/build/components/StdinContext.js +0 -1
  72. package/node_modules/ink/build/components/StdinContext.js.map +1 -1
  73. package/node_modules/ink/build/components/Text.d.ts +1 -1
  74. package/node_modules/ink/build/components/Text.js +1 -1
  75. package/node_modules/ink/build/components/Text.js.map +1 -1
  76. package/node_modules/ink/build/components/Transform.d.ts +1 -1
  77. package/node_modules/ink/build/devtools-window-polyfill.js +4 -7
  78. package/node_modules/ink/build/devtools-window-polyfill.js.map +1 -1
  79. package/node_modules/ink/build/devtools.js +6 -31
  80. package/node_modules/ink/build/devtools.js.map +1 -1
  81. package/node_modules/ink/build/dom.d.ts +1 -5
  82. package/node_modules/ink/build/dom.js +1 -20
  83. package/node_modules/ink/build/dom.js.map +1 -1
  84. package/node_modules/ink/build/experimental/apply-style.js +140 -0
  85. package/node_modules/ink/build/experimental/dom.js +123 -0
  86. package/node_modules/ink/build/experimental/output.js +91 -0
  87. package/node_modules/ink/build/experimental/reconciler.js +141 -0
  88. package/node_modules/ink/build/experimental/renderer.js +81 -0
  89. package/node_modules/ink/build/hooks/use-app.d.ts +1 -1
  90. package/node_modules/ink/build/hooks/use-app.js +1 -1
  91. package/node_modules/ink/build/hooks/use-cursor.d.ts +1 -1
  92. package/node_modules/ink/build/hooks/use-cursor.js +1 -1
  93. package/node_modules/ink/build/hooks/use-focus-manager.d.ts +2 -17
  94. package/node_modules/ink/build/hooks/use-focus-manager.js +1 -2
  95. package/node_modules/ink/build/hooks/use-focus-manager.js.map +1 -1
  96. package/node_modules/ink/build/hooks/use-focus.d.ts +1 -2
  97. package/node_modules/ink/build/hooks/use-focus.js +4 -5
  98. package/node_modules/ink/build/hooks/use-focus.js.map +1 -1
  99. package/node_modules/ink/build/hooks/use-input.d.ts +1 -2
  100. package/node_modules/ink/build/hooks/use-input.js +80 -82
  101. package/node_modules/ink/build/hooks/use-input.js.map +1 -1
  102. package/node_modules/ink/build/hooks/use-is-screen-reader-enabled.d.ts +1 -2
  103. package/node_modules/ink/build/hooks/use-is-screen-reader-enabled.js +1 -2
  104. package/node_modules/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -1
  105. package/node_modules/ink/build/hooks/use-stderr.d.ts +1 -1
  106. package/node_modules/ink/build/hooks/use-stderr.js +1 -1
  107. package/node_modules/ink/build/hooks/use-stdin.d.ts +2 -4
  108. package/node_modules/ink/build/hooks/use-stdin.js +1 -2
  109. package/node_modules/ink/build/hooks/use-stdin.js.map +1 -1
  110. package/node_modules/ink/build/hooks/use-stdout.d.ts +1 -1
  111. package/node_modules/ink/build/hooks/use-stdout.js +1 -1
  112. package/node_modules/ink/build/hooks/useInput.js +38 -0
  113. package/node_modules/ink/build/index.d.ts +1 -8
  114. package/node_modules/ink/build/index.js +0 -4
  115. package/node_modules/ink/build/index.js.map +1 -1
  116. package/node_modules/ink/build/ink.d.ts +3 -48
  117. package/node_modules/ink/build/ink.js +155 -325
  118. package/node_modules/ink/build/ink.js.map +1 -1
  119. package/node_modules/ink/build/input-parser.d.ts +1 -4
  120. package/node_modules/ink/build/input-parser.js +30 -70
  121. package/node_modules/ink/build/input-parser.js.map +1 -1
  122. package/node_modules/ink/build/instance.js +205 -0
  123. package/node_modules/ink/build/layout.d.ts +7 -0
  124. package/node_modules/ink/build/layout.js +33 -0
  125. package/node_modules/ink/build/layout.js.map +1 -0
  126. package/node_modules/ink/build/log-update.d.ts +0 -1
  127. package/node_modules/ink/build/log-update.js +1 -13
  128. package/node_modules/ink/build/log-update.js.map +1 -1
  129. package/node_modules/ink/build/measure-element.d.ts +0 -4
  130. package/node_modules/ink/build/measure-element.js +0 -4
  131. package/node_modules/ink/build/measure-element.js.map +1 -1
  132. package/node_modules/ink/build/options.d.ts +52 -0
  133. package/node_modules/ink/build/options.js +2 -0
  134. package/node_modules/ink/build/options.js.map +1 -0
  135. package/node_modules/ink/build/output.js +0 -25
  136. package/node_modules/ink/build/output.js.map +1 -1
  137. package/node_modules/ink/build/parse-keypress.d.ts +3 -1
  138. package/node_modules/ink/build/parse-keypress.js +17 -19
  139. package/node_modules/ink/build/parse-keypress.js.map +1 -1
  140. package/node_modules/ink/build/reconciler.js +27 -46
  141. package/node_modules/ink/build/reconciler.js.map +1 -1
  142. package/node_modules/ink/build/render-border.js +18 -29
  143. package/node_modules/ink/build/render-border.js.map +1 -1
  144. package/node_modules/ink/build/render-to-string.js +1 -2
  145. package/node_modules/ink/build/render-to-string.js.map +1 -1
  146. package/node_modules/ink/build/render.d.ts +2 -57
  147. package/node_modules/ink/build/render.js +11 -18
  148. package/node_modules/ink/build/render.js.map +1 -1
  149. package/node_modules/ink/build/screen-reader-update.d.ts +13 -0
  150. package/node_modules/ink/build/screen-reader-update.js +38 -0
  151. package/node_modules/ink/build/screen-reader-update.js.map +1 -0
  152. package/node_modules/ink/build/styles.d.ts +16 -78
  153. package/node_modules/ink/build/styles.js +31 -102
  154. package/node_modules/ink/build/styles.js.map +1 -1
  155. package/node_modules/ink/build/utils.d.ts +2 -9
  156. package/node_modules/ink/build/utils.js +3 -18
  157. package/node_modules/ink/build/utils.js.map +1 -1
  158. package/node_modules/ink/build/wrap-text.js +0 -7
  159. package/node_modules/ink/build/wrap-text.js.map +1 -1
  160. package/node_modules/ink/build/write-synchronized.d.ts +1 -1
  161. package/node_modules/ink/build/write-synchronized.js +2 -4
  162. package/node_modules/ink/build/write-synchronized.js.map +1 -1
  163. package/node_modules/ink/node_modules/emoji-regex/LICENSE-MIT.txt +20 -0
  164. package/node_modules/ink/node_modules/emoji-regex/README.md +107 -0
  165. package/node_modules/ink/node_modules/emoji-regex/index.d.ts +3 -0
  166. package/node_modules/ink/node_modules/emoji-regex/index.js +4 -0
  167. package/node_modules/ink/node_modules/emoji-regex/index.mjs +4 -0
  168. package/node_modules/ink/node_modules/emoji-regex/package.json +45 -0
  169. package/node_modules/{wrap-ansi → ink/node_modules/wrap-ansi}/index.d.ts +1 -1
  170. package/node_modules/ink/node_modules/wrap-ansi/index.js +222 -0
  171. package/node_modules/ink/node_modules/wrap-ansi/node_modules/string-width/index.d.ts +39 -0
  172. package/node_modules/ink/node_modules/wrap-ansi/node_modules/string-width/index.js +82 -0
  173. package/node_modules/ink/node_modules/wrap-ansi/node_modules/string-width/license +9 -0
  174. package/node_modules/ink/node_modules/wrap-ansi/node_modules/string-width/package.json +64 -0
  175. package/node_modules/ink/node_modules/wrap-ansi/node_modules/string-width/readme.md +66 -0
  176. package/node_modules/{wrap-ansi → ink/node_modules/wrap-ansi}/package.json +11 -11
  177. package/node_modules/{wrap-ansi → ink/node_modules/wrap-ansi}/readme.md +0 -2
  178. package/node_modules/ink/package.json +98 -34
  179. package/node_modules/ink/readme.md +48 -554
  180. package/node_modules/slice-ansi/index.d.ts +1 -1
  181. package/node_modules/slice-ansi/index.js +89 -146
  182. package/node_modules/slice-ansi/package.json +5 -5
  183. package/node_modules/slice-ansi/readme.md +0 -1
  184. package/node_modules/slice-ansi/tokenize-ansi.js +1 -1
  185. package/package.json +14 -10
  186. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.d.ts +188 -0
  187. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.d.ts.map +1 -0
  188. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.js +293 -0
  189. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.js.map +1 -0
  190. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/package.json +25 -0
  191. package/lib/cli/commands/db/snapshot/capture.mjs +0 -26
  192. package/lib/cli/renderers/db-snapshot-capture/text.mjs +0 -3
  193. package/node_modules/@alcalzone/ansi-tokenize/build/consts.d.ts +0 -17
  194. package/node_modules/@alcalzone/ansi-tokenize/build/consts.js +0 -28
  195. package/node_modules/@alcalzone/ansi-tokenize/build/consts.js.map +0 -1
  196. package/node_modules/ink/build/components/AnimationContext.d.ts +0 -9
  197. package/node_modules/ink/build/components/AnimationContext.js +0 -13
  198. package/node_modules/ink/build/components/AnimationContext.js.map +0 -1
  199. package/node_modules/ink/build/hooks/use-animation.d.ts +0 -49
  200. package/node_modules/ink/build/hooks/use-animation.js +0 -87
  201. package/node_modules/ink/build/hooks/use-animation.js.map +0 -1
  202. package/node_modules/ink/build/hooks/use-box-metrics.d.ts +0 -59
  203. package/node_modules/ink/build/hooks/use-box-metrics.js +0 -88
  204. package/node_modules/ink/build/hooks/use-box-metrics.js.map +0 -1
  205. package/node_modules/ink/build/hooks/use-paste.d.ts +0 -35
  206. package/node_modules/ink/build/hooks/use-paste.js +0 -62
  207. package/node_modules/ink/build/hooks/use-paste.js.map +0 -1
  208. package/node_modules/ink/build/hooks/use-window-size.d.ts +0 -18
  209. package/node_modules/ink/build/hooks/use-window-size.js +0 -22
  210. package/node_modules/ink/build/hooks/use-window-size.js.map +0 -1
  211. package/node_modules/wrap-ansi/index.js +0 -468
  212. /package/node_modules/{wrap-ansi → ink/node_modules/wrap-ansi}/license +0 -0
@@ -24,8 +24,6 @@ Since Ink is a React renderer, all features of React are supported.
24
24
  Head over to the [React](https://reactjs.org) website for documentation on how to use it.
25
25
  Only Ink's methods are documented in this readme.
26
26
 
27
- **Fully AI-generated pull requests are not accepted. You can use AI, but should be verified and cleaned up by a human. Only Opus 4.6+ (high-effort) and Codex 5.4+ (extra high) are accepted models. Preferably created with Opus and verified by Codex.**
28
-
29
27
  ---
30
28
 
31
29
  <div align="center">
@@ -44,9 +42,6 @@ Only Ink's methods are documented in this readme.
44
42
  npm install ink react
45
43
  ```
46
44
 
47
- > [!NOTE]
48
- > This readme documents the upcoming version of Ink. For the latest stable release, see [Ink on npm](https://www.npmjs.com/package/ink).
49
-
50
45
  ## Usage
51
46
 
52
47
  ```jsx
@@ -132,7 +127,7 @@ render(<Counter />);
132
127
  - [ElevenLabs CLI](https://github.com/elevenlabs/cli) - ElevenLabs agents client.
133
128
  - [SSH AI Chat](https://github.com/miantiao-me/ssh-ai-chat) - Chat with AI over SSH.
134
129
 
135
- _(PRs welcome. Append new entries at the end. Repos must have 100+ stars and showcase Ink beyond a basic list picker.)_
130
+ *(PRs welcome. Append new entries at the end. Repos must have 100+ stars and showcase Ink beyond a basic list picker.)*
136
131
 
137
132
  ## Contents
138
133
 
@@ -147,17 +142,13 @@ _(PRs welcome. Append new entries at the end. Repos must have 100+ stars and sho
147
142
  - [`<Transform>`](#transform)
148
143
  - [Hooks](#hooks)
149
144
  - [`useInput`](#useinputinputhandler-options)
150
- - [`usePaste`](#usepastehandler-options)
151
145
  - [`useApp`](#useapp)
152
146
  - [`useStdin`](#usestdin)
153
147
  - [`useStdout`](#usestdout)
154
- - [`useBoxMetrics`](#useboxmetricsref)
155
148
  - [`useStderr`](#usestderr)
156
- - [`useWindowSize`](#usewindowsize)
157
149
  - [`useFocus`](#usefocusoptions)
158
150
  - [`useFocusManager`](#usefocusmanager)
159
151
  - [`useCursor`](#usecursor)
160
- - [`useAnimation`](#useanimationoptions)
161
152
  - [API](#api)
162
153
  - [Testing](#testing)
163
154
  - [Using React Devtools](#using-react-devtools)
@@ -276,8 +267,7 @@ const Example = () => (
276
267
  render(<Example />);
277
268
  ```
278
269
 
279
- > [!NOTE]
280
- > `<Text>` allows only text nodes and nested `<Text>` components inside of it. For example, `<Box>` component can't be used inside `<Text>`.
270
+ **Note:** `<Text>` allows only text nodes and nested `<Text>` components inside of it. For example, `<Box>` component can't be used inside `<Text>`.
281
271
 
282
272
  #### color
283
273
 
@@ -369,12 +359,11 @@ Invert background and foreground colors.
369
359
  #### wrap
370
360
 
371
361
  Type: `string`\
372
- Allowed values: `wrap` `hard` `truncate` `truncate-start` `truncate-middle` `truncate-end`\
362
+ Allowed values: `wrap` `truncate` `truncate-start` `truncate-middle` `truncate-end`\
373
363
  Default: `wrap`
374
364
 
375
365
  This property tells Ink to wrap or truncate text if its width is larger than the container.
376
366
  If `wrap` is passed (the default), Ink will wrap text and split it into multiple lines.
377
- If `hard` is passed, Ink will fill each line to the full column width, breaking words as necessary.
378
367
  If `truncate-*` is passed, Ink will truncate text instead, resulting in one line of text with the rest cut off.
379
368
 
380
369
  ```jsx
@@ -383,11 +372,6 @@ If `truncate-*` is passed, Ink will truncate text instead, resulting in one line
383
372
  </Box>
384
373
  //=> 'Hello\nWorld'
385
374
 
386
- <Box width={7}>
387
- <Text wrap="hard">Hello World</Text>
388
- </Box>
389
- //=> 'Hello W\norld'
390
-
391
375
  // `truncate` is an alias to `truncate-end`
392
376
  <Box width={7}>
393
377
  <Text wrap="truncate">Hello World</Text>
@@ -481,33 +465,11 @@ Percentages aren't supported yet; see https://github.com/facebook/yoga/issues/87
481
465
 
482
466
  ##### minHeight
483
467
 
484
- Type: `number` `string`
485
-
486
- Sets a minimum height of the element in lines (rows).
487
- You can also set it as a percentage, which will calculate the minimum height based on the height of the parent element.
488
-
489
- ##### maxWidth
490
-
491
468
  Type: `number`
492
469
 
493
- Sets a maximum width of the element.
470
+ Sets a minimum height of the element.
494
471
  Percentages aren't supported yet; see https://github.com/facebook/yoga/issues/872.
495
472
 
496
- ##### maxHeight
497
-
498
- Type: `number` `string`
499
-
500
- Sets a maximum height of the element in lines (rows).
501
- You can also set it as a percentage, which will calculate the maximum height based on the height of the parent element.
502
-
503
- ##### aspectRatio
504
-
505
- Type: `number`
506
-
507
- Defines the aspect ratio (width/height) for the element.
508
-
509
- Use it with at least one size constraint (`width`, `height`, `minHeight`, or `maxHeight`) so Ink can derive the missing dimension.
510
-
511
473
  #### Padding
512
474
 
513
475
  ##### paddingTop
@@ -812,7 +774,7 @@ See [flex-wrap](https://css-tricks.com/almanac/properties/f/flex-wrap/).
812
774
  ##### alignItems
813
775
 
814
776
  Type: `string`\
815
- Allowed values: `flex-start` `center` `flex-end` `stretch` `baseline`
777
+ Allowed values: `flex-start` `center` `flex-end`
816
778
 
817
779
  See [align-items](https://css-tricks.com/almanac/properties/a/align-items/).
818
780
 
@@ -870,7 +832,7 @@ See [align-items](https://css-tricks.com/almanac/properties/a/align-items/).
870
832
 
871
833
  Type: `string`\
872
834
  Default: `auto`\
873
- Allowed values: `auto` `flex-start` `center` `flex-end` `stretch` `baseline`
835
+ Allowed values: `auto` `flex-start` `center` `flex-end`
874
836
 
875
837
  See [align-self](https://css-tricks.com/almanac/properties/a/align-self/).
876
838
 
@@ -903,16 +865,6 @@ See [align-self](https://css-tricks.com/almanac/properties/a/align-self/).
903
865
  // X
904
866
  ```
905
867
 
906
- ##### alignContent
907
-
908
- Type: `string`\
909
- Default: `flex-start`\
910
- Allowed values: `flex-start` `flex-end` `center` `stretch` `space-between` `space-around` `space-evenly`
911
-
912
- Defines alignment between flex lines on the cross axis when `flexWrap` creates multiple lines.
913
- See [align-content](https://css-tricks.com/almanac/properties/a/align-content/).
914
- Unlike CSS (`stretch`), Ink defaults to `flex-start` so wrapped lines stay compact and fixed-height boxes don't gain unexpected empty rows unless you opt in to stretching.
915
-
916
868
  ##### justifyContent
917
869
 
918
870
  Type: `string`\
@@ -955,46 +907,6 @@ See [justify-content](https://css-tricks.com/almanac/properties/j/justify-conten
955
907
  // [ X Y ]
956
908
  ```
957
909
 
958
- #### Position
959
-
960
- ##### position
961
-
962
- Type: `string`\
963
- Allowed values: `relative` `absolute` `static`\
964
- Default: `relative`
965
-
966
- Controls how the element is positioned.
967
-
968
- When `position` is `static`, `top`, `right`, `bottom`, and `left` are ignored.
969
-
970
- ##### top
971
-
972
- Type: `number` `string`
973
-
974
- Top offset for positioned elements.
975
- You can also set it as a percentage of the parent size.
976
-
977
- ##### right
978
-
979
- Type: `number` `string`
980
-
981
- Right offset for positioned elements.
982
- You can also set it as a percentage of the parent size.
983
-
984
- ##### bottom
985
-
986
- Type: `number` `string`
987
-
988
- Bottom offset for positioned elements.
989
- You can also set it as a percentage of the parent size.
990
-
991
- ##### left
992
-
993
- Type: `number` `string`
994
-
995
- Left offset for positioned elements.
996
- You can also set it as a percentage of the parent size.
997
-
998
910
  #### Visibility
999
911
 
1000
912
  ##### display
@@ -1090,7 +1002,7 @@ Alternatively, pass a custom border style like so:
1090
1002
  bottomLeft: '↗',
1091
1003
  bottom: '↑',
1092
1004
  bottomRight: '↖',
1093
- right: '←',
1005
+ right: '←'
1094
1006
  }}
1095
1007
  >
1096
1008
  <Text>Custom</Text>
@@ -1232,76 +1144,6 @@ Dim the right border color.
1232
1144
  </Box>
1233
1145
  ```
1234
1146
 
1235
- ##### borderBackgroundColor
1236
-
1237
- Type: `string`
1238
-
1239
- Change border background color.
1240
- Accepts the same values as [`backgroundColor`](#backgroundcolor) in `<Text>` component.
1241
- A shorthand for setting `borderTopBackgroundColor`, `borderRightBackgroundColor`, `borderBottomBackgroundColor`, and `borderLeftBackgroundColor`.
1242
-
1243
- ```jsx
1244
- <Box borderStyle="round" borderColor="white" borderBackgroundColor="green">
1245
- <Text>Hello world</Text>
1246
- </Box>
1247
- ```
1248
-
1249
- ##### borderTopBackgroundColor
1250
-
1251
- Type: `string`
1252
-
1253
- Change top border background color.
1254
- Accepts the same values as [`backgroundColor`](#backgroundcolor) in `<Text>` component.
1255
- Falls back to `borderBackgroundColor` if not specified.
1256
-
1257
- ```jsx
1258
- <Box borderStyle="round" borderColor="white" borderTopBackgroundColor="green">
1259
- <Text>Hello world</Text>
1260
- </Box>
1261
- ```
1262
-
1263
- ##### borderBottomBackgroundColor
1264
-
1265
- Type: `string`
1266
-
1267
- Change bottom border background color.
1268
- Accepts the same values as [`backgroundColor`](#backgroundcolor) in `<Text>` component.
1269
- Falls back to `borderBackgroundColor` if not specified.
1270
-
1271
- ```jsx
1272
- <Box borderStyle="round" borderColor="white" borderBottomBackgroundColor="green">
1273
- <Text>Hello world</Text>
1274
- </Box>
1275
- ```
1276
-
1277
- ##### borderRightBackgroundColor
1278
-
1279
- Type: `string`
1280
-
1281
- Change right border background color.
1282
- Accepts the same values as [`backgroundColor`](#backgroundcolor) in `<Text>` component.
1283
- Falls back to `borderBackgroundColor` if not specified.
1284
-
1285
- ```jsx
1286
- <Box borderStyle="round" borderColor="white" borderRightBackgroundColor="green">
1287
- <Text>Hello world</Text>
1288
- </Box>
1289
- ```
1290
-
1291
- ##### borderLeftBackgroundColor
1292
-
1293
- Type: `string`
1294
-
1295
- Change left border background color.
1296
- Accepts the same values as [`backgroundColor`](#backgroundcolor) in `<Text>` component.
1297
- Falls back to `borderBackgroundColor` if not specified.
1298
-
1299
- ```jsx
1300
- <Box borderStyle="round" borderColor="white" borderLeftBackgroundColor="green">
1301
- <Text>Hello world</Text>
1302
- </Box>
1303
- ```
1304
-
1305
1147
  ##### borderTop
1306
1148
 
1307
1149
  Type: `boolean`\
@@ -1346,23 +1188,11 @@ Accepts the same values as [`color`](#color) in the `<Text>` component.
1346
1188
  <Text>Red background</Text>
1347
1189
  </Box>
1348
1190
 
1349
- <Box
1350
- backgroundColor="#FF8800"
1351
- width={20}
1352
- height={3}
1353
- marginTop={1}
1354
- alignSelf="flex-start"
1355
- >
1191
+ <Box backgroundColor="#FF8800" width={20} height={3} marginTop={1} alignSelf="flex-start">
1356
1192
  <Text>Orange background</Text>
1357
1193
  </Box>
1358
1194
 
1359
- <Box
1360
- backgroundColor="rgb(0, 255, 0)"
1361
- width={20}
1362
- height={3}
1363
- marginTop={1}
1364
- alignSelf="flex-start"
1365
- >
1195
+ <Box backgroundColor="rgb(0, 255, 0)" width={20} height={3} marginTop={1} alignSelf="flex-start">
1366
1196
  <Text>Green background</Text>
1367
1197
  </Box>
1368
1198
  </Box>
@@ -1381,12 +1211,7 @@ The background color fills the entire `<Box>` area and is inherited by child `<T
1381
1211
  Background colors work with borders and padding:
1382
1212
 
1383
1213
  ```jsx
1384
- <Box
1385
- backgroundColor="cyan"
1386
- borderStyle="round"
1387
- padding={1}
1388
- alignSelf="flex-start"
1389
- >
1214
+ <Box backgroundColor="cyan" borderStyle="round" padding={1} alignSelf="flex-start">
1390
1215
  <Text>Background with border and padding</Text>
1391
1216
  </Box>
1392
1217
  ```
@@ -1495,8 +1320,8 @@ const Example = () => {
1495
1320
  ...previousTests,
1496
1321
  {
1497
1322
  id: previousTests.length,
1498
- title: `Test #${previousTests.length + 1}`,
1499
- },
1323
+ title: `Test #${previousTests.length + 1}`
1324
+ }
1500
1325
  ]);
1501
1326
 
1502
1327
  timer = setTimeout(run, 100);
@@ -1532,8 +1357,9 @@ const Example = () => {
1532
1357
  render(<Example />);
1533
1358
  ```
1534
1359
 
1535
- > [!NOTE]
1536
- > `<Static>` only renders new items in the `items` prop and ignores items that were previously rendered. This means that when you add new items to the `items` array, changes you make to previous items will not trigger a rerender.
1360
+ **Note:** `<Static>` only renders new items in the `items` prop and ignores items
1361
+ that were previously rendered. This means that when you add new items to the `items`
1362
+ array, changes you make to previous items will not trigger a rerender.
1537
1363
 
1538
1364
  See [examples/static](examples/static/static.tsx) for an example usage of `<Static>` component.
1539
1365
 
@@ -1588,11 +1414,7 @@ For example, you might want to apply a [gradient to text](https://github.com/sin
1588
1414
  These use cases can't accept React nodes as input; they expect a string.
1589
1415
  That's what the `<Transform>` component does: it gives you an output string of its child components and lets you transform it in any way.
1590
1416
 
1591
- > [!NOTE]
1592
- > `<Transform>` must be applied only to `<Text>` children components and shouldn't change the dimensions of the output; otherwise, the layout will be incorrect.
1593
-
1594
- > [!IMPORTANT]
1595
- > When children use `<Text>` styling props (e.g. `color`, `bold`), the string passed to `transform` will contain [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code). If your transform manipulates whitespace or does string operations like `.trim()`, you may need to use ANSI-aware methods (e.g. from [`slice-ansi`](https://github.com/chalk/slice-ansi) or [`strip-ansi`](https://github.com/chalk/strip-ansi)).
1417
+ **Note:** `<Transform>` must be applied only to `<Text>` children components and shouldn't change the dimensions of the output; otherwise, the layout will be incorrect.
1596
1418
 
1597
1419
  ```jsx
1598
1420
  import {render, Transform} from 'ink';
@@ -1633,7 +1455,11 @@ const text =
1633
1455
  'of my hands only. I lived there two years and two months. At ' +
1634
1456
  'present I am a sojourner in civilized life again.';
1635
1457
 
1636
- render(<HangingIndent indent={4}>{text}</HangingIndent>);
1458
+ render(
1459
+ <HangingIndent indent={4}>
1460
+ {text}
1461
+ </HangingIndent>
1462
+ );
1637
1463
  ```
1638
1464
 
1639
1465
  #### transform(outputLine, index)
@@ -1659,7 +1485,7 @@ The zero-indexed line number of the line that's currently being transformed.
1659
1485
 
1660
1486
  ### useInput(inputHandler, options?)
1661
1487
 
1662
- A React hook that returns `void` and handles user input.
1488
+ This hook is used for handling user input.
1663
1489
  It's a more convenient alternative to using `useStdin` and listening for `data` events.
1664
1490
  The callback you pass to `useInput` is called for each character when the user enters any input.
1665
1491
  However, if the user pastes text and it's more than one character, the callback will be called only once, and the whole string will be passed as `input`.
@@ -1838,58 +1664,9 @@ Default: `true`
1838
1664
  Enable or disable capturing of user input.
1839
1665
  Useful when there are multiple `useInput` hooks used at once to avoid handling the same input several times.
1840
1666
 
1841
- ### usePaste(handler, options?)
1842
-
1843
- A React hook that calls `handler` whenever the user pastes text. Bracketed paste mode (`\x1b[?2004h`) is automatically enabled while the hook is active, so pasted text arrives as a single string rather than being misinterpreted as individual key presses.
1844
-
1845
- `usePaste` and `useInput` can be used together in the same component. They operate on separate event channels, so paste content is never forwarded to `useInput` handlers when `usePaste` is active.
1846
-
1847
- ```jsx
1848
- import {useInput, usePaste} from 'ink';
1849
-
1850
- const MyInput = () => {
1851
- useInput((input, key) => {
1852
- // Only receives typed characters and key events, not pasted text.
1853
- if (key.return) {
1854
- // Submit
1855
- }
1856
- });
1857
-
1858
- usePaste((text) => {
1859
- // Receives the full pasted string, including newlines.
1860
- console.log('Pasted:', text);
1861
- });
1862
-
1863
- return …
1864
- };
1865
- ```
1866
-
1867
- #### handler(text)
1868
-
1869
- Type: `Function`
1870
-
1871
- Called with the full pasted string whenever the user pastes text. The string is delivered verbatim — newlines, escape sequences, and other special characters are preserved exactly as pasted.
1872
-
1873
- ##### text
1874
-
1875
- Type: `string`
1876
-
1877
- The pasted text.
1878
-
1879
- #### options
1880
-
1881
- Type: `object`
1882
-
1883
- ##### isActive
1884
-
1885
- Type: `boolean`\
1886
- Default: `true`
1887
-
1888
- Enable or disable the paste handler. Useful when multiple components use `usePaste` and only one should be active at a time.
1889
-
1890
1667
  ### useApp()
1891
1668
 
1892
- A React hook that returns app lifecycle methods.
1669
+ `useApp` is a React hook that exposes a method to manually exit the app (unmount).
1893
1670
 
1894
1671
  #### exit(errorOrResult?)
1895
1672
 
@@ -1901,14 +1678,12 @@ Exit (unmount) the whole Ink app.
1901
1678
 
1902
1679
  Type: `Error | unknown`
1903
1680
 
1904
- Optional value that controls how [`waitUntilExit`](#waituntilexit) settles:
1905
-
1681
+ Optional value that controls how [`waitUntilExit`](waituntilexit) settles:
1906
1682
  - `exit()` resolves with `undefined`.
1907
1683
  - `exit(error)` rejects when `error` is an `Error`.
1908
1684
  - `exit(value)` resolves with `value`.
1909
1685
 
1910
1686
  ```js
1911
- import {useEffect} from 'react';
1912
1687
  import {useApp} from 'ink';
1913
1688
 
1914
1689
  const Example = () => {
@@ -1919,39 +1694,15 @@ const Example = () => {
1919
1694
  setTimeout(() => {
1920
1695
  exit();
1921
1696
  }, 5000);
1922
- }, [exit]);
1697
+ }, []);
1923
1698
 
1924
1699
  return …
1925
1700
  };
1926
1701
  ```
1927
1702
 
1928
- #### waitUntilRenderFlush()
1929
-
1930
- Type: `Function`
1931
-
1932
- Returns a promise that settles after pending render output is flushed to stdout.
1933
-
1934
- ```js
1935
- import {useEffect} from 'react';
1936
- import {useApp} from 'ink';
1937
-
1938
- const Example = () => {
1939
- const {waitUntilRenderFlush} = useApp();
1940
-
1941
- useEffect(() => {
1942
- void (async () => {
1943
- await waitUntilRenderFlush();
1944
- runNextCommand();
1945
- })();
1946
- }, [waitUntilRenderFlush]);
1947
-
1948
- return …;
1949
- };
1950
- ```
1951
-
1952
1703
  ### useStdin()
1953
1704
 
1954
- A React hook that returns the stdin stream and stdin-related utilities.
1705
+ `useStdin` is a React hook that exposes the stdin stream.
1955
1706
 
1956
1707
  #### stdin
1957
1708
 
@@ -2025,7 +1776,7 @@ const Example = () => {
2025
1776
 
2026
1777
  ### useStdout()
2027
1778
 
2028
- A React hook that returns the stdout stream where Ink renders your app and stdout-related utilities.
1779
+ `useStdout` is a React hook that exposes the stdout stream where Ink renders your app.
2029
1780
 
2030
1781
  #### stdout
2031
1782
 
@@ -2071,73 +1822,9 @@ const Example = () => {
2071
1822
 
2072
1823
  See additional usage example in [examples/use-stdout](examples/use-stdout/use-stdout.tsx).
2073
1824
 
2074
- ### useBoxMetrics(ref)
2075
-
2076
- A React hook that returns the current layout metrics for a tracked box element.
2077
- It updates when layout changes (for example terminal resize, sibling/content changes, or position changes).
2078
-
2079
- Use `hasMeasured` to detect when the currently tracked element has been measured.
2080
-
2081
- #### ref
2082
-
2083
- Type: `React.RefObject<DOMElement>`
2084
-
2085
- A ref to the `<Box>` element to track.
2086
-
2087
- ```jsx
2088
- import {useRef} from 'react';
2089
- import {Box, Text, useBoxMetrics} from 'ink';
2090
-
2091
- const Example = () => {
2092
- const ref = useRef(null);
2093
- const {width, height, left, top, hasMeasured} = useBoxMetrics(ref);
2094
-
2095
- return (
2096
- <Box ref={ref}>
2097
- <Text>
2098
- {hasMeasured ? `${width}x${height} at ${left},${top}` : 'Measuring...'}
2099
- </Text>
2100
- </Box>
2101
- );
2102
- };
2103
- ```
2104
-
2105
- #### width
2106
-
2107
- Type: `number`
2108
-
2109
- Element width.
2110
-
2111
- #### height
2112
-
2113
- Type: `number`
2114
-
2115
- Element height.
2116
-
2117
- #### left
2118
-
2119
- Type: `number`
2120
-
2121
- Distance from the left edge of the parent.
2122
-
2123
- #### top
2124
-
2125
- Type: `number`
2126
-
2127
- Distance from the top edge of the parent.
2128
-
2129
- #### hasMeasured
2130
-
2131
- Type: `boolean`
2132
-
2133
- Whether the currently tracked element has been measured.
2134
-
2135
- > [!NOTE]
2136
- > The hook returns `{width: 0, height: 0, left: 0, top: 0}` until the first layout pass completes. It also returns zeros when the tracked ref is detached.
2137
-
2138
1825
  ### useStderr()
2139
1826
 
2140
- A React hook that returns the stderr stream and stderr-related utilities.
1827
+ `useStderr` is a React hook that exposes the stderr stream.
2141
1828
 
2142
1829
  #### stderr
2143
1830
 
@@ -2184,42 +1871,8 @@ const Example = () => {
2184
1871
  };
2185
1872
  ```
2186
1873
 
2187
- ### useWindowSize()
2188
-
2189
- A React hook that returns the current terminal dimensions and re-renders the component whenever the terminal is resized.
2190
-
2191
- ```js
2192
- import {Text, useWindowSize} from 'ink';
2193
-
2194
- const Example = () => {
2195
- const {columns, rows} = useWindowSize();
2196
-
2197
- return (
2198
- <Text>
2199
- {columns}x{rows}
2200
- </Text>
2201
- );
2202
- };
2203
- ```
2204
-
2205
- #### columns
2206
-
2207
- Type: `number`
2208
-
2209
- Number of columns (horizontal character cells).
2210
-
2211
- #### rows
2212
-
2213
- Type: `number`
2214
-
2215
- Number of rows (vertical character cells).
2216
-
2217
- > [!NOTE]
2218
- > When the terminal is resized narrower, ghost lines may briefly appear depending on the terminal emulator's reflow behavior.
2219
-
2220
1874
  ### useFocus(options?)
2221
1875
 
2222
- A React hook that returns focus state and focus controls for the current component.
2223
1876
  A component that uses the `useFocus` hook becomes "focusable" to Ink, so when the user presses <kbd>Tab</kbd>, Ink will switch focus to this component.
2224
1877
  If there are multiple components that execute the `useFocus` hook, focus will be given to them in the order in which these components are rendered.
2225
1878
  This hook returns an object with an `isFocused` boolean property, which determines whether this component is focused.
@@ -2264,14 +1917,13 @@ See example in [examples/use-focus](examples/use-focus/use-focus.tsx) and [examp
2264
1917
 
2265
1918
  ### useFocusManager()
2266
1919
 
2267
- A React hook that returns methods to manage focus across focusable components.
1920
+ This hook exposes methods to enable or disable focus management for all components or manually switch focus to the next or previous components.
2268
1921
 
2269
1922
  #### enableFocus()
2270
1923
 
2271
1924
  Enable focus management for all components.
2272
1925
 
2273
- > [!NOTE]
2274
- > You don't need to call this method manually unless you've disabled focus management. Focus management is enabled by default.
1926
+ **Note:** You don't need to call this method manually unless you've disabled focus management. Focus management is enabled by default.
2275
1927
 
2276
1928
  ```js
2277
1929
  import {useFocusManager} from 'ink';
@@ -2312,8 +1964,7 @@ Switch focus to the next focusable component.
2312
1964
  If there's no active component right now, focus will be given to the first focusable component.
2313
1965
  If the active component is the last in the list of focusable components, focus will be switched to the first focusable component.
2314
1966
 
2315
- > [!NOTE]
2316
- > Ink calls this method when user presses <kbd>Tab</kbd>.
1967
+ **Note:** Ink calls this method when user presses <kbd>Tab</kbd>.
2317
1968
 
2318
1969
  ```js
2319
1970
  import {useFocusManager} from 'ink';
@@ -2335,8 +1986,7 @@ Switch focus to the previous focusable component.
2335
1986
  If there's no active component right now, focus will be given to the first focusable component.
2336
1987
  If the active component is the first in the list of focusable components, focus will be switched to the last focusable component.
2337
1988
 
2338
- > [!NOTE]
2339
- > Ink calls this method when user presses <kbd>Shift</kbd>+<kbd>Tab</kbd>.
1989
+ **Note:** Ink calls this method when user presses <kbd>Shift</kbd>+<kbd>Tab</kbd>.
2340
1990
 
2341
1991
  ```js
2342
1992
  import {useFocusManager} from 'ink';
@@ -2359,7 +2009,7 @@ const Example = () => {
2359
2009
  Type: `string`
2360
2010
 
2361
2011
  Switch focus to the component with the given [`id`](#id).
2362
- If there's no component with that ID, focus is not changed.
2012
+ If there's no component with that ID, focus will be given to the next focusable component.
2363
2013
 
2364
2014
  ```js
2365
2015
  import {useFocusManager, useInput} from 'ink';
@@ -2378,26 +2028,9 @@ const Example = () => {
2378
2028
  };
2379
2029
  ```
2380
2030
 
2381
- #### activeId
2382
-
2383
- Type: `string | undefined`
2384
-
2385
- The ID of the currently focused component, or `undefined` if no component is focused.
2386
-
2387
- ```js
2388
- import {Text, useFocusManager} from 'ink';
2389
-
2390
- const Example = () => {
2391
- const {activeId} = useFocusManager();
2392
-
2393
- return <Text>Focused: {activeId ?? 'none'}</Text>;
2394
- };
2395
- ```
2396
-
2397
2031
  ### useCursor()
2398
2032
 
2399
- A React hook that returns methods to control the terminal cursor position after each render.
2400
- This is essential for IME (Input Method Editor) support, where the composing character is displayed at the cursor location.
2033
+ `useCursor` lets you control the terminal cursor position after each render. This is essential for IME (Input Method Editor) support, where the composing character is displayed at the cursor location.
2401
2034
 
2402
2035
  ```jsx
2403
2036
  import {useState} from 'react';
@@ -2414,10 +2047,7 @@ const TextInput = () => {
2414
2047
  return (
2415
2048
  <Box flexDirection="column">
2416
2049
  <Text>Type here:</Text>
2417
- <Text>
2418
- {prompt}
2419
- {text}
2420
- </Text>
2050
+ <Text>{prompt}{text}</Text>
2421
2051
  </Box>
2422
2052
  );
2423
2053
  };
@@ -2449,8 +2079,7 @@ Row position from the top of the Ink output (0 = first line).
2449
2079
 
2450
2080
  ### useIsScreenReaderEnabled()
2451
2081
 
2452
- A React hook that returns whether a screen reader is enabled.
2453
- This is useful when you want to render different output for screen readers.
2082
+ Returns whether a screen reader is enabled. This is useful when you want to render different output for screen readers.
2454
2083
 
2455
2084
  ```jsx
2456
2085
  import {useIsScreenReaderEnabled, Text} from 'ink';
@@ -2468,65 +2097,6 @@ const Example = () => {
2468
2097
  };
2469
2098
  ```
2470
2099
 
2471
- ### useAnimation(options?)
2472
-
2473
- A React hook that drives animations. Returns a frame counter, elapsed time, frame delta, and a reset function. All animations share a single timer internally, so multiple animated components consolidate into one render cycle.
2474
-
2475
- ```jsx
2476
- import {Text, useAnimation} from 'ink';
2477
-
2478
- const Spinner = () => {
2479
- const {frame} = useAnimation({interval: 80});
2480
- const characters = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
2481
-
2482
- return <Text>{characters[frame % characters.length]}</Text>;
2483
- };
2484
- ```
2485
-
2486
- #### options
2487
-
2488
- Type: `object`
2489
-
2490
- ##### interval
2491
-
2492
- Type: `number`\
2493
- Default: `100`
2494
-
2495
- Time between ticks in milliseconds.
2496
-
2497
- ##### isActive
2498
-
2499
- Type: `boolean`\
2500
- Default: `true`
2501
-
2502
- Whether the animation is running. When set to `false`, the animation stops. When toggled back to `true`, all values reset to `0`.
2503
-
2504
- #### Return value
2505
-
2506
- ##### frame
2507
-
2508
- Type: `number`
2509
-
2510
- Discrete counter that increments by 1 each interval. Useful for indexed sequences like spinner frames.
2511
-
2512
- ##### time
2513
-
2514
- Type: `number`
2515
-
2516
- Total elapsed time in milliseconds since the animation started or was last reset. Useful for continuous math-based animations like sine waves: `Math.sin(time / 1000 * Math.PI * 2)`.
2517
-
2518
- ##### delta
2519
-
2520
- Type: `number`
2521
-
2522
- Time in milliseconds since the previous rendered tick. Accounts for throttled renders. Useful for physics-based or velocity-driven motion: `position += speed * delta`.
2523
-
2524
- ##### reset
2525
-
2526
- Type: `() => void`
2527
-
2528
- Resets `frame`, `time`, and `delta` to `0` and restarts timing from the current moment. Useful for one-shot animations triggered by events.
2529
-
2530
2100
  ## API
2531
2101
 
2532
2102
  #### render(tree, options?)
@@ -2581,8 +2151,6 @@ Patch console methods to ensure console output doesn't mix with Ink's output.
2581
2151
  When any of the `console.*` methods are called (like `console.log()`), Ink intercepts their output, clears the main output, renders output from the console method, and then rerenders the main output again.
2582
2152
  That way, both are visible and don't overlap each other.
2583
2153
 
2584
- Once unmount starts, Ink restores the native console before React cleanup runs. Teardown-time `console.*` output then follows the normal console behavior instead of being rerouted through Ink.
2585
-
2586
2154
  This functionality is powered by [patch-console](https://github.com/vadimdemedes/patch-console), so if you need to disable Ink's interception of output but want to build something custom, you can use that.
2587
2155
 
2588
2156
  ###### onRender
@@ -2590,9 +2158,7 @@ This functionality is powered by [patch-console](https://github.com/vadimdemedes
2590
2158
  Type: `({renderTime: number}) => void`\
2591
2159
  Default: `undefined`
2592
2160
 
2593
- Runs the given callback after each render and re-render with render metrics.
2594
- This callback runs after Ink commits a frame, but it does not wait for `stdout`/`stderr` stream callbacks.
2595
- To run code after output is flushed, use [`waitUntilRenderFlush()`](#waituntilrenderflush).
2161
+ Runs the given callback after each render and re-render with a metrics object.
2596
2162
 
2597
2163
  ###### isScreenReaderEnabled
2598
2164
 
@@ -2634,7 +2200,6 @@ Default: `false`
2634
2200
  Enable React Concurrent Rendering mode.
2635
2201
 
2636
2202
  When enabled:
2637
-
2638
2203
  - Suspense boundaries work correctly with async data fetching
2639
2204
  - `useTransition` and `useDeferredValue` hooks are fully functional
2640
2205
  - Updates can be interrupted for higher priority work
@@ -2643,48 +2208,7 @@ When enabled:
2643
2208
  render(<MyApp />, {concurrent: true});
2644
2209
  ```
2645
2210
 
2646
- > [!NOTE]
2647
- > Concurrent mode changes the timing of renders. Some tests may need to use `act()` to properly await updates. Reusing the same stdout across multiple `render()` calls without unmounting is unsupported. Call `unmount()` first if you need to change the rendering mode or create a fresh instance.
2648
-
2649
- ###### interactive
2650
-
2651
- Type: `boolean`\
2652
- Default: `true` (`false` if in CI (detected via [`is-in-ci`](https://github.com/sindresorhus/is-in-ci)) or `stdout.isTTY` is falsy)
2653
-
2654
- Override automatic interactive mode detection.
2655
-
2656
- By default, Ink detects whether the environment is interactive based on CI detection and `stdout.isTTY`. When non-interactive, Ink skips terminal-specific features like ANSI erase sequences, cursor manipulation, synchronized output, resize handling, and kitty keyboard auto-detection. Only the final frame of non-static output is written at unmount.
2657
-
2658
- Most users should not need to set this option. Use it when you have your own "interactive" detection logic that differs from the built-in behavior.
2659
-
2660
- > [!NOTE]
2661
- > Reusing the same stdout across multiple `render()` calls without unmounting is unsupported. Call `unmount()` first if you need to change this option or create a fresh instance.
2662
-
2663
- ```jsx
2664
- // Use your own detection logic
2665
- const isInteractive = myCustomDetection();
2666
- render(<MyApp />, {interactive: isInteractive});
2667
- ```
2668
-
2669
- ###### alternateScreen
2670
-
2671
- Type: `boolean`\
2672
- Default: `false`
2673
-
2674
- Render the app in the terminal's alternate screen buffer. When enabled, the app renders on a separate screen, and the original terminal content is restored when the app exits. This is the same mechanism used by programs like vim, htop, and less.
2675
-
2676
- Note: The terminal's scrollback buffer is not available while in the alternate screen. This is standard terminal behavior; programs like vim use the alternate screen specifically to avoid polluting the user's scrollback history.
2677
-
2678
- Ink intentionally treats alternate-screen teardown output as disposable. It does not preserve or replay teardown-time frames, hook writes, or `console.*` output after restoring the primary screen.
2679
-
2680
- Only works in interactive mode. Ignored when `interactive` is `false` or in a non-interactive environment (CI, piped stdout).
2681
-
2682
- > [!NOTE]
2683
- > Reusing the same stdout across multiple `render()` calls without unmounting is unsupported. Call `unmount()` first if you need to change this option or create a fresh instance.
2684
-
2685
- ```jsx
2686
- render(<MyApp />, {alternateScreen: true});
2687
- ```
2211
+ **Note:** Concurrent mode changes the timing of renders. Some tests may need to use `act()` to properly await updates. The `concurrent` option only takes effect on the first render for a given stdout. If you need to change the rendering mode, call `unmount()` first.
2688
2212
 
2689
2213
  ###### kittyKeyboard
2690
2214
 
@@ -2727,7 +2251,6 @@ Default: `['disambiguateEscapeCodes']`
2727
2251
  Protocol flags to request from the terminal. Pass an array of flag name strings.
2728
2252
 
2729
2253
  Available flags:
2730
-
2731
2254
  - `'disambiguateEscapeCodes'` - Disambiguate escape codes
2732
2255
  - `'reportEventTypes'` - Report key press, repeat, and release events
2733
2256
  - `'reportAlternateKeys'` - Report alternate key encodings
@@ -2768,7 +2291,7 @@ console.log(output);
2768
2291
 
2769
2292
  **Notes:**
2770
2293
 
2771
- - Terminal-specific hooks (`useInput`, `useStdin`, `useStdout`, `useStderr`, `useWindowSize`, `useApp`, `useFocus`, `useFocusManager`) return default no-op values since there is no terminal session. They will not throw, but they will not function as in a live terminal.
2294
+ - Terminal-specific hooks (`useInput`, `useStdin`, `useStdout`, `useStderr`, `useApp`, `useFocus`, `useFocusManager`) return default no-op values since there is no terminal session. They will not throw, but they will not function as in a live terminal.
2772
2295
  - `useEffect` callbacks will execute during rendering (due to synchronous rendering mode), but state updates they trigger will not affect the returned output, which reflects the initial render.
2773
2296
  - `useLayoutEffect` callbacks fire synchronously during commit, so state updates they trigger **will** be reflected in the output.
2774
2297
  - The `<Static>` component is supported — its output is prepended to the dynamic output.
@@ -2832,7 +2355,6 @@ unmount();
2832
2355
  Returns a promise that settles when the app is unmounted.
2833
2356
 
2834
2357
  It resolves with the value passed to `exit(value)` and rejects with the error passed to `exit(error)`.
2835
- When `unmount()` is called manually, it settles after unmount-related stdout writes complete.
2836
2358
 
2837
2359
  ```jsx
2838
2360
  const {unmount, waitUntilExit} = render(<MyApp />);
@@ -2842,26 +2364,11 @@ setTimeout(unmount, 1000);
2842
2364
  await waitUntilExit(); // resolves after `unmount()` is called
2843
2365
  ```
2844
2366
 
2845
- ##### waitUntilRenderFlush()
2846
-
2847
- Returns a promise that settles after pending render output is flushed to stdout.
2848
-
2849
- Useful when you need to run code only after a frame is written:
2850
-
2851
- ```jsx
2852
- const {rerender, waitUntilRenderFlush} = render(<MyApp step="loading" />);
2853
-
2854
- rerender(<MyApp step="ready" />);
2855
- await waitUntilRenderFlush(); // output for "ready" is flushed
2856
-
2857
- runNextCommand();
2858
- ```
2859
-
2860
2367
  ##### cleanup()
2861
2368
 
2862
- Unmount the current app and delete the internal Ink instance associated with the current `stdout`.
2369
+ Delete the internal Ink instance associated with the current `stdout`.
2863
2370
  This is mostly useful for advanced cases (for example, tests) where you need `render()` to create a fresh instance for the same stream.
2864
- Unlike deleting the internal instance directly, this also tears down terminal state such as the alternate screen.
2371
+ This does not unmount the current app.
2865
2372
 
2866
2373
  ##### clear()
2867
2374
 
@@ -2878,8 +2385,7 @@ Measure the dimensions of a particular `<Box>` element.
2878
2385
  Returns an object with `width` and `height` properties.
2879
2386
  This function is useful when your component needs to know the amount of available space it has. You can use it when you need to change the layout based on the length of its content.
2880
2387
 
2881
- > [!NOTE]
2882
- > `measureElement()` returns `{width: 0, height: 0}` when called during render (before layout is calculated). Call it from post-render code, such as `useEffect`, `useLayoutEffect`, input handlers, or timer callbacks. When content changes, pass the relevant dependency to your effect so it re-measures after each update.
2388
+ **Note:** `measureElement()` returns correct results only after the initial render, when the layout has been calculated. Until then, `width` and `height` equal zero. It's recommended to call `measureElement()` in a `useEffect` hook, which fires after the component has rendered.
2883
2389
 
2884
2390
  ##### ref
2885
2391
 
@@ -2948,8 +2454,7 @@ npx react-devtools
2948
2454
  After it starts, you should see the component tree of your CLI.
2949
2455
  You can even inspect and change the props of components, and see the results immediately in the CLI, without restarting it.
2950
2456
 
2951
- > [!NOTE]
2952
- > You must manually quit your CLI via <kbd>Ctrl</kbd>+<kbd>C</kbd> after you're done testing.
2457
+ **Note**: You must manually quit your CLI via <kbd>Ctrl</kbd>+<kbd>C</kbd> after you're done testing.
2953
2458
 
2954
2459
  ## Screen Reader Support
2955
2460
 
@@ -3005,49 +2510,38 @@ Default: `false`
3005
2510
 
3006
2511
  Hide the element from screen readers.
3007
2512
 
3008
- ### `aria-role`
2513
+ ##### aria-role
3009
2514
 
3010
2515
  Type: `string`
3011
2516
 
3012
2517
  The role of the element.
3013
2518
 
3014
2519
  Supported values:
3015
-
3016
2520
  - `button`
3017
2521
  - `checkbox`
3018
- - `combobox`
2522
+ - `radio`
2523
+ - `radiogroup`
3019
2524
  - `list`
3020
- - `listbox`
3021
2525
  - `listitem`
3022
2526
  - `menu`
3023
2527
  - `menuitem`
3024
- - `option`
3025
2528
  - `progressbar`
3026
- - `radio`
3027
- - `radiogroup`
3028
2529
  - `tab`
3029
2530
  - `tablist`
3030
- - `table`
3031
- - `textbox`
3032
2531
  - `timer`
3033
2532
  - `toolbar`
2533
+ - `table`
3034
2534
 
3035
- ### `aria-state`
2535
+ ##### aria-state
3036
2536
 
3037
2537
  Type: `object`
3038
2538
 
3039
2539
  The state of the element.
3040
2540
 
3041
2541
  Supported values:
3042
-
3043
- - `busy` (boolean)
3044
2542
  - `checked` (boolean)
3045
2543
  - `disabled` (boolean)
3046
2544
  - `expanded` (boolean)
3047
- - `multiline` (boolean)
3048
- - `multiselectable` (boolean)
3049
- - `readonly` (boolean)
3050
- - `required` (boolean)
3051
2545
  - `selected` (boolean)
3052
2546
 
3053
2547
  ## Creating Components