@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
251 lines (246 loc) • 8.06 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.insertContentWithTitle = insertContentWithTitle;
var _reactNative = require("react-native");
var _element = require("@wordpress/element");
var _richText = require("@wordpress/rich-text");
var _htmlEntities = require("@wordpress/html-entities");
var _data = require("@wordpress/data");
var _components = require("@wordpress/components");
var _compose = require("@wordpress/compose");
var _i18n = require("@wordpress/i18n");
var _blocks = require("@wordpress/blocks");
var _blockEditor = require("@wordpress/block-editor");
var _editor = require("@wordpress/editor");
var _dom = require("@wordpress/dom");
var _style = _interopRequireDefault(require("./style.scss"));
var _jsxRuntime = require("react/jsx-runtime");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
/** @typedef {import('./types').RichTextValue} RichTextValue */
/**
* Internal dependencies
*/
/**
* Inserts content with title
*
* This function processes the given content and title, updating the title
* and content based on certain conditions. If the content is an array of
* blocks, it will check the first block for a heading or paragraph to use
* as the title. If the content is a string, it will strip HTML and update
* the title and content accordingly.
*
* @param {string} title The post title.
* @param {Array | string} content The content to be processed. It can be an array of blocks or a string.
* @param {Function} onUpdateTitle Callback function to update the title.
* @param {Function} onUpdateContent Callback function to update the content.
* @param {RichTextValue} value The initial value object, default is an object with empty text.
*/
function insertContentWithTitle(title, content, onUpdateTitle, onUpdateContent, value = (0, _richText.create)({
text: ''
})) {
if (!content.length) {
return;
}
if (typeof content !== 'string') {
const [firstBlock] = content;
if (!title && (firstBlock.name === 'core/heading' || firstBlock.name === 'core/paragraph')) {
// Strip HTML to avoid unwanted HTML being added to the title.
// In the majority of cases it is assumed that HTML in the title
// is undesirable.
const contentNoHTML = (0, _dom.__unstableStripHTML)(firstBlock.attributes.content);
onUpdateTitle(contentNoHTML);
onUpdateContent(content.slice(1));
} else {
onUpdateContent(content);
}
} else {
// Strip HTML to avoid unwanted HTML being added to the title.
// In the majority of cases it is assumed that HTML in the title
// is undesirable.
const contentNoHTML = (0, _dom.__unstableStripHTML)(content);
const newValue = (0, _richText.insert)(value, (0, _richText.create)({
html: contentNoHTML
}));
onUpdateTitle((0, _richText.toHTMLString)({
value: newValue
}));
}
}
class PostTitle extends _element.Component {
constructor(props) {
super(props);
this.setRef = this.setRef.bind(this);
this.onPaste = this.onPaste.bind(this);
}
componentDidUpdate(prevProps) {
// Unselect if any other block is selected and blur the RichText.
if (this.props.isSelected && !prevProps.isAnyBlockSelected && this.props.isAnyBlockSelected) {
if (this.richTextRef) {
this.richTextRef.blur();
}
this.props.onUnselect();
}
}
componentDidMount() {
if (this.props.innerRef) {
this.props.innerRef(this);
}
}
handleFocusOutside() {
this.props.onUnselect();
}
focus() {
this.props.onSelect();
}
onPaste({
value,
plainText,
html
}) {
const {
title,
onInsertBlockAfter: onInsertBlocks,
onUpdate
} = this.props;
const content = (0, _blocks.pasteHandler)({
HTML: html,
plainText
});
insertContentWithTitle(title, content, onUpdate, onInsertBlocks, value);
}
setRef(richText) {
this.richTextRef = richText;
}
getTitle(title, postType) {
if ('page' === postType) {
return !title ? /* translators: accessibility text. empty page title. */
(0, _i18n.__)('Page title. Empty') : (0, _i18n.sprintf)( /* translators: accessibility text. %s: text content of the page title. */
(0, _i18n.__)('Page title. %s'), title);
}
return !title ? /* translators: accessibility text. empty post title. */
(0, _i18n.__)('Post title. Empty') : (0, _i18n.sprintf)( /* translators: accessibility text. %s: text content of the post title. */
(0, _i18n.__)('Post title. %s'), title);
}
render() {
const {
placeholder,
style,
title,
focusedBorderColor,
borderStyle,
isDimmed,
postType,
globalStyles
} = this.props;
const decodedPlaceholder = (0, _htmlEntities.decodeEntities)(placeholder);
const borderColor = this.props.isSelected ? focusedBorderColor : 'transparent';
const titleStyles = {
...style,
...(globalStyles?.text && {
color: globalStyles.text,
placeholderColor: globalStyles.text
})
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
testID: "post-title",
style: [_style.default.titleContainer, borderStyle, {
borderColor
}, isDimmed && _style.default.dimmed],
accessible: !this.props.isSelected,
accessibilityLabel: this.getTitle(title, postType),
accessibilityHint: (0, _i18n.__)('Updates the title.'),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.RichText.Raw, {
ref: this.setRef,
accessibilityLabel: this.getTitle(title, postType),
tagName: "p",
tagsToEliminate: ['strong'],
unstableOnFocus: this.props.onSelect,
onBlur: this.props.onBlur // Always assign onBlur as a props.
,
style: titleStyles,
styles: _style.default,
fontSize: 24,
lineHeight: 1,
fontWeight: "bold",
deleteEnter: true,
onChange: value => {
this.props.onUpdate(value);
},
onPaste: this.onPaste,
placeholder: decodedPlaceholder,
value: title,
onSelectionChange: () => {},
onEnter: this.props.onEnterPress,
disableEditingMenu: true,
__unstableIsSelected: this.props.isSelected,
__unstableOnCreateUndoLevel: () => {}
})
});
}
}
var _default = exports.default = (0, _compose.compose)((0, _data.withSelect)(select => {
const {
isPostTitleSelected,
getEditedPostAttribute
} = select(_editor.store);
const {
getSelectedBlockClientId,
getBlockRootClientId,
getSettings
} = select(_blockEditor.store);
const selectedId = getSelectedBlockClientId();
const selectionIsNested = !!getBlockRootClientId(selectedId);
const globalStyles = getSettings()?.__experimentalGlobalStylesBaseStyles?.color;
return {
postType: getEditedPostAttribute('type'),
title: getEditedPostAttribute('title'),
isAnyBlockSelected: !!selectedId,
isSelected: isPostTitleSelected(),
isDimmed: selectionIsNested,
globalStyles
};
}), (0, _data.withDispatch)(dispatch => {
const {
undo,
redo,
togglePostTitleSelection,
editPost
} = dispatch(_editor.store);
const {
clearSelectedBlock,
insertDefaultBlock,
insertBlocks
} = dispatch(_blockEditor.store);
return {
onEnterPress() {
insertDefaultBlock(undefined, undefined, 0);
},
onUndo: undo,
onRedo: redo,
onSelect() {
togglePostTitleSelection(true);
clearSelectedBlock();
},
onUnselect() {
togglePostTitleSelection(false);
},
onUpdate(title) {
editPost({
title
});
},
onInsertBlockAfter(blocks) {
insertBlocks(blocks, 0);
}
};
}), _compose.withInstanceId, _components.withFocusOutside)(PostTitle);
//# sourceMappingURL=index.native.js.map