UNPKG

@wordpress/block-editor

Version:
653 lines (651 loc) 24.6 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/block-editor/src/components/block-list/block.js var block_exports = {}; __export(block_exports, { default: () => block_default }); module.exports = __toCommonJS(block_exports); var import_clsx = __toESM(require("clsx")); var import_element = require("@wordpress/element"); var import_blocks = require("@wordpress/blocks"); var import_components = require("@wordpress/components"); var import_data = require("@wordpress/data"); var import_compose = require("@wordpress/compose"); var import_dom = require("@wordpress/dom"); var import_block_edit = __toESM(require("../block-edit/index.cjs")); var import_block_invalid_warning = __toESM(require("./block-invalid-warning.cjs")); var import_block_crash_warning = __toESM(require("./block-crash-warning.cjs")); var import_block_crash_boundary = __toESM(require("./block-crash-boundary.cjs")); var import_block_html = __toESM(require("./block-html.cjs")); var import_use_block_props = require("./use-block-props/index.cjs"); var import_store = require("../../store/index.cjs"); var import_layout = require("./layout.cjs"); var import_private_block_context = require("./private-block-context.cjs"); var import_block_visibility = require("../block-visibility/index.cjs"); var import_lock_unlock = require("../../lock-unlock.cjs"); var import_private_keys = require("../../store/private-keys.cjs"); var import_jsx_runtime = require("react/jsx-runtime"); function mergeWrapperProps(propsA, propsB) { const newProps = { ...propsA, ...propsB }; if (propsA?.hasOwnProperty("className") && propsB?.hasOwnProperty("className")) { newProps.className = (0, import_clsx.default)(propsA.className, propsB.className); } if (propsA?.hasOwnProperty("style") && propsB?.hasOwnProperty("style")) { newProps.style = { ...propsA.style, ...propsB.style }; } return newProps; } function Block({ children, isHtml, ...props }) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...(0, import_use_block_props.useBlockProps)(props, { __unstableIsHtml: isHtml }), children }); } function BlockListBlock({ block: { __unstableBlockSource }, mode, isLocked, canRemove, clientId, isSelected, isSelectionEnabled, className, __unstableLayoutClassNames: layoutClassNames, name, isValid, attributes, wrapperProps, setAttributes, onReplace, onRemove, onInsertBlocksAfter, onMerge, toggleSelection }) { const { mayDisplayControls, mayDisplayParentControls, isSelectionWithinCurrentSection, themeSupportsLayout, ...context } = (0, import_element.useContext)(import_private_block_context.PrivateBlockContext); const parentLayout = (0, import_layout.useLayout)() || {}; let blockEdit = /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_block_edit.default, { name, isSelected, attributes, setAttributes, insertBlocksAfter: isLocked ? void 0 : onInsertBlocksAfter, onReplace: canRemove ? onReplace : void 0, onRemove: canRemove ? onRemove : void 0, mergeBlocks: canRemove ? onMerge : void 0, clientId, isSelectionEnabled, toggleSelection, __unstableLayoutClassNames: layoutClassNames, __unstableParentLayout: Object.keys(parentLayout).length ? parentLayout : void 0, mayDisplayControls, mayDisplayParentControls, mayDisplayPatternEditingControls: isSelectionWithinCurrentSection, blockEditingMode: context.blockEditingMode, isPreviewMode: context.isPreviewMode } ); const blockType = (0, import_blocks.getBlockType)(name); if (blockType?.getEditWrapperProps) { wrapperProps = mergeWrapperProps( wrapperProps, blockType.getEditWrapperProps(attributes) ); } const isAligned = wrapperProps && !!wrapperProps["data-align"] && !themeSupportsLayout; const isSticky = className?.includes("is-position-sticky"); if (isAligned) { blockEdit = /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { className: (0, import_clsx.default)("wp-block", isSticky && className), "data-align": wrapperProps["data-align"], children: blockEdit } ); } let block; if (!isValid) { const saveContent = __unstableBlockSource ? (0, import_blocks.serializeRawBlock)(__unstableBlockSource) : (0, import_blocks.getSaveContent)(blockType, attributes); block = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Block, { className: "has-warning", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_invalid_warning.default, { clientId }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_element.RawHTML, { children: (0, import_dom.safeHTML)(saveContent) }) ] }); } else if (mode === "html") { block = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "none" }, children: blockEdit }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Block, { isHtml: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_html.default, { clientId }) }) ] }); } else if (blockType?.apiVersion > 1) { block = blockEdit; } else { block = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Block, { children: blockEdit }); } const { "data-align": dataAlign, ...restWrapperProps } = wrapperProps ?? {}; const updatedWrapperProps = { ...restWrapperProps, className: (0, import_clsx.default)( restWrapperProps.className, dataAlign && themeSupportsLayout && `align${dataAlign}`, !(dataAlign && isSticky) && className ) }; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_private_block_context.PrivateBlockContext.Provider, { value: { wrapperProps: updatedWrapperProps, isAligned, isSelectionWithinCurrentSection, ...context }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_block_crash_boundary.default, { fallback: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Block, { className: "has-warning", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_crash_warning.default, {}) }), children: block } ) } ); } var applyWithDispatch = (0, import_data.withDispatch)((dispatch, ownProps, registry) => { const { updateBlockAttributes, insertBlocks, mergeBlocks, replaceBlocks, toggleSelection, __unstableMarkLastChangeAsPersistent, moveBlocksToPosition, removeBlock, selectBlock } = dispatch(import_store.store); return { setAttributes(nextAttributes) { const { getMultiSelectedBlockClientIds } = registry.select(import_store.store); const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(); const { clientId, attributes } = ownProps; const clientIds = multiSelectedBlockClientIds.length ? multiSelectedBlockClientIds : [clientId]; const newAttributes = typeof nextAttributes === "function" ? nextAttributes(attributes) : nextAttributes; updateBlockAttributes(clientIds, newAttributes); }, onInsertBlocks(blocks, index) { const { rootClientId } = ownProps; insertBlocks(blocks, index, rootClientId); }, onInsertBlocksAfter(blocks) { const { clientId, rootClientId } = ownProps; const { getBlockIndex } = registry.select(import_store.store); const index = getBlockIndex(clientId); insertBlocks(blocks, index + 1, rootClientId); }, onMerge(forward) { const { clientId, rootClientId } = ownProps; const { getPreviousBlockClientId, getNextBlockClientId, getBlock, getBlockAttributes, getBlockName, getBlockOrder, getBlockIndex, getBlockRootClientId, canInsertBlockType } = registry.select(import_store.store); function switchToDefaultOrRemove() { const block = getBlock(clientId); const defaultBlockName = (0, import_blocks.getDefaultBlockName)(); const defaultBlockType = (0, import_blocks.getBlockType)(defaultBlockName); if (getBlockName(clientId) !== defaultBlockName) { const replacement = (0, import_blocks.switchToBlockType)( block, defaultBlockName ); if (replacement && replacement.length) { replaceBlocks(clientId, replacement); } } else if ((0, import_blocks.isUnmodifiedDefaultBlock)(block)) { const nextBlockClientId = getNextBlockClientId(clientId); if (nextBlockClientId) { registry.batch(() => { removeBlock(clientId); selectBlock(nextBlockClientId); }); } } else if (defaultBlockType.merge) { const attributes = defaultBlockType.merge( {}, block.attributes ); replaceBlocks( [clientId], [(0, import_blocks.createBlock)(defaultBlockName, attributes)] ); } } function moveFirstItemUp(_clientId, changeSelection = true) { const wrapperBlockName = getBlockName(_clientId); const wrapperBlockType = (0, import_blocks.getBlockType)(wrapperBlockName); const isTextualWrapper = wrapperBlockType.category === "text"; const targetRootClientId = getBlockRootClientId(_clientId); const blockOrder = getBlockOrder(_clientId); const [firstClientId] = blockOrder; if (blockOrder.length === 1 && (0, import_blocks.isUnmodifiedBlock)(getBlock(firstClientId))) { removeBlock(_clientId); } else if (isTextualWrapper) { registry.batch(() => { if (canInsertBlockType( getBlockName(firstClientId), targetRootClientId )) { moveBlocksToPosition( [firstClientId], _clientId, targetRootClientId, getBlockIndex(_clientId) ); } else { const replacement = (0, import_blocks.switchToBlockType)( getBlock(firstClientId), (0, import_blocks.getDefaultBlockName)() ); if (replacement && replacement.length && replacement.every( (block) => canInsertBlockType( block.name, targetRootClientId ) )) { insertBlocks( replacement, getBlockIndex(_clientId), targetRootClientId, changeSelection ); removeBlock(firstClientId, false); } else { switchToDefaultOrRemove(); } } if (!getBlockOrder(_clientId).length && (0, import_blocks.isUnmodifiedBlock)(getBlock(_clientId))) { removeBlock(_clientId, false); } }); } else { switchToDefaultOrRemove(); } } if (forward) { if (rootClientId) { const nextRootClientId = getNextBlockClientId(rootClientId); if (nextRootClientId) { if (getBlockName(rootClientId) === getBlockName(nextRootClientId)) { const rootAttributes = getBlockAttributes(rootClientId); const previousRootAttributes = getBlockAttributes(nextRootClientId); if (Object.keys(rootAttributes).every( (key) => rootAttributes[key] === previousRootAttributes[key] )) { registry.batch(() => { moveBlocksToPosition( getBlockOrder(nextRootClientId), nextRootClientId, rootClientId ); removeBlock(nextRootClientId, false); }); return; } } else { mergeBlocks(rootClientId, nextRootClientId); return; } } } const nextBlockClientId = getNextBlockClientId(clientId); if (!nextBlockClientId) { return; } if (getBlockOrder(nextBlockClientId).length) { moveFirstItemUp(nextBlockClientId, false); } else { mergeBlocks(clientId, nextBlockClientId); } } else { const previousBlockClientId = getPreviousBlockClientId(clientId); if (previousBlockClientId) { mergeBlocks(previousBlockClientId, clientId); } else if (rootClientId) { const previousRootClientId = getPreviousBlockClientId(rootClientId); if (previousRootClientId && getBlockName(rootClientId) === getBlockName(previousRootClientId)) { const rootAttributes = getBlockAttributes(rootClientId); const previousRootAttributes = getBlockAttributes(previousRootClientId); if (Object.keys(rootAttributes).every( (key) => rootAttributes[key] === previousRootAttributes[key] )) { registry.batch(() => { moveBlocksToPosition( getBlockOrder(rootClientId), rootClientId, previousRootClientId ); removeBlock(rootClientId, false); }); return; } } moveFirstItemUp(rootClientId); } else { switchToDefaultOrRemove(); } } }, onReplace(blocks, indexToSelect, initialPosition) { if (blocks.length && !(0, import_blocks.isUnmodifiedDefaultBlock)(blocks[blocks.length - 1])) { __unstableMarkLastChangeAsPersistent(); } const replacementBlocks = blocks?.length === 1 && Array.isArray(blocks[0]) ? blocks[0] : blocks; replaceBlocks( [ownProps.clientId], replacementBlocks, indexToSelect, initialPosition ); }, onRemove() { removeBlock(ownProps.clientId); }, toggleSelection(selectionEnabled) { toggleSelection(selectionEnabled); } }; }); BlockListBlock = (0, import_compose.compose)( applyWithDispatch, (0, import_components.withFilters)("editor.BlockListBlock") )(BlockListBlock); function BlockListBlockProvider(props) { const { clientId, rootClientId } = props; const selectedProps = (0, import_data.useSelect)( (select) => { const { isBlockSelected, getBlockMode, isSelectionEnabled: isSelectionEnabled2, getTemplateLock, isSectionBlock: _isSectionBlock, getParentSectionBlock, getBlockWithoutAttributes, getBlockAttributes, canRemoveBlock, canMoveBlock, getSettings, getEditedContentOnlySection, getBlockEditingMode, getBlockName, isFirstMultiSelectedBlock, getMultiSelectedBlockClientIds, hasSelectedInnerBlock, getBlocksByName, getBlockIndex, isBlockMultiSelected, isBlockSubtreeDisabled, isBlockHighlighted, __unstableIsFullySelected, __unstableSelectionHasUnmergeableBlock, isBlockBeingDragged, isDragging: isDragging2, __unstableHasActiveBlockOverlayActive, getSelectedBlocksInitialCaretPosition } = (0, import_lock_unlock.unlock)(select(import_store.store)); const blockWithoutAttributes2 = getBlockWithoutAttributes(clientId); if (!blockWithoutAttributes2) { return; } const { hasBlockSupport: _hasBlockSupport, getActiveBlockVariation } = select(import_blocks.store); const attributes2 = getBlockAttributes(clientId); const { name: blockName, isValid: isValid2 } = blockWithoutAttributes2; const blockType2 = (0, import_blocks.getBlockType)(blockName); const settings = getSettings(); const { supportsLayout, isPreviewMode: isPreviewMode2, __experimentalBlockBindingsSupportedAttributes } = settings; const bindableAttributes2 = __experimentalBlockBindingsSupportedAttributes?.[blockName]; const blockVisibility2 = attributes2?.metadata?.blockVisibility; const deviceType2 = settings?.[import_private_keys.deviceTypeKey]?.toLowerCase() || "desktop"; const hasLightBlockWrapper = blockType2?.apiVersion > 1; const previewContext = { isPreviewMode: isPreviewMode2, blockWithoutAttributes: blockWithoutAttributes2, name: blockName, attributes: attributes2, isValid: isValid2, themeSupportsLayout: supportsLayout, index: getBlockIndex(clientId), isReusable: (0, import_blocks.isReusableBlock)(blockType2), className: hasLightBlockWrapper ? attributes2.className : void 0, defaultClassName: hasLightBlockWrapper ? (0, import_blocks.getBlockDefaultClassName)(blockName) : void 0, blockTitle: blockType2?.title, bindableAttributes: bindableAttributes2, blockVisibility: blockVisibility2, deviceType: deviceType2 }; if (isPreviewMode2) { return previewContext; } const _isSelected = isBlockSelected(clientId); const canRemove2 = canRemoveBlock(clientId); const canMove2 = canMoveBlock(clientId); const match = getActiveBlockVariation(blockName, attributes2); const isMultiSelected2 = isBlockMultiSelected(clientId); const checkDeep = true; const isAncestorOfSelectedBlock = hasSelectedInnerBlock( clientId, checkDeep ); const blockEditingMode2 = getBlockEditingMode(clientId); const sectionBlockClientId = _isSectionBlock(clientId) ? clientId : getParentSectionBlock(clientId); const multiple = (0, import_blocks.hasBlockSupport)(blockName, "multiple", true); const blocksWithSameName = multiple ? [] : getBlocksByName(blockName); const isInvalid = blocksWithSameName.length && blocksWithSameName[0] !== clientId; return { ...previewContext, mode: getBlockMode(clientId), isSelectionEnabled: isSelectionEnabled2(), isLocked: !!getTemplateLock(rootClientId), isSectionBlock: _isSectionBlock(clientId), isWithinSectionBlock: !!sectionBlockClientId, isSelectionWithinCurrentSection: isBlockSelected(sectionBlockClientId) || hasSelectedInnerBlock(sectionBlockClientId, checkDeep), blockType: blockType2, canRemove: canRemove2, canMove: canMove2, isSelected: _isSelected, isEditingContentOnlySection: getEditedContentOnlySection() === clientId, blockEditingMode: blockEditingMode2, mayDisplayControls: _isSelected || isFirstMultiSelectedBlock(clientId) && getMultiSelectedBlockClientIds().every( (id) => getBlockName(id) === blockName ), mayDisplayParentControls: _hasBlockSupport( getBlockName(clientId), "__experimentalExposeControlsToChildren", false ) && hasSelectedInnerBlock(clientId), blockApiVersion: blockType2?.apiVersion || 1, blockTitle: match?.title || blockType2?.title, isSubtreeDisabled: blockEditingMode2 === "disabled" && isBlockSubtreeDisabled(clientId), hasOverlay: __unstableHasActiveBlockOverlayActive(clientId) && !isDragging2(), initialPosition: _isSelected ? getSelectedBlocksInitialCaretPosition() : void 0, isHighlighted: isBlockHighlighted(clientId), isMultiSelected: isMultiSelected2, isPartiallySelected: isMultiSelected2 && !__unstableIsFullySelected() && !__unstableSelectionHasUnmergeableBlock(), isDragging: isBlockBeingDragged(clientId), hasChildSelected: isAncestorOfSelectedBlock, isEditingDisabled: blockEditingMode2 === "disabled", hasEditableOutline: blockEditingMode2 !== "disabled" && getBlockEditingMode(rootClientId) === "disabled", originalBlockClientId: isInvalid ? blocksWithSameName[0] : false, blockVisibility: blockVisibility2, deviceType: deviceType2 }; }, [clientId, rootClientId] ); const { isPreviewMode, // Fill values that end up as a public API and may not be defined in // preview mode. mode = "visual", isSelectionEnabled = false, isLocked = false, canRemove = false, canMove = false, blockWithoutAttributes, name, attributes, isValid, isSelected = false, themeSupportsLayout, isEditingContentOnlySection, blockEditingMode, mayDisplayControls, mayDisplayParentControls, index, blockApiVersion, blockType, blockTitle, isSubtreeDisabled, hasOverlay, initialPosition, isHighlighted, isMultiSelected, isPartiallySelected, isReusable, isDragging, hasChildSelected, isSectionBlock, isWithinSectionBlock, isSelectionWithinCurrentSection, isEditingDisabled, hasEditableOutline, className, defaultClassName, originalBlockClientId, bindableAttributes, blockVisibility, deviceType } = selectedProps; const { isBlockCurrentlyHidden } = (0, import_block_visibility.useBlockVisibility)({ blockVisibility, deviceType }); const block = (0, import_element.useMemo)( () => ({ ...blockWithoutAttributes, attributes }), [blockWithoutAttributes, attributes] ); if (!selectedProps) { return null; } const privateContext = { isPreviewMode, clientId, className, index, mode, name, blockApiVersion, blockType, blockTitle, isSelected, isSubtreeDisabled, hasOverlay, initialPosition, blockEditingMode, isHighlighted, isMultiSelected, isPartiallySelected, isReusable, isDragging, hasChildSelected, isSectionBlock, isWithinSectionBlock, isSelectionWithinCurrentSection, isEditingDisabled, hasEditableOutline, isEditingContentOnlySection, defaultClassName, mayDisplayControls, mayDisplayParentControls, originalBlockClientId, themeSupportsLayout, canMove, isBlockCurrentlyHidden, bindableAttributes, blockVisibility, deviceType }; if (isBlockCurrentlyHidden && !isSelected && !isMultiSelected && !hasChildSelected) { return null; } return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_private_block_context.PrivateBlockContext.Provider, { value: privateContext, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( BlockListBlock, { ...props, ...{ mode, isSelectionEnabled, isLocked, canRemove, canMove, // Users of the editor.BlockListBlock filter used to be able // to access the block prop. Ideally these blocks would rely // on the clientId prop only. This is kept for backward // compatibility reasons. block, name, attributes, isValid, isSelected } } ) }); } var block_default = (0, import_element.memo)(BlockListBlockProvider); //# sourceMappingURL=block.cjs.map