diff --git a/packages/console/src/components/TextInput/index.module.scss b/packages/console/src/components/TextInput/index.module.scss index c8e0c8df8..7e888390a 100644 --- a/packages/console/src/components/TextInput/index.module.scss +++ b/packages/console/src/components/TextInput/index.module.scss @@ -6,6 +6,12 @@ display: none; } +.hideTextContainerContent { + input { + -webkit-text-security: disc; + } +} + .container { display: flex; align-items: center; diff --git a/packages/console/src/components/TextInput/index.tsx b/packages/console/src/components/TextInput/index.tsx index 3d5833cb1..2bb5ae6da 100644 --- a/packages/console/src/components/TextInput/index.tsx +++ b/packages/console/src/components/TextInput/index.tsx @@ -9,21 +9,52 @@ import { forwardRef, type Ref, useEffect, + useState, } from 'react'; +import EyeClosed from '@/assets/images/eye-closed.svg'; +import Eye from '@/assets/images/eye.svg'; +import IconButton from '@/components/IconButton'; + import * as styles from './index.module.scss'; type Props = Omit, 'size'> & { error?: string | boolean; icon?: ReactElement; suffix?: ReactElement; + isConfidential?: boolean; }; function TextInput( - { error, icon, suffix, disabled, className, readOnly, type = 'text', ...rest }: Props, + { + error, + icon, + suffix, + disabled, + className, + readOnly, + type = 'text', + isConfidential = false, + ...rest + }: Props, reference: Ref> ) { const innerRef = useRef(null); + const [isContentHidden, setIsContentHidden] = useState(true); + + const toggleHiddenContent = () => { + setIsContentHidden((previous) => !previous); + }; + + const suffixIcon = + isConfidential && type === 'text' ? ( + + {isContentHidden ? : } + + ) : ( + suffix + ); + useImperativeHandle(reference, () => innerRef.current); useEffect(() => { @@ -54,6 +85,7 @@ function TextInput( className={classNames( styles.container, error && styles.error, + isConfidential && isContentHidden && type === 'text' && styles.hideTextContainerContent, icon && styles.withIcon, disabled && styles.disabled, readOnly && styles.readOnly @@ -61,9 +93,9 @@ function TextInput( > {icon && {icon}} - {suffix && - cloneElement(suffix, { - className: classNames([suffix.props.className, styles.suffix]), + {suffixIcon && + cloneElement(suffixIcon, { + className: classNames([suffixIcon.props.className, styles.suffix]), })} {Boolean(error) && typeof error === 'string' && ( diff --git a/packages/console/src/pages/Connectors/components/ConfigForm/index.tsx b/packages/console/src/pages/Connectors/components/ConfigForm/index.tsx index e0698743b..c5b15daab 100644 --- a/packages/console/src/pages/Connectors/components/ConfigForm/index.tsx +++ b/packages/console/src/pages/Connectors/components/ConfigForm/index.tsx @@ -60,7 +60,13 @@ function ConfigForm({ formItems }: Props) { }); if (item.type === ConnectorConfigFormItemType.Text) { - return ; + return ( + + ); } if (item.type === ConnectorConfigFormItemType.MultilineText) { diff --git a/packages/toolkit/connector-kit/src/types.ts b/packages/toolkit/connector-kit/src/types.ts index f98effc44..f167d9dcf 100644 --- a/packages/toolkit/connector-kit/src/types.ts +++ b/packages/toolkit/connector-kit/src/types.ts @@ -114,6 +114,7 @@ const baseConfigFormItem = { .optional(), description: z.string().optional(), tooltip: z.string().optional(), + isConfidential: z.boolean().optional(), // For `Text` type only. }; const connectorConfigFormItemGuard = z.discriminatedUnion('type', [