UNPKG

@wordpress/block-library

Version:
140 lines (130 loc) 5.84 kB
import { createElement, Fragment } from "@wordpress/element"; /** * External dependencies */ import { isEmpty } from 'lodash'; /** * WordPress dependencies */ import { useSelect } from '@wordpress/data'; import { BlockSettingsMenuControls, BlockTitle, useBlockProps, Warning, store as blockEditorStore, __experimentalRecursionProvider as RecursionProvider, __experimentalUseHasRecursion as useHasRecursion } from '@wordpress/block-editor'; import { Spinner, Modal, MenuItem } from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; import { useState, createInterpolateElement } from '@wordpress/element'; /** * Internal dependencies */ import TemplatePartPlaceholder from './placeholder'; import TemplatePartSelectionModal from './selection-modal'; import { TemplatePartAdvancedControls } from './advanced-controls'; import TemplatePartInnerBlocks from './inner-blocks'; import { createTemplatePartId } from './utils/create-template-part-id'; import { useAlternativeBlockPatterns, useAlternativeTemplateParts, useTemplatePartArea } from './utils/hooks'; export default function TemplatePartEdit(_ref) { let { attributes, setAttributes, clientId, isSelected } = _ref; const { slug, theme, tagName, layout = {} } = attributes; const templatePartId = createTemplatePartId(theme, slug); const hasAlreadyRendered = useHasRecursion(templatePartId); const [isTemplatePartSelectionOpen, setIsTemplatePartSelectionOpen] = useState(false); // Set the postId block attribute if it did not exist, // but wait until the inner blocks have loaded to allow // new edits to trigger this. const { isResolved, innerBlocks, isMissing, area } = useSelect(select => { const { getEditedEntityRecord, hasFinishedResolution } = select(coreStore); const { getBlocks } = select(blockEditorStore); const getEntityArgs = ['postType', 'wp_template_part', templatePartId]; const entityRecord = templatePartId ? getEditedEntityRecord(...getEntityArgs) : null; const _area = (entityRecord === null || entityRecord === void 0 ? void 0 : entityRecord.area) || attributes.area; const hasResolvedEntity = templatePartId ? hasFinishedResolution('getEditedEntityRecord', getEntityArgs) : false; return { innerBlocks: getBlocks(clientId), isResolved: hasResolvedEntity, isMissing: hasResolvedEntity && isEmpty(entityRecord), area: _area }; }, [templatePartId, clientId]); const { templateParts } = useAlternativeTemplateParts(area, templatePartId); const blockPatterns = useAlternativeBlockPatterns(area, clientId); const hasReplacements = !!templateParts.length || !!blockPatterns.length; const areaObject = useTemplatePartArea(area); const blockProps = useBlockProps(); const isPlaceholder = !slug; const isEntityAvailable = !isPlaceholder && !isMissing && isResolved; const TagName = tagName || areaObject.tagName; // The `isSelected` check ensures the `BlockSettingsMenuControls` fill // doesn't render multiple times. The block controls has similar internal check. const canReplace = isSelected && isEntityAvailable && hasReplacements && (area === 'header' || area === 'footer'); // We don't want to render a missing state if we have any inner blocks. // A new template part is automatically created if we have any inner blocks but no entity. if (innerBlocks.length === 0 && (slug && !theme || slug && isMissing)) { return createElement(TagName, blockProps, createElement(Warning, null, sprintf( /* translators: %s: Template part slug */ __('Template part has been deleted or is unavailable: %s'), slug))); } if (isEntityAvailable && hasAlreadyRendered) { return createElement(TagName, blockProps, createElement(Warning, null, __('Block cannot be rendered inside itself.'))); } return createElement(Fragment, null, createElement(RecursionProvider, { uniqueId: templatePartId }, createElement(TemplatePartAdvancedControls, { tagName: tagName, setAttributes: setAttributes, isEntityAvailable: isEntityAvailable, templatePartId: templatePartId, defaultWrapper: areaObject.tagName }), isPlaceholder && createElement(TagName, blockProps, createElement(TemplatePartPlaceholder, { area: attributes.area, templatePartId: templatePartId, clientId: clientId, setAttributes: setAttributes, onOpenSelectionModal: () => setIsTemplatePartSelectionOpen(true) })), canReplace && createElement(BlockSettingsMenuControls, null, () => createElement(MenuItem, { onClick: () => { setIsTemplatePartSelectionOpen(true); } }, createInterpolateElement(__('Replace <BlockTitle />'), { BlockTitle: createElement(BlockTitle, { clientId: clientId, maximumLength: 25 }) }))), isEntityAvailable && createElement(TemplatePartInnerBlocks, { tagName: TagName, blockProps: blockProps, postId: templatePartId, hasInnerBlocks: innerBlocks.length > 0, layout: layout }), !isPlaceholder && !isResolved && createElement(TagName, blockProps, createElement(Spinner, null))), isTemplatePartSelectionOpen && createElement(Modal, { overlayClassName: "block-editor-template-part__selection-modal", title: sprintf( // Translators: %s as template part area title ("Header", "Footer", etc.). __('Choose a %s'), areaObject.label.toLowerCase()), closeLabel: __('Cancel'), onRequestClose: () => setIsTemplatePartSelectionOpen(false) }, createElement(TemplatePartSelectionModal, { templatePartId: templatePartId, clientId: clientId, area: area, setAttributes: setAttributes, onClose: () => setIsTemplatePartSelectionOpen(false) }))); } //# sourceMappingURL=index.js.map