@townco/ui 0.1.6 → 0.1.8

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 (255) hide show
  1. package/README.md +11 -11
  2. package/dist/core/hooks/index.d.ts +1 -0
  3. package/dist/core/hooks/index.js +1 -0
  4. package/dist/core/hooks/use-chat-input.d.ts +17 -17
  5. package/dist/core/hooks/use-chat-input.js +55 -64
  6. package/dist/core/hooks/use-chat-messages.d.ts +11 -11
  7. package/dist/core/hooks/use-chat-messages.js +114 -121
  8. package/dist/core/hooks/use-chat-session.d.ts +5 -5
  9. package/dist/core/hooks/use-chat-session.js +80 -78
  10. package/dist/core/hooks/use-media-query.d.ts +5 -5
  11. package/dist/core/hooks/use-media-query.js +42 -38
  12. package/dist/core/index.d.ts +1 -1
  13. package/dist/core/index.js +1 -1
  14. package/dist/core/schemas/chat.d.ts +56 -83
  15. package/dist/core/schemas/chat.js +25 -27
  16. package/dist/core/store/chat-store.d.ts +22 -28
  17. package/dist/core/store/chat-store.js +50 -59
  18. package/dist/gui/components/Button.d.ts +7 -23
  19. package/dist/gui/components/Button.js +27 -40
  20. package/dist/gui/components/Card.d.ts +7 -26
  21. package/dist/gui/components/Card.js +8 -54
  22. package/dist/gui/components/ChatHeader.d.ts +31 -58
  23. package/dist/gui/components/ChatHeader.js +68 -171
  24. package/dist/gui/components/ChatInput.d.ts +54 -58
  25. package/dist/gui/components/ChatInput.js +207 -194
  26. package/dist/gui/components/ChatInputCommandMenu.d.ts +20 -0
  27. package/dist/gui/components/ChatInputCommandMenu.js +62 -0
  28. package/dist/gui/components/ChatLayout.d.ts +41 -71
  29. package/dist/gui/components/ChatLayout.js +87 -214
  30. package/dist/gui/components/ChatPanelTabContent.d.ts +9 -18
  31. package/dist/gui/components/ChatPanelTabContent.js +10 -88
  32. package/dist/gui/components/ChatSecondaryPanel.d.ts +11 -14
  33. package/dist/gui/components/ChatSecondaryPanel.js +38 -115
  34. package/dist/gui/components/ChatSidebar.d.ts +13 -26
  35. package/dist/gui/components/ChatSidebar.js +14 -48
  36. package/dist/gui/components/ChatStatus.d.ts +2 -4
  37. package/dist/gui/components/ChatStatus.js +34 -45
  38. package/dist/gui/components/Conversation.d.ts +14 -17
  39. package/dist/gui/components/Conversation.js +83 -143
  40. package/dist/gui/components/Dialog.d.ts +11 -57
  41. package/dist/gui/components/Dialog.js +8 -84
  42. package/dist/gui/components/DropdownMenu.d.ts +20 -101
  43. package/dist/gui/components/DropdownMenu.js +14 -161
  44. package/dist/gui/components/HeightTransition.d.ts +7 -12
  45. package/dist/gui/components/HeightTransition.js +77 -88
  46. package/dist/gui/components/Input.d.ts +6 -13
  47. package/dist/gui/components/Input.js +16 -27
  48. package/dist/gui/components/Label.d.ts +1 -7
  49. package/dist/gui/components/Label.js +2 -12
  50. package/dist/gui/components/MarkdownRenderer.d.ts +4 -6
  51. package/dist/gui/components/MarkdownRenderer.js +81 -178
  52. package/dist/gui/components/Message.d.ts +22 -25
  53. package/dist/gui/components/Message.js +97 -44
  54. package/dist/gui/components/MessageContent.d.ts +22 -29
  55. package/dist/gui/components/MessageContent.js +85 -157
  56. package/dist/gui/components/Reasoning.d.ts +24 -30
  57. package/dist/gui/components/Reasoning.js +60 -187
  58. package/dist/gui/components/Response.d.ts +9 -11
  59. package/dist/gui/components/Response.js +90 -229
  60. package/dist/gui/components/Select.d.ts +10 -69
  61. package/dist/gui/components/Select.js +12 -118
  62. package/dist/gui/components/Sonner.d.ts +1 -3
  63. package/dist/gui/components/Sonner.js +18 -29
  64. package/dist/gui/components/Tabs.d.ts +4 -24
  65. package/dist/gui/components/Tabs.js +4 -32
  66. package/dist/gui/components/Task.d.ts +24 -28
  67. package/dist/gui/components/Task.js +31 -164
  68. package/dist/gui/components/Textarea.d.ts +7 -15
  69. package/dist/gui/components/Textarea.js +46 -63
  70. package/dist/gui/components/ThinkingBlock.d.ts +10 -20
  71. package/dist/gui/components/ThinkingBlock.js +35 -134
  72. package/dist/gui/components/TodoList.d.ts +10 -12
  73. package/dist/gui/components/TodoList.js +7 -22
  74. package/dist/gui/components/TodoListItem.d.ts +6 -9
  75. package/dist/gui/components/TodoListItem.js +4 -18
  76. package/dist/gui/components/index.d.ts +16 -59
  77. package/dist/gui/components/index.js +18 -42
  78. package/dist/gui/lib/utils.js +1 -1
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.js +1 -1
  81. package/dist/index.test.js +1 -0
  82. package/dist/sdk/client/acp-client.d.ts +76 -88
  83. package/dist/sdk/client/acp-client.js +217 -215
  84. package/dist/sdk/index.d.ts +1 -1
  85. package/dist/sdk/index.js +1 -1
  86. package/dist/sdk/schemas/agent.d.ts +64 -111
  87. package/dist/sdk/schemas/agent.js +24 -24
  88. package/dist/sdk/schemas/message.d.ts +147 -245
  89. package/dist/sdk/schemas/message.js +40 -40
  90. package/dist/sdk/schemas/session.d.ts +135 -219
  91. package/dist/sdk/schemas/session.js +27 -27
  92. package/dist/sdk/transports/http.d.ts +55 -55
  93. package/dist/sdk/transports/http.js +469 -472
  94. package/dist/sdk/transports/stdio.d.ts +20 -20
  95. package/dist/sdk/transports/stdio.js +286 -289
  96. package/dist/sdk/transports/types.d.ts +42 -42
  97. package/dist/sdk/transports/websocket.d.ts +12 -12
  98. package/dist/sdk/transports/websocket.js +46 -52
  99. package/dist/tui/components/ChatView.d.ts +2 -4
  100. package/dist/tui/components/ChatView.js +18 -51
  101. package/dist/tui/components/GameOfLife.js +35 -64
  102. package/dist/tui/components/InputBox.d.ts +11 -18
  103. package/dist/tui/components/InputBox.js +10 -70
  104. package/dist/tui/components/MessageList.d.ts +2 -4
  105. package/dist/tui/components/MessageList.js +10 -37
  106. package/dist/tui/components/MultiSelect.d.ts +10 -15
  107. package/dist/tui/components/MultiSelect.js +73 -116
  108. package/dist/tui/components/ReadlineInput.d.ts +6 -12
  109. package/dist/tui/components/ReadlineInput.js +237 -252
  110. package/dist/tui/components/SingleSelect.d.ts +9 -15
  111. package/dist/tui/components/SingleSelect.js +43 -84
  112. package/dist/tui/components/StatusBar.d.ts +6 -11
  113. package/dist/tui/components/StatusBar.js +67 -102
  114. package/dist/tui/index.d.ts +1 -1
  115. package/dist/tui/index.js +1 -1
  116. package/package.json +6 -4
  117. package/src/styles/global.css +2 -0
  118. package/dist/core/hooks/index.d.ts.map +0 -1
  119. package/dist/core/hooks/index.js.map +0 -1
  120. package/dist/core/hooks/use-chat-input.d.ts.map +0 -1
  121. package/dist/core/hooks/use-chat-input.js.map +0 -1
  122. package/dist/core/hooks/use-chat-messages.d.ts.map +0 -1
  123. package/dist/core/hooks/use-chat-messages.js.map +0 -1
  124. package/dist/core/hooks/use-chat-session.d.ts.map +0 -1
  125. package/dist/core/hooks/use-chat-session.js.map +0 -1
  126. package/dist/core/index.d.ts.map +0 -1
  127. package/dist/core/index.js.map +0 -1
  128. package/dist/core/schemas/chat.d.ts.map +0 -1
  129. package/dist/core/schemas/chat.js.map +0 -1
  130. package/dist/core/schemas/index.d.ts.map +0 -1
  131. package/dist/core/schemas/index.js.map +0 -1
  132. package/dist/core/store/chat-store.d.ts.map +0 -1
  133. package/dist/core/store/chat-store.js.map +0 -1
  134. package/dist/gui/components/Button.d.ts.map +0 -1
  135. package/dist/gui/components/Button.js.map +0 -1
  136. package/dist/gui/components/Card.d.ts.map +0 -1
  137. package/dist/gui/components/Card.js.map +0 -1
  138. package/dist/gui/components/ChatInput.d.ts.map +0 -1
  139. package/dist/gui/components/ChatInput.js.map +0 -1
  140. package/dist/gui/components/ChatInterface.d.ts +0 -12
  141. package/dist/gui/components/ChatInterface.d.ts.map +0 -1
  142. package/dist/gui/components/ChatInterface.js +0 -204
  143. package/dist/gui/components/ChatInterface.js.map +0 -1
  144. package/dist/gui/components/ChatPreview.d.ts +0 -12
  145. package/dist/gui/components/ChatPreview.d.ts.map +0 -1
  146. package/dist/gui/components/ChatPreview.js +0 -214
  147. package/dist/gui/components/ChatPreview.js.map +0 -1
  148. package/dist/gui/components/ChatSecondaryPanel.d.ts.map +0 -1
  149. package/dist/gui/components/ChatSecondaryPanel.js.map +0 -1
  150. package/dist/gui/components/ChatStatus.d.ts.map +0 -1
  151. package/dist/gui/components/ChatStatus.js.map +0 -1
  152. package/dist/gui/components/ChatView.d.ts +0 -8
  153. package/dist/gui/components/ChatView.d.ts.map +0 -1
  154. package/dist/gui/components/ChatView.js +0 -42
  155. package/dist/gui/components/ChatView.js.map +0 -1
  156. package/dist/gui/components/ConfigPanel.d.ts +0 -20
  157. package/dist/gui/components/ConfigPanel.d.ts.map +0 -1
  158. package/dist/gui/components/ConfigPanel.js +0 -225
  159. package/dist/gui/components/ConfigPanel.js.map +0 -1
  160. package/dist/gui/components/Conversation.d.ts.map +0 -1
  161. package/dist/gui/components/Conversation.js.map +0 -1
  162. package/dist/gui/components/Dialog.d.ts.map +0 -1
  163. package/dist/gui/components/Dialog.js.map +0 -1
  164. package/dist/gui/components/HeightTransition.d.ts.map +0 -1
  165. package/dist/gui/components/HeightTransition.js.map +0 -1
  166. package/dist/gui/components/Input.d.ts.map +0 -1
  167. package/dist/gui/components/Input.js.map +0 -1
  168. package/dist/gui/components/InputBox.d.ts +0 -21
  169. package/dist/gui/components/InputBox.d.ts.map +0 -1
  170. package/dist/gui/components/InputBox.js +0 -90
  171. package/dist/gui/components/InputBox.js.map +0 -1
  172. package/dist/gui/components/Label.d.ts.map +0 -1
  173. package/dist/gui/components/Label.js.map +0 -1
  174. package/dist/gui/components/MarkdownRenderer.d.ts.map +0 -1
  175. package/dist/gui/components/MarkdownRenderer.js.map +0 -1
  176. package/dist/gui/components/Message.d.ts.map +0 -1
  177. package/dist/gui/components/Message.js.map +0 -1
  178. package/dist/gui/components/MessageContent.d.ts.map +0 -1
  179. package/dist/gui/components/MessageContent.js.map +0 -1
  180. package/dist/gui/components/MessageList.d.ts.map +0 -1
  181. package/dist/gui/components/MessageList.js.map +0 -1
  182. package/dist/gui/components/PlaygroundLayout.d.ts +0 -14
  183. package/dist/gui/components/PlaygroundLayout.d.ts.map +0 -1
  184. package/dist/gui/components/PlaygroundLayout.js +0 -49
  185. package/dist/gui/components/PlaygroundLayout.js.map +0 -1
  186. package/dist/gui/components/Reasoning.d.ts.map +0 -1
  187. package/dist/gui/components/Reasoning.js.map +0 -1
  188. package/dist/gui/components/Response.d.ts.map +0 -1
  189. package/dist/gui/components/Response.js.map +0 -1
  190. package/dist/gui/components/Select.d.ts.map +0 -1
  191. package/dist/gui/components/Select.js.map +0 -1
  192. package/dist/gui/components/StatusBar.d.ts +0 -12
  193. package/dist/gui/components/StatusBar.d.ts.map +0 -1
  194. package/dist/gui/components/StatusBar.js +0 -58
  195. package/dist/gui/components/StatusBar.js.map +0 -1
  196. package/dist/gui/components/Tabs.d.ts.map +0 -1
  197. package/dist/gui/components/Tabs.js.map +0 -1
  198. package/dist/gui/components/Task.d.ts.map +0 -1
  199. package/dist/gui/components/Task.js.map +0 -1
  200. package/dist/gui/components/Textarea.d.ts.map +0 -1
  201. package/dist/gui/components/Textarea.js.map +0 -1
  202. package/dist/gui/components/ThinkingBlock.d.ts.map +0 -1
  203. package/dist/gui/components/ThinkingBlock.js.map +0 -1
  204. package/dist/gui/components/TodoList.d.ts.map +0 -1
  205. package/dist/gui/components/TodoList.js.map +0 -1
  206. package/dist/gui/components/TodoListItem.d.ts.map +0 -1
  207. package/dist/gui/components/TodoListItem.js.map +0 -1
  208. package/dist/gui/components/index.d.ts.map +0 -1
  209. package/dist/gui/components/index.js.map +0 -1
  210. package/dist/gui/index.d.ts.map +0 -1
  211. package/dist/gui/index.js.map +0 -1
  212. package/dist/gui/lib/utils.d.ts.map +0 -1
  213. package/dist/gui/lib/utils.js.map +0 -1
  214. package/dist/index.d.ts.map +0 -1
  215. package/dist/index.js.map +0 -1
  216. package/dist/sdk/client/acp-client.d.ts.map +0 -1
  217. package/dist/sdk/client/acp-client.js.map +0 -1
  218. package/dist/sdk/client/index.d.ts.map +0 -1
  219. package/dist/sdk/client/index.js.map +0 -1
  220. package/dist/sdk/index.d.ts.map +0 -1
  221. package/dist/sdk/index.js.map +0 -1
  222. package/dist/sdk/schemas/agent.d.ts.map +0 -1
  223. package/dist/sdk/schemas/agent.js.map +0 -1
  224. package/dist/sdk/schemas/index.d.ts.map +0 -1
  225. package/dist/sdk/schemas/index.js.map +0 -1
  226. package/dist/sdk/schemas/message.d.ts.map +0 -1
  227. package/dist/sdk/schemas/message.js.map +0 -1
  228. package/dist/sdk/schemas/session.d.ts.map +0 -1
  229. package/dist/sdk/schemas/session.js.map +0 -1
  230. package/dist/sdk/transports/http.d.ts.map +0 -1
  231. package/dist/sdk/transports/http.js.map +0 -1
  232. package/dist/sdk/transports/index.d.ts.map +0 -1
  233. package/dist/sdk/transports/index.js.map +0 -1
  234. package/dist/sdk/transports/stdio.d.ts.map +0 -1
  235. package/dist/sdk/transports/stdio.js.map +0 -1
  236. package/dist/sdk/transports/types.d.ts.map +0 -1
  237. package/dist/sdk/transports/types.js.map +0 -1
  238. package/dist/sdk/transports/websocket.d.ts.map +0 -1
  239. package/dist/sdk/transports/websocket.js.map +0 -1
  240. package/dist/tui/components/ChatView.d.ts.map +0 -1
  241. package/dist/tui/components/ChatView.js.map +0 -1
  242. package/dist/tui/components/GameOfLife.d.ts.map +0 -1
  243. package/dist/tui/components/GameOfLife.js.map +0 -1
  244. package/dist/tui/components/InputBox.d.ts.map +0 -1
  245. package/dist/tui/components/InputBox.js.map +0 -1
  246. package/dist/tui/components/MessageList.d.ts.map +0 -1
  247. package/dist/tui/components/MessageList.js.map +0 -1
  248. package/dist/tui/components/ReadlineInput.d.ts.map +0 -1
  249. package/dist/tui/components/ReadlineInput.js.map +0 -1
  250. package/dist/tui/components/StatusBar.d.ts.map +0 -1
  251. package/dist/tui/components/StatusBar.js.map +0 -1
  252. package/dist/tui/components/index.d.ts.map +0 -1
  253. package/dist/tui/components/index.js.map +0 -1
  254. package/dist/tui/index.d.ts.map +0 -1
  255. package/dist/tui/index.js.map +0 -1
@@ -1,255 +1,240 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
2
  import { Text, useInput } from "ink";
2
3
  import React, { useState } from "react";
3
- import {
4
- Fragment as _Fragment,
5
- jsx as _jsx,
6
- jsxs as _jsxs,
7
- } from "react/jsx-runtime";
8
- export function ReadlineInput({
9
- value,
10
- onChange,
11
- onSubmit,
12
- onEscape,
13
- placeholder = "",
14
- }) {
15
- const [cursorOffset, setCursorOffset] = useState(0);
16
- useInput((input, key) => {
17
- // Handle Esc: Call escape handler
18
- if (key.escape) {
19
- if (onEscape) {
20
- onEscape();
21
- }
22
- return;
23
- }
24
- // Handle special keys
25
- if (key.return) {
26
- const cursorPos = value.length + cursorOffset;
27
- // Shift+Enter: Insert backslash and newline
28
- if (key.shift) {
29
- const newValue = `${value.slice(0, cursorPos)}\\\n${value.slice(cursorPos)}`;
30
- onChange(newValue);
31
- if (cursorOffset < 0) {
32
- setCursorOffset(cursorOffset - 2);
33
- }
34
- return;
35
- }
36
- // Check if cursor is at end and last character is backslash (line continuation)
37
- if (cursorPos === value.length && value.endsWith("\\")) {
38
- // Remove backslash and add newline (line continuation)
39
- const newValue = `${value.slice(0, -1)}\n`;
40
- onChange(newValue);
41
- setCursorOffset(0); // Move cursor to end
42
- return;
43
- }
44
- // Alt+Enter adds a newline, Enter submits
45
- if (key.meta) {
46
- const newValue = `${value.slice(0, cursorPos)}\n${value.slice(cursorPos)}`;
47
- onChange(newValue);
48
- if (cursorOffset < 0) {
49
- setCursorOffset(cursorOffset - 1);
50
- }
51
- } else {
52
- onSubmit();
53
- }
54
- return;
55
- }
56
- if (key.ctrl) {
57
- // Ctrl+A: Move to beginning of line
58
- if (input === "a") {
59
- setCursorOffset(-value.length);
60
- return;
61
- }
62
- // Ctrl+E: Move to end of line
63
- if (input === "e") {
64
- setCursorOffset(0);
65
- return;
66
- }
67
- // Ctrl+W: Delete word backward
68
- if (input === "w") {
69
- const cursorPos = value.length + cursorOffset;
70
- const before = value.slice(0, cursorPos);
71
- const after = value.slice(cursorPos);
72
- // Find the start of the word to delete
73
- const match = before.match(/\s*\S*$/);
74
- if (match) {
75
- const newBefore = before.slice(0, -match[0].length);
76
- onChange(newBefore + after);
77
- setCursorOffset(-after.length);
78
- }
79
- return;
80
- }
81
- // Ctrl+U: Delete from cursor to beginning of line
82
- if (input === "u") {
83
- const cursorPos = value.length + cursorOffset;
84
- onChange(value.slice(cursorPos));
85
- setCursorOffset(-value.slice(cursorPos).length);
86
- return;
87
- }
88
- // Ctrl+K: Delete from cursor to end of line
89
- if (input === "k") {
90
- const cursorPos = value.length + cursorOffset;
91
- onChange(value.slice(0, cursorPos));
92
- setCursorOffset(0);
93
- return;
94
- }
95
- // Ctrl+D: Delete character forward
96
- if (input === "d") {
97
- const cursorPos = value.length + cursorOffset;
98
- if (cursorPos < value.length) {
99
- onChange(value.slice(0, cursorPos) + value.slice(cursorPos + 1));
100
- }
101
- return;
102
- }
103
- // Ctrl+B: Move backward one character
104
- if (input === "b") {
105
- const cursorPos = value.length + cursorOffset;
106
- if (cursorPos > 0) {
107
- setCursorOffset(cursorOffset - 1);
108
- }
109
- return;
110
- }
111
- // Ctrl+F: Move forward one character
112
- if (input === "f") {
113
- const cursorPos = value.length + cursorOffset;
114
- if (cursorPos < value.length) {
115
- setCursorOffset(cursorOffset + 1);
116
- }
117
- return;
118
- }
119
- }
120
- // Handle backspace
121
- if (key.backspace || key.delete) {
122
- const cursorPos = value.length + cursorOffset;
123
- if (cursorPos > 0) {
124
- onChange(value.slice(0, cursorPos - 1) + value.slice(cursorPos));
125
- if (cursorOffset < 0) {
126
- setCursorOffset(cursorOffset + 1);
127
- }
128
- }
129
- return;
130
- }
131
- // Handle left/right arrow keys
132
- if (key.leftArrow) {
133
- const cursorPos = value.length + cursorOffset;
134
- if (cursorPos > 0) {
135
- setCursorOffset(cursorOffset - 1);
136
- }
137
- return;
138
- }
139
- if (key.rightArrow) {
140
- const cursorPos = value.length + cursorOffset;
141
- if (cursorPos < value.length) {
142
- setCursorOffset(cursorOffset + 1);
143
- }
144
- return;
145
- }
146
- // Handle up/down arrow keys for multi-line navigation
147
- if (key.upArrow) {
148
- const cursorPos = value.length + cursorOffset;
149
- const lines = value.split("\n");
150
- // Find which line we're on and our position within it
151
- let currentLineIndex = 0;
152
- let charCount = 0;
153
- let posInLine = cursorPos;
154
- for (let i = 0; i < lines.length; i++) {
155
- const line = lines[i];
156
- if (!line) continue;
157
- const lineLength = line.length + (i < lines.length - 1 ? 1 : 0); // +1 for \n
158
- if (charCount + lineLength > cursorPos || i === lines.length - 1) {
159
- currentLineIndex = i;
160
- posInLine = cursorPos - charCount;
161
- break;
162
- }
163
- charCount += lineLength;
164
- }
165
- // Move to previous line if possible
166
- if (currentLineIndex > 0) {
167
- const prevLine = lines[currentLineIndex - 1];
168
- const currentLine = lines[currentLineIndex];
169
- if (prevLine && currentLine) {
170
- const prevLineStart = charCount - currentLine.length - 1;
171
- const targetPos = Math.min(posInLine, prevLine.length);
172
- const newCursorPos = prevLineStart + targetPos;
173
- setCursorOffset(newCursorPos - value.length);
174
- }
175
- }
176
- return;
177
- }
178
- if (key.downArrow) {
179
- const cursorPos = value.length + cursorOffset;
180
- const lines = value.split("\n");
181
- // Find which line we're on and our position within it
182
- let currentLineIndex = 0;
183
- let charCount = 0;
184
- let posInLine = cursorPos;
185
- for (let i = 0; i < lines.length; i++) {
186
- const line = lines[i];
187
- if (!line) continue;
188
- const lineLength = line.length + (i < lines.length - 1 ? 1 : 0); // +1 for \n
189
- if (charCount + lineLength > cursorPos || i === lines.length - 1) {
190
- currentLineIndex = i;
191
- posInLine = cursorPos - charCount;
192
- break;
193
- }
194
- charCount += lineLength;
195
- }
196
- // Move to next line if possible
197
- if (currentLineIndex < lines.length - 1) {
198
- const nextLine = lines[currentLineIndex + 1];
199
- const currentLine = lines[currentLineIndex];
200
- if (nextLine && currentLine) {
201
- const nextLineStart = charCount + currentLine.length + 1;
202
- const targetPos = Math.min(posInLine, nextLine.length);
203
- const newCursorPos = nextLineStart + targetPos;
204
- setCursorOffset(newCursorPos - value.length);
205
- }
206
- }
207
- return;
208
- }
209
- // Regular character input and paste detection
210
- // Ink automatically detects paste and sends the whole string at once
211
- if (!key.ctrl && !key.meta && input.length > 0) {
212
- const cursorPos = value.length + cursorOffset;
213
- // Check if this is a paste with more than 3 lines
214
- let contentToInsert = input;
215
- if (input.length > 1) {
216
- // Pasted content (more than 1 char at once)
217
- const lines = input.split("\n");
218
- if (lines.length > 3) {
219
- contentToInsert = `[Pasted +${lines.length} lines]`;
220
- }
221
- }
222
- const newValue =
223
- value.slice(0, cursorPos) + contentToInsert + value.slice(cursorPos);
224
- onChange(newValue);
225
- // Keep cursor at the same relative position
226
- if (cursorOffset < 0) {
227
- setCursorOffset(cursorOffset - contentToInsert.length);
228
- }
229
- }
230
- });
231
- // Reset cursor when value changes externally (e.g., after submit)
232
- React.useEffect(() => {
233
- if (value.length === 0) {
234
- setCursorOffset(0);
235
- }
236
- }, [value]);
237
- // Display the input with cursor
238
- const cursorPos = value.length + cursorOffset;
239
- // Show placeholder if empty
240
- if (value.length === 0) {
241
- return _jsxs(_Fragment, {
242
- children: [
243
- _jsx(Text, { inverse: true, children: " " }),
244
- _jsx(Text, { dimColor: true, children: placeholder }),
245
- ],
246
- });
247
- }
248
- // Show value with cursor
249
- const before = value.slice(0, cursorPos);
250
- const cursor = value[cursorPos] || " ";
251
- const after = value.slice(cursorPos + 1);
252
- return _jsxs(Text, {
253
- children: [before, _jsx(Text, { inverse: true, children: cursor }), after],
254
- });
4
+ export function ReadlineInput({ value, onChange, onSubmit, onEscape, placeholder = "", }) {
5
+ const [cursorOffset, setCursorOffset] = useState(0);
6
+ useInput((input, key) => {
7
+ // Handle Esc: Call escape handler
8
+ if (key.escape) {
9
+ if (onEscape) {
10
+ onEscape();
11
+ }
12
+ return;
13
+ }
14
+ // Handle special keys
15
+ if (key.return) {
16
+ const cursorPos = value.length + cursorOffset;
17
+ // Shift+Enter: Insert backslash and newline
18
+ if (key.shift) {
19
+ const newValue = `${value.slice(0, cursorPos)}\\\n${value.slice(cursorPos)}`;
20
+ onChange(newValue);
21
+ if (cursorOffset < 0) {
22
+ setCursorOffset(cursorOffset - 2);
23
+ }
24
+ return;
25
+ }
26
+ // Check if cursor is at end and last character is backslash (line continuation)
27
+ if (cursorPos === value.length && value.endsWith("\\")) {
28
+ // Remove backslash and add newline (line continuation)
29
+ const newValue = `${value.slice(0, -1)}\n`;
30
+ onChange(newValue);
31
+ setCursorOffset(0); // Move cursor to end
32
+ return;
33
+ }
34
+ // Alt+Enter adds a newline, Enter submits
35
+ if (key.meta) {
36
+ const newValue = `${value.slice(0, cursorPos)}\n${value.slice(cursorPos)}`;
37
+ onChange(newValue);
38
+ if (cursorOffset < 0) {
39
+ setCursorOffset(cursorOffset - 1);
40
+ }
41
+ }
42
+ else {
43
+ onSubmit();
44
+ }
45
+ return;
46
+ }
47
+ if (key.ctrl) {
48
+ // Ctrl+A: Move to beginning of line
49
+ if (input === "a") {
50
+ setCursorOffset(-value.length);
51
+ return;
52
+ }
53
+ // Ctrl+E: Move to end of line
54
+ if (input === "e") {
55
+ setCursorOffset(0);
56
+ return;
57
+ }
58
+ // Ctrl+W: Delete word backward
59
+ if (input === "w") {
60
+ const cursorPos = value.length + cursorOffset;
61
+ const before = value.slice(0, cursorPos);
62
+ const after = value.slice(cursorPos);
63
+ // Find the start of the word to delete
64
+ const match = before.match(/\s*\S*$/);
65
+ if (match) {
66
+ const newBefore = before.slice(0, -match[0].length);
67
+ onChange(newBefore + after);
68
+ setCursorOffset(-after.length);
69
+ }
70
+ return;
71
+ }
72
+ // Ctrl+U: Delete from cursor to beginning of line
73
+ if (input === "u") {
74
+ const cursorPos = value.length + cursorOffset;
75
+ onChange(value.slice(cursorPos));
76
+ setCursorOffset(-value.slice(cursorPos).length);
77
+ return;
78
+ }
79
+ // Ctrl+K: Delete from cursor to end of line
80
+ if (input === "k") {
81
+ const cursorPos = value.length + cursorOffset;
82
+ onChange(value.slice(0, cursorPos));
83
+ setCursorOffset(0);
84
+ return;
85
+ }
86
+ // Ctrl+D: Delete character forward
87
+ if (input === "d") {
88
+ const cursorPos = value.length + cursorOffset;
89
+ if (cursorPos < value.length) {
90
+ onChange(value.slice(0, cursorPos) + value.slice(cursorPos + 1));
91
+ }
92
+ return;
93
+ }
94
+ // Ctrl+B: Move backward one character
95
+ if (input === "b") {
96
+ const cursorPos = value.length + cursorOffset;
97
+ if (cursorPos > 0) {
98
+ setCursorOffset(cursorOffset - 1);
99
+ }
100
+ return;
101
+ }
102
+ // Ctrl+F: Move forward one character
103
+ if (input === "f") {
104
+ const cursorPos = value.length + cursorOffset;
105
+ if (cursorPos < value.length) {
106
+ setCursorOffset(cursorOffset + 1);
107
+ }
108
+ return;
109
+ }
110
+ }
111
+ // Handle backspace
112
+ if (key.backspace || key.delete) {
113
+ const cursorPos = value.length + cursorOffset;
114
+ if (cursorPos > 0) {
115
+ onChange(value.slice(0, cursorPos - 1) + value.slice(cursorPos));
116
+ if (cursorOffset < 0) {
117
+ setCursorOffset(cursorOffset + 1);
118
+ }
119
+ }
120
+ return;
121
+ }
122
+ // Handle left/right arrow keys
123
+ if (key.leftArrow) {
124
+ const cursorPos = value.length + cursorOffset;
125
+ if (cursorPos > 0) {
126
+ setCursorOffset(cursorOffset - 1);
127
+ }
128
+ return;
129
+ }
130
+ if (key.rightArrow) {
131
+ const cursorPos = value.length + cursorOffset;
132
+ if (cursorPos < value.length) {
133
+ setCursorOffset(cursorOffset + 1);
134
+ }
135
+ return;
136
+ }
137
+ // Handle up/down arrow keys for multi-line navigation
138
+ if (key.upArrow) {
139
+ const cursorPos = value.length + cursorOffset;
140
+ const lines = value.split("\n");
141
+ // Find which line we're on and our position within it
142
+ let currentLineIndex = 0;
143
+ let charCount = 0;
144
+ let posInLine = cursorPos;
145
+ for (let i = 0; i < lines.length; i++) {
146
+ const line = lines[i];
147
+ if (!line)
148
+ continue;
149
+ const lineLength = line.length + (i < lines.length - 1 ? 1 : 0); // +1 for \n
150
+ if (charCount + lineLength > cursorPos || i === lines.length - 1) {
151
+ currentLineIndex = i;
152
+ posInLine = cursorPos - charCount;
153
+ break;
154
+ }
155
+ charCount += lineLength;
156
+ }
157
+ // Move to previous line if possible
158
+ if (currentLineIndex > 0) {
159
+ const prevLine = lines[currentLineIndex - 1];
160
+ const currentLine = lines[currentLineIndex];
161
+ if (prevLine && currentLine) {
162
+ const prevLineStart = charCount - currentLine.length - 1;
163
+ const targetPos = Math.min(posInLine, prevLine.length);
164
+ const newCursorPos = prevLineStart + targetPos;
165
+ setCursorOffset(newCursorPos - value.length);
166
+ }
167
+ }
168
+ return;
169
+ }
170
+ if (key.downArrow) {
171
+ const cursorPos = value.length + cursorOffset;
172
+ const lines = value.split("\n");
173
+ // Find which line we're on and our position within it
174
+ let currentLineIndex = 0;
175
+ let charCount = 0;
176
+ let posInLine = cursorPos;
177
+ for (let i = 0; i < lines.length; i++) {
178
+ const line = lines[i];
179
+ if (!line)
180
+ continue;
181
+ const lineLength = line.length + (i < lines.length - 1 ? 1 : 0); // +1 for \n
182
+ if (charCount + lineLength > cursorPos || i === lines.length - 1) {
183
+ currentLineIndex = i;
184
+ posInLine = cursorPos - charCount;
185
+ break;
186
+ }
187
+ charCount += lineLength;
188
+ }
189
+ // Move to next line if possible
190
+ if (currentLineIndex < lines.length - 1) {
191
+ const nextLine = lines[currentLineIndex + 1];
192
+ const currentLine = lines[currentLineIndex];
193
+ if (nextLine && currentLine) {
194
+ const nextLineStart = charCount + currentLine.length + 1;
195
+ const targetPos = Math.min(posInLine, nextLine.length);
196
+ const newCursorPos = nextLineStart + targetPos;
197
+ setCursorOffset(newCursorPos - value.length);
198
+ }
199
+ }
200
+ return;
201
+ }
202
+ // Regular character input and paste detection
203
+ // Ink automatically detects paste and sends the whole string at once
204
+ if (!key.ctrl && !key.meta && input.length > 0) {
205
+ const cursorPos = value.length + cursorOffset;
206
+ // Check if this is a paste with more than 3 lines
207
+ let contentToInsert = input;
208
+ if (input.length > 1) {
209
+ // Pasted content (more than 1 char at once)
210
+ const lines = input.split("\n");
211
+ if (lines.length > 3) {
212
+ contentToInsert = `[Pasted +${lines.length} lines]`;
213
+ }
214
+ }
215
+ const newValue = value.slice(0, cursorPos) + contentToInsert + value.slice(cursorPos);
216
+ onChange(newValue);
217
+ // Keep cursor at the same relative position
218
+ if (cursorOffset < 0) {
219
+ setCursorOffset(cursorOffset - contentToInsert.length);
220
+ }
221
+ }
222
+ });
223
+ // Reset cursor when value changes externally (e.g., after submit)
224
+ React.useEffect(() => {
225
+ if (value.length === 0) {
226
+ setCursorOffset(0);
227
+ }
228
+ }, [value]);
229
+ // Display the input with cursor
230
+ const cursorPos = value.length + cursorOffset;
231
+ // Show placeholder if empty
232
+ if (value.length === 0) {
233
+ return (_jsxs(_Fragment, { children: [_jsx(Text, { inverse: true, children: " " }), _jsx(Text, { dimColor: true, children: placeholder })] }));
234
+ }
235
+ // Show value with cursor
236
+ const before = value.slice(0, cursorPos);
237
+ const cursor = value[cursorPos] || " ";
238
+ const after = value.slice(cursorPos + 1);
239
+ return (_jsxs(Text, { children: [before, _jsx(Text, { inverse: true, children: cursor }), after] }));
255
240
  }
@@ -1,19 +1,13 @@
1
1
  export interface SingleSelectOption {
2
- label: string;
3
- value: string;
4
- description?: string;
2
+ label: string;
3
+ value: string;
4
+ description?: string;
5
5
  }
6
6
  export interface SingleSelectProps {
7
- options: SingleSelectOption[];
8
- selected: string | null;
9
- onChange: (selected: string) => void;
10
- onSubmit: (selected: string) => void;
11
- onCancel?: () => void;
7
+ options: SingleSelectOption[];
8
+ selected: string | null;
9
+ onChange: (selected: string) => void;
10
+ onSubmit: (selected: string) => void;
11
+ onCancel?: () => void;
12
12
  }
13
- export declare function SingleSelect({
14
- options,
15
- selected: _selected,
16
- onChange,
17
- onSubmit,
18
- onCancel,
19
- }: SingleSelectProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function SingleSelect({ options, selected: _selected, onChange, onSubmit, onCancel, }: SingleSelectProps): import("react/jsx-runtime").JSX.Element;