ink 6.8.0 → 7.0.0
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.
- package/build/components/AnimationContext.d.ts +9 -0
- package/build/components/AnimationContext.js +13 -0
- package/build/components/AnimationContext.js.map +1 -0
- package/build/components/App.d.ts +4 -1
- package/build/components/App.js +140 -20
- package/build/components/App.js.map +1 -1
- package/build/components/AppContext.d.ts +28 -2
- package/build/components/AppContext.js +2 -1
- package/build/components/AppContext.js.map +1 -1
- package/build/components/Box.d.ts +16 -3
- package/build/components/ErrorBoundary.d.ts +2 -2
- package/build/components/ErrorOverview.js +6 -6
- package/build/components/ErrorOverview.js.map +1 -1
- package/build/components/Static.js.map +1 -1
- package/build/components/StdinContext.d.ts +7 -1
- package/build/components/StdinContext.js +1 -0
- package/build/components/StdinContext.js.map +1 -1
- package/build/components/Text.d.ts +1 -1
- package/build/components/Text.js +1 -1
- package/build/components/Text.js.map +1 -1
- package/build/components/Transform.d.ts +1 -1
- package/build/devtools-window-polyfill.js +7 -4
- package/build/devtools-window-polyfill.js.map +1 -1
- package/build/devtools.js +31 -6
- package/build/devtools.js.map +1 -1
- package/build/dom.d.ts +5 -1
- package/build/dom.js +20 -1
- package/build/dom.js.map +1 -1
- package/build/hooks/use-animation.d.ts +49 -0
- package/build/hooks/use-animation.js +87 -0
- package/build/hooks/use-animation.js.map +1 -0
- package/build/hooks/use-app.d.ts +5 -2
- package/build/hooks/use-app.js +1 -1
- package/build/hooks/use-box-metrics.d.ts +59 -0
- package/build/hooks/use-box-metrics.js +88 -0
- package/build/hooks/use-box-metrics.js.map +1 -0
- package/build/hooks/use-cursor.d.ts +1 -1
- package/build/hooks/use-cursor.js +1 -1
- package/build/hooks/use-focus-manager.d.ts +17 -2
- package/build/hooks/use-focus-manager.js +2 -1
- package/build/hooks/use-focus-manager.js.map +1 -1
- package/build/hooks/use-focus.d.ts +2 -1
- package/build/hooks/use-focus.js +5 -4
- package/build/hooks/use-focus.js.map +1 -1
- package/build/hooks/use-input.d.ts +2 -1
- package/build/hooks/use-input.js +82 -80
- package/build/hooks/use-input.js.map +1 -1
- package/build/hooks/use-is-screen-reader-enabled.d.ts +2 -1
- package/build/hooks/use-is-screen-reader-enabled.js +2 -1
- package/build/hooks/use-is-screen-reader-enabled.js.map +1 -1
- package/build/hooks/use-paste.d.ts +35 -0
- package/build/hooks/use-paste.js +62 -0
- package/build/hooks/use-paste.js.map +1 -0
- package/build/hooks/use-stderr.d.ts +1 -1
- package/build/hooks/use-stderr.js +1 -1
- package/build/hooks/use-stdin.d.ts +4 -2
- package/build/hooks/use-stdin.js +2 -1
- package/build/hooks/use-stdin.js.map +1 -1
- package/build/hooks/use-stdout.d.ts +1 -1
- package/build/hooks/use-stdout.js +1 -1
- package/build/hooks/use-window-size.d.ts +18 -0
- package/build/hooks/use-window-size.js +22 -0
- package/build/hooks/use-window-size.js.map +1 -0
- package/build/index.d.ts +8 -1
- package/build/index.js +4 -0
- package/build/index.js.map +1 -1
- package/build/ink.d.ts +48 -3
- package/build/ink.js +325 -155
- package/build/ink.js.map +1 -1
- package/build/input-parser.d.ts +4 -1
- package/build/input-parser.js +70 -30
- package/build/input-parser.js.map +1 -1
- package/build/log-update.d.ts +1 -0
- package/build/log-update.js +13 -1
- package/build/log-update.js.map +1 -1
- package/build/measure-element.d.ts +4 -0
- package/build/measure-element.js +4 -0
- package/build/measure-element.js.map +1 -1
- package/build/output.js +25 -0
- package/build/output.js.map +1 -1
- package/build/parse-keypress.d.ts +1 -3
- package/build/parse-keypress.js +19 -17
- package/build/parse-keypress.js.map +1 -1
- package/build/reconciler.js +46 -27
- package/build/reconciler.js.map +1 -1
- package/build/render-border.js +29 -18
- package/build/render-border.js.map +1 -1
- package/build/render-to-string.js +2 -1
- package/build/render-to-string.js.map +1 -1
- package/build/render.d.ts +57 -2
- package/build/render.js +18 -11
- package/build/render.js.map +1 -1
- package/build/styles.d.ts +78 -16
- package/build/styles.js +102 -31
- package/build/styles.js.map +1 -1
- package/build/utils.d.ts +9 -2
- package/build/utils.js +18 -3
- package/build/utils.js.map +1 -1
- package/build/wrap-text.js +7 -0
- package/build/wrap-text.js.map +1 -1
- package/build/write-synchronized.d.ts +1 -1
- package/build/write-synchronized.js +4 -2
- package/build/write-synchronized.js.map +1 -1
- package/package.json +34 -98
- package/readme.md +554 -48
- package/build/apply-styles.js +0 -175
- package/build/build-layout.js +0 -77
- package/build/calculate-wrapped-text.js +0 -53
- package/build/components/Color.js +0 -62
- package/build/components/Cursor.d.ts +0 -83
- package/build/components/Cursor.js +0 -53
- package/build/components/Cursor.js.map +0 -1
- package/build/experimental/apply-style.js +0 -140
- package/build/experimental/dom.js +0 -123
- package/build/experimental/output.js +0 -91
- package/build/experimental/reconciler.js +0 -141
- package/build/experimental/renderer.js +0 -81
- package/build/hooks/useInput.js +0 -38
- package/build/instance.js +0 -205
- package/build/layout.d.ts +0 -7
- package/build/layout.js +0 -33
- package/build/layout.js.map +0 -1
- package/build/options.d.ts +0 -52
- package/build/options.js +0 -2
- package/build/options.js.map +0 -1
- package/build/screen-reader-update.d.ts +0 -13
- package/build/screen-reader-update.js +0 -38
- package/build/screen-reader-update.js.map +0 -1
package/readme.md
CHANGED
|
@@ -24,6 +24,8 @@ 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
|
+
|
|
27
29
|
---
|
|
28
30
|
|
|
29
31
|
<div align="center">
|
|
@@ -42,6 +44,9 @@ Only Ink's methods are documented in this readme.
|
|
|
42
44
|
npm install ink react
|
|
43
45
|
```
|
|
44
46
|
|
|
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
|
+
|
|
45
50
|
## Usage
|
|
46
51
|
|
|
47
52
|
```jsx
|
|
@@ -127,7 +132,7 @@ render(<Counter />);
|
|
|
127
132
|
- [ElevenLabs CLI](https://github.com/elevenlabs/cli) - ElevenLabs agents client.
|
|
128
133
|
- [SSH AI Chat](https://github.com/miantiao-me/ssh-ai-chat) - Chat with AI over SSH.
|
|
129
134
|
|
|
130
|
-
|
|
135
|
+
_(PRs welcome. Append new entries at the end. Repos must have 100+ stars and showcase Ink beyond a basic list picker.)_
|
|
131
136
|
|
|
132
137
|
## Contents
|
|
133
138
|
|
|
@@ -142,13 +147,17 @@ render(<Counter />);
|
|
|
142
147
|
- [`<Transform>`](#transform)
|
|
143
148
|
- [Hooks](#hooks)
|
|
144
149
|
- [`useInput`](#useinputinputhandler-options)
|
|
150
|
+
- [`usePaste`](#usepastehandler-options)
|
|
145
151
|
- [`useApp`](#useapp)
|
|
146
152
|
- [`useStdin`](#usestdin)
|
|
147
153
|
- [`useStdout`](#usestdout)
|
|
154
|
+
- [`useBoxMetrics`](#useboxmetricsref)
|
|
148
155
|
- [`useStderr`](#usestderr)
|
|
156
|
+
- [`useWindowSize`](#usewindowsize)
|
|
149
157
|
- [`useFocus`](#usefocusoptions)
|
|
150
158
|
- [`useFocusManager`](#usefocusmanager)
|
|
151
159
|
- [`useCursor`](#usecursor)
|
|
160
|
+
- [`useAnimation`](#useanimationoptions)
|
|
152
161
|
- [API](#api)
|
|
153
162
|
- [Testing](#testing)
|
|
154
163
|
- [Using React Devtools](#using-react-devtools)
|
|
@@ -267,7 +276,8 @@ const Example = () => (
|
|
|
267
276
|
render(<Example />);
|
|
268
277
|
```
|
|
269
278
|
|
|
270
|
-
|
|
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>`.
|
|
271
281
|
|
|
272
282
|
#### color
|
|
273
283
|
|
|
@@ -359,11 +369,12 @@ Invert background and foreground colors.
|
|
|
359
369
|
#### wrap
|
|
360
370
|
|
|
361
371
|
Type: `string`\
|
|
362
|
-
Allowed values: `wrap` `truncate` `truncate-start` `truncate-middle` `truncate-end`\
|
|
372
|
+
Allowed values: `wrap` `hard` `truncate` `truncate-start` `truncate-middle` `truncate-end`\
|
|
363
373
|
Default: `wrap`
|
|
364
374
|
|
|
365
375
|
This property tells Ink to wrap or truncate text if its width is larger than the container.
|
|
366
376
|
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.
|
|
367
378
|
If `truncate-*` is passed, Ink will truncate text instead, resulting in one line of text with the rest cut off.
|
|
368
379
|
|
|
369
380
|
```jsx
|
|
@@ -372,6 +383,11 @@ If `truncate-*` is passed, Ink will truncate text instead, resulting in one line
|
|
|
372
383
|
</Box>
|
|
373
384
|
//=> 'Hello\nWorld'
|
|
374
385
|
|
|
386
|
+
<Box width={7}>
|
|
387
|
+
<Text wrap="hard">Hello World</Text>
|
|
388
|
+
</Box>
|
|
389
|
+
//=> 'Hello W\norld'
|
|
390
|
+
|
|
375
391
|
// `truncate` is an alias to `truncate-end`
|
|
376
392
|
<Box width={7}>
|
|
377
393
|
<Text wrap="truncate">Hello World</Text>
|
|
@@ -465,11 +481,33 @@ Percentages aren't supported yet; see https://github.com/facebook/yoga/issues/87
|
|
|
465
481
|
|
|
466
482
|
##### minHeight
|
|
467
483
|
|
|
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
|
+
|
|
468
491
|
Type: `number`
|
|
469
492
|
|
|
470
|
-
Sets a
|
|
493
|
+
Sets a maximum width of the element.
|
|
471
494
|
Percentages aren't supported yet; see https://github.com/facebook/yoga/issues/872.
|
|
472
495
|
|
|
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
|
+
|
|
473
511
|
#### Padding
|
|
474
512
|
|
|
475
513
|
##### paddingTop
|
|
@@ -774,7 +812,7 @@ See [flex-wrap](https://css-tricks.com/almanac/properties/f/flex-wrap/).
|
|
|
774
812
|
##### alignItems
|
|
775
813
|
|
|
776
814
|
Type: `string`\
|
|
777
|
-
Allowed values: `flex-start` `center` `flex-end`
|
|
815
|
+
Allowed values: `flex-start` `center` `flex-end` `stretch` `baseline`
|
|
778
816
|
|
|
779
817
|
See [align-items](https://css-tricks.com/almanac/properties/a/align-items/).
|
|
780
818
|
|
|
@@ -832,7 +870,7 @@ See [align-items](https://css-tricks.com/almanac/properties/a/align-items/).
|
|
|
832
870
|
|
|
833
871
|
Type: `string`\
|
|
834
872
|
Default: `auto`\
|
|
835
|
-
Allowed values: `auto` `flex-start` `center` `flex-end`
|
|
873
|
+
Allowed values: `auto` `flex-start` `center` `flex-end` `stretch` `baseline`
|
|
836
874
|
|
|
837
875
|
See [align-self](https://css-tricks.com/almanac/properties/a/align-self/).
|
|
838
876
|
|
|
@@ -865,6 +903,16 @@ See [align-self](https://css-tricks.com/almanac/properties/a/align-self/).
|
|
|
865
903
|
// X
|
|
866
904
|
```
|
|
867
905
|
|
|
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
|
+
|
|
868
916
|
##### justifyContent
|
|
869
917
|
|
|
870
918
|
Type: `string`\
|
|
@@ -907,6 +955,46 @@ See [justify-content](https://css-tricks.com/almanac/properties/j/justify-conten
|
|
|
907
955
|
// [ X Y ]
|
|
908
956
|
```
|
|
909
957
|
|
|
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
|
+
|
|
910
998
|
#### Visibility
|
|
911
999
|
|
|
912
1000
|
##### display
|
|
@@ -1002,7 +1090,7 @@ Alternatively, pass a custom border style like so:
|
|
|
1002
1090
|
bottomLeft: '↗',
|
|
1003
1091
|
bottom: '↑',
|
|
1004
1092
|
bottomRight: '↖',
|
|
1005
|
-
right: '←'
|
|
1093
|
+
right: '←',
|
|
1006
1094
|
}}
|
|
1007
1095
|
>
|
|
1008
1096
|
<Text>Custom</Text>
|
|
@@ -1144,6 +1232,76 @@ Dim the right border color.
|
|
|
1144
1232
|
</Box>
|
|
1145
1233
|
```
|
|
1146
1234
|
|
|
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
|
+
|
|
1147
1305
|
##### borderTop
|
|
1148
1306
|
|
|
1149
1307
|
Type: `boolean`\
|
|
@@ -1188,11 +1346,23 @@ Accepts the same values as [`color`](#color) in the `<Text>` component.
|
|
|
1188
1346
|
<Text>Red background</Text>
|
|
1189
1347
|
</Box>
|
|
1190
1348
|
|
|
1191
|
-
<Box
|
|
1349
|
+
<Box
|
|
1350
|
+
backgroundColor="#FF8800"
|
|
1351
|
+
width={20}
|
|
1352
|
+
height={3}
|
|
1353
|
+
marginTop={1}
|
|
1354
|
+
alignSelf="flex-start"
|
|
1355
|
+
>
|
|
1192
1356
|
<Text>Orange background</Text>
|
|
1193
1357
|
</Box>
|
|
1194
1358
|
|
|
1195
|
-
<Box
|
|
1359
|
+
<Box
|
|
1360
|
+
backgroundColor="rgb(0, 255, 0)"
|
|
1361
|
+
width={20}
|
|
1362
|
+
height={3}
|
|
1363
|
+
marginTop={1}
|
|
1364
|
+
alignSelf="flex-start"
|
|
1365
|
+
>
|
|
1196
1366
|
<Text>Green background</Text>
|
|
1197
1367
|
</Box>
|
|
1198
1368
|
</Box>
|
|
@@ -1211,7 +1381,12 @@ The background color fills the entire `<Box>` area and is inherited by child `<T
|
|
|
1211
1381
|
Background colors work with borders and padding:
|
|
1212
1382
|
|
|
1213
1383
|
```jsx
|
|
1214
|
-
<Box
|
|
1384
|
+
<Box
|
|
1385
|
+
backgroundColor="cyan"
|
|
1386
|
+
borderStyle="round"
|
|
1387
|
+
padding={1}
|
|
1388
|
+
alignSelf="flex-start"
|
|
1389
|
+
>
|
|
1215
1390
|
<Text>Background with border and padding</Text>
|
|
1216
1391
|
</Box>
|
|
1217
1392
|
```
|
|
@@ -1320,8 +1495,8 @@ const Example = () => {
|
|
|
1320
1495
|
...previousTests,
|
|
1321
1496
|
{
|
|
1322
1497
|
id: previousTests.length,
|
|
1323
|
-
title: `Test #${previousTests.length + 1}
|
|
1324
|
-
}
|
|
1498
|
+
title: `Test #${previousTests.length + 1}`,
|
|
1499
|
+
},
|
|
1325
1500
|
]);
|
|
1326
1501
|
|
|
1327
1502
|
timer = setTimeout(run, 100);
|
|
@@ -1357,9 +1532,8 @@ const Example = () => {
|
|
|
1357
1532
|
render(<Example />);
|
|
1358
1533
|
```
|
|
1359
1534
|
|
|
1360
|
-
|
|
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.
|
|
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.
|
|
1363
1537
|
|
|
1364
1538
|
See [examples/static](examples/static/static.tsx) for an example usage of `<Static>` component.
|
|
1365
1539
|
|
|
@@ -1414,7 +1588,11 @@ For example, you might want to apply a [gradient to text](https://github.com/sin
|
|
|
1414
1588
|
These use cases can't accept React nodes as input; they expect a string.
|
|
1415
1589
|
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.
|
|
1416
1590
|
|
|
1417
|
-
|
|
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)).
|
|
1418
1596
|
|
|
1419
1597
|
```jsx
|
|
1420
1598
|
import {render, Transform} from 'ink';
|
|
@@ -1455,11 +1633,7 @@ const text =
|
|
|
1455
1633
|
'of my hands only. I lived there two years and two months. At ' +
|
|
1456
1634
|
'present I am a sojourner in civilized life again.';
|
|
1457
1635
|
|
|
1458
|
-
render(
|
|
1459
|
-
<HangingIndent indent={4}>
|
|
1460
|
-
{text}
|
|
1461
|
-
</HangingIndent>
|
|
1462
|
-
);
|
|
1636
|
+
render(<HangingIndent indent={4}>{text}</HangingIndent>);
|
|
1463
1637
|
```
|
|
1464
1638
|
|
|
1465
1639
|
#### transform(outputLine, index)
|
|
@@ -1485,7 +1659,7 @@ The zero-indexed line number of the line that's currently being transformed.
|
|
|
1485
1659
|
|
|
1486
1660
|
### useInput(inputHandler, options?)
|
|
1487
1661
|
|
|
1488
|
-
|
|
1662
|
+
A React hook that returns `void` and handles user input.
|
|
1489
1663
|
It's a more convenient alternative to using `useStdin` and listening for `data` events.
|
|
1490
1664
|
The callback you pass to `useInput` is called for each character when the user enters any input.
|
|
1491
1665
|
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`.
|
|
@@ -1664,9 +1838,58 @@ Default: `true`
|
|
|
1664
1838
|
Enable or disable capturing of user input.
|
|
1665
1839
|
Useful when there are multiple `useInput` hooks used at once to avoid handling the same input several times.
|
|
1666
1840
|
|
|
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
|
+
|
|
1667
1890
|
### useApp()
|
|
1668
1891
|
|
|
1669
|
-
|
|
1892
|
+
A React hook that returns app lifecycle methods.
|
|
1670
1893
|
|
|
1671
1894
|
#### exit(errorOrResult?)
|
|
1672
1895
|
|
|
@@ -1678,12 +1901,14 @@ Exit (unmount) the whole Ink app.
|
|
|
1678
1901
|
|
|
1679
1902
|
Type: `Error | unknown`
|
|
1680
1903
|
|
|
1681
|
-
Optional value that controls how [`waitUntilExit`](waituntilexit) settles:
|
|
1904
|
+
Optional value that controls how [`waitUntilExit`](#waituntilexit) settles:
|
|
1905
|
+
|
|
1682
1906
|
- `exit()` resolves with `undefined`.
|
|
1683
1907
|
- `exit(error)` rejects when `error` is an `Error`.
|
|
1684
1908
|
- `exit(value)` resolves with `value`.
|
|
1685
1909
|
|
|
1686
1910
|
```js
|
|
1911
|
+
import {useEffect} from 'react';
|
|
1687
1912
|
import {useApp} from 'ink';
|
|
1688
1913
|
|
|
1689
1914
|
const Example = () => {
|
|
@@ -1694,15 +1919,39 @@ const Example = () => {
|
|
|
1694
1919
|
setTimeout(() => {
|
|
1695
1920
|
exit();
|
|
1696
1921
|
}, 5000);
|
|
1697
|
-
}, []);
|
|
1922
|
+
}, [exit]);
|
|
1698
1923
|
|
|
1699
1924
|
return …
|
|
1700
1925
|
};
|
|
1701
1926
|
```
|
|
1702
1927
|
|
|
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
|
+
|
|
1703
1952
|
### useStdin()
|
|
1704
1953
|
|
|
1705
|
-
|
|
1954
|
+
A React hook that returns the stdin stream and stdin-related utilities.
|
|
1706
1955
|
|
|
1707
1956
|
#### stdin
|
|
1708
1957
|
|
|
@@ -1776,7 +2025,7 @@ const Example = () => {
|
|
|
1776
2025
|
|
|
1777
2026
|
### useStdout()
|
|
1778
2027
|
|
|
1779
|
-
|
|
2028
|
+
A React hook that returns the stdout stream where Ink renders your app and stdout-related utilities.
|
|
1780
2029
|
|
|
1781
2030
|
#### stdout
|
|
1782
2031
|
|
|
@@ -1822,9 +2071,73 @@ const Example = () => {
|
|
|
1822
2071
|
|
|
1823
2072
|
See additional usage example in [examples/use-stdout](examples/use-stdout/use-stdout.tsx).
|
|
1824
2073
|
|
|
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
|
+
|
|
1825
2138
|
### useStderr()
|
|
1826
2139
|
|
|
1827
|
-
|
|
2140
|
+
A React hook that returns the stderr stream and stderr-related utilities.
|
|
1828
2141
|
|
|
1829
2142
|
#### stderr
|
|
1830
2143
|
|
|
@@ -1871,8 +2184,42 @@ const Example = () => {
|
|
|
1871
2184
|
};
|
|
1872
2185
|
```
|
|
1873
2186
|
|
|
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
|
+
|
|
1874
2220
|
### useFocus(options?)
|
|
1875
2221
|
|
|
2222
|
+
A React hook that returns focus state and focus controls for the current component.
|
|
1876
2223
|
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.
|
|
1877
2224
|
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.
|
|
1878
2225
|
This hook returns an object with an `isFocused` boolean property, which determines whether this component is focused.
|
|
@@ -1917,13 +2264,14 @@ See example in [examples/use-focus](examples/use-focus/use-focus.tsx) and [examp
|
|
|
1917
2264
|
|
|
1918
2265
|
### useFocusManager()
|
|
1919
2266
|
|
|
1920
|
-
|
|
2267
|
+
A React hook that returns methods to manage focus across focusable components.
|
|
1921
2268
|
|
|
1922
2269
|
#### enableFocus()
|
|
1923
2270
|
|
|
1924
2271
|
Enable focus management for all components.
|
|
1925
2272
|
|
|
1926
|
-
|
|
2273
|
+
> [!NOTE]
|
|
2274
|
+
> You don't need to call this method manually unless you've disabled focus management. Focus management is enabled by default.
|
|
1927
2275
|
|
|
1928
2276
|
```js
|
|
1929
2277
|
import {useFocusManager} from 'ink';
|
|
@@ -1964,7 +2312,8 @@ Switch focus to the next focusable component.
|
|
|
1964
2312
|
If there's no active component right now, focus will be given to the first focusable component.
|
|
1965
2313
|
If the active component is the last in the list of focusable components, focus will be switched to the first focusable component.
|
|
1966
2314
|
|
|
1967
|
-
|
|
2315
|
+
> [!NOTE]
|
|
2316
|
+
> Ink calls this method when user presses <kbd>Tab</kbd>.
|
|
1968
2317
|
|
|
1969
2318
|
```js
|
|
1970
2319
|
import {useFocusManager} from 'ink';
|
|
@@ -1986,7 +2335,8 @@ Switch focus to the previous focusable component.
|
|
|
1986
2335
|
If there's no active component right now, focus will be given to the first focusable component.
|
|
1987
2336
|
If the active component is the first in the list of focusable components, focus will be switched to the last focusable component.
|
|
1988
2337
|
|
|
1989
|
-
|
|
2338
|
+
> [!NOTE]
|
|
2339
|
+
> Ink calls this method when user presses <kbd>Shift</kbd>+<kbd>Tab</kbd>.
|
|
1990
2340
|
|
|
1991
2341
|
```js
|
|
1992
2342
|
import {useFocusManager} from 'ink';
|
|
@@ -2009,7 +2359,7 @@ const Example = () => {
|
|
|
2009
2359
|
Type: `string`
|
|
2010
2360
|
|
|
2011
2361
|
Switch focus to the component with the given [`id`](#id).
|
|
2012
|
-
If there's no component with that ID, focus
|
|
2362
|
+
If there's no component with that ID, focus is not changed.
|
|
2013
2363
|
|
|
2014
2364
|
```js
|
|
2015
2365
|
import {useFocusManager, useInput} from 'ink';
|
|
@@ -2028,9 +2378,26 @@ const Example = () => {
|
|
|
2028
2378
|
};
|
|
2029
2379
|
```
|
|
2030
2380
|
|
|
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
|
+
|
|
2031
2397
|
### useCursor()
|
|
2032
2398
|
|
|
2033
|
-
|
|
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.
|
|
2034
2401
|
|
|
2035
2402
|
```jsx
|
|
2036
2403
|
import {useState} from 'react';
|
|
@@ -2047,7 +2414,10 @@ const TextInput = () => {
|
|
|
2047
2414
|
return (
|
|
2048
2415
|
<Box flexDirection="column">
|
|
2049
2416
|
<Text>Type here:</Text>
|
|
2050
|
-
<Text>
|
|
2417
|
+
<Text>
|
|
2418
|
+
{prompt}
|
|
2419
|
+
{text}
|
|
2420
|
+
</Text>
|
|
2051
2421
|
</Box>
|
|
2052
2422
|
);
|
|
2053
2423
|
};
|
|
@@ -2079,7 +2449,8 @@ Row position from the top of the Ink output (0 = first line).
|
|
|
2079
2449
|
|
|
2080
2450
|
### useIsScreenReaderEnabled()
|
|
2081
2451
|
|
|
2082
|
-
|
|
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.
|
|
2083
2454
|
|
|
2084
2455
|
```jsx
|
|
2085
2456
|
import {useIsScreenReaderEnabled, Text} from 'ink';
|
|
@@ -2097,6 +2468,65 @@ const Example = () => {
|
|
|
2097
2468
|
};
|
|
2098
2469
|
```
|
|
2099
2470
|
|
|
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
|
+
|
|
2100
2530
|
## API
|
|
2101
2531
|
|
|
2102
2532
|
#### render(tree, options?)
|
|
@@ -2151,6 +2581,8 @@ Patch console methods to ensure console output doesn't mix with Ink's output.
|
|
|
2151
2581
|
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.
|
|
2152
2582
|
That way, both are visible and don't overlap each other.
|
|
2153
2583
|
|
|
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
|
+
|
|
2154
2586
|
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.
|
|
2155
2587
|
|
|
2156
2588
|
###### onRender
|
|
@@ -2158,7 +2590,9 @@ This functionality is powered by [patch-console](https://github.com/vadimdemedes
|
|
|
2158
2590
|
Type: `({renderTime: number}) => void`\
|
|
2159
2591
|
Default: `undefined`
|
|
2160
2592
|
|
|
2161
|
-
Runs the given callback after each render and re-render with
|
|
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).
|
|
2162
2596
|
|
|
2163
2597
|
###### isScreenReaderEnabled
|
|
2164
2598
|
|
|
@@ -2200,6 +2634,7 @@ Default: `false`
|
|
|
2200
2634
|
Enable React Concurrent Rendering mode.
|
|
2201
2635
|
|
|
2202
2636
|
When enabled:
|
|
2637
|
+
|
|
2203
2638
|
- Suspense boundaries work correctly with async data fetching
|
|
2204
2639
|
- `useTransition` and `useDeferredValue` hooks are fully functional
|
|
2205
2640
|
- Updates can be interrupted for higher priority work
|
|
@@ -2208,7 +2643,48 @@ When enabled:
|
|
|
2208
2643
|
render(<MyApp />, {concurrent: true});
|
|
2209
2644
|
```
|
|
2210
2645
|
|
|
2211
|
-
|
|
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
|
+
```
|
|
2212
2688
|
|
|
2213
2689
|
###### kittyKeyboard
|
|
2214
2690
|
|
|
@@ -2251,6 +2727,7 @@ Default: `['disambiguateEscapeCodes']`
|
|
|
2251
2727
|
Protocol flags to request from the terminal. Pass an array of flag name strings.
|
|
2252
2728
|
|
|
2253
2729
|
Available flags:
|
|
2730
|
+
|
|
2254
2731
|
- `'disambiguateEscapeCodes'` - Disambiguate escape codes
|
|
2255
2732
|
- `'reportEventTypes'` - Report key press, repeat, and release events
|
|
2256
2733
|
- `'reportAlternateKeys'` - Report alternate key encodings
|
|
@@ -2291,7 +2768,7 @@ console.log(output);
|
|
|
2291
2768
|
|
|
2292
2769
|
**Notes:**
|
|
2293
2770
|
|
|
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.
|
|
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.
|
|
2295
2772
|
- `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.
|
|
2296
2773
|
- `useLayoutEffect` callbacks fire synchronously during commit, so state updates they trigger **will** be reflected in the output.
|
|
2297
2774
|
- The `<Static>` component is supported — its output is prepended to the dynamic output.
|
|
@@ -2355,6 +2832,7 @@ unmount();
|
|
|
2355
2832
|
Returns a promise that settles when the app is unmounted.
|
|
2356
2833
|
|
|
2357
2834
|
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.
|
|
2358
2836
|
|
|
2359
2837
|
```jsx
|
|
2360
2838
|
const {unmount, waitUntilExit} = render(<MyApp />);
|
|
@@ -2364,11 +2842,26 @@ setTimeout(unmount, 1000);
|
|
|
2364
2842
|
await waitUntilExit(); // resolves after `unmount()` is called
|
|
2365
2843
|
```
|
|
2366
2844
|
|
|
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
|
+
|
|
2367
2860
|
##### cleanup()
|
|
2368
2861
|
|
|
2369
|
-
|
|
2862
|
+
Unmount the current app and delete the internal Ink instance associated with the current `stdout`.
|
|
2370
2863
|
This is mostly useful for advanced cases (for example, tests) where you need `render()` to create a fresh instance for the same stream.
|
|
2371
|
-
|
|
2864
|
+
Unlike deleting the internal instance directly, this also tears down terminal state such as the alternate screen.
|
|
2372
2865
|
|
|
2373
2866
|
##### clear()
|
|
2374
2867
|
|
|
@@ -2385,7 +2878,8 @@ Measure the dimensions of a particular `<Box>` element.
|
|
|
2385
2878
|
Returns an object with `width` and `height` properties.
|
|
2386
2879
|
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.
|
|
2387
2880
|
|
|
2388
|
-
|
|
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.
|
|
2389
2883
|
|
|
2390
2884
|
##### ref
|
|
2391
2885
|
|
|
@@ -2454,7 +2948,8 @@ npx react-devtools
|
|
|
2454
2948
|
After it starts, you should see the component tree of your CLI.
|
|
2455
2949
|
You can even inspect and change the props of components, and see the results immediately in the CLI, without restarting it.
|
|
2456
2950
|
|
|
2457
|
-
|
|
2951
|
+
> [!NOTE]
|
|
2952
|
+
> You must manually quit your CLI via <kbd>Ctrl</kbd>+<kbd>C</kbd> after you're done testing.
|
|
2458
2953
|
|
|
2459
2954
|
## Screen Reader Support
|
|
2460
2955
|
|
|
@@ -2510,38 +3005,49 @@ Default: `false`
|
|
|
2510
3005
|
|
|
2511
3006
|
Hide the element from screen readers.
|
|
2512
3007
|
|
|
2513
|
-
|
|
3008
|
+
### `aria-role`
|
|
2514
3009
|
|
|
2515
3010
|
Type: `string`
|
|
2516
3011
|
|
|
2517
3012
|
The role of the element.
|
|
2518
3013
|
|
|
2519
3014
|
Supported values:
|
|
3015
|
+
|
|
2520
3016
|
- `button`
|
|
2521
3017
|
- `checkbox`
|
|
2522
|
-
- `
|
|
2523
|
-
- `radiogroup`
|
|
3018
|
+
- `combobox`
|
|
2524
3019
|
- `list`
|
|
3020
|
+
- `listbox`
|
|
2525
3021
|
- `listitem`
|
|
2526
3022
|
- `menu`
|
|
2527
3023
|
- `menuitem`
|
|
3024
|
+
- `option`
|
|
2528
3025
|
- `progressbar`
|
|
3026
|
+
- `radio`
|
|
3027
|
+
- `radiogroup`
|
|
2529
3028
|
- `tab`
|
|
2530
3029
|
- `tablist`
|
|
3030
|
+
- `table`
|
|
3031
|
+
- `textbox`
|
|
2531
3032
|
- `timer`
|
|
2532
3033
|
- `toolbar`
|
|
2533
|
-
- `table`
|
|
2534
3034
|
|
|
2535
|
-
|
|
3035
|
+
### `aria-state`
|
|
2536
3036
|
|
|
2537
3037
|
Type: `object`
|
|
2538
3038
|
|
|
2539
3039
|
The state of the element.
|
|
2540
3040
|
|
|
2541
3041
|
Supported values:
|
|
3042
|
+
|
|
3043
|
+
- `busy` (boolean)
|
|
2542
3044
|
- `checked` (boolean)
|
|
2543
3045
|
- `disabled` (boolean)
|
|
2544
3046
|
- `expanded` (boolean)
|
|
3047
|
+
- `multiline` (boolean)
|
|
3048
|
+
- `multiselectable` (boolean)
|
|
3049
|
+
- `readonly` (boolean)
|
|
3050
|
+
- `required` (boolean)
|
|
2545
3051
|
- `selected` (boolean)
|
|
2546
3052
|
|
|
2547
3053
|
## Creating Components
|