@wordpress/block-library
Version:
Block library for the WordPress editor.
200 lines (188 loc) • 4.93 kB
JavaScript
/**
* External dependencies
*/
import clsx from 'clsx';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import {
InspectorControls,
RichText,
useBlockProps,
__experimentalUseBorderProps as useBorderProps,
__experimentalUseColorProps as useColorProps,
} from '@wordpress/block-editor';
import {
TextControl,
CheckboxControl,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';
import { useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
function InputFieldBlock( { attributes, setAttributes, className } ) {
const { type, name, label, inlineLabel, required, placeholder, value } =
attributes;
const blockProps = useBlockProps();
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
const ref = useRef();
const TagName = type === 'textarea' ? 'textarea' : 'input';
const borderProps = useBorderProps( attributes );
const colorProps = useColorProps( attributes );
if ( ref.current ) {
ref.current.focus();
}
// Note: radio inputs aren't implemented yet.
const isCheckboxOrRadio = type === 'checkbox' || type === 'radio';
const controls = (
<>
{ 'hidden' !== type && (
<InspectorControls>
<ToolsPanel
label={ __( 'Settings' ) }
resetAll={ () => {
setAttributes( {
inlineLabel: false,
required: false,
} );
} }
dropdownMenuProps={ dropdownMenuProps }
>
{ 'checkbox' !== type && (
<ToolsPanelItem
label={ __( 'Inline label' ) }
hasValue={ () => !! inlineLabel }
onDeselect={ () =>
setAttributes( { inlineLabel: false } )
}
isShownByDefault
>
<CheckboxControl
__nextHasNoMarginBottom
label={ __( 'Inline label' ) }
checked={ inlineLabel }
onChange={ ( newVal ) => {
setAttributes( {
inlineLabel: newVal,
} );
} }
/>
</ToolsPanelItem>
) }
<ToolsPanelItem
label={ __( 'Required' ) }
hasValue={ () => !! required }
onDeselect={ () =>
setAttributes( { required: false } )
}
isShownByDefault
>
<CheckboxControl
__nextHasNoMarginBottom
label={ __( 'Required' ) }
checked={ required }
onChange={ ( newVal ) => {
setAttributes( {
required: newVal,
} );
} }
/>
</ToolsPanelItem>
</ToolsPanel>
</InspectorControls>
) }
<InspectorControls group="advanced">
<TextControl
__next40pxDefaultSize
__nextHasNoMarginBottom
autoComplete="off"
label={ __( 'Name' ) }
value={ name }
onChange={ ( newVal ) => {
setAttributes( {
name: newVal,
} );
} }
help={ __(
'Affects the "name" attribute of the input element, and is used as a name for the form submission results.'
) }
/>
</InspectorControls>
</>
);
const content = (
<RichText
tagName="span"
className="wp-block-form-input__label-content"
value={ label }
onChange={ ( newLabel ) => setAttributes( { label: newLabel } ) }
aria-label={ label ? __( 'Label' ) : __( 'Empty label' ) }
data-empty={ ! label }
placeholder={ __( 'Type the label for this input' ) }
/>
);
if ( 'hidden' === type ) {
return (
<>
{ controls }
<input
type="hidden"
className={ clsx(
className,
'wp-block-form-input__input',
colorProps.className,
borderProps.className
) }
aria-label={ __( 'Value' ) }
value={ value }
onChange={ ( event ) =>
setAttributes( { value: event.target.value } )
}
/>
</>
);
}
return (
<div { ...blockProps }>
{ controls }
<span
className={ clsx( 'wp-block-form-input__label', {
'is-label-inline': inlineLabel || 'checkbox' === type,
} ) }
>
{ ! isCheckboxOrRadio && content }
<TagName
type={ 'textarea' === type ? undefined : type }
className={ clsx(
className,
'wp-block-form-input__input',
colorProps.className,
borderProps.className
) }
aria-label={ __( 'Optional placeholder text' ) }
// We hide the placeholder field's placeholder when there is a value. This
// stops screen readers from reading the placeholder field's placeholder
// which is confusing.
placeholder={
placeholder ? undefined : __( 'Optional placeholder…' )
}
value={ placeholder }
onChange={ ( event ) =>
setAttributes( { placeholder: event.target.value } )
}
aria-required={ required }
style={ {
...borderProps.style,
...colorProps.style,
} }
/>
{ isCheckboxOrRadio && content }
</span>
</div>
);
}
export default InputFieldBlock;