UNPKG

@wordpress/block-library

Version:
375 lines (330 loc) 15.6 kB
"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