From 66d1b4bd10ac0923bbe8789d90a561b9c09d2714 Mon Sep 17 00:00:00 2001 From: heavyweight Date: Mon, 8 Sep 2025 15:54:01 +0200 Subject: [PATCH 1/2] Add password field --- .../dataviews/src/dataform-controls/index.tsx | 2 + .../src/dataform-controls/password.tsx | 94 +++++++++++++++++++ .../utils/validated-text.tsx | 2 +- packages/dataviews/src/field-types/index.tsx | 5 + .../dataviews/src/field-types/password.tsx | 71 ++++++++++++++ .../src/field-types/stories/index.story.tsx | 40 ++++++++ packages/dataviews/src/types.ts | 1 + packages/dataviews/src/validation.ts | 2 + 8 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 packages/dataviews/src/dataform-controls/password.tsx create mode 100644 packages/dataviews/src/field-types/password.tsx diff --git a/packages/dataviews/src/dataform-controls/index.tsx b/packages/dataviews/src/dataform-controls/index.tsx index 899174faa97ffe..ed50be78433e31 100644 --- a/packages/dataviews/src/dataform-controls/index.tsx +++ b/packages/dataviews/src/dataform-controls/index.tsx @@ -25,6 +25,7 @@ import toggle from './toggle'; import toggleGroup from './toggle-group'; import array from './array'; import color from './color'; +import password from './password'; interface FormControls { [ key: string ]: ComponentType< DataFormControlProps< any > >; @@ -40,6 +41,7 @@ const FORM_CONTROLS: FormControls = { telephone, url, integer, + password, radio, select, text, diff --git a/packages/dataviews/src/dataform-controls/password.tsx b/packages/dataviews/src/dataform-controls/password.tsx new file mode 100644 index 00000000000000..d9ff4243d7ddce --- /dev/null +++ b/packages/dataviews/src/dataform-controls/password.tsx @@ -0,0 +1,94 @@ +/** + * WordPress dependencies + */ +import { + Button, + privateApis, + __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper, +} from '@wordpress/components'; +import { useCallback, useState } from '@wordpress/element'; +import { seen, unseen } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import type { DataFormControlProps } from '../types'; +import { unlock } from '../lock-unlock'; + +const { ValidatedInputControl } = unlock( privateApis ); + +export default function Password< Item >( { + data, + field, + onChange, + hideLabelFromVision, +}: DataFormControlProps< Item > ) { + const { id, label, placeholder, description } = field; + const value = field.getValue( { item: data } ); + const [ isVisible, setIsVisible ] = useState( false ); + const [ customValidity, setCustomValidity ] = + useState< + React.ComponentProps< + typeof ValidatedInputControl + >[ 'customValidity' ] + >( undefined ); + + const onChangeControl = useCallback( + ( newValue: string ) => + onChange( { + [ id ]: newValue, + } ), + [ id, onChange ] + ); + + const toggleVisibility = useCallback( () => { + setIsVisible( ( prev ) => ! prev ); + }, [] ); + + return ( + { + const message = field.isValid?.custom?.( + { + ...data, + [ id ]: newValue, + }, + field + ); + + if ( message ) { + setCustomValidity( { + type: 'invalid', + message, + } ); + return; + } + + setCustomValidity( undefined ); + } } + customValidity={ customValidity } + label={ label } + placeholder={ placeholder } + value={ value ?? '' } + help={ description } + onChange={ onChangeControl } + hideLabelFromVision={ hideLabelFromVision } + type={ isVisible ? 'text' : 'password' } + suffix={ + +