@inquirer/password
Advanced tools
+9
-1
@@ -6,2 +6,3 @@ import { type Theme } from '@inquirer/core'; | ||
| maskedText: string; | ||
| keysHelpTip: (keys: [key: string, action: string][]) => string | undefined; | ||
| }; | ||
@@ -12,6 +13,13 @@ }; | ||
| mask?: boolean | string; | ||
| toggleMask?: boolean; | ||
| validate?: (value: string) => boolean | string | Promise<string | boolean>; | ||
| theme?: PartialDeep<Theme<PasswordTheme>>; | ||
| }; | ||
| declare const _default: import("@inquirer/type").Prompt<string, PasswordConfig>; | ||
| declare const _default: import("@inquirer/type").Prompt<string, { | ||
| message: string; | ||
| mask?: boolean | string | undefined; | ||
| toggleMask?: boolean | undefined; | ||
| validate?: ((value: string) => boolean | string | Promise<string | boolean>) | undefined; | ||
| theme?: PartialDeep<Theme<PasswordTheme>> | undefined; | ||
| } & PasswordConfig>; | ||
| export default _default; |
+27
-8
| import { createPrompt, useState, useKeypress, usePrefix, isEnterKey, makeTheme, } from '@inquirer/core'; | ||
| import { cursorHide } from '@inquirer/ansi'; | ||
| import { styleText } from 'node:util'; | ||
| const passwordTheme = { | ||
| style: { | ||
| maskedText: '[input is masked]', | ||
| keysHelpTip: (keys) => keys | ||
| .map(([key, action]) => `${styleText('bold', key)} ${styleText('dim', action)}`) | ||
| .join(styleText('dim', ' • ')), | ||
| }, | ||
| }; | ||
| export default createPrompt((config, done) => { | ||
| const { validate = () => true } = config; | ||
| const { toggleMask = true, validate = () => true } = config; | ||
| const theme = makeTheme(passwordTheme, config.theme); | ||
@@ -14,2 +18,3 @@ const [status, setStatus] = useState('idle'); | ||
| const [value, setValue] = useState(''); | ||
| const [revealed, setRevealed] = useState(false); | ||
| const prefix = usePrefix({ status, theme }); | ||
@@ -38,2 +43,5 @@ useKeypress(async (key, rl) => { | ||
| } | ||
| else if (toggleMask && key.ctrl && key.name === 't') { | ||
| setRevealed((prev) => !prev); | ||
| } | ||
| else { | ||
@@ -45,5 +53,8 @@ setValue(rl.line); | ||
| const message = theme.style.message(config.message, status); | ||
| const showPlaintext = toggleMask && revealed && status === 'idle'; | ||
| let formattedValue = ''; | ||
| let helpTip; | ||
| if (config.mask) { | ||
| if (showPlaintext) { | ||
| formattedValue = value; | ||
| } | ||
| else if (config.mask) { | ||
| const maskChar = typeof config.mask === 'string' ? config.mask : '*'; | ||
@@ -53,3 +64,3 @@ formattedValue = maskChar.repeat(value.length); | ||
| else if (status !== 'done') { | ||
| helpTip = `${theme.style.help(theme.style.maskedText)}${cursorHide}`; | ||
| formattedValue = theme.style.help(theme.style.maskedText); | ||
| } | ||
@@ -59,7 +70,15 @@ if (status === 'done') { | ||
| } | ||
| let error = ''; | ||
| if (errorMsg) { | ||
| error = theme.style.error(errorMsg); | ||
| else if (!config.mask) { | ||
| formattedValue += cursorHide; | ||
| } | ||
| return [[prefix, message, config.mask ? formattedValue : helpTip].join(' '), error]; | ||
| const content = [prefix, message, formattedValue].filter(Boolean).join(' '); | ||
| const bottomContent = [ | ||
| errorMsg ? theme.style.error(errorMsg) : '', | ||
| toggleMask && status === 'idle' | ||
| ? theme.style.keysHelpTip([['ctrl+t', 'toggle visibility']]) | ||
| : '', | ||
| ] | ||
| .filter(Boolean) | ||
| .join('\n'); | ||
| return [content, bottomContent]; | ||
| }); |
+4
-4
| { | ||
| "name": "@inquirer/password", | ||
| "version": "5.1.2", | ||
| "version": "5.2.0", | ||
| "description": "Inquirer password prompt", | ||
@@ -71,4 +71,4 @@ "keywords": [ | ||
| "@inquirer/ansi": "^2.0.7", | ||
| "@inquirer/core": "^12.0.0", | ||
| "@inquirer/type": "^4.0.7" | ||
| "@inquirer/core": "^12.0.1", | ||
| "@inquirer/type": "^4.1.0" | ||
| }, | ||
@@ -92,3 +92,3 @@ "devDependencies": { | ||
| "types": "./dist/index.d.ts", | ||
| "gitHead": "999706755afbdcae271f62decbd9bcd05560905b" | ||
| "gitHead": "51ac389603405e8f9f315ce49416153d95c5fefe" | ||
| } |
+24
-6
@@ -63,8 +63,9 @@ # `@inquirer/password` | ||
| | Property | Type | Required | Description | | ||
| | -------- | ----------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | message | `string` | yes | The question to ask | | ||
| | mask | `boolean` | no | Show a `*` mask over the input or keep it transparent | | ||
| | validate | `string => boolean \| string \| Promise<boolean \| string>` | no | On submit, validate the filtered answered content. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. | | ||
| | theme | [See Theming](#Theming) | no | Customize look of the prompt. | | ||
| | Property | Type | Required | Description | | ||
| | ---------- | ----------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | message | `string` | yes | The question to ask | | ||
| | mask | `boolean \| string` | no | Show a `*` mask over the input, use a custom mask character, or keep it transparent. | | ||
| | toggleMask | `boolean` | no | Allow the user to press `ctrl+t` to temporarily reveal the typed value. Defaults to `true`; set to `false` to disable both the shortcut and its help line. | | ||
| | validate | `string => boolean \| string \| Promise<boolean \| string>` | no | On submit, validate the filtered answered content. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. | | ||
| | theme | [See Theming](#Theming) | no | Customize look of the prompt. | | ||
@@ -87,2 +88,4 @@ ## Theming | ||
| help: (text: string) => string; | ||
| maskedText: string; | ||
| keysHelpTip: (keys: [key: string, action: string][]) => string | undefined; | ||
| }; | ||
@@ -92,2 +95,17 @@ }; | ||
| `maskedText` is the inline tip shown when `mask` is off and the value is hidden (default: `[input is masked]`). | ||
| ### `theme.style.keysHelpTip` | ||
| This function customizes the keyboard shortcut help displayed on the line below the prompt. It receives `[['ctrl+t', 'toggle visibility']]` while the value is hidden. Use it to change the formatting or localize the action, or return `undefined` to hide the help line entirely. | ||
| ```js | ||
| theme: { | ||
| style: { | ||
| keysHelpTip: (keys) => | ||
| keys.map(([key, action]) => `${key}: ${action}`).join(' | '), | ||
| }, | ||
| } | ||
| ``` | ||
| # License | ||
@@ -94,0 +112,0 @@ |
10955
24.18%102
36%112
19.15%Updated
Updated