@jrichman/ink 6.3.1 → 6.4.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.
Files changed (44) hide show
  1. package/build/components/Box.d.ts +26 -2
  2. package/build/components/Box.js +8 -3
  3. package/build/components/Box.js.map +1 -1
  4. package/build/devtools.d.ts +1 -1
  5. package/build/devtools.js +10 -1
  6. package/build/devtools.js.map +1 -1
  7. package/build/dom.d.ts +12 -6
  8. package/build/dom.js +25 -6
  9. package/build/dom.js.map +1 -1
  10. package/build/index.d.ts +3 -1
  11. package/build/index.js +3 -1
  12. package/build/index.js.map +1 -1
  13. package/build/ink.d.ts +14 -1
  14. package/build/ink.js +39 -12
  15. package/build/ink.js.map +1 -1
  16. package/build/measure-element.d.ts +0 -8
  17. package/build/measure-element.js +0 -50
  18. package/build/measure-element.js.map +1 -1
  19. package/build/measure-text.d.ts +11 -3
  20. package/build/measure-text.js +161 -13
  21. package/build/measure-text.js.map +1 -1
  22. package/build/output.d.ts +8 -2
  23. package/build/output.js +111 -61
  24. package/build/output.js.map +1 -1
  25. package/build/reconciler.js +24 -0
  26. package/build/reconciler.js.map +1 -1
  27. package/build/render-background.js +1 -1
  28. package/build/render-background.js.map +1 -1
  29. package/build/render-border.js +13 -5
  30. package/build/render-border.js.map +1 -1
  31. package/build/render-node-to-output.d.ts +2 -0
  32. package/build/render-node-to-output.js +233 -54
  33. package/build/render-node-to-output.js.map +1 -1
  34. package/build/render.d.ts +7 -3
  35. package/build/render.js +1 -0
  36. package/build/render.js.map +1 -1
  37. package/build/scroll.d.ts +3 -0
  38. package/build/scroll.js +58 -1
  39. package/build/scroll.js.map +1 -1
  40. package/build/wrap-text.d.ts +6 -3
  41. package/build/wrap-text.js +118 -29
  42. package/build/wrap-text.js.map +1 -1
  43. package/package.json +5 -6
  44. package/readme.md +15 -1
@@ -1,31 +1,120 @@
1
- import wrapAnsi from 'wrap-ansi';
2
- import cliTruncate from 'cli-truncate';
3
- const cache = {};
4
- const wrapText = (text, maxWidth, wrapType) => {
5
- const cacheKey = text + String(maxWidth) + String(wrapType);
6
- const cachedText = cache[cacheKey];
7
- if (cachedText) {
8
- return cachedText;
9
- }
10
- let wrappedText = text;
11
- if (wrapType === 'wrap') {
12
- wrappedText = wrapAnsi(text, maxWidth, {
13
- trim: false,
14
- hard: true,
15
- });
16
- }
17
- if (wrapType.startsWith('truncate')) {
18
- let position = 'end';
19
- if (wrapType === 'truncate-middle') {
20
- position = 'middle';
21
- }
22
- if (wrapType === 'truncate-start') {
23
- position = 'start';
24
- }
25
- wrappedText = cliTruncate(text, maxWidth, { position });
26
- }
27
- cache[cacheKey] = wrappedText;
28
- return wrappedText;
1
+ import { inkCharacterWidth, styledCharsWidth } from './measure-text.js';
2
+ export const sliceStyledChars = (styledChars, begin, end) => {
3
+ let width = 0;
4
+ const result = [];
5
+ for (const char of styledChars) {
6
+ const charWidth = inkCharacterWidth(char.value);
7
+ const charStart = width;
8
+ const charEnd = width + charWidth;
9
+ if (end !== undefined && charEnd > end) {
10
+ break;
11
+ }
12
+ if (charStart >= begin) {
13
+ result.push(char);
14
+ }
15
+ width += charWidth;
16
+ }
17
+ return result;
18
+ };
19
+ export const truncateStyledChars = (styledChars, columns, options = {}) => {
20
+ const { position = 'end' } = options;
21
+ const truncationCharacter = '…';
22
+ const truncationStyledChar = {
23
+ type: 'char',
24
+ value: truncationCharacter,
25
+ fullWidth: false,
26
+ styles: [],
27
+ };
28
+ if (columns < 1) {
29
+ return [];
30
+ }
31
+ if (columns === 1) {
32
+ return [truncationStyledChar];
33
+ }
34
+ const textWidth = styledCharsWidth(styledChars);
35
+ if (textWidth <= columns) {
36
+ return styledChars;
37
+ }
38
+ const truncationWidth = inkCharacterWidth(truncationCharacter);
39
+ if (position === 'start') {
40
+ const right = sliceStyledChars(styledChars, textWidth - columns + truncationWidth, textWidth);
41
+ return [truncationStyledChar, ...right];
42
+ }
43
+ if (position === 'middle') {
44
+ const leftWidth = Math.ceil(columns / 2);
45
+ const rightWidth = columns - leftWidth;
46
+ const left = sliceStyledChars(styledChars, 0, leftWidth - truncationWidth);
47
+ const right = sliceStyledChars(styledChars, textWidth - rightWidth, textWidth);
48
+ return [...left, truncationStyledChar, ...right];
49
+ }
50
+ const left = sliceStyledChars(styledChars, 0, columns - truncationWidth);
51
+ return [...left, truncationStyledChar];
52
+ };
53
+ const wrapWord = (rows, word, columns) => {
54
+ let currentLine = rows.at(-1);
55
+ let visible = styledCharsWidth(currentLine);
56
+ for (const character of word) {
57
+ const characterLength = inkCharacterWidth(character.value);
58
+ if (visible + characterLength > columns && visible > 0) {
59
+ rows.push([]);
60
+ currentLine = rows.at(-1);
61
+ visible = 0;
62
+ }
63
+ currentLine.push(character);
64
+ visible += characterLength;
65
+ }
66
+ };
67
+ export const wrapStyledChars = (styledChars, columns) => {
68
+ const rows = [[]];
69
+ const words = [];
70
+ let currentWord = [];
71
+ for (const char of styledChars) {
72
+ if (char.value === ' ') {
73
+ if (currentWord.length > 0) {
74
+ words.push(currentWord);
75
+ }
76
+ currentWord = [];
77
+ }
78
+ else {
79
+ currentWord.push(char);
80
+ }
81
+ }
82
+ if (currentWord.length > 0) {
83
+ words.push(currentWord);
84
+ }
85
+ const space = {
86
+ type: 'char',
87
+ value: ' ',
88
+ fullWidth: false,
89
+ styles: [],
90
+ };
91
+ for (const [index, word] of words.entries()) {
92
+ const wordWidth = styledCharsWidth(word);
93
+ let rowWidth = styledCharsWidth(rows.at(-1));
94
+ if (index > 0) {
95
+ rows.at(-1).push(space);
96
+ rowWidth++;
97
+ }
98
+ if (wordWidth > columns) {
99
+ if (index > 0) {
100
+ rows[rows.length - 1] = rows.at(-1).slice(0, -1);
101
+ if (rows.at(-1).length > 0) {
102
+ rows.push([]);
103
+ }
104
+ }
105
+ wrapWord(rows, word, columns);
106
+ continue;
107
+ }
108
+ if (rowWidth + wordWidth > columns && rowWidth > 0) {
109
+ if (index > 0) {
110
+ rows[rows.length - 1] = rows.at(-1).slice(0, -1);
111
+ }
112
+ rows.push(word);
113
+ }
114
+ else {
115
+ rows.at(-1).push(...word);
116
+ }
117
+ }
118
+ return rows;
29
119
  };
30
- export default wrapText;
31
120
  //# sourceMappingURL=wrap-text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrap-text.js","sourceRoot":"","sources":["../src/wrap-text.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,WAAW,MAAM,cAAc,CAAC;AAGvC,MAAM,KAAK,GAA2B,EAAE,CAAC;AAEzC,MAAM,QAAQ,GAAG,CAChB,IAAY,EACZ,QAAgB,EAChB,QAA4B,EACnB,EAAE;IACX,MAAM,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,IAAI,WAAW,GAAG,IAAI,CAAC;IAEvB,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACzB,WAAW,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE;YACtC,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,IAAI;SACV,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,QAAS,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,IAAI,QAAQ,GAA+B,KAAK,CAAC;QAEjD,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YACpC,QAAQ,GAAG,QAAQ,CAAC;QACrB,CAAC;QAED,IAAI,QAAQ,KAAK,gBAAgB,EAAE,CAAC;YACnC,QAAQ,GAAG,OAAO,CAAC;QACpB,CAAC;QAED,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAC,QAAQ,EAAC,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC;IAE9B,OAAO,WAAW,CAAC;AACpB,CAAC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"wrap-text.js","sourceRoot":"","sources":["../src/wrap-text.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jrichman/ink",
3
- "version": "6.3.1",
4
- "description": "React for CLI local version for Gemini CLI",
3
+ "version": "6.4.0",
4
+ "description": "React for CLI",
5
5
  "license": "MIT",
6
6
  "repository": "jacob314/ink",
7
7
  "author": {
@@ -43,7 +43,7 @@
43
43
  "text"
44
44
  ],
45
45
  "dependencies": {
46
- "@alcalzone/ansi-tokenize": "^0.2.0",
46
+ "@alcalzone/ansi-tokenize": "^0.2.1",
47
47
  "ansi-escapes": "^7.0.0",
48
48
  "ansi-styles": "^6.2.1",
49
49
  "auto-bind": "^5.0.1",
@@ -62,7 +62,6 @@
62
62
  "stack-utils": "^2.0.6",
63
63
  "string-width": "^8.1.0",
64
64
  "type-fest": "^4.27.0",
65
- "widest-line": "^5.0.0",
66
65
  "wrap-ansi": "^9.0.0",
67
66
  "ws": "^8.18.0",
68
67
  "yoga-layout": "~3.2.1"
@@ -73,8 +72,8 @@
73
72
  "@sinonjs/fake-timers": "^14.0.0",
74
73
  "@types/ms": "^2.1.0",
75
74
  "@types/node": "^22.15.24",
76
- "@types/react": "^19.1.8",
77
- "@types/react-reconciler": "^0.32.0",
75
+ "@types/react": "^19.1.5",
76
+ "@types/react-reconciler": "^0.32.2",
78
77
  "@types/signal-exit": "^3.0.0",
79
78
  "@types/sinon": "^17.0.3",
80
79
  "@types/stack-utils": "^2.0.2",
package/readme.md CHANGED
@@ -73,7 +73,6 @@ Feel free to play around with the code and fork this Repl at [https://repl.it/@v
73
73
 
74
74
  ## Who's Using Ink?
75
75
 
76
- - [Codex](https://github.com/openai/codex) - An agentic coding tool made by OpenAI.
77
76
  - [Claude Code](https://github.com/anthropics/claude-code) - An agentic coding tool made by Anthropic.
78
77
  - [Gemini CLI](https://github.com/google-gemini/gemini-cli) - An agentic coding tool made by Google.
79
78
  - [GitHub Copilot for CLI](https://githubnext.com/projects/copilot-cli) - Just say what you want the shell to do.
@@ -123,6 +122,7 @@ Feel free to play around with the code and fork this Repl at [https://repl.it/@v
123
122
  - [tweakcc](https://github.com/Piebald-AI/tweakcc) - Customize your Claude Code styling.
124
123
  - [argonaut](https://github.com/darksworm/argonaut) - Manage Argo CD resources.
125
124
  - [Qodo Command](https://github.com/qodo-ai/command) - Build, run, and manage AI agents.
125
+ - [Nanocoder](https://github.com/nano-collective/nanocoder) - A community-built, local-first AI coding agent with multi-provider support.
126
126
 
127
127
  *(PRs welcome. Append new entries at the end. Repos must have 100+ stars and showcase Ink beyond a basic list picker.)*
128
128
 
@@ -2009,6 +2009,13 @@ Default: `process.stdin`
2009
2009
 
2010
2010
  Input stream where app will listen for input.
2011
2011
 
2012
+ ###### stderr
2013
+
2014
+ Type: `stream.Writable`\
2015
+ Default: `process.stderr`
2016
+
2017
+ Error stream.
2018
+
2012
2019
  ###### exitOnCtrlC
2013
2020
 
2014
2021
  Type: `boolean`\
@@ -2028,6 +2035,13 @@ That way, both are visible and don't overlap each other.
2028
2035
 
2029
2036
  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.
2030
2037
 
2038
+ ###### onRender
2039
+
2040
+ Type: `({renderTime: number}) => void`\
2041
+ Default: `undefined`
2042
+
2043
+ Runs the given callback after each render and re-render with a metrics object.
2044
+
2031
2045
  ###### debug
2032
2046
 
2033
2047
  Type: `boolean`\