: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
(0,external_wp_i18n_namespaceObject.__)('%1$s (%2$s of %3$s)'), transformedValue, termPosition, termsCount);
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("span", {
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave,
children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("span", {
className: "components-form-token-field__token-text",
id: `components-form-token-field__token-text-${instanceId}`,
children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(visually_hidden_component, {
children: termPositionAndCount
}), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", {
children: transformedValue
}), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_button, {
className: "components-form-token-field__remove-token",
onClick: !disabled ? onClick : undefined,
"aria-describedby": `components-form-token-field__token-text-${instanceId}`
;// CONCATENATED MODULE: ./node_modules/@wordpress/components/build-module/form-token-field/styles.js
const deprecatedPaddings = ({
}) => !__next40pxDefaultSize && /*#__PURE__*/emotion_react_browser_esm_css("padding-top:", space(hasTokens ? 1 : 0.5), ";padding-bottom:", space(hasTokens ? 1 : 0.5), ";" + ( true ? "" : 0), true ? "" : 0);
const TokensAndInputWrapperFlex = /*#__PURE__*/emotion_styled_base_browser_esm(flex_component, true ? {
} : 0)("padding:7px;", boxSizingReset, " ", deprecatedPaddings, ";" + ( true ? "" : 0));
;// CONCATENATED MODULE: ./node_modules/@wordpress/components/build-module/form-token-field/index.js
const form_token_field_identity = value => value;
* A `FormTokenField` is a field similar to the tags and categories fields in the interim editor chrome,
* or the "to" field in Mail on OS X. Tokens can be entered by typing them or selecting them from a list of suggested tokens.
* Up to one hundred suggestions that match what the user has typed so far will be shown from which the user can pick from (auto-complete).
* Tokens are separated by the "," character. Suggestions can be selected with the up or down arrows and added with the tab or enter key.
* The `value` property is handled in a manner similar to controlled form components.
* See [Forms](https://react.dev/reference/react-dom/components#form-components) in the React Documentation for more information.
function FormTokenField(props) {
label = (0,external_wp_i18n_namespaceObject.__)('Add item'),
displayTransform = form_token_field_identity,
saveTransform = token => token.trim(),
onInputChange = () => {},
added: (0,external_wp_i18n_namespaceObject.__)('Item added.'),
removed: (0,external_wp_i18n_namespaceObject.__)('Item removed.'),
remove: (0,external_wp_i18n_namespaceObject.__)('Remove item'),
__experimentalInvalid: (0,external_wp_i18n_namespaceObject.__)('Invalid item')
__experimentalRenderItem,
__experimentalExpandOnFocus = false,
__experimentalValidateInput = () => true,
__experimentalShowHowTo = true,
__next40pxDefaultSize = false,
__experimentalAutoSelectFirstMatch = false,
__nextHasNoMarginBottom = false,
} = useDeprecated36pxDefaultSizeProp(props);
const instanceId = (0,external_wp_compose_namespaceObject.useInstanceId)(FormTokenField);
// We reset to these initial values again in the onBlur
const [incompleteTokenValue, setIncompleteTokenValue] = (0,external_wp_element_namespaceObject.useState)('');
const [inputOffsetFromEnd, setInputOffsetFromEnd] = (0,external_wp_element_namespaceObject.useState)(0);
const [isActive, setIsActive] = (0,external_wp_element_namespaceObject.useState)(false);
const [isExpanded, setIsExpanded] = (0,external_wp_element_namespaceObject.useState)(false);
const [selectedSuggestionIndex, setSelectedSuggestionIndex] = (0,external_wp_element_namespaceObject.useState)(-1);
const [selectedSuggestionScroll, setSelectedSuggestionScroll] = (0,external_wp_element_namespaceObject.useState)(false);
const prevSuggestions = (0,external_wp_compose_namespaceObject.usePrevious)(suggestions);
const prevValue = (0,external_wp_compose_namespaceObject.usePrevious)(value);
const input = (0,external_wp_element_namespaceObject.useRef)(null);
const tokensAndInput = (0,external_wp_element_namespaceObject.useRef)(null);
const debouncedSpeak = (0,external_wp_compose_namespaceObject.useDebounce)(external_wp_a11y_namespaceObject.speak, 500);
(0,external_wp_element_namespaceObject.useEffect)(() => {
// Make sure to focus the input when the isActive state is true.
if (isActive && !hasFocus()) {
(0,external_wp_element_namespaceObject.useEffect)(() => {
const suggestionsDidUpdate = !external_wp_isShallowEqual_default()(suggestions, prevSuggestions || []);
if (suggestionsDidUpdate || value !== prevValue) {
updateSuggestions(suggestionsDidUpdate);
// TODO: updateSuggestions() should first be refactored so its actual deps are clearer.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [suggestions, prevSuggestions, value, prevValue]);
(0,external_wp_element_namespaceObject.useEffect)(() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [incompleteTokenValue]);
(0,external_wp_element_namespaceObject.useEffect)(() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [__experimentalAutoSelectFirstMatch]);
if (disabled && isActive) {
setIncompleteTokenValue('');
return input.current === input.current?.ownerDocument.activeElement;
function onFocusHandler(event) {
// If focus is on the input or on the container, set the isActive state to true.
if (hasFocus() || event.target === tokensAndInput.current) {
setIsExpanded(__experimentalExpandOnFocus || isExpanded);
* Otherwise, focus is on one of the token "remove" buttons and we
* set the isActive state to false to prevent the input to be
* re-focused, see componentDidUpdate().
if ('function' === typeof onFocus) {
if (inputHasValidValue() && __experimentalValidateInput(incompleteTokenValue)) {
if (tokenizeOnBlur && inputHasValidValue()) {
addNewToken(incompleteTokenValue);
// Reset to initial state
setIncompleteTokenValue('');
setInputOffsetFromEnd(0);
if (__experimentalExpandOnFocus) {
// If `__experimentalExpandOnFocus` is true, don't close the suggestions list when
// the user clicks on it (`tokensAndInput` will be the element that caused the blur).
const hasFocusWithin = event.relatedTarget === tokensAndInput.current;
setIsExpanded(hasFocusWithin);
// Else collapse the suggestion list. This will result in the suggestion list closing
// after a suggestion has been submitted since that causes a blur.
setSelectedSuggestionIndex(-1);
setSelectedSuggestionScroll(false);
function onKeyDown(event) {
let preventDefault = false;
if (event.defaultPrevented) {
preventDefault = handleDeleteKey(deleteTokenBeforeInput);
preventDefault = addCurrentToken();
preventDefault = handleLeftArrowKey();
preventDefault = handleUpArrowKey();
preventDefault = handleRightArrowKey();
preventDefault = handleDownArrowKey();
preventDefault = handleDeleteKey(deleteTokenAfterInput);
preventDefault = addCurrentToken();
preventDefault = handleEscapeKey(event);
function onKeyPress(event) {
let preventDefault = false;
preventDefault = handleCommaKey();
function onContainerTouched(event) {
// Prevent clicking/touching the tokensAndInput container from blurring
// the input and adding the current token.
if (event.target === tokensAndInput.current && isActive) {
function onTokenClickRemove(event) {
deleteToken(event.value);
function onSuggestionHovered(suggestion) {
const index = getMatchingSuggestions().indexOf(suggestion);
setSelectedSuggestionIndex(index);
setSelectedSuggestionScroll(false);
function onSuggestionSelected(suggestion) {
function onInputChangeHandler(event) {
const text = event.value;
const separator = tokenizeOnSpace ? /[ ,\t]+/ : /[,\t]+/;
const items = text.split(separator);
const tokenValue = items[items.length - 1] || '';
addNewTokens(items.slice(0, -1));
setIncompleteTokenValue(tokenValue);
onInputChange(tokenValue);
function handleDeleteKey(_deleteToken) {
let preventDefault = false;
if (hasFocus() && isInputEmpty()) {
function handleLeftArrowKey() {
let preventDefault = false;
moveInputBeforePreviousToken();
function handleRightArrowKey() {
let preventDefault = false;
moveInputAfterNextToken();
function handleUpArrowKey() {
setSelectedSuggestionIndex(index => {
return (index === 0 ? getMatchingSuggestions(incompleteTokenValue, suggestions, value, maxSuggestions, saveTransform).length : index) - 1;
setSelectedSuggestionScroll(true);
return true; // PreventDefault.
function handleDownArrowKey() {
setSelectedSuggestionIndex(index => {
return (index + 1) % getMatchingSuggestions(incompleteTokenValue, suggestions, value, maxSuggestions, saveTransform).length;
setSelectedSuggestionScroll(true);
return true; // PreventDefault.
function handleEscapeKey(event) {
if (event.target instanceof HTMLInputElement) {
setIncompleteTokenValue(event.target.value);
setSelectedSuggestionIndex(-1);
setSelectedSuggestionScroll(false);
return true; // PreventDefault.
function handleCommaKey() {
if (inputHasValidValue()) {
addNewToken(incompleteTokenValue);
return true; // PreventDefault.
function moveInputToIndex(index) {
setInputOffsetFromEnd(value.length - Math.max(index, -1) - 1);
function moveInputBeforePreviousToken() {
setInputOffsetFromEnd(prevInputOffsetFromEnd => {
return Math.min(prevInputOffsetFromEnd + 1, value.length);
function moveInputAfterNextToken() {
setInputOffsetFromEnd(prevInputOffsetFromEnd => {
return Math.max(prevInputOffsetFromEnd - 1, 0);
function deleteTokenBeforeInput() {
const index = getIndexOfInput() - 1;
deleteToken(value[index]);
function deleteTokenAfterInput() {
const index = getIndexOfInput();
if (index < value.length) {
deleteToken(value[index]);
// Update input offset since it's the offset from the last token.
function addCurrentToken() {
let preventDefault = false;
const selectedSuggestion = getSelectedSuggestion();
if (selectedSuggestion) {
addNewToken(selectedSuggestion);
} else if (inputHasValidValue()) {
addNewToken(incompleteTokenValue);
function addNewTokens(tokens) {
const tokensToAdd = [...new Set(tokens.map(saveTransform).filter(Boolean).filter(token => !valueContainsToken(token)))];
if (tokensToAdd.length > 0) {
const newValue = [...value];
newValue.splice(getIndexOfInput(), 0, ...tokensToAdd);
function addNewToken(token) {
if (!__experimentalValidateInput(token)) {
(0,external_wp_a11y_namespaceObject.speak)(messages.__experimentalInvalid, 'assertive');
(0,external_wp_a11y_namespaceObject.speak)(messages.added, 'assertive');
setIncompleteTokenValue('');
setSelectedSuggestionIndex(-1);
setSelectedSuggestionScroll(false);
setIsExpanded(!__experimentalExpandOnFocus);
if (isActive && !tokenizeOnBlur) {
function deleteToken(token) {
const newTokens = value.filter(item => {
return getTokenValue(item) !== getTokenValue(token);
(0,external_wp_a11y_namespaceObject.speak)(messages.removed, 'assertive');
function getTokenValue(token) {
if ('object' === typeof token) {
function getMatchingSuggestions(searchValue = incompleteTokenValue, _suggestions = suggestions, _value = value, _maxSuggestions = maxSuggestions, _saveTransform = saveTransform) {
let match = _saveTransform(searchValue);
const startsWithMatch = [];
const containsMatch = [];
const normalizedValue = _value.map(item => {
if (typeof item === 'string') {
if (match.length === 0) {
_suggestions = _suggestions.filter(suggestion => !normalizedValue.includes(suggestion));
match = match.toLocaleLowerCase();
_suggestions.forEach(suggestion => {
const index = suggestion.toLocaleLowerCase().indexOf(match);
if (normalizedValue.indexOf(suggestion) === -1) {
startsWithMatch.push(suggestion);
containsMatch.push(suggestion);
_suggestions = startsWithMatch.concat(containsMatch);
return _suggestions.slice(0, _maxSuggestions);
function getSelectedSuggestion() {
if (selectedSuggestionIndex !== -1) {
return getMatchingSuggestions()[selectedSuggestionIndex];
function valueContainsToken(token) {
return value.some(item => {
return getTokenValue(token) === getTokenValue(item);
function getIndexOfInput() {
return value.length - inputOffsetFromEnd;
function isInputEmpty() {
return incompleteTokenValue.length === 0;
function inputHasValidValue() {
return saveTransform(incompleteTokenValue).length > 0;
function updateSuggestions(resetSelectedSuggestion = true) {
const inputHasMinimumChars = incompleteTokenValue.trim().length > 1;
const matchingSuggestions = getMatchingSuggestions(incompleteTokenValue);
const hasMatchingSuggestions = matchingSuggestions.length > 0;
const shouldExpandIfFocuses = hasFocus() && __experimentalExpandOnFocus;
setIsExpanded(shouldExpandIfFocuses || inputHasMinimumChars && hasMatchingSuggestions);
if (resetSelectedSuggestion) {
if (__experimentalAutoSelectFirstMatch && inputHasMinimumChars && hasMatchingSuggestions) {
setSelectedSuggestionIndex(0);
setSelectedSuggestionScroll(true);
setSelectedSuggestionIndex(-1);
setSelectedSuggestionScroll(false);
if (inputHasMinimumChars) {
const message = hasMatchingSuggestions ? (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %d: number of results. */
(0,external_wp_i18n_namespaceObject._n)('%d result found, use up and down arrow keys to navigate.', '%d results found, use up and down arrow keys to navigate.', matchingSuggestions.length), matchingSuggestions.length) : (0,external_wp_i18n_namespaceObject.__)('No results.');
debouncedSpeak(message, 'assertive');
function renderTokensAndInput() {
const components = value.map(renderToken);
components.splice(getIndexOfInput(), 0, renderInput());