@wordpress/block-library
Version:
Block library for the WordPress editor.
375 lines (330 loc) • 15.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = SearchEdit;
var _element = require("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _reactNative = require("react-native");
var _classnames = _interopRequireDefault(require("classnames"));
var _blockEditor = require("@wordpress/block-editor");
var _components = require("@wordpress/components");
var _i18n = require("@wordpress/i18n");
var _icons = require("@wordpress/icons");
var _compose = require("@wordpress/compose");
var _style = _interopRequireDefault(require("./style.scss"));
var _styles$widthMargin, _styles$widthMargin2;
/**
* Constants
*/
const MIN_BUTTON_WIDTH = 75;
const MARGINS = ((_styles$widthMargin = _style.default.widthMargin) === null || _styles$widthMargin === void 0 ? void 0 : _styles$widthMargin.marginLeft) + ((_styles$widthMargin2 = _style.default.widthMargin) === null || _styles$widthMargin2 === void 0 ? void 0 : _styles$widthMargin2.paddingLeft);
const BUTTON_OPTIONS = [{
value: 'button-inside',
label: (0, _i18n.__)('Button inside')
}, {
value: 'button-outside',
label: (0, _i18n.__)('Button outside')
}, {
value: 'no-button',
label: (0, _i18n.__)('No button')
}];
function SearchEdit(_ref) {
var _style$baseColors, _style$baseColors2, _style$baseColors2$co, _style$baseColors3, _style$baseColors4, _style$baseColors4$co, _style$baseColors5, _style$baseColors5$bl, _style$baseColors5$bl2, _attributes$style, _styles$richTextButto2;
let {
onFocus,
isSelected,
attributes,
setAttributes,
className,
blockWidth,
style
} = _ref;
const [isButtonSelected, setIsButtonSelected] = (0, _element.useState)(false);
const [isLabelSelected, setIsLabelSelected] = (0, _element.useState)(false);
const [isPlaceholderSelected, setIsPlaceholderSelected] = (0, _element.useState)(false);
const [isLongButton, setIsLongButton] = (0, _element.useState)(false);
const [buttonWidth, setButtonWidth] = (0, _element.useState)(MIN_BUTTON_WIDTH);
const [isScreenReaderEnabled, setIsScreenReaderEnabled] = (0, _element.useState)(false);
const textInputRef = (0, _element.useRef)(null);
const {
label,
showLabel,
buttonPosition,
buttonUseIcon,
placeholder,
buttonText
} = attributes;
/*
* Check if screenreader is enabled and save to state. This is important for
* properly creating accessibilityLabel text.
*/
(0, _element.useEffect)(() => {
const a11yInfoChangeSubscription = _reactNative.AccessibilityInfo.addEventListener('screenReaderChanged', handleScreenReaderToggled);
_reactNative.AccessibilityInfo.isScreenReaderEnabled().then(screenReaderEnabled => {
setIsScreenReaderEnabled(screenReaderEnabled);
});
return () => {
a11yInfoChangeSubscription.remove();
};
}, []);
const handleScreenReaderToggled = screenReaderEnabled => {
setIsScreenReaderEnabled(screenReaderEnabled);
};
/*
* Called when the value of isSelected changes. Blurs the PlainText component
* used by the placeholder when this block loses focus.
*/
(0, _element.useEffect)(() => {
if (hasTextInput() && isPlaceholderSelected && !isSelected) {
textInputRef.current.blur();
}
}, [isSelected]);
(0, _element.useEffect)(() => {
const maxButtonWidth = Math.floor(blockWidth / 2 - MARGINS);
const tempIsLongButton = buttonWidth > maxButtonWidth; // Update this value only if it has changed to avoid flickering.
if (isLongButton !== tempIsLongButton) {
setIsLongButton(tempIsLongButton);
}
}, [blockWidth, buttonWidth]);
const hasTextInput = () => {
return textInputRef && textInputRef.current;
};
const onLayoutButton = _ref2 => {
let {
nativeEvent
} = _ref2;
const {
width
} = nativeEvent === null || nativeEvent === void 0 ? void 0 : nativeEvent.layout;
if (width) {
setButtonWidth(width);
}
};
const getBlockClassNames = () => {
return (0, _classnames.default)(className, 'button-inside' === buttonPosition ? 'wp-block-search__button-inside' : undefined, 'button-outside' === buttonPosition ? 'wp-block-search__button-outside' : undefined, 'no-button' === buttonPosition ? 'wp-block-search__no-button' : undefined, 'button-only' === buttonPosition ? 'wp-block-search__button-only' : undefined, !buttonUseIcon && 'no-button' !== buttonPosition ? 'wp-block-search__text-button' : undefined, buttonUseIcon && 'no-button' !== buttonPosition ? 'wp-block-search__icon-button' : undefined);
};
const getSelectedButtonPositionLabel = option => {
switch (option) {
case 'button-inside':
return (0, _i18n.__)('Inside');
case 'button-outside':
return (0, _i18n.__)('Outside');
case 'no-button':
return (0, _i18n.__)('No button');
}
};
const blockProps = (0, _blockEditor.useBlockProps)({
className: getBlockClassNames()
});
const controls = (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_components.PanelBody, {
title: (0, _i18n.__)('Search settings')
}, (0, _element.createElement)(_components.ToggleControl, {
label: (0, _i18n.__)('Hide search heading'),
checked: !showLabel,
onChange: () => {
setAttributes({
showLabel: !showLabel
});
}
}), (0, _element.createElement)(_components.SelectControl, {
label: (0, _i18n.__)('Button position'),
value: getSelectedButtonPositionLabel(buttonPosition),
onChange: position => {
setAttributes({
buttonPosition: position
});
},
options: BUTTON_OPTIONS,
hideCancelButton: true
}), buttonPosition !== 'no-button' && (0, _element.createElement)(_components.ToggleControl, {
label: (0, _i18n.__)('Use icon button'),
checked: buttonUseIcon,
onChange: () => {
setAttributes({
buttonUseIcon: !buttonUseIcon
});
}
})));
const isButtonInside = buttonPosition === 'button-inside';
const borderStyle = (0, _compose.usePreferredColorSchemeStyle)(_style.default.border, _style.default.borderDark);
const inputStyle = [!isButtonInside && borderStyle, (0, _compose.usePreferredColorSchemeStyle)(_style.default.plainTextInput, _style.default.plainTextInputDark), (style === null || style === void 0 ? void 0 : (_style$baseColors = style.baseColors) === null || _style$baseColors === void 0 ? void 0 : _style$baseColors.color) && {
color: style === null || style === void 0 ? void 0 : (_style$baseColors2 = style.baseColors) === null || _style$baseColors2 === void 0 ? void 0 : (_style$baseColors2$co = _style$baseColors2.color) === null || _style$baseColors2$co === void 0 ? void 0 : _style$baseColors2$co.text
}];
const placeholderStyle = { ...(0, _compose.usePreferredColorSchemeStyle)(_style.default.plainTextPlaceholder, _style.default.plainTextPlaceholderDark),
...((style === null || style === void 0 ? void 0 : (_style$baseColors3 = style.baseColors) === null || _style$baseColors3 === void 0 ? void 0 : _style$baseColors3.color) && {
color: style === null || style === void 0 ? void 0 : (_style$baseColors4 = style.baseColors) === null || _style$baseColors4 === void 0 ? void 0 : (_style$baseColors4$co = _style$baseColors4.color) === null || _style$baseColors4$co === void 0 ? void 0 : _style$baseColors4$co.text
})
};
const searchBarStyle = [_style.default.searchBarContainer, isButtonInside && borderStyle, isLongButton && {
flexDirection: 'column'
}];
/**
* If a screenreader is enabled, create a descriptive label for this field. If
* not, return a label that is used during automated UI tests.
*
* @return {string} The accessibilityLabel for the Search Button
*/
const getAccessibilityLabelForButton = () => {
if (!isScreenReaderEnabled) {
return 'search-block-button';
}
return `${(0, _i18n.__)('Search button. Current button text is')} ${buttonText}`;
};
/**
* If a screenreader is enabled, create a descriptive label for this field. If
* not, return a label that is used during automated UI tests.
*
* @return {string} The accessibilityLabel for the Search Input
* placeholder field.
*/
const getAccessibilityLabelForPlaceholder = () => {
if (!isScreenReaderEnabled) {
return 'search-block-input';
}
const title = (0, _i18n.__)('Search input field.');
const description = placeholder ? `${(0, _i18n.__)('Current placeholder text is')} ${placeholder}` : (0, _i18n.__)('No custom placeholder set');
return `${title} ${description}`;
};
/**
* If a screenreader is enabled, create a descriptive label for this field. If
* not, return a label that is used during automated UI tests.
*
* @return {string} The accessibilityLabel for the Search Label field
*/
const getAccessibilityLabelForLabel = () => {
if (!isScreenReaderEnabled) {
return 'search-block-label';
}
return `${(0, _i18n.__)('Search block label. Current text is')} ${label}`;
};
const renderTextField = () => {
return (0, _element.createElement)(_reactNative.View, {
style: _style.default.searchInputContainer,
accessible: true,
accessibilityRole: "none",
accessibilityHint: isScreenReaderEnabled ? (0, _i18n.__)('Double tap to edit placeholder text') : undefined,
accessibilityLabel: getAccessibilityLabelForPlaceholder()
}, (0, _element.createElement)(_blockEditor.PlainText, {
ref: textInputRef,
isSelected: isPlaceholderSelected,
className: "wp-block-search__input",
style: inputStyle,
numberOfLines: 1,
ellipsizeMode: "tail" // Currently only works on ios.
,
label: null,
value: placeholder,
placeholder: placeholder ? undefined : (0, _i18n.__)('Optional placeholder…'),
onChange: newVal => setAttributes({
placeholder: newVal
}),
onFocus: () => {
setIsPlaceholderSelected(true);
onFocus();
},
onBlur: () => setIsPlaceholderSelected(false),
placeholderTextColor: placeholderStyle === null || placeholderStyle === void 0 ? void 0 : placeholderStyle.color
}));
}; // To achieve proper expanding and shrinking `RichText` on Android, there is a need to set
// a `placeholder` as an empty string when `RichText` is focused,
// because `AztecView` is calculating a `minWidth` based on placeholder text.
const buttonPlaceholderText = isButtonSelected || !isButtonSelected && buttonText && buttonText !== '' ? '' : (0, _i18n.__)('Add button text');
const baseButtonStyles = { ...(style === null || style === void 0 ? void 0 : (_style$baseColors5 = style.baseColors) === null || _style$baseColors5 === void 0 ? void 0 : (_style$baseColors5$bl = _style$baseColors5.blocks) === null || _style$baseColors5$bl === void 0 ? void 0 : (_style$baseColors5$bl2 = _style$baseColors5$bl['core/button']) === null || _style$baseColors5$bl2 === void 0 ? void 0 : _style$baseColors5$bl2.color),
...(attributes === null || attributes === void 0 ? void 0 : (_attributes$style = attributes.style) === null || _attributes$style === void 0 ? void 0 : _attributes$style.color),
...((style === null || style === void 0 ? void 0 : style.color) && {
text: style.color
})
};
const richTextButtonContainerStyle = [_style.default.buttonContainer, isLongButton && _style.default.buttonContainerWide, (baseButtonStyles === null || baseButtonStyles === void 0 ? void 0 : baseButtonStyles.background) && {
backgroundColor: baseButtonStyles.background,
borderWidth: 0
}, (style === null || style === void 0 ? void 0 : style.backgroundColor) && {
backgroundColor: style.backgroundColor,
borderWidth: 0
}];
const richTextButtonStyle = { ..._style.default.richTextButton,
...((baseButtonStyles === null || baseButtonStyles === void 0 ? void 0 : baseButtonStyles.text) && {
color: baseButtonStyles.text,
placeholderColor: baseButtonStyles.text
})
};
const iconStyles = { ..._style.default.icon,
...((baseButtonStyles === null || baseButtonStyles === void 0 ? void 0 : baseButtonStyles.text) && {
fill: baseButtonStyles.text
})
};
const renderButton = () => {
var _styles$richTextButto;
return (0, _element.createElement)(_reactNative.View, {
style: richTextButtonContainerStyle
}, buttonUseIcon && (0, _element.createElement)(_components.Icon, (0, _extends2.default)({
icon: _icons.search
}, iconStyles, {
onLayout: onLayoutButton
})), !buttonUseIcon && (0, _element.createElement)(_reactNative.View, {
accessible: true,
accessibilityRole: "none",
accessibilityHint: isScreenReaderEnabled ? (0, _i18n.__)('Double tap to edit button text') : undefined,
accessibilityLabel: getAccessibilityLabelForButton(),
onLayout: onLayoutButton
}, (0, _element.createElement)(_blockEditor.RichText, {
className: "wp-block-search__button",
identifier: "text",
tagName: "p",
style: richTextButtonStyle,
placeholder: buttonPlaceholderText,
value: buttonText,
withoutInteractiveFormatting: true,
onChange: html => setAttributes({
buttonText: html
}),
minWidth: MIN_BUTTON_WIDTH,
maxWidth: blockWidth - MARGINS,
textAlign: "center",
isSelected: isButtonSelected,
__unstableMobileNoFocusOnMount: !isSelected,
unstableOnFocus: () => {
setIsButtonSelected(true);
},
onBlur: () => {
setIsButtonSelected(false);
},
selectionColor: (_styles$richTextButto = _style.default.richTextButtonCursor) === null || _styles$richTextButto === void 0 ? void 0 : _styles$richTextButto.color
})));
};
return (0, _element.createElement)(_reactNative.View, (0, _extends2.default)({}, blockProps, {
style: _style.default.searchBlockContainer,
importantForAccessibility: isSelected ? 'yes' : 'no-hide-descendants',
accessibilityElementsHidden: isSelected ? false : true
}), isSelected && controls, showLabel && (0, _element.createElement)(_reactNative.View, {
accessible: true,
accessibilityRole: "none",
accessibilityHint: isScreenReaderEnabled ? (0, _i18n.__)('Double tap to edit label text') : undefined,
accessibilityLabel: getAccessibilityLabelForLabel()
}, (0, _element.createElement)(_blockEditor.RichText, {
className: "wp-block-search__label",
identifier: "text",
tagName: "p",
style: _style.default.richTextLabel,
placeholder: (0, _i18n.__)('Add label…'),
withoutInteractiveFormatting: true,
value: label,
onChange: html => setAttributes({
label: html
}),
isSelected: isLabelSelected,
__unstableMobileNoFocusOnMount: !isSelected,
unstableOnFocus: () => {
setIsLabelSelected(true);
},
onBlur: () => {
setIsLabelSelected(false);
},
selectionColor: (_styles$richTextButto2 = _style.default.richTextButtonCursor) === null || _styles$richTextButto2 === void 0 ? void 0 : _styles$richTextButto2.color
})), ('button-inside' === buttonPosition || 'button-outside' === buttonPosition) && (0, _element.createElement)(_reactNative.View, {
style: searchBarStyle
}, renderTextField(), renderButton()), 'button-only' === buttonPosition && renderButton(), 'no-button' === buttonPosition && renderTextField());
}
//# sourceMappingURL=edit.native.js.map