in assets/js/components/user-input/UserInputKeywords.js [44:240]
export default function UserInputKeywords( { slug, max, next, isActive } ) {
const keywordsContainer = useRef();
const values = useSelect(
( select ) => select( CORE_USER ).getUserInputSetting( slug ) || []
);
const { setUserInputSetting } = useDispatch( CORE_USER );
// Add an empty string if the values array is empty.
if ( values.length === 0 ) {
values.push( '' );
}
// Store values in local state to prevent
// https://github.com/google/site-kit-wp/issues/2900#issuecomment-814843972.
const [ localValues, setLocalValues ] = useState( values );
const focusInput = ( querySelector ) => {
const input = keywordsContainer.current.querySelector( querySelector );
if ( input ) {
setTimeout( () => {
input.focus();
}, 50 );
}
};
useEffect( () => {
if ( keywordsContainer?.current && isActive ) {
focusInput(
'.googlesitekit-user-input__text-option:first-child .mdc-text-field__input'
);
}
}, [ isActive ] );
const updateKeywords = useCallback(
( keywords ) => {
const EOT = String.fromCharCode( 4 );
let newKeywords = keywords
// Trim keywords to allow no empty spaces at the beginning and at max one space at the end.
.map( ( keyword ) =>
keyword.replace( /(\S)\s+$/, '$1 ' ).replace( /^\s+/, '' )
)
// EOT is added to the end to properly combine two sequential empty spaces at the end.
.concat( [ '', EOT ] )
.join( EOT )
.replace( new RegExp( `${ EOT }{3,}`, 'g' ), EOT ); // Combine two sequential empty spaces into one.
if ( newKeywords === EOT ) {
newKeywords = [ '' ];
} else {
newKeywords = newKeywords.split( EOT ).slice( 0, max );
}
setLocalValues( newKeywords );
setUserInputSetting( slug, newKeywords );
},
[ slug, max, setUserInputSetting ]
);
const deleteKeyword = useCallback(
( index ) => {
updateKeywords( [
...values.slice( 0, index ),
...values.slice( index + 1 ),
] );
},
[ updateKeywords, values ]
);
const onKeywordDelete = useCallback(
( index ) => {
deleteKeyword( index );
},
[ deleteKeyword ]
);
const onKeywordChange = useCallback(
( index, { target } ) => {
if ( target.value[ target.value.length - 1 ] === ',' ) {
return;
}
updateKeywords( [
...values.slice( 0, index ),
target.value,
...values.slice( index + 1 ),
] );
},
[ updateKeywords, values ]
);
const onKeyDown = useCallback(
( index, { keyCode, target } ) => {
const nonEmptyValues = values.filter(
( value ) => value.length > 0
);
const nonEmptyValuesLength = nonEmptyValues.length;
if (
keyCode === ENTER &&
nonEmptyValuesLength === max &&
next &&
typeof next === 'function'
) {
next();
return;
}
if (
( keyCode === ENTER || keyCode === COMMA ) &&
nonEmptyValuesLength < max
) {
updateKeywords( [
...values.slice( 0, index + 1 ),
'',
...values.slice( index + 1 ),
] );
focusInput( `#${ slug }-keyword-${ index + 1 }` );
}
if ( target.value.length === 0 && keyCode === BACKSPACE ) {
// The input is empty, so pressing backspace should delete the last keyword.
deleteKeyword( nonEmptyValuesLength - 1 );
focusInput(
`#${ slug }-keyword-${ nonEmptyValuesLength - 1 }`
);
}
},
[ next, max, deleteKeyword, slug, updateKeywords, values ]
);
return (
<Cell lgStart={ 6 } lgSize={ 6 } mdSize={ 8 } smSize={ 4 }>
<div
ref={ keywordsContainer }
className="googlesitekit-user-input__text-options"
>
{ localValues.map( ( value, i ) => (
<div
key={ i }
className={ classnames( {
'googlesitekit-user-input__text-option':
localValues.length > i + 1 || value.length > 0,
} ) }
>
<VisuallyHidden>
<label htmlFor={ `${ slug }-keyword-${ i }` }>
{ sprintf(
/* translators: %s is the keyword number; 1, 2, or 3 */
__( 'Keyword %s', 'google-site-kit' ),
i + 1 // Keys are zero-indexed; this starts keyword at "1".
) }
</label>
</VisuallyHidden>
<TextField
label={ __(
'Enter minimum one (1), maximum three (3) terms',
'google-site-kit'
) }
noLabel
>
<Input
id={ `${ slug }-keyword-${ i }` }
value={ value }
size={
value.length > 0 ? value.length : undefined
}
onChange={ onKeywordChange.bind( null, i ) }
onKeyDown={ onKeyDown.bind( null, i ) }
tabIndex={ ! isActive ? '-1' : undefined }
maxLength={ 40 }
/>
</TextField>
{ ( value.length > 0 ||
i + 1 < localValues.length ) && (
<Button
text
icon={ <CloseIcon width="11" height="11" /> }
onClick={ onKeywordDelete.bind( null, i ) }
/>
) }
</div>
) ) }
</div>
<p className="googlesitekit-user-input__note">
{ __(
'Separate with commas or the Enter key',
'google-site-kit'
) }
</p>
</Cell>
);
}