@shopify/cli-kit 3.31.1 → 3.32.1

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 (252) hide show
  1. package/README.md +1 -1
  2. package/dist/api.d.ts +2 -5
  3. package/dist/api.js +2 -5
  4. package/dist/api.js.map +1 -1
  5. package/dist/constants.d.ts +1 -0
  6. package/dist/constants.js +1 -0
  7. package/dist/constants.js.map +1 -1
  8. package/dist/environment/local.d.ts +1 -0
  9. package/dist/environment/local.js +4 -1
  10. package/dist/environment/local.js.map +1 -1
  11. package/dist/file.d.ts +10 -3
  12. package/dist/file.js +34 -34
  13. package/dist/file.js.map +1 -1
  14. package/dist/http/fetch.js +1 -1
  15. package/dist/http/fetch.js.map +1 -1
  16. package/dist/http.d.ts +0 -1
  17. package/dist/http.js +0 -1
  18. package/dist/http.js.map +1 -1
  19. package/dist/index.d.ts +0 -8
  20. package/dist/index.js +0 -8
  21. package/dist/index.js.map +1 -1
  22. package/dist/metadata.d.ts +1 -1
  23. package/dist/metadata.js.map +1 -1
  24. package/dist/monorail.d.ts +1 -1
  25. package/dist/monorail.js.map +1 -1
  26. package/dist/npm.js +1 -1
  27. package/dist/npm.js.map +1 -1
  28. package/dist/output.d.ts +2 -2
  29. package/dist/output.js +1 -1
  30. package/dist/output.js.map +1 -1
  31. package/dist/path.d.ts +3 -1
  32. package/dist/path.js +2 -2
  33. package/dist/path.js.map +1 -1
  34. package/dist/plugins.d.ts +1 -1
  35. package/dist/plugins.js.map +1 -1
  36. package/dist/{json.d.ts → private/common/json.d.ts} +0 -0
  37. package/dist/{json.js → private/common/json.js} +0 -0
  38. package/dist/private/common/json.js.map +1 -0
  39. package/dist/private/node/analytics.d.ts +27 -0
  40. package/dist/private/node/analytics.js +57 -0
  41. package/dist/private/node/analytics.js.map +1 -0
  42. package/dist/private/node/api/graphql.d.ts +5 -0
  43. package/dist/private/node/api/graphql.js +63 -0
  44. package/dist/private/node/api/graphql.js.map +1 -0
  45. package/dist/{api/common.d.ts → private/node/api/headers.d.ts} +3 -8
  46. package/dist/{api/common.js → private/node/api/headers.js} +20 -60
  47. package/dist/private/node/api/headers.js.map +1 -0
  48. package/dist/private/node/ui/components/Alert.test.js +5 -5
  49. package/dist/private/node/ui/components/Alert.test.js.map +1 -1
  50. package/dist/private/node/ui/components/Banner.js +5 -5
  51. package/dist/private/node/ui/components/Banner.js.map +1 -1
  52. package/dist/private/node/ui/components/Banner.test.js +11 -11
  53. package/dist/private/node/ui/components/Banner.test.js.map +1 -1
  54. package/dist/private/node/ui/components/Command.test.js +3 -3
  55. package/dist/private/node/ui/components/Command.test.js.map +1 -1
  56. package/dist/private/node/ui/components/ConcurrentOutput.d.ts +2 -2
  57. package/dist/private/node/ui/components/ConcurrentOutput.js +1 -1
  58. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  59. package/dist/private/node/ui/components/ConcurrentOutput.test.js +3 -3
  60. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
  61. package/dist/private/node/ui/components/FatalError.test.js +9 -9
  62. package/dist/private/node/ui/components/FatalError.test.js.map +1 -1
  63. package/dist/private/node/ui/components/FilePath.test.js +3 -3
  64. package/dist/private/node/ui/components/FilePath.test.js.map +1 -1
  65. package/dist/private/node/ui/components/FullScreen.js +11 -9
  66. package/dist/private/node/ui/components/FullScreen.js.map +1 -1
  67. package/dist/private/node/ui/components/Link.test.js +5 -5
  68. package/dist/private/node/ui/components/Link.test.js.map +1 -1
  69. package/dist/private/node/ui/components/List.test.js +5 -5
  70. package/dist/private/node/ui/components/List.test.js.map +1 -1
  71. package/dist/private/node/ui/components/SelectInput.d.ts +2 -2
  72. package/dist/private/node/ui/components/SelectInput.js +16 -24
  73. package/dist/private/node/ui/components/SelectInput.js.map +1 -1
  74. package/dist/private/node/ui/components/SelectInput.test.js +62 -32
  75. package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
  76. package/dist/private/node/ui/components/{Prompt.d.ts → SelectPrompt.d.ts} +4 -3
  77. package/dist/private/node/ui/components/SelectPrompt.js +46 -0
  78. package/dist/private/node/ui/components/SelectPrompt.js.map +1 -0
  79. package/dist/private/node/ui/components/{Prompt.test.d.ts → SelectPrompt.test.d.ts} +0 -0
  80. package/dist/private/node/ui/components/{Prompt.test.js → SelectPrompt.test.js} +7 -6
  81. package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -0
  82. package/dist/private/node/ui/components/Table.js +2 -2
  83. package/dist/private/node/ui/components/Table.js.map +1 -1
  84. package/dist/private/node/ui/components/Tasks.d.ts +1 -1
  85. package/dist/private/node/ui/components/Tasks.js +3 -3
  86. package/dist/private/node/ui/components/Tasks.js.map +1 -1
  87. package/dist/private/node/ui/components/Tasks.test.js +4 -4
  88. package/dist/private/node/ui/components/Tasks.test.js.map +1 -1
  89. package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
  90. package/dist/private/node/ui/components/TextInput.d.ts +9 -0
  91. package/dist/private/node/ui/components/TextInput.js +74 -0
  92. package/dist/private/node/ui/components/TextInput.js.map +1 -0
  93. package/dist/private/node/ui/components/TextInput.test.d.ts +1 -0
  94. package/dist/private/node/ui/components/TextInput.test.js +139 -0
  95. package/dist/private/node/ui/components/TextInput.test.js.map +1 -0
  96. package/dist/private/node/ui/components/TextPrompt.d.ts +8 -0
  97. package/dist/private/node/ui/components/TextPrompt.js +52 -0
  98. package/dist/private/node/ui/components/TextPrompt.js.map +1 -0
  99. package/dist/private/node/ui/components/TextPrompt.test.d.ts +1 -0
  100. package/dist/private/node/ui/components/TextPrompt.test.js +68 -0
  101. package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -0
  102. package/dist/private/node/ui/components/TokenizedText.test.js +3 -3
  103. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
  104. package/dist/private/node/ui/components/UserInput.test.js +3 -3
  105. package/dist/private/node/ui/components/UserInput.test.js.map +1 -1
  106. package/dist/private/node/ui/hooks/use-layout.d.ts +6 -3
  107. package/dist/private/node/ui/hooks/use-layout.js +17 -8
  108. package/dist/private/node/ui/hooks/use-layout.js.map +1 -1
  109. package/dist/private/node/ui.d.ts +2 -3
  110. package/dist/private/node/ui.js +7 -16
  111. package/dist/private/node/ui.js.map +1 -1
  112. package/dist/public/common/array.js +1 -1
  113. package/dist/public/common/array.js.map +1 -1
  114. package/dist/public/common/collection.js +1 -1
  115. package/dist/public/common/collection.js.map +1 -1
  116. package/dist/public/common/function.js +1 -1
  117. package/dist/public/common/function.js.map +1 -1
  118. package/dist/public/common/lang.js +1 -1
  119. package/dist/public/common/lang.js.map +1 -1
  120. package/dist/public/common/object.js +4 -4
  121. package/dist/public/common/object.js.map +1 -1
  122. package/dist/public/common/string.d.ts +55 -1
  123. package/dist/public/common/string.js +93 -1
  124. package/dist/public/common/string.js.map +1 -1
  125. package/dist/public/common/url.d.ts +7 -0
  126. package/dist/public/common/url.js +17 -0
  127. package/dist/public/common/url.js.map +1 -0
  128. package/dist/public/node/abort.d.ts +16 -0
  129. package/dist/public/node/abort.js +17 -0
  130. package/dist/public/node/abort.js.map +1 -0
  131. package/dist/public/node/analytics.d.ts +13 -0
  132. package/dist/public/node/analytics.js +82 -0
  133. package/dist/public/node/analytics.js.map +1 -0
  134. package/dist/public/node/api/admin.d.ts +11 -0
  135. package/dist/public/node/api/admin.js +70 -0
  136. package/dist/public/node/api/admin.js.map +1 -0
  137. package/dist/public/node/api/oxygen.d.ts +22 -0
  138. package/dist/public/node/api/oxygen.js +40 -0
  139. package/dist/public/node/api/oxygen.js.map +1 -0
  140. package/dist/{api → public/node/api}/partners.d.ts +11 -3
  141. package/dist/public/node/api/partners.js +40 -0
  142. package/dist/public/node/api/partners.js.map +1 -0
  143. package/dist/public/node/archiver.js +1 -1
  144. package/dist/public/node/archiver.js.map +1 -1
  145. package/dist/public/node/base-command.js +1 -1
  146. package/dist/public/node/base-command.js.map +1 -1
  147. package/dist/public/node/crypto.d.ts +42 -0
  148. package/dist/public/node/crypto.js +55 -0
  149. package/dist/public/node/crypto.js.map +1 -0
  150. package/dist/public/node/error-handler.js +3 -2
  151. package/dist/public/node/error-handler.js.map +1 -1
  152. package/dist/public/node/framework.js +1 -1
  153. package/dist/public/node/framework.js.map +1 -1
  154. package/dist/public/node/hooks/postrun.js +2 -2
  155. package/dist/public/node/hooks/postrun.js.map +1 -1
  156. package/dist/public/node/hooks/prerun.js +2 -2
  157. package/dist/public/node/hooks/prerun.js.map +1 -1
  158. package/dist/{template.d.ts → public/node/liquid.d.ts} +10 -2
  159. package/dist/{template.js → public/node/liquid.js} +18 -13
  160. package/dist/public/node/liquid.js.map +1 -0
  161. package/dist/public/node/node-package-manager.d.ts +3 -3
  162. package/dist/public/node/node-package-manager.js +1 -1
  163. package/dist/public/node/node-package-manager.js.map +1 -1
  164. package/dist/public/node/os.d.ts +16 -0
  165. package/dist/{os.js → public/node/os.js} +33 -29
  166. package/dist/public/node/os.js.map +1 -0
  167. package/dist/public/node/presets.d.ts +1 -1
  168. package/dist/public/node/presets.js +2 -2
  169. package/dist/public/node/presets.js.map +1 -1
  170. package/dist/public/node/ruby.d.ts +13 -9
  171. package/dist/public/node/ruby.js +91 -23
  172. package/dist/public/node/ruby.js.map +1 -1
  173. package/dist/public/node/tcp.d.ts +2 -0
  174. package/dist/public/node/tcp.js +9 -0
  175. package/dist/public/node/tcp.js.map +1 -1
  176. package/dist/public/node/toml.d.ts +15 -0
  177. package/dist/public/node/toml.js +20 -0
  178. package/dist/public/node/toml.js.map +1 -0
  179. package/dist/public/node/ui.d.ts +12 -17
  180. package/dist/public/node/ui.js +25 -29
  181. package/dist/public/node/ui.js.map +1 -1
  182. package/dist/public/node/vscode.d.ts +14 -0
  183. package/dist/{vscode.js → public/node/vscode.js} +13 -7
  184. package/dist/public/node/vscode.js.map +1 -0
  185. package/dist/session/authorize.d.ts +4 -0
  186. package/dist/session/authorize.js +8 -3
  187. package/dist/session/authorize.js.map +1 -1
  188. package/dist/{api/identity.d.ts → session/identity-token-validation.d.ts} +0 -0
  189. package/dist/{api/identity.js → session/identity-token-validation.js} +1 -1
  190. package/dist/session/identity-token-validation.js.map +1 -0
  191. package/dist/session/redirect-listener.js +6 -3
  192. package/dist/session/redirect-listener.js.map +1 -1
  193. package/dist/session/schema.d.ts +18 -18
  194. package/dist/session/store.js +1 -1
  195. package/dist/session/store.js.map +1 -1
  196. package/dist/session.js +3 -3
  197. package/dist/session.js.map +1 -1
  198. package/dist/system.d.ts +2 -2
  199. package/dist/system.js +1 -1
  200. package/dist/system.js.map +1 -1
  201. package/dist/testing/ui.d.ts +1 -1
  202. package/dist/testing/ui.js +1 -1
  203. package/dist/testing/ui.js.map +1 -1
  204. package/dist/tsconfig.tsbuildinfo +1 -1
  205. package/dist/ui/inquirer/autocomplete.d.ts +2 -2
  206. package/dist/ui/inquirer/autocomplete.js +1 -1
  207. package/dist/ui/inquirer/autocomplete.js.map +1 -1
  208. package/dist/ui/inquirer/input.d.ts +2 -2
  209. package/dist/ui/inquirer/input.js.map +1 -1
  210. package/dist/ui/inquirer/password.d.ts +2 -2
  211. package/dist/ui/inquirer/password.js.map +1 -1
  212. package/dist/ui/inquirer/select.d.ts +2 -2
  213. package/dist/ui/inquirer/select.js +2 -2
  214. package/dist/ui/inquirer/select.js.map +1 -1
  215. package/package.json +30 -27
  216. package/dist/abort.d.ts +0 -1
  217. package/dist/abort.js +0 -2
  218. package/dist/abort.js.map +0 -1
  219. package/dist/analytics.d.ts +0 -44
  220. package/dist/analytics.js +0 -154
  221. package/dist/analytics.js.map +0 -1
  222. package/dist/api/admin.d.ts +0 -3
  223. package/dist/api/admin.js +0 -56
  224. package/dist/api/admin.js.map +0 -1
  225. package/dist/api/common.js.map +0 -1
  226. package/dist/api/identity.js.map +0 -1
  227. package/dist/api/oxygen.d.ts +0 -5
  228. package/dist/api/oxygen.js +0 -30
  229. package/dist/api/oxygen.js.map +0 -1
  230. package/dist/api/partners.js +0 -44
  231. package/dist/api/partners.js.map +0 -1
  232. package/dist/http/graphql.d.ts +0 -13
  233. package/dist/http/graphql.js +0 -12
  234. package/dist/http/graphql.js.map +0 -1
  235. package/dist/id.d.ts +0 -6
  236. package/dist/id.js +0 -18
  237. package/dist/id.js.map +0 -1
  238. package/dist/json.js.map +0 -1
  239. package/dist/os.d.ts +0 -10
  240. package/dist/os.js.map +0 -1
  241. package/dist/private/node/ui/components/Prompt.js +0 -23
  242. package/dist/private/node/ui/components/Prompt.js.map +0 -1
  243. package/dist/private/node/ui/components/Prompt.test.js.map +0 -1
  244. package/dist/string.d.ts +0 -28
  245. package/dist/string.js +0 -77
  246. package/dist/string.js.map +0 -1
  247. package/dist/template.js.map +0 -1
  248. package/dist/toml.d.ts +0 -3
  249. package/dist/toml.js +0 -8
  250. package/dist/toml.js.map +0 -1
  251. package/dist/vscode.d.ts +0 -8
  252. package/dist/vscode.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { Box } from 'ink';
1
+ import { Box, useStdout } from 'ink';
2
2
  import React, { useEffect, useState } from 'react';
3
3
  /**
4
4
  * `FullScreen` renders all output in a new buffer and makes it full screen. This is useful when:
@@ -6,24 +6,26 @@ import React, { useEffect, useState } from 'react';
6
6
  * - You want to respond to the resize event of the terminal. Whenever the user resizes their terminal window the output's height and width will be recalculated and re-rendered properly.
7
7
  */
8
8
  const FullScreen = ({ children }) => {
9
+ const { stdout } = useStdout();
10
+ const standardOutput = stdout;
9
11
  const [size, setSize] = useState({
10
- columns: process.stdout.columns,
11
- rows: process.stdout.rows,
12
+ columns: standardOutput.columns,
13
+ rows: standardOutput.rows,
12
14
  });
13
15
  useEffect(() => {
14
16
  function onResize() {
15
17
  setSize({
16
- columns: process.stdout.columns,
17
- rows: process.stdout.rows,
18
+ columns: standardOutput.columns,
19
+ rows: standardOutput.rows,
18
20
  });
19
21
  }
20
- process.stdout.on('resize', onResize);
22
+ standardOutput.on('resize', onResize);
21
23
  // switch to an alternate buffer
22
- process.stdout.write('\u001B[?1049h');
24
+ standardOutput.write('\u001B[?1049h');
23
25
  return () => {
24
- process.stdout.off('resize', onResize);
26
+ standardOutput.off('resize', onResize);
25
27
  // switch back to the main buffer
26
- process.stdout.write('\u001B[?1049l');
28
+ standardOutput.write('\u001B[?1049l');
27
29
  };
28
30
  }, []);
29
31
  return (React.createElement(Box, { width: size.columns, height: size.rows }, children));
@@ -1 +1 @@
1
- {"version":3,"file":"FullScreen.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FullScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAEhD;;;;GAIG;AACH,MAAM,UAAU,GAAa,CAAC,EAAC,QAAQ,EAAC,EAAe,EAAE;IACvD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC;QAC/B,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO;QAC/B,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;KAC1B,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,QAAQ;YACf,OAAO,CAAC;gBACN,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO;gBAC/B,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;aAC1B,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QACrC,gCAAgC;QAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QACrC,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACtC,iCAAiC;YACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QACvC,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,oBAAC,GAAG,IAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,IACxC,QAAQ,CACL,CACP,CAAA;AACH,CAAC,CAAA;AAED,eAAe,UAAU,CAAA","sourcesContent":["import {Box} from 'ink'\nimport React, {useEffect, useState} from 'react'\n\n/**\n * `FullScreen` renders all output in a new buffer and makes it full screen. This is useful when:\n * - You want to preserve terminal history. `ink` [normally clears the terminal history](https://github.com/vadimdemedes/ink/issues/382) if the rendered output is taller than the terminal window. By rendering in a separate buffer history will be preserved and will be visible after pressing `Ctrl+C`.\n * - You want to respond to the resize event of the terminal. Whenever the user resizes their terminal window the output's height and width will be recalculated and re-rendered properly.\n */\nconst FullScreen: React.FC = ({children}): JSX.Element => {\n const [size, setSize] = useState({\n columns: process.stdout.columns,\n rows: process.stdout.rows,\n })\n\n useEffect(() => {\n function onResize() {\n setSize({\n columns: process.stdout.columns,\n rows: process.stdout.rows,\n })\n }\n\n process.stdout.on('resize', onResize)\n // switch to an alternate buffer\n process.stdout.write('\\u001B[?1049h')\n return () => {\n process.stdout.off('resize', onResize)\n // switch back to the main buffer\n process.stdout.write('\\u001B[?1049l')\n }\n }, [])\n\n return (\n <Box width={size.columns} height={size.rows}>\n {children}\n </Box>\n )\n}\n\nexport default FullScreen\n"]}
1
+ {"version":3,"file":"FullScreen.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FullScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAE,SAAS,EAAC,MAAM,KAAK,CAAA;AAClC,OAAO,KAAK,EAAE,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAEhD;;;;GAIG;AACH,MAAM,UAAU,GAAa,CAAC,EAAC,QAAQ,EAAC,EAAe,EAAE;IACvD,MAAM,EAAC,MAAM,EAAC,GAAG,SAAS,EAAE,CAAA;IAC5B,MAAM,cAAc,GAAG,MAAO,CAAA;IAE9B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC;QAC/B,OAAO,EAAE,cAAc,CAAC,OAAO;QAC/B,IAAI,EAAE,cAAc,CAAC,IAAI;KAC1B,CAAC,CAAA;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,QAAQ;YACf,OAAO,CAAC;gBACN,OAAO,EAAE,cAAc,CAAC,OAAO;gBAC/B,IAAI,EAAE,cAAc,CAAC,IAAI;aAC1B,CAAC,CAAA;QACJ,CAAC;QAED,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QACrC,gCAAgC;QAChC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QACrC,OAAO,GAAG,EAAE;YACV,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;YACtC,iCAAiC;YACjC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QACvC,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,oBAAC,GAAG,IAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,IACxC,QAAQ,CACL,CACP,CAAA;AACH,CAAC,CAAA;AAED,eAAe,UAAU,CAAA","sourcesContent":["import {Box, useStdout} from 'ink'\nimport React, {useEffect, useState} from 'react'\n\n/**\n * `FullScreen` renders all output in a new buffer and makes it full screen. This is useful when:\n * - You want to preserve terminal history. `ink` [normally clears the terminal history](https://github.com/vadimdemedes/ink/issues/382) if the rendered output is taller than the terminal window. By rendering in a separate buffer history will be preserved and will be visible after pressing `Ctrl+C`.\n * - You want to respond to the resize event of the terminal. Whenever the user resizes their terminal window the output's height and width will be recalculated and re-rendered properly.\n */\nconst FullScreen: React.FC = ({children}): JSX.Element => {\n const {stdout} = useStdout()\n const standardOutput = stdout!\n\n const [size, setSize] = useState({\n columns: standardOutput.columns,\n rows: standardOutput.rows,\n })\n\n useEffect(() => {\n function onResize() {\n setSize({\n columns: standardOutput.columns,\n rows: standardOutput.rows,\n })\n }\n\n standardOutput.on('resize', onResize)\n // switch to an alternate buffer\n standardOutput.write('\\u001B[?1049h')\n return () => {\n standardOutput.off('resize', onResize)\n // switch back to the main buffer\n standardOutput.write('\\u001B[?1049l')\n }\n }, [])\n\n return (\n <Box width={size.columns} height={size.rows}>\n {children}\n </Box>\n )\n}\n\nexport default FullScreen\n"]}
@@ -1,22 +1,22 @@
1
1
  import { Link } from './Link.js';
2
- import { renderString } from '../../ui.js';
3
2
  import { describe, expect, test } from 'vitest';
4
3
  import React from 'react';
4
+ import { render } from 'ink-testing-library';
5
5
  describe('Link', async () => {
6
6
  test("renders correctly with a fallback for terminals that don't support hyperlinks", async () => {
7
7
  const link = {
8
8
  url: 'https://example.com',
9
9
  label: 'Example',
10
10
  };
11
- const { output } = renderString(React.createElement(Link, { ...link }));
12
- expect(output).toMatchInlineSnapshot('"Example ( https://example.com )"');
11
+ const { lastFrame } = render(React.createElement(Link, { ...link }));
12
+ expect(lastFrame()).toMatchInlineSnapshot('"Example ( https://example.com )"');
13
13
  });
14
14
  test("it doesn't render a fallback if only url is passed", async () => {
15
15
  const link = {
16
16
  url: 'https://example.com',
17
17
  };
18
- const { output } = renderString(React.createElement(Link, { ...link }));
19
- expect(output).toMatchInlineSnapshot('"https://example.com"');
18
+ const { lastFrame } = render(React.createElement(Link, { ...link }));
19
+ expect(lastFrame()).toMatchInlineSnapshot('"https://example.com"');
20
20
  });
21
21
  });
22
22
  //# sourceMappingURL=Link.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Link.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IAC1B,IAAI,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,IAAI,GAAG;YACX,GAAG,EAAE,qBAAqB;YAC1B,KAAK,EAAE,SAAS;SACjB,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,IAAI,GAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,4CAA4C,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,IAAI,GAAG;YACX,GAAG,EAAE,qBAAqB;SAC3B,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,IAAI,GAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,uBAAuB,CAAC,CAAA;IAC/D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Link} from './Link.js'\nimport {renderString} from '../../ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('Link', async () => {\n test(\"renders correctly with a fallback for terminals that don't support hyperlinks\", async () => {\n const link = {\n url: 'https://example.com',\n label: 'Example',\n }\n\n const {output} = renderString(<Link {...link} />)\n\n expect(output).toMatchInlineSnapshot('\"Example \u001b[2m( https://example.com )\u001b[22m\"')\n })\n\n test(\"it doesn't render a fallback if only url is passed\", async () => {\n const link = {\n url: 'https://example.com',\n }\n\n const {output} = renderString(<Link {...link} />)\n\n expect(output).toMatchInlineSnapshot('\"https://example.com\"')\n })\n})\n"]}
1
+ {"version":3,"file":"Link.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAA;AAE1C,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IAC1B,IAAI,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,IAAI,GAAG;YACX,GAAG,EAAE,qBAAqB;YAC1B,KAAK,EAAE,SAAS;SACjB,CAAA;QAED,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,IAAI,OAAK,IAAI,GAAI,CAAC,CAAA;QAE9C,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC,4CAA4C,CAAC,CAAA;IACzF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,IAAI,GAAG;YACX,GAAG,EAAE,qBAAqB;SAC3B,CAAA;QAED,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,IAAI,OAAK,IAAI,GAAI,CAAC,CAAA;QAE9C,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC,uBAAuB,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Link} from './Link.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\nimport {render} from 'ink-testing-library'\n\ndescribe('Link', async () => {\n test(\"renders correctly with a fallback for terminals that don't support hyperlinks\", async () => {\n const link = {\n url: 'https://example.com',\n label: 'Example',\n }\n\n const {lastFrame} = render(<Link {...link} />)\n\n expect(lastFrame()).toMatchInlineSnapshot('\"Example \u001b[2m( https://example.com )\u001b[22m\"')\n })\n\n test(\"it doesn't render a fallback if only url is passed\", async () => {\n const link = {\n url: 'https://example.com',\n }\n\n const {lastFrame} = render(<Link {...link} />)\n\n expect(lastFrame()).toMatchInlineSnapshot('\"https://example.com\"')\n })\n})\n"]}
@@ -1,8 +1,8 @@
1
1
  import { List } from './List.js';
2
- import { renderString } from '../../ui.js';
3
2
  import { unstyled } from '../../../../output.js';
4
3
  import { describe, expect, test } from 'vitest';
5
4
  import React from 'react';
5
+ import { render } from 'ink-testing-library';
6
6
  describe('List', async () => {
7
7
  test('renders unordered items', async () => {
8
8
  const options = {
@@ -10,8 +10,8 @@ describe('List', async () => {
10
10
  items: ['Item 1', 'Item 2', 'Item 3'],
11
11
  ordered: false,
12
12
  };
13
- const { output } = renderString(React.createElement(List, { ...options }));
14
- expect(unstyled(output)).toMatchInlineSnapshot(`
13
+ const { lastFrame } = render(React.createElement(List, { ...options }));
14
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
15
15
  "List title
16
16
  • Item 1
17
17
  • Item 2
@@ -23,8 +23,8 @@ describe('List', async () => {
23
23
  items: ['Item 1', 'Item 2', 'Item 3'],
24
24
  ordered: true,
25
25
  };
26
- const { output } = renderString(React.createElement(List, { ...options }));
27
- expect(unstyled(output)).toMatchInlineSnapshot(`
26
+ const { lastFrame } = render(React.createElement(List, { ...options }));
27
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
28
28
  " 1. Item 1
29
29
  2. Item 2
30
30
  3. Item 3"
@@ -1 +1 @@
1
- {"version":3,"file":"List.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IAC1B,IAAI,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,KAAK;SACf,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,OAAO,GAAI,CAAC,CAAA;QAEpD,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;KAK/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,IAAI;SACd,CAAA;QAED,MAAM,EAAC,MAAM,EAAC,GAAG,YAAY,CAAC,oBAAC,IAAI,OAAK,OAAO,GAAI,CAAC,CAAA;QAEpD,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;KAI/C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {List} from './List.js'\nimport {renderString} from '../../ui.js'\nimport {unstyled} from '../../../../output.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('List', async () => {\n test('renders unordered items', async () => {\n const options = {\n title: 'List title',\n items: ['Item 1', 'Item 2', 'Item 3'],\n ordered: false,\n }\n\n const {output} = renderString(<List {...options} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \"List title\n • Item 1\n • Item 2\n • Item 3\"\n `)\n })\n\n test('renders ordered items', async () => {\n const options = {\n items: ['Item 1', 'Item 2', 'Item 3'],\n ordered: true,\n }\n\n const {output} = renderString(<List {...options} />)\n\n expect(unstyled(output!)).toMatchInlineSnapshot(`\n \" 1. Item 1\n 2. Item 2\n 3. Item 3\"\n `)\n })\n})\n"]}
1
+ {"version":3,"file":"List.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAA;AAE1C,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IAC1B,IAAI,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,KAAK;SACf,CAAA;QAED,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,IAAI,OAAK,OAAO,GAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;KAKpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,OAAO,EAAE,IAAI;SACd,CAAA;QAED,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,IAAI,OAAK,OAAO,GAAI,CAAC,CAAA;QAEjD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;KAIpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {List} from './List.js'\nimport {unstyled} from '../../../../output.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\nimport {render} from 'ink-testing-library'\n\ndescribe('List', async () => {\n test('renders unordered items', async () => {\n const options = {\n title: 'List title',\n items: ['Item 1', 'Item 2', 'Item 3'],\n ordered: false,\n }\n\n const {lastFrame} = render(<List {...options} />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"List title\n • Item 1\n • Item 2\n • Item 3\"\n `)\n })\n\n test('renders ordered items', async () => {\n const options = {\n items: ['Item 1', 'Item 2', 'Item 3'],\n ordered: true,\n }\n\n const {lastFrame} = render(<List {...options} />)\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \" 1. Item 1\n 2. Item 2\n 3. Item 3\"\n `)\n })\n})\n"]}
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  export interface Props<T> {
3
3
  items: Item<T>[];
4
- onSelect: (value: T) => void;
4
+ onChange: (item: Item<T>) => void;
5
5
  }
6
6
  export interface Item<T> {
7
7
  label: string;
@@ -9,4 +9,4 @@ export interface Item<T> {
9
9
  key?: string;
10
10
  group?: string;
11
11
  }
12
- export default function SelectInput<T>({ items, onSelect }: React.PropsWithChildren<Props<T>>): JSX.Element | null;
12
+ export default function SelectInput<T>({ items, onChange }: React.PropsWithChildren<Props<T>>): JSX.Element | null;
@@ -1,9 +1,8 @@
1
- import { isTruthy } from '../../../../environment/utilities.js';
2
1
  import { isEqual } from '../../../../public/common/lang.js';
3
2
  import { groupBy } from '../../../../public/common/collection.js';
4
3
  import { mapValues } from '../../../../public/common/object.js';
5
4
  import React, { useState, useEffect, useRef, useCallback } from 'react';
6
- import { Box, Text, useApp, useInput } from 'ink';
5
+ import { Box, useInput, Text } from 'ink';
7
6
  function groupItems(items) {
8
7
  let index = 0;
9
8
  return mapValues(groupBy(items, 'group'), (groupItems) => groupItems.map((groupItem) => {
@@ -12,53 +11,46 @@ function groupItems(items) {
12
11
  return item;
13
12
  }));
14
13
  }
15
- export default function SelectInput({ items, onSelect }) {
14
+ export default function SelectInput({ items, onChange }) {
16
15
  const [inputStack, setInputStack] = useState(null);
17
16
  const [inputTimeout, setInputTimeout] = useState(null);
18
17
  const [selectedIndex, setSelectedIndex] = useState(0);
19
18
  const keys = useRef(new Set(items.map((item) => item.key)));
20
- const { exit: unmountInk } = useApp();
21
19
  const groupedItems = groupItems(items);
20
+ const groupedItemsValues = Object.values(groupedItems).flat();
22
21
  const groupTitles = Object.keys(groupedItems);
23
22
  const previousItems = useRef(items);
23
+ const changeSelection = useCallback((index) => {
24
+ const groupedItem = groupedItemsValues.find((item) => item.index === index);
25
+ setSelectedIndex(index);
26
+ onChange(items.find((item) => item.value === groupedItem.value));
27
+ }, [items]);
24
28
  // reset index when items change
25
29
  useEffect(() => {
26
30
  if (!isEqual(previousItems.current.map((item) => item.value), items.map((item) => item.value))) {
27
- setSelectedIndex(0);
31
+ changeSelection(0);
28
32
  }
29
33
  previousItems.current = items;
30
34
  }, [items]);
31
35
  const handleInput = useCallback((input, key) => {
32
- if (input === 'c' && key.ctrl) {
33
- // Exceptions being throw in these hooks aren't being caught by our errorHandler.
34
- // See also how we handle exceptions in CouncurrentOutput for reference.
35
- process.exit(1);
36
- }
37
36
  const parsedInput = parseInt(input, 10);
38
37
  if (parsedInput !== 0 && parsedInput <= items.length + 1) {
39
- setSelectedIndex(parsedInput - 1);
38
+ changeSelection(parsedInput - 1);
40
39
  }
41
40
  else if (keys.current.has(input)) {
42
- const index = items.findIndex((item) => item.key === input);
43
- if (index !== -1) {
44
- setSelectedIndex(index);
41
+ const groupedItem = groupedItemsValues.find((item) => item.key === input);
42
+ if (groupedItem !== undefined) {
43
+ changeSelection(groupedItem.index);
45
44
  }
46
45
  }
47
46
  if (key.upArrow) {
48
47
  const lastIndex = items.length - 1;
49
- setSelectedIndex(selectedIndex === 0 ? lastIndex : selectedIndex - 1);
48
+ changeSelection(selectedIndex === 0 ? lastIndex : selectedIndex - 1);
50
49
  }
51
50
  else if (key.downArrow) {
52
- setSelectedIndex(selectedIndex === items.length - 1 ? 0 : selectedIndex + 1);
53
- }
54
- else if (key.return) {
55
- onSelect(items[selectedIndex].value);
56
- // This is a workaround needed because Ink behaves differently in CI when
57
- // unmounting. See https://github.com/vadimdemedes/ink/pull/266
58
- if (!isTruthy(process.env.CI))
59
- unmountInk();
51
+ changeSelection(selectedIndex === items.length - 1 ? 0 : selectedIndex + 1);
60
52
  }
61
- }, [selectedIndex, items, onSelect]);
53
+ }, [selectedIndex, items]);
62
54
  useInput((input, key) => {
63
55
  if (input.length > 0 && Object.values(key).every((value) => value === false)) {
64
56
  const newInputStack = inputStack === null ? input : inputStack + input;
@@ -1 +1 @@
1
- {"version":3,"file":"SelectInput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/SelectInput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {isTruthy} from '../../../../environment/utilities.js'\nimport {isEqual} from '../../../../public/common/lang.js'\nimport {groupBy} from '../../../../public/common/collection.js'\nimport {mapValues} from '../../../../public/common/object.js'\nimport React, {useState, useEffect, useRef, useCallback} from 'react'\nimport {Box, Key, Text, useApp, useInput} from 'ink'\n\nexport interface Props<T> {\n items: Item<T>[]\n onSelect: (value: T) => void\n}\n\nexport interface Item<T> {\n label: string\n value: T\n key?: string\n group?: string\n}\n\nfunction groupItems<T>(items: Item<T>[]) {\n let index = 0\n\n return mapValues(groupBy(items, 'group'), (groupItems) =>\n groupItems.map((groupItem) => {\n const item = {...groupItem, key: groupItem.key ?? (index + 1).toString(), index}\n index += 1\n return item\n }),\n )\n}\n\nexport default function SelectInput<T>({items, onSelect}: React.PropsWithChildren<Props<T>>): JSX.Element | null {\n const [inputStack, setInputStack] = useState<string | null>(null)\n const [inputTimeout, setInputTimeout] = useState<NodeJS.Timeout | null>(null)\n const [selectedIndex, setSelectedIndex] = useState(0)\n const keys = useRef(new Set(items.map((item) => item.key)))\n const {exit: unmountInk} = useApp()\n const groupedItems = groupItems(items)\n const groupTitles = Object.keys(groupedItems)\n\n const previousItems = useRef<Item<T>[]>(items)\n\n // reset index when items change\n useEffect(() => {\n if (\n !isEqual(\n previousItems.current.map((item) => item.value),\n items.map((item) => item.value),\n )\n ) {\n setSelectedIndex(0)\n }\n\n previousItems.current = items\n }, [items])\n\n const handleInput = useCallback(\n (input: string, key: Key) => {\n if (input === 'c' && key.ctrl) {\n // Exceptions being throw in these hooks aren't being caught by our errorHandler.\n // See also how we handle exceptions in CouncurrentOutput for reference.\n process.exit(1)\n }\n\n const parsedInput = parseInt(input, 10)\n\n if (parsedInput !== 0 && parsedInput <= items.length + 1) {\n setSelectedIndex(parsedInput - 1)\n } else if (keys.current.has(input)) {\n const index = items.findIndex((item) => item.key === input)\n if (index !== -1) {\n setSelectedIndex(index)\n }\n }\n\n if (key.upArrow) {\n const lastIndex = items.length - 1\n\n setSelectedIndex(selectedIndex === 0 ? lastIndex : selectedIndex - 1)\n } else if (key.downArrow) {\n setSelectedIndex(selectedIndex === items.length - 1 ? 0 : selectedIndex + 1)\n } else if (key.return) {\n onSelect(items[selectedIndex]!.value)\n // This is a workaround needed because Ink behaves differently in CI when\n // unmounting. See https://github.com/vadimdemedes/ink/pull/266\n if (!isTruthy(process.env.CI)) unmountInk()\n }\n },\n [selectedIndex, items, onSelect],\n )\n\n useInput((input, key) => {\n if (input.length > 0 && Object.values(key).every((value) => value === false)) {\n const newInputStack = inputStack === null ? input : inputStack + input\n\n setInputStack(newInputStack)\n\n if (inputTimeout !== null) {\n clearTimeout(inputTimeout)\n }\n\n setInputTimeout(\n setTimeout(() => {\n handleInput(newInputStack, key)\n setInputStack(null)\n setInputTimeout(null)\n }, 300),\n )\n } else {\n handleInput(input, key)\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n {groupTitles.map((title) => {\n const hasTitle = title !== 'undefined'\n\n return (\n <Box key={title} flexDirection=\"column\" marginTop={hasTitle ? 1 : 0}>\n {hasTitle && (\n <Box marginLeft={3}>\n <Text bold>{title}</Text>\n </Box>\n )}\n {groupedItems[title]!.map((item) => {\n const isSelected = item.index === selectedIndex\n\n return (\n <Box key={item.key}>\n <Box marginRight={2}>{isSelected ? <Text color=\"cyan\">{`>`}</Text> : <Text> </Text>}</Box>\n\n <Text color={isSelected ? 'cyan' : undefined}>{`(${item.key}) ${item.label}`}</Text>\n </Box>\n )\n })}\n </Box>\n )\n })}\n\n <Box marginTop={1} marginLeft={3}>\n <Text dimColor>navigate with arrows, enter to select</Text>\n </Box>\n </Box>\n )\n}\n"]}
1
+ {"version":3,"file":"SelectInput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/SelectInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,mCAAmC,CAAA;AACzD,OAAO,EAAC,OAAO,EAAC,MAAM,yCAAyC,CAAA;AAC/D,OAAO,EAAC,SAAS,EAAC,MAAM,qCAAqC,CAAA;AAC7D,OAAO,KAAK,EAAE,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAC,MAAM,OAAO,CAAA;AACrE,OAAO,EAAC,GAAG,EAAO,QAAQ,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AAc5C,SAAS,UAAU,CAAI,KAAgB;IACrC,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CACvD,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,EAAC,GAAG,SAAS,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAC,CAAA;QAChF,KAAK,IAAI,CAAC,CAAA;QACV,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAI,EAAC,KAAK,EAAE,QAAQ,EAAoC;IACzF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IACjE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAwB,IAAI,CAAC,CAAA;IAC7E,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACrD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC3D,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IACtC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAC7C,MAAM,aAAa,GAAG,MAAM,CAAY,KAAK,CAAC,CAAA;IAE9C,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,KAAa,EAAE,EAAE;QAChB,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAE,CAAA;QAC5E,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACvB,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAE,CAAC,CAAA;IACnE,CAAC,EACD,CAAC,KAAK,CAAC,CACR,CAAA;IAED,gCAAgC;IAChC,SAAS,CAAC,GAAG,EAAE;QACb,IACE,CAAC,OAAO,CACN,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAC/C,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAChC,EACD;YACA,eAAe,CAAC,CAAC,CAAC,CAAA;SACnB;QAED,aAAa,CAAC,OAAO,GAAG,KAAK,CAAA;IAC/B,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,KAAa,EAAE,GAAQ,EAAE,EAAE;QAC1B,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAEvC,IAAI,WAAW,KAAK,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;YACxD,eAAe,CAAC,WAAW,GAAG,CAAC,CAAC,CAAA;SACjC;aAAM,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YAClC,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,CAAA;YACzE,IAAI,WAAW,KAAK,SAAS,EAAE;gBAC7B,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;aACnC;SACF;QAED,IAAI,GAAG,CAAC,OAAO,EAAE;YACf,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;YAElC,eAAe,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAA;SACrE;aAAM,IAAI,GAAG,CAAC,SAAS,EAAE;YACxB,eAAe,CAAC,aAAa,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAA;SAC5E;IACH,CAAC,EACD,CAAC,aAAa,EAAE,KAAK,CAAC,CACvB,CAAA;IAED,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE;YAC5E,MAAM,aAAa,GAAG,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,KAAK,CAAA;YAEtE,aAAa,CAAC,aAAa,CAAC,CAAA;YAE5B,IAAI,YAAY,KAAK,IAAI,EAAE;gBACzB,YAAY,CAAC,YAAY,CAAC,CAAA;aAC3B;YAED,eAAe,CACb,UAAU,CAAC,GAAG,EAAE;gBACd,WAAW,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;gBAC/B,aAAa,CAAC,IAAI,CAAC,CAAA;gBACnB,eAAe,CAAC,IAAI,CAAC,CAAA;YACvB,CAAC,EAAE,GAAG,CAAC,CACR,CAAA;SACF;aAAM;YACL,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;SACxB;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;QACxB,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACzB,MAAM,QAAQ,GAAG,KAAK,KAAK,WAAW,CAAA;YAEtC,OAAO,CACL,oBAAC,GAAG,IAAC,GAAG,EAAE,KAAK,EAAE,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChE,QAAQ,IAAI,CACX,oBAAC,GAAG,IAAC,UAAU,EAAE,CAAC;oBAChB,oBAAC,IAAI,IAAC,IAAI,UAAE,KAAK,CAAQ,CACrB,CACP;gBACA,YAAY,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;oBACjC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,KAAK,aAAa,CAAA;oBAE/C,OAAO,CACL,oBAAC,GAAG,IAAC,GAAG,EAAE,IAAI,CAAC,GAAG;wBAChB,oBAAC,GAAG,IAAC,WAAW,EAAE,CAAC,IAAG,UAAU,CAAC,CAAC,CAAC,oBAAC,IAAI,IAAC,KAAK,EAAC,MAAM,IAAE,GAAG,CAAQ,CAAC,CAAC,CAAC,oBAAC,IAAI,YAAS,CAAO;wBAE1F,oBAAC,IAAI,IAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,IAAG,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,CAAQ,CAChF,CACP,CAAA;gBACH,CAAC,CAAC,CACE,CACP,CAAA;QACH,CAAC,CAAC;QAEF,oBAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;YAC9B,oBAAC,IAAI,IAAC,QAAQ,kDAA6C,CACvD,CACF,CACP,CAAA;AACH,CAAC","sourcesContent":["import {isEqual} from '../../../../public/common/lang.js'\nimport {groupBy} from '../../../../public/common/collection.js'\nimport {mapValues} from '../../../../public/common/object.js'\nimport React, {useState, useEffect, useRef, useCallback} from 'react'\nimport {Box, Key, useInput, Text} from 'ink'\n\nexport interface Props<T> {\n items: Item<T>[]\n onChange: (item: Item<T>) => void\n}\n\nexport interface Item<T> {\n label: string\n value: T\n key?: string\n group?: string\n}\n\nfunction groupItems<T>(items: Item<T>[]) {\n let index = 0\n\n return mapValues(groupBy(items, 'group'), (groupItems) =>\n groupItems.map((groupItem) => {\n const item = {...groupItem, key: groupItem.key ?? (index + 1).toString(), index}\n index += 1\n return item\n }),\n )\n}\n\nexport default function SelectInput<T>({items, onChange}: React.PropsWithChildren<Props<T>>): JSX.Element | null {\n const [inputStack, setInputStack] = useState<string | null>(null)\n const [inputTimeout, setInputTimeout] = useState<NodeJS.Timeout | null>(null)\n const [selectedIndex, setSelectedIndex] = useState(0)\n const keys = useRef(new Set(items.map((item) => item.key)))\n const groupedItems = groupItems(items)\n const groupedItemsValues = Object.values(groupedItems).flat()\n const groupTitles = Object.keys(groupedItems)\n const previousItems = useRef<Item<T>[]>(items)\n\n const changeSelection = useCallback(\n (index: number) => {\n const groupedItem = groupedItemsValues.find((item) => item.index === index)!\n setSelectedIndex(index)\n onChange(items.find((item) => item.value === groupedItem.value)!)\n },\n [items],\n )\n\n // reset index when items change\n useEffect(() => {\n if (\n !isEqual(\n previousItems.current.map((item) => item.value),\n items.map((item) => item.value),\n )\n ) {\n changeSelection(0)\n }\n\n previousItems.current = items\n }, [items])\n\n const handleInput = useCallback(\n (input: string, key: Key) => {\n const parsedInput = parseInt(input, 10)\n\n if (parsedInput !== 0 && parsedInput <= items.length + 1) {\n changeSelection(parsedInput - 1)\n } else if (keys.current.has(input)) {\n const groupedItem = groupedItemsValues.find((item) => item.key === input)\n if (groupedItem !== undefined) {\n changeSelection(groupedItem.index)\n }\n }\n\n if (key.upArrow) {\n const lastIndex = items.length - 1\n\n changeSelection(selectedIndex === 0 ? lastIndex : selectedIndex - 1)\n } else if (key.downArrow) {\n changeSelection(selectedIndex === items.length - 1 ? 0 : selectedIndex + 1)\n }\n },\n [selectedIndex, items],\n )\n\n useInput((input, key) => {\n if (input.length > 0 && Object.values(key).every((value) => value === false)) {\n const newInputStack = inputStack === null ? input : inputStack + input\n\n setInputStack(newInputStack)\n\n if (inputTimeout !== null) {\n clearTimeout(inputTimeout)\n }\n\n setInputTimeout(\n setTimeout(() => {\n handleInput(newInputStack, key)\n setInputStack(null)\n setInputTimeout(null)\n }, 300),\n )\n } else {\n handleInput(input, key)\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n {groupTitles.map((title) => {\n const hasTitle = title !== 'undefined'\n\n return (\n <Box key={title} flexDirection=\"column\" marginTop={hasTitle ? 1 : 0}>\n {hasTitle && (\n <Box marginLeft={3}>\n <Text bold>{title}</Text>\n </Box>\n )}\n {groupedItems[title]!.map((item) => {\n const isSelected = item.index === selectedIndex\n\n return (\n <Box key={item.key}>\n <Box marginRight={2}>{isSelected ? <Text color=\"cyan\">{`>`}</Text> : <Text> </Text>}</Box>\n\n <Text color={isSelected ? 'cyan' : undefined}>{`(${item.key}) ${item.label}`}</Text>\n </Box>\n )\n })}\n </Box>\n )\n })}\n\n <Box marginTop={1} marginLeft={3}>\n <Text dimColor>navigate with arrows, enter to select</Text>\n </Box>\n </Box>\n )\n}\n"]}
@@ -1,13 +1,13 @@
1
1
  import SelectInput from './SelectInput.js';
2
- import { waitForInputsToBeReady, waitForChange, sendInput } from '../../../../testing/ui.js';
2
+ import { waitForInputsToBeReady, sendInput } from '../../../../testing/ui.js';
3
3
  import { describe, expect, test, vi } from 'vitest';
4
4
  import React from 'react';
5
5
  import { render } from 'ink-testing-library';
6
6
  const ARROW_UP = '\u001B[A';
7
7
  const ARROW_DOWN = '\u001B[B';
8
- const ENTER = '\r';
9
8
  describe('SelectInput', async () => {
10
9
  test('move up with up arrow key', async () => {
10
+ const onChange = vi.fn();
11
11
  const items = [
12
12
  {
13
13
  label: 'First',
@@ -22,7 +22,7 @@ describe('SelectInput', async () => {
22
22
  value: 'third',
23
23
  },
24
24
  ];
25
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: () => { } }));
25
+ const renderInstance = render(React.createElement(SelectInput, { items: items, onChange: onChange }));
26
26
  await waitForInputsToBeReady();
27
27
  await sendInput(renderInstance, ARROW_UP);
28
28
  expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
@@ -32,8 +32,10 @@ describe('SelectInput', async () => {
32
32
 
33
33
  navigate with arrows, enter to select"
34
34
  `);
35
+ expect(onChange).toHaveBeenCalledWith(items[2]);
35
36
  });
36
37
  test('move down with down arrow key', async () => {
38
+ const onChange = vi.fn();
37
39
  const items = [
38
40
  {
39
41
  label: 'First',
@@ -48,7 +50,7 @@ describe('SelectInput', async () => {
48
50
  value: 'third',
49
51
  },
50
52
  ];
51
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: () => { } }));
53
+ const renderInstance = render(React.createElement(SelectInput, { items: items, onChange: onChange }));
52
54
  await waitForInputsToBeReady();
53
55
  await sendInput(renderInstance, ARROW_DOWN);
54
56
  expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
@@ -58,30 +60,10 @@ describe('SelectInput', async () => {
58
60
 
59
61
  navigate with arrows, enter to select"
60
62
  `);
61
- });
62
- test('select item with enter key', async () => {
63
- const onEnter = vi.fn();
64
- const items = [
65
- {
66
- label: 'First',
67
- value: 'first',
68
- },
69
- {
70
- label: 'Second',
71
- value: 'second',
72
- },
73
- {
74
- label: 'Third',
75
- value: 'third',
76
- },
77
- ];
78
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: onEnter }));
79
- await waitForInputsToBeReady();
80
- await sendInput(renderInstance, ARROW_DOWN);
81
- await waitForChange(() => renderInstance.stdin.write(ENTER), () => onEnter.mock.calls.length);
82
- expect(onEnter).toHaveBeenCalledWith(items[1].value);
63
+ expect(onChange).toHaveBeenCalledWith(items[1]);
83
64
  });
84
65
  test('handles keys with multiple digits', async () => {
66
+ const onChange = vi.fn();
85
67
  const items = [
86
68
  {
87
69
  label: 'First',
@@ -97,7 +79,7 @@ describe('SelectInput', async () => {
97
79
  key: '10',
98
80
  },
99
81
  ];
100
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: () => { } }));
82
+ const renderInstance = render(React.createElement(SelectInput, { items: items, onChange: onChange }));
101
83
  await waitForInputsToBeReady();
102
84
  await sendInput(renderInstance, '1', '0');
103
85
  expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
@@ -107,8 +89,10 @@ describe('SelectInput', async () => {
107
89
 
108
90
  navigate with arrows, enter to select"
109
91
  `);
92
+ expect(onChange).toHaveBeenCalledWith(items[2]);
110
93
  });
111
94
  test('handles custom keys', async () => {
95
+ const onChange = vi.fn();
112
96
  const items = [
113
97
  {
114
98
  label: 'First',
@@ -124,7 +108,7 @@ describe('SelectInput', async () => {
124
108
  key: 't',
125
109
  },
126
110
  ];
127
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: () => { } }));
111
+ const renderInstance = render(React.createElement(SelectInput, { items: items, onChange: onChange }));
128
112
  await waitForInputsToBeReady();
129
113
  await sendInput(renderInstance, 't');
130
114
  expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
@@ -134,8 +118,10 @@ describe('SelectInput', async () => {
134
118
 
135
119
  navigate with arrows, enter to select"
136
120
  `);
121
+ expect(onChange).toHaveBeenCalledWith(items[2]);
137
122
  });
138
123
  test('rotate after reaching the end of the list', async () => {
124
+ const onChange = vi.fn();
139
125
  const items = [
140
126
  {
141
127
  label: 'First',
@@ -150,7 +136,7 @@ describe('SelectInput', async () => {
150
136
  value: 'third',
151
137
  },
152
138
  ];
153
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: () => { } }));
139
+ const renderInstance = render(React.createElement(SelectInput, { items: items, onChange: onChange }));
154
140
  await waitForInputsToBeReady();
155
141
  await sendInput(renderInstance, ARROW_DOWN);
156
142
  await sendInput(renderInstance, ARROW_DOWN);
@@ -162,21 +148,23 @@ describe('SelectInput', async () => {
162
148
 
163
149
  navigate with arrows, enter to select"
164
150
  `);
151
+ expect(onChange).toHaveBeenCalledWith(items[0]);
165
152
  });
166
153
  test('support groups', async () => {
154
+ const onChange = vi.fn();
167
155
  const items = [
168
156
  { label: 'first', value: 'first', key: 'f' },
169
157
  { label: 'second', value: 'second', key: 's' },
170
158
  { label: 'third', value: 'third' },
171
159
  { label: 'fourth', value: 'fourth' },
172
- { label: 'fifth', value: 'fifth', group: 'Automations' },
160
+ { label: 'fifth', value: 'fifth', group: 'Automations', key: 'a' },
173
161
  { label: 'sixth', value: 'sixth', group: 'Automations' },
174
162
  { label: 'seventh', value: 'seventh' },
175
163
  { label: 'eighth', value: 'eighth', group: 'Merchant Admin' },
176
164
  { label: 'ninth', value: 'ninth', group: 'Merchant Admin' },
177
165
  { label: 'tenth', value: 'tenth' },
178
166
  ];
179
- const renderInstance = render(React.createElement(SelectInput, { items: items, onSelect: () => { } }));
167
+ const renderInstance = render(React.createElement(SelectInput, { items: items, onChange: onChange }));
180
168
  expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
181
169
  "> (f) first
182
170
  (s) second
@@ -186,7 +174,48 @@ describe('SelectInput', async () => {
186
174
  (6) tenth
187
175
 
188
176
  Automations
189
- (7) fifth
177
+ (a) fifth
178
+ (8) sixth
179
+
180
+ Merchant Admin
181
+ (9) eighth
182
+ (10) ninth
183
+
184
+ navigate with arrows, enter to select"
185
+ `);
186
+ await waitForInputsToBeReady();
187
+ await sendInput(renderInstance, 'a');
188
+ expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
189
+ " (f) first
190
+ (s) second
191
+ (3) third
192
+ (4) fourth
193
+ (5) seventh
194
+ (6) tenth
195
+
196
+ Automations
197
+ > (a) fifth
198
+ (8) sixth
199
+
200
+ Merchant Admin
201
+ (9) eighth
202
+ (10) ninth
203
+
204
+ navigate with arrows, enter to select"
205
+ `);
206
+ expect(onChange).toHaveBeenCalledWith(items[4]);
207
+ await sendInput(renderInstance, ARROW_UP);
208
+ await sendInput(renderInstance, ARROW_UP);
209
+ expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`
210
+ " (f) first
211
+ (s) second
212
+ (3) third
213
+ (4) fourth
214
+ > (5) seventh
215
+ (6) tenth
216
+
217
+ Automations
218
+ (a) fifth
190
219
  (8) sixth
191
220
 
192
221
  Merchant Admin
@@ -195,6 +224,7 @@ describe('SelectInput', async () => {
195
224
 
196
225
  navigate with arrows, enter to select"
197
226
  `);
227
+ expect(onChange).toHaveBeenCalledWith(items[6]);
198
228
  });
199
229
  });
200
230
  //# sourceMappingURL=SelectInput.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SelectInput.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/SelectInput.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import SelectInput from './SelectInput.js'\nimport {waitForInputsToBeReady, waitForChange, sendInput} from '../../../../testing/ui.js'\nimport {describe, expect, test, vi} from 'vitest'\nimport React from 'react'\nimport {render} from 'ink-testing-library'\n\nconst ARROW_UP = '\\u001B[A'\nconst ARROW_DOWN = '\\u001B[B'\nconst ENTER = '\\r'\n\ndescribe('SelectInput', async () => {\n test('move up with up arrow key', async () => {\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={() => {}} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_UP)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n (2) Second\n \u001b[36m>\u001b[39m \u001b[36m(3) Third\u001b[39m\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n })\n\n test('move down with down arrow key', async () => {\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={() => {}} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n \u001b[36m>\u001b[39m \u001b[36m(2) Second\u001b[39m\n (3) Third\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n })\n\n test('select item with enter key', async () => {\n const onEnter = vi.fn()\n\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={onEnter} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_DOWN)\n await waitForChange(\n () => renderInstance.stdin.write(ENTER),\n () => onEnter.mock.calls.length,\n )\n\n expect(onEnter).toHaveBeenCalledWith(items[1]!.value)\n })\n\n test('handles keys with multiple digits', async () => {\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Tenth',\n value: 'tenth',\n key: '10',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={() => {}} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, '1', '0')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n (2) Second\n \u001b[36m>\u001b[39m \u001b[36m(10) Tenth\u001b[39m\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n })\n\n test('handles custom keys', async () => {\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n key: 't',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={() => {}} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, 't')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n (2) Second\n \u001b[36m>\u001b[39m \u001b[36m(t) Third\u001b[39m\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n })\n\n test('rotate after reaching the end of the list', async () => {\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={() => {}} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_DOWN)\n await sendInput(renderInstance, ARROW_DOWN)\n await sendInput(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[36m>\u001b[39m \u001b[36m(1) First\u001b[39m\n (2) Second\n (3) Third\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n })\n\n test('support groups', async () => {\n const items = [\n {label: 'first', value: 'first', key: 'f'},\n {label: 'second', value: 'second', key: 's'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n {label: 'fifth', value: 'fifth', group: 'Automations'},\n {label: 'sixth', value: 'sixth', group: 'Automations'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth', group: 'Merchant Admin'},\n {label: 'ninth', value: 'ninth', group: 'Merchant Admin'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(<SelectInput items={items} onSelect={() => {}} />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[36m>\u001b[39m \u001b[36m(f) first\u001b[39m\n (s) second\n (3) third\n (4) fourth\n (5) seventh\n (6) tenth\n\n \u001b[1mAutomations\u001b[22m\n (7) fifth\n (8) sixth\n\n \u001b[1mMerchant Admin\u001b[22m\n (9) eighth\n (10) ninth\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n })\n})\n"]}
1
+ {"version":3,"file":"SelectInput.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/SelectInput.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import SelectInput from './SelectInput.js'\nimport {waitForInputsToBeReady, sendInput} from '../../../../testing/ui.js'\nimport {describe, expect, test, vi} from 'vitest'\nimport React from 'react'\nimport {render} from 'ink-testing-library'\n\nconst ARROW_UP = '\\u001B[A'\nconst ARROW_DOWN = '\\u001B[B'\n\ndescribe('SelectInput', async () => {\n test('move up with up arrow key', async () => {\n const onChange = vi.fn()\n\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onChange={onChange} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_UP)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n (2) Second\n \u001b[36m>\u001b[39m \u001b[36m(3) Third\u001b[39m\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[2]!)\n })\n\n test('move down with down arrow key', async () => {\n const onChange = vi.fn()\n\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onChange={onChange} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n \u001b[36m>\u001b[39m \u001b[36m(2) Second\u001b[39m\n (3) Third\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[1]!)\n })\n\n test('handles keys with multiple digits', async () => {\n const onChange = vi.fn()\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Tenth',\n value: 'tenth',\n key: '10',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onChange={onChange} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, '1', '0')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n (2) Second\n \u001b[36m>\u001b[39m \u001b[36m(10) Tenth\u001b[39m\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[2]!)\n })\n\n test('handles custom keys', async () => {\n const onChange = vi.fn()\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n key: 't',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onChange={onChange} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, 't')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (1) First\n (2) Second\n \u001b[36m>\u001b[39m \u001b[36m(t) Third\u001b[39m\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[2]!)\n })\n\n test('rotate after reaching the end of the list', async () => {\n const onChange = vi.fn()\n const items = [\n {\n label: 'First',\n value: 'first',\n },\n {\n label: 'Second',\n value: 'second',\n },\n {\n label: 'Third',\n value: 'third',\n },\n ]\n\n const renderInstance = render(<SelectInput items={items} onChange={onChange} />)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, ARROW_DOWN)\n await sendInput(renderInstance, ARROW_DOWN)\n await sendInput(renderInstance, ARROW_DOWN)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[36m>\u001b[39m \u001b[36m(1) First\u001b[39m\n (2) Second\n (3) Third\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[0]!)\n })\n\n test('support groups', async () => {\n const onChange = vi.fn()\n\n const items = [\n {label: 'first', value: 'first', key: 'f'},\n {label: 'second', value: 'second', key: 's'},\n {label: 'third', value: 'third'},\n {label: 'fourth', value: 'fourth'},\n {label: 'fifth', value: 'fifth', group: 'Automations', key: 'a'},\n {label: 'sixth', value: 'sixth', group: 'Automations'},\n {label: 'seventh', value: 'seventh'},\n {label: 'eighth', value: 'eighth', group: 'Merchant Admin'},\n {label: 'ninth', value: 'ninth', group: 'Merchant Admin'},\n {label: 'tenth', value: 'tenth'},\n ]\n\n const renderInstance = render(<SelectInput items={items} onChange={onChange} />)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[36m>\u001b[39m \u001b[36m(f) first\u001b[39m\n (s) second\n (3) third\n (4) fourth\n (5) seventh\n (6) tenth\n\n \u001b[1mAutomations\u001b[22m\n (a) fifth\n (8) sixth\n\n \u001b[1mMerchant Admin\u001b[22m\n (9) eighth\n (10) ninth\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n\n await waitForInputsToBeReady()\n await sendInput(renderInstance, 'a')\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (f) first\n (s) second\n (3) third\n (4) fourth\n (5) seventh\n (6) tenth\n\n \u001b[1mAutomations\u001b[22m\n \u001b[36m>\u001b[39m \u001b[36m(a) fifth\u001b[39m\n (8) sixth\n\n \u001b[1mMerchant Admin\u001b[22m\n (9) eighth\n (10) ninth\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[4]!)\n\n await sendInput(renderInstance, ARROW_UP)\n await sendInput(renderInstance, ARROW_UP)\n\n expect(renderInstance.lastFrame()).toMatchInlineSnapshot(`\n \" (f) first\n (s) second\n (3) third\n (4) fourth\n \u001b[36m>\u001b[39m \u001b[36m(5) seventh\u001b[39m\n (6) tenth\n\n \u001b[1mAutomations\u001b[22m\n (a) fifth\n (8) sixth\n\n \u001b[1mMerchant Admin\u001b[22m\n (9) eighth\n (10) ninth\n\n \u001b[2mnavigate with arrows, enter to select\u001b[22m\"\n `)\n expect(onChange).toHaveBeenCalledWith(items[6]!)\n })\n})\n"]}
@@ -1,10 +1,11 @@
1
1
  import { Props as SelectProps } from './SelectInput.js';
2
2
  import { Props as TableProps } from './Table.js';
3
- import React from 'react';
3
+ import React, { ReactElement } from 'react';
4
4
  export interface Props<T> {
5
5
  message: string;
6
6
  choices: SelectProps<T>['items'];
7
- onChoose: SelectProps<T>['onSelect'];
7
+ onSubmit: (value: T) => void;
8
8
  infoTable?: TableProps['table'];
9
9
  }
10
- export default function Prompt<T>({ message, choices, infoTable, onChoose, }: React.PropsWithChildren<Props<T>>): JSX.Element | null;
10
+ declare function SelectPrompt<T>({ message, choices, infoTable, onSubmit, }: React.PropsWithChildren<Props<T>>): ReactElement | null;
11
+ export { SelectPrompt };
@@ -0,0 +1,46 @@
1
+ import SelectInput from './SelectInput.js';
2
+ import Table from './Table.js';
3
+ import { handleCtrlC } from '../../ui.js';
4
+ import React, { useCallback, useState } from 'react';
5
+ import { Box, measureElement, Text, useApp, useInput, useStdout } from 'ink';
6
+ import { figures } from 'listr2';
7
+ import ansiEscapes from 'ansi-escapes';
8
+ function SelectPrompt({ message, choices, infoTable, onSubmit, }) {
9
+ const [answer, setAnswer] = useState(choices[0]);
10
+ const { exit: unmountInk } = useApp();
11
+ const [submitted, setSubmitted] = useState(false);
12
+ const { stdout } = useStdout();
13
+ const [height, setHeight] = useState(0);
14
+ const measuredRef = useCallback((node) => {
15
+ if (node !== null) {
16
+ const { height } = measureElement(node);
17
+ setHeight(height);
18
+ }
19
+ }, []);
20
+ useInput(useCallback((input, key) => {
21
+ handleCtrlC(input, key);
22
+ if (key.return) {
23
+ if (stdout && height >= stdout.rows) {
24
+ stdout.write(ansiEscapes.clearTerminal);
25
+ }
26
+ setSubmitted(true);
27
+ unmountInk();
28
+ onSubmit(answer.value);
29
+ }
30
+ }, [answer, onSubmit, height]));
31
+ return (React.createElement(Box, { flexDirection: "column", marginBottom: 1, ref: measuredRef },
32
+ React.createElement(Box, null,
33
+ React.createElement(Box, { marginRight: 2 },
34
+ React.createElement(Text, null, "?")),
35
+ React.createElement(Text, null, message)),
36
+ infoTable && !submitted && (React.createElement(Box, { marginLeft: 7 },
37
+ React.createElement(Table, { table: infoTable }))),
38
+ submitted ? (React.createElement(Box, null,
39
+ React.createElement(Box, { marginRight: 2 },
40
+ React.createElement(Text, { color: "cyan" }, figures.tick)),
41
+ React.createElement(Text, { color: "cyan" }, answer.label))) : (React.createElement(SelectInput, { items: choices, onChange: (item) => {
42
+ setAnswer(item);
43
+ } }))));
44
+ }
45
+ export { SelectPrompt };
46
+ //# sourceMappingURL=SelectPrompt.js.map