Fix File
•
/
home
/
sportsfe...
/
httpdocs
/
clone
/
wp-inclu...
/
js
/
dist
•
File:
block-editor.js
•
Content:
} // Find all tabbables within node. const textInputs = external_wp_dom_namespaceObject.focus.tabbable.find(ref.current).filter(node => (0,external_wp_dom_namespaceObject.isTextField)(node)); // If reversed (e.g. merge via backspace), use the last in the set of // tabbables. const isReverse = -1 === initialPosition; const target = textInputs[isReverse ? textInputs.length - 1 : 0] || ref.current; if (!isInsideRootBlock(ref.current, target)) { ref.current.focus(); return; } // Check to see if element is focussable before a generic caret insert. if (!ref.current.getAttribute('contenteditable')) { const focusElement = external_wp_dom_namespaceObject.focus.tabbable.findNext(ref.current); // Make sure focusElement is valid, contained in the same block, and a form field. if (focusElement && isInsideRootBlock(ref.current, focusElement) && (0,external_wp_dom_namespaceObject.isFormElement)(focusElement)) { focusElement.focus(); return; } } (0,external_wp_dom_namespaceObject.placeCaretAtHorizontalEdge)(target, isReverse); }, [initialPosition, clientId]); return ref; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/use-is-hovered.js /** * WordPress dependencies */ function listener(event) { if (event.defaultPrevented) { return; } const action = event.type === 'mouseover' ? 'add' : 'remove'; event.preventDefault(); event.currentTarget.classList[action]('is-hovered'); } /* * Adds `is-hovered` class when the block is hovered and in navigation or * outline mode. */ function useIsHovered() { return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { node.addEventListener('mouseout', listener); node.addEventListener('mouseover', listener); return () => { node.removeEventListener('mouseout', listener); node.removeEventListener('mouseover', listener); // Remove class in case it lingers. node.classList.remove('is-hovered'); }; }, []); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/use-focus-handler.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Selects the block if it receives focus. * * @param {string} clientId Block client ID. */ function useFocusHandler(clientId) { const { isBlockSelected } = (0,external_wp_data_namespaceObject.useSelect)(store); const { selectBlock, selectionChange } = (0,external_wp_data_namespaceObject.useDispatch)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { /** * Marks the block as selected when focused and not already * selected. This specifically handles the case where block does not * set focus on its own (via `setFocus`), typically if there is no * focusable input in the block. * * @param {FocusEvent} event Focus event. */ function onFocus(event) { // When the whole editor is editable, let writing flow handle // selection. if (node.parentElement.closest('[contenteditable="true"]')) { return; } // Check synchronously because a non-selected block might be // getting data through `useSelect` asynchronously. if (isBlockSelected(clientId)) { // Potentially change selection away from rich text. if (!event.target.isContentEditable) { selectionChange(clientId); } return; } // If an inner block is focussed, that block is resposible for // setting the selected block. if (!isInsideRootBlock(node, event.target)) { return; } selectBlock(clientId); } node.addEventListener('focusin', onFocus); return () => { node.removeEventListener('focusin', onFocus); }; }, [isBlockSelected, selectBlock]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Adds block behaviour: * - Removes the block on BACKSPACE. * - Inserts a default block on ENTER. * - Disables dragging of block contents. * * @param {string} clientId Block client ID. */ function useEventHandlers({ clientId, isSelected }) { const { getBlockRootClientId, getBlockIndex } = (0,external_wp_data_namespaceObject.useSelect)(store); const { insertAfterBlock, removeBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { if (!isSelected) { return; } /** * Interprets keydown event intent to remove or insert after block if * key event occurs on wrapper node. This can occur when the block has * no text fields of its own, particularly after initial insertion, to * allow for easy deletion and continuous writing flow to add additional * content. * * @param {KeyboardEvent} event Keydown event. */ function onKeyDown(event) { const { keyCode, target } = event; if (keyCode !== external_wp_keycodes_namespaceObject.ENTER && keyCode !== external_wp_keycodes_namespaceObject.BACKSPACE && keyCode !== external_wp_keycodes_namespaceObject.DELETE) { return; } if (target !== node || (0,external_wp_dom_namespaceObject.isTextField)(target)) { return; } event.preventDefault(); if (keyCode === external_wp_keycodes_namespaceObject.ENTER) { insertAfterBlock(clientId); } else { removeBlock(clientId); } } /** * Prevents default dragging behavior within a block. To do: we must * handle this in the future and clean up the drag target. * * @param {DragEvent} event Drag event. */ function onDragStart(event) { event.preventDefault(); } node.addEventListener('keydown', onKeyDown); node.addEventListener('dragstart', onDragStart); return () => { node.removeEventListener('keydown', onKeyDown); node.removeEventListener('dragstart', onDragStart); }; }, [clientId, isSelected, getBlockRootClientId, getBlockIndex, insertAfterBlock, removeBlock]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/use-nav-mode-exit.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Allows navigation mode to be exited by clicking in the selected block. * * @param {string} clientId Block client ID. */ function useNavModeExit(clientId) { const { isNavigationMode, isBlockSelected } = (0,external_wp_data_namespaceObject.useSelect)(store); const { setNavigationMode, selectBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { function onMouseDown(event) { // Don't select a block if it's already handled by a child // block. if (isNavigationMode() && !event.defaultPrevented) { // Prevent focus from moving to the block. event.preventDefault(); // When clicking on a selected block, exit navigation mode. if (isBlockSelected(clientId)) { setNavigationMode(false); } else { selectBlock(clientId); } } } node.addEventListener('mousedown', onMouseDown); return () => { node.removeEventListener('mousedown', onMouseDown); }; }, [clientId, isNavigationMode, isBlockSelected, setNavigationMode]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/use-intersection-observer.js /** * WordPress dependencies */ /** * Internal dependencies */ function useIntersectionObserver() { const observer = (0,external_wp_element_namespaceObject.useContext)(block_list_IntersectionObserver); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { if (observer) { observer.observe(node); return () => { observer.unobserve(node); }; } }, [observer]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/use-scroll-into-view.js /** * WordPress dependencies */ function useScrollIntoView({ isSelected }) { const prefersReducedMotion = (0,external_wp_compose_namespaceObject.useReducedMotion)(); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { if (isSelected) { const { ownerDocument } = node; const { defaultView } = ownerDocument; if (!defaultView.IntersectionObserver) { return; } const observer = new defaultView.IntersectionObserver(entries => { // Once observing starts, we always get an initial // entry with the intersecting state. if (!entries[0].isIntersecting) { node.scrollIntoView({ behavior: prefersReducedMotion ? 'instant' : 'smooth' }); } observer.disconnect(); }); observer.observe(node); return () => { observer.disconnect(); }; } }, [isSelected]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/use-flash-editable-blocks/index.js /** * WordPress dependencies */ /** * Internal dependencies */ function useFlashEditableBlocks({ clientId = '', isEnabled = true } = {}) { const { getEnabledClientIdsTree } = unlock((0,external_wp_data_namespaceObject.useSelect)(store)); return (0,external_wp_compose_namespaceObject.useRefEffect)(element => { if (!isEnabled) { return; } const flashEditableBlocks = () => { getEnabledClientIdsTree(clientId).forEach(({ clientId: id }) => { const block = element.querySelector(`[data-block="${id}"]`); if (!block) { return; } block.classList.remove('has-editable-outline'); // Force reflow to trigger the animation. // eslint-disable-next-line no-unused-expressions block.offsetWidth; block.classList.add('has-editable-outline'); }); }; const handleClick = event => { const shouldFlash = event.target === element || event.target.classList.contains('is-root-container'); if (!shouldFlash) { return; } if (event.defaultPrevented) { return; } event.preventDefault(); flashEditableBlocks(); }; element.addEventListener('click', handleClick); return () => element.removeEventListener('click', handleClick); }, [isEnabled]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-block-props/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * This hook is used to lightly mark an element as a block element. The element * should be the outermost element of a block. Call this hook and pass the * returned props to the element to mark as a block. If you define a ref for the * element, it is important to pass the ref to this hook, which the hook in turn * will pass to the component through the props it returns. Optionally, you can * also pass any other props through this hook, and they will be merged and * returned. * * Use of this hook on the outermost element of a block is required if using API >= v2. * * @example * ```js * import { useBlockProps } from '@wordpress/block-editor'; * * export default function Edit() { * * const blockProps = useBlockProps( * className: 'my-custom-class', * style: { * color: '#222222', * backgroundColor: '#eeeeee' * } * ) * * return ( * <div { ...blockProps }> * * </div> * ) * } * * ``` * * * @param {Object} props Optional. Props to pass to the element. Must contain * the ref if one is defined. * @param {Object} options Options for internal use only. * @param {boolean} options.__unstableIsHtml * * @return {Object} Props to pass to the element to mark as a block. */ function use_block_props_useBlockProps(props = {}, { __unstableIsHtml } = {}) { const { clientId, className, wrapperProps = {}, isAligned, index, mode, name, blockApiVersion, blockTitle, isSelected, isSubtreeDisabled, hasOverlay, initialPosition, blockEditingMode, isHighlighted, isMultiSelected, isPartiallySelected, isReusable, isDragging, hasChildSelected, isBlockMovingMode, canInsertMovingBlock, isEditingDisabled, hasEditableOutline, isTemporarilyEditingAsBlocks, defaultClassName, templateLock } = (0,external_wp_element_namespaceObject.useContext)(PrivateBlockContext); // translators: %s: Type of block (i.e. Text, Image etc) const blockLabel = (0,external_wp_i18n_namespaceObject.sprintf)((0,external_wp_i18n_namespaceObject.__)('Block: %s'), blockTitle); const htmlSuffix = mode === 'html' && !__unstableIsHtml ? '-visual' : ''; const mergedRefs = (0,external_wp_compose_namespaceObject.useMergeRefs)([props.ref, useFocusFirstElement({ clientId, initialPosition }), useBlockRefProvider(clientId), useFocusHandler(clientId), useEventHandlers({ clientId, isSelected }), useNavModeExit(clientId), useIsHovered(), useIntersectionObserver(), use_moving_animation({ triggerAnimationOnChange: index, clientId }), (0,external_wp_compose_namespaceObject.useDisabled)({ isDisabled: !hasOverlay }), useFlashEditableBlocks({ clientId, isEnabled: name === 'core/block' || templateLock === 'contentOnly' }), useScrollIntoView({ isSelected })]); const blockEditContext = useBlockEditContext(); const hasBlockBindings = !!blockEditContext[blockBindingsKey]; const bindingsStyle = hasBlockBindings && canBindBlock(name) ? { '--wp-admin-theme-color': 'var(--wp-block-synced-color)', '--wp-admin-theme-color--rgb': 'var(--wp-block-synced-color--rgb)' } : {}; // Ensures it warns only inside the `edit` implementation for the block. if (blockApiVersion < 2 && clientId === blockEditContext.clientId) { true ? external_wp_warning_default()(`Block type "${name}" must support API version 2 or higher to work correctly with "useBlockProps" method.`) : 0; } let hasNegativeMargin = false; if (wrapperProps?.style?.marginTop?.charAt(0) === '-' || wrapperProps?.style?.marginBottom?.charAt(0) === '-' || wrapperProps?.style?.marginLeft?.charAt(0) === '-' || wrapperProps?.style?.marginRight?.charAt(0) === '-') { hasNegativeMargin = true; } return { tabIndex: blockEditingMode === 'disabled' ? -1 : 0, ...wrapperProps, ...props, ref: mergedRefs, id: `block-${clientId}${htmlSuffix}`, role: 'document', 'aria-label': blockLabel, 'data-block': clientId, 'data-type': name, 'data-title': blockTitle, inert: isSubtreeDisabled ? 'true' : undefined, className: dist_clsx('block-editor-block-list__block', { // The wp-block className is important for editor styles. 'wp-block': !isAligned, 'has-block-overlay': hasOverlay, 'is-selected': isSelected, 'is-highlighted': isHighlighted, 'is-multi-selected': isMultiSelected, 'is-partially-selected': isPartiallySelected, 'is-reusable': isReusable, 'is-dragging': isDragging, 'has-child-selected': hasChildSelected, 'is-block-moving-mode': isBlockMovingMode, 'can-insert-moving-block': canInsertMovingBlock, 'is-editing-disabled': isEditingDisabled, 'has-editable-outline': hasEditableOutline, 'has-negative-margin': hasNegativeMargin, 'is-content-locked-temporarily-editing-as-blocks': isTemporarilyEditingAsBlocks }, className, props.className, wrapperProps.className, defaultClassName), style: { ...wrapperProps.style, ...props.style, ...bindingsStyle } }; } /** * Call within a save function to get the props for the block wrapper. * * @param {Object} props Optional. Props to pass to the element. */ use_block_props_useBlockProps.save = external_wp_blocks_namespaceObject.__unstableGetBlockProps; ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/block.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Merges wrapper props with special handling for classNames and styles. * * @param {Object} propsA * @param {Object} propsB * * @return {Object} Merged props. */ function mergeWrapperProps(propsA, propsB) { const newProps = { ...propsA, ...propsB }; // May be set to undefined, so check if the property is set! if (propsA?.hasOwnProperty('className') && propsB?.hasOwnProperty('className')) { newProps.className = dist_clsx(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,external_ReactJSXRuntime_namespaceObject.jsx)("div", { ...use_block_props_useBlockProps(props, { __unstableIsHtml: isHtml }), children: children }); } function BlockListBlock({ block: { __unstableBlockSource }, mode, isLocked, canRemove, clientId, isSelected, isSelectionEnabled, className, __unstableLayoutClassNames: layoutClassNames, name, isValid, attributes, wrapperProps, setAttributes, onReplace, onInsertBlocksAfter, onMerge, toggleSelection }) { var _wrapperProps; const { mayDisplayControls, mayDisplayParentControls, themeSupportsLayout, ...context } = (0,external_wp_element_namespaceObject.useContext)(PrivateBlockContext); const { removeBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); const onRemove = (0,external_wp_element_namespaceObject.useCallback)(() => removeBlock(clientId), [clientId, removeBlock]); const parentLayout = useLayout() || {}; // We wrap the BlockEdit component in a div that hides it when editing in // HTML mode. This allows us to render all of the ancillary pieces // (InspectorControls, etc.) which are inside `BlockEdit` but not // `BlockHTML`, even in HTML mode. let blockEdit = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockEdit, { name: name, isSelected: isSelected, attributes: attributes, setAttributes: setAttributes, insertBlocksAfter: isLocked ? undefined : onInsertBlocksAfter, onReplace: canRemove ? onReplace : undefined, onRemove: canRemove ? onRemove : undefined, mergeBlocks: canRemove ? onMerge : undefined, clientId: clientId, isSelectionEnabled: isSelectionEnabled, toggleSelection: toggleSelection, __unstableLayoutClassNames: layoutClassNames, __unstableParentLayout: Object.keys(parentLayout).length ? parentLayout : undefined, mayDisplayControls: mayDisplayControls, mayDisplayParentControls: mayDisplayParentControls, blockEditingMode: context.blockEditingMode, isPreviewMode: context.isPreviewMode }); const blockType = (0,external_wp_blocks_namespaceObject.getBlockType)(name); // Determine whether the block has props to apply to the wrapper. if (blockType?.getEditWrapperProps) { wrapperProps = mergeWrapperProps(wrapperProps, blockType.getEditWrapperProps(attributes)); } const isAligned = wrapperProps && !!wrapperProps['data-align'] && !themeSupportsLayout; // Support for sticky position in classic themes with alignment wrappers. const isSticky = className?.includes('is-position-sticky'); // For aligned blocks, provide a wrapper element so the block can be // positioned relative to the block column. // This is only kept for classic themes that don't support layout // Historically we used to rely on extra divs and data-align to // provide the alignments styles in the editor. // Due to the differences between frontend and backend, we migrated // to the layout feature, and we're now aligning the markup of frontend // and backend. if (isAligned) { blockEdit = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: dist_clsx('wp-block', isSticky && className), "data-align": wrapperProps['data-align'], children: blockEdit }); } let block; if (!isValid) { const saveContent = __unstableBlockSource ? (0,external_wp_blocks_namespaceObject.serializeRawBlock)(__unstableBlockSource) : (0,external_wp_blocks_namespaceObject.getSaveContent)(blockType, attributes); block = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(Block, { className: "has-warning", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockInvalidWarning, { clientId: clientId }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_element_namespaceObject.RawHTML, { children: (0,external_wp_dom_namespaceObject.safeHTML)(saveContent) })] }); } else if (mode === 'html') { // Render blockEdit so the inspector controls don't disappear. // See #8969. block = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { style: { display: 'none' }, children: blockEdit }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Block, { isHtml: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_html, { clientId: clientId }) })] }); } else if (blockType?.apiVersion > 1) { block = blockEdit; } else { block = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Block, { children: blockEdit }); } const { 'data-align': dataAlign, ...restWrapperProps } = (_wrapperProps = wrapperProps) !== null && _wrapperProps !== void 0 ? _wrapperProps : {}; const updatedWrapperProps = { ...restWrapperProps, className: dist_clsx(restWrapperProps.className, dataAlign && themeSupportsLayout && `align${dataAlign}`, !(dataAlign && isSticky) && className) }; // We set a new context with the adjusted and filtered wrapperProps (through // `editor.BlockListBlock`), which the `BlockListBlockProvider` did not have // access to. // Note that the context value doesn't have to be memoized in this case // because when it changes, this component will be re-rendered anyway, and // none of the consumers (BlockListBlock and useBlockProps) are memoized or // "pure". This is different from the public BlockEditContext, where // consumers might be memoized or "pure". return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PrivateBlockContext.Provider, { value: { wrapperProps: updatedWrapperProps, isAligned, ...context }, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_crash_boundary, { fallback: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Block, { className: "has-warning", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_crash_warning, {}) }), children: block }) }); } const applyWithDispatch = (0,external_wp_data_namespaceObject.withDispatch)((dispatch, ownProps, registry) => { const { updateBlockAttributes, insertBlocks, mergeBlocks, replaceBlocks, toggleSelection, __unstableMarkLastChangeAsPersistent, moveBlocksToPosition, removeBlock, selectBlock } = dispatch(store); // Do not add new properties here, use `useDispatch` instead to avoid // leaking new props to the public API (editor.BlockListBlock filter). return { setAttributes(newAttributes) { const { getMultiSelectedBlockClientIds } = registry.select(store); const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(); const { clientId } = ownProps; const clientIds = multiSelectedBlockClientIds.length ? multiSelectedBlockClientIds : [clientId]; updateBlockAttributes(clientIds, newAttributes); }, onInsertBlocks(blocks, index) { const { rootClientId } = ownProps; insertBlocks(blocks, index, rootClientId); }, onInsertBlocksAfter(blocks) { const { clientId, rootClientId } = ownProps; const { getBlockIndex } = registry.select(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(store); function switchToDefaultOrRemove() { const block = getBlock(clientId); const defaultBlockName = (0,external_wp_blocks_namespaceObject.getDefaultBlockName)(); if (getBlockName(clientId) !== defaultBlockName) { const replacement = (0,external_wp_blocks_namespaceObject.switchToBlockType)(block, defaultBlockName); if (replacement && replacement.length) { replaceBlocks(clientId, replacement); } } else if ((0,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(block)) { const nextBlockClientId = getNextBlockClientId(clientId); if (nextBlockClientId) { registry.batch(() => { removeBlock(clientId); selectBlock(nextBlockClientId); }); } } } /** * Moves the block with clientId up one level. If the block type * cannot be inserted at the new location, it will be attempted to * convert to the default block type. * * @param {string} _clientId The block to move. * @param {boolean} changeSelection Whether to change the selection * to the moved block. */ function moveFirstItemUp(_clientId, changeSelection = true) { const targetRootClientId = getBlockRootClientId(_clientId); const blockOrder = getBlockOrder(_clientId); const [firstClientId] = blockOrder; if (blockOrder.length === 1 && (0,external_wp_blocks_namespaceObject.isUnmodifiedBlock)(getBlock(firstClientId))) { removeBlock(_clientId); } else { registry.batch(() => { if (canInsertBlockType(getBlockName(firstClientId), targetRootClientId)) { moveBlocksToPosition([firstClientId], _clientId, targetRootClientId, getBlockIndex(_clientId)); } else { const replacement = (0,external_wp_blocks_namespaceObject.switchToBlockType)(getBlock(firstClientId), (0,external_wp_blocks_namespaceObject.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,external_wp_blocks_namespaceObject.isUnmodifiedBlock)(getBlock(_clientId))) { removeBlock(_clientId, false); } }); } } // For `Delete` or forward merge, we should do the exact same thing // as `Backspace`, but from the other block. if (forward) { if (rootClientId) { const nextRootClientId = getNextBlockClientId(rootClientId); if (nextRootClientId) { // If there is a block that follows with the same parent // block name and the same attributes, merge the inner // blocks. 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 there is a preceding block with the same parent block // name and the same attributes, merge the inner blocks. 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,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(blocks[blocks.length - 1])) { __unstableMarkLastChangeAsPersistent(); } //Unsynced patterns are nested in an array so we need to flatten them. const replacementBlocks = blocks?.length === 1 && Array.isArray(blocks[0]) ? blocks[0] : blocks; replaceBlocks([ownProps.clientId], replacementBlocks, indexToSelect, initialPosition); }, toggleSelection(selectionEnabled) { toggleSelection(selectionEnabled); } }; }); // This component is used by the BlockListBlockProvider component below. It will // add the props necessary for the `editor.BlockListBlock` filters. BlockListBlock = (0,external_wp_compose_namespaceObject.compose)(applyWithDispatch, (0,external_wp_components_namespaceObject.withFilters)('editor.BlockListBlock'))(BlockListBlock); // This component provides all the information we need through a single store // subscription (useSelect mapping). Only the necessary props are passed down // to the BlockListBlock component, which is a filtered component, so these // props are public API. To avoid adding to the public API, we use a private // context to pass the rest of the information to the filtered BlockListBlock // component, and useBlockProps. function BlockListBlockProvider(props) { const { clientId, rootClientId } = props; const selectedProps = (0,external_wp_data_namespaceObject.useSelect)(select => { const { isBlockSelected, getBlockMode, isSelectionEnabled, getTemplateLock, getBlockWithoutAttributes, getBlockAttributes, canRemoveBlock, canMoveBlock, getSettings, getTemporarilyEditingAsBlocks, getBlockEditingMode, getBlockName, isFirstMultiSelectedBlock, getMultiSelectedBlockClientIds, hasSelectedInnerBlock, getBlocksByName, getBlockIndex, isBlockMultiSelected, isBlockSubtreeDisabled, isBlockHighlighted, __unstableIsFullySelected, __unstableSelectionHasUnmergeableBlock, isBlockBeingDragged, isDragging, hasBlockMovingClientId, canInsertBlockType, __unstableHasActiveBlockOverlayActive, __unstableGetEditorMode, getSelectedBlocksInitialCaretPosition } = unlock(select(store)); const blockWithoutAttributes = getBlockWithoutAttributes(clientId); // This is a temporary fix. // This function should never be called when a block is not // present in the state. It happens now because the order in // withSelect rendering is not correct. if (!blockWithoutAttributes) { return; } const { hasBlockSupport: _hasBlockSupport, getActiveBlockVariation } = select(external_wp_blocks_namespaceObject.store); const attributes = getBlockAttributes(clientId); const { name: blockName, isValid } = blockWithoutAttributes; const blockType = (0,external_wp_blocks_namespaceObject.getBlockType)(blockName); const { supportsLayout, __unstableIsPreviewMode: isPreviewMode } = getSettings(); const hasLightBlockWrapper = blockType?.apiVersion > 1; const previewContext = { isPreviewMode, blockWithoutAttributes, name: blockName, attributes, isValid, themeSupportsLayout: supportsLayout, index: getBlockIndex(clientId), isReusable: (0,external_wp_blocks_namespaceObject.isReusableBlock)(blockType), className: hasLightBlockWrapper ? attributes.className : undefined, defaultClassName: hasLightBlockWrapper ? (0,external_wp_blocks_namespaceObject.getBlockDefaultClassName)(blockName) : undefined, blockTitle: blockType?.title }; // When in preview mode, we can avoid a lot of selection and // editing related selectors. if (isPreviewMode) { return previewContext; } const _isSelected = isBlockSelected(clientId); const canRemove = canRemoveBlock(clientId); const canMove = canMoveBlock(clientId); const match = getActiveBlockVariation(blockName, attributes); const isMultiSelected = isBlockMultiSelected(clientId); const checkDeep = true; const isAncestorOfSelectedBlock = hasSelectedInnerBlock(clientId, checkDeep); const movingClientId = hasBlockMovingClientId(); const blockEditingMode = getBlockEditingMode(clientId); const multiple = (0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockName, 'multiple', true); // For block types with `multiple` support, there is no "original // block" to be found in the content, as the block itself is valid. const blocksWithSameName = multiple ? [] : getBlocksByName(blockName); const isInvalid = blocksWithSameName.length && blocksWithSameName[0] !== clientId; return { ...previewContext, mode: getBlockMode(clientId), isSelectionEnabled: isSelectionEnabled(), isLocked: !!getTemplateLock(rootClientId), templateLock: getTemplateLock(clientId), canRemove, canMove, isSelected: _isSelected, isTemporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks() === clientId, blockEditingMode, mayDisplayControls: _isSelected || isFirstMultiSelectedBlock(clientId) && getMultiSelectedBlockClientIds().every(id => getBlockName(id) === blockName), mayDisplayParentControls: _hasBlockSupport(getBlockName(clientId), '__experimentalExposeControlsToChildren', false) && hasSelectedInnerBlock(clientId), blockApiVersion: blockType?.apiVersion || 1, blockTitle: match?.title || blockType?.title, isSubtreeDisabled: blockEditingMode === 'disabled' && isBlockSubtreeDisabled(clientId), hasOverlay: __unstableHasActiveBlockOverlayActive(clientId) && !isDragging(), initialPosition: _isSelected && (__unstableGetEditorMode() === 'edit' || __unstableGetEditorMode() === 'zoom-out') // Don't recalculate the initialPosition when toggling in/out of zoom-out mode ? getSelectedBlocksInitialCaretPosition() : undefined, isHighlighted: isBlockHighlighted(clientId), isMultiSelected, isPartiallySelected: isMultiSelected && !__unstableIsFullySelected() && !__unstableSelectionHasUnmergeableBlock(), isDragging: isBlockBeingDragged(clientId), hasChildSelected: isAncestorOfSelectedBlock, isBlockMovingMode: !!movingClientId, canInsertMovingBlock: movingClientId && canInsertBlockType(getBlockName(movingClientId), rootClientId), isEditingDisabled: blockEditingMode === 'disabled', hasEditableOutline: blockEditingMode !== 'disabled' && getBlockEditingMode(rootClientId) === 'disabled', originalBlockClientId: isInvalid ? blocksWithSameName[0] : false }; }, [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, isTemporarilyEditingAsBlocks, blockEditingMode, mayDisplayControls, mayDisplayParentControls, index, blockApiVersion, blockTitle, isSubtreeDisabled, hasOverlay, initialPosition, isHighlighted, isMultiSelected, isPartiallySelected, isReusable, isDragging, hasChildSelected, isBlockMovingMode, canInsertMovingBlock, templateLock, isEditingDisabled, hasEditableOutline, className, defaultClassName, originalBlockClientId } = selectedProps; // 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. const block = (0,external_wp_element_namespaceObject.useMemo)(() => ({ ...blockWithoutAttributes, attributes }), [blockWithoutAttributes, attributes]); // Block is sometimes not mounted at the right time, causing it be // undefined see issue for more info // https://github.com/WordPress/gutenberg/issues/17013 if (!selectedProps) { return null; } const privateContext = { isPreviewMode, clientId, className, index, mode, name, blockApiVersion, blockTitle, isSelected, isSubtreeDisabled, hasOverlay, initialPosition, blockEditingMode, isHighlighted, isMultiSelected, isPartiallySelected, isReusable, isDragging, hasChildSelected, isBlockMovingMode, canInsertMovingBlock, templateLock, isEditingDisabled, hasEditableOutline, isTemporarilyEditingAsBlocks, defaultClassName, mayDisplayControls, mayDisplayParentControls, originalBlockClientId, themeSupportsLayout }; // Here we separate between the props passed to BlockListBlock and any other // information we selected for internal use. BlockListBlock is a filtered // component and thus ALL the props are PUBLIC API. // Note that the context value doesn't have to be memoized in this case // because when it changes, this component will be re-rendered anyway, and // none of the consumers (BlockListBlock and useBlockProps) are memoized or // "pure". This is different from the public BlockEditContext, where // consumers might be memoized or "pure". return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PrivateBlockContext.Provider, { value: privateContext, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.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 }) }); } /* harmony default export */ const block_list_block = ((0,external_wp_element_namespaceObject.memo)(BlockListBlockProvider)); ;// CONCATENATED MODULE: external ["wp","htmlEntities"] const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"]; ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/tips.js /** * WordPress dependencies */ const globalTips = [(0,external_wp_element_namespaceObject.createInterpolateElement)((0,external_wp_i18n_namespaceObject.__)('While writing, you can press <kbd>/</kbd> to quickly insert new blocks.'), { kbd: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("kbd", {}) }), (0,external_wp_element_namespaceObject.createInterpolateElement)((0,external_wp_i18n_namespaceObject.__)('Indent a list by pressing <kbd>space</kbd> at the beginning of a line.'), { kbd: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("kbd", {}) }), (0,external_wp_element_namespaceObject.createInterpolateElement)((0,external_wp_i18n_namespaceObject.__)('Outdent a list by pressing <kbd>backspace</kbd> at the beginning of a line.'), { kbd: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("kbd", {}) }), (0,external_wp_i18n_namespaceObject.__)('Drag files into the editor to automatically insert media blocks.'), (0,external_wp_i18n_namespaceObject.__)("Change a block's type by pressing the block icon on the toolbar.")]; function Tips() { const [randomIndex] = (0,external_wp_element_namespaceObject.useState)( // Disable Reason: I'm not generating an HTML id. // eslint-disable-next-line no-restricted-syntax Math.floor(Math.random() * globalTips.length)); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Tip, { children: globalTips[randomIndex] }); } /* harmony default export */ const tips = (Tips); ;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/chevron-right.js /** * WordPress dependencies */ const chevronRight = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, { d: "M10.6 6L9.4 7l4.6 5-4.6 5 1.2 1 5.4-6z" }) }); /* harmony default export */ const chevron_right = (chevronRight); ;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/chevron-left.js /** * WordPress dependencies */ const chevronLeft = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, { d: "M14.6 7l-1.2-1L8 12l5.4 6 1.2-1-4.6-5z" }) }); /* harmony default export */ const chevron_left = (chevronLeft); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-card/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function BlockCard({ title, icon, description, blockType, className }) { if (blockType) { external_wp_deprecated_default()('`blockType` property in `BlockCard component`', { since: '5.7', alternative: '`title, icon and description` properties' }); ({ title, icon, description } = blockType); } const { parentNavBlockClientId } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getSelectedBlockClientId, getBlockParentsByBlockName } = select(store); const _selectedBlockClientId = getSelectedBlockClientId(); return { parentNavBlockClientId: getBlockParentsByBlockName(_selectedBlockClientId, 'core/navigation', true)[0] }; }, []); const { selectBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: dist_clsx('block-editor-block-card', className), children: [parentNavBlockClientId && /*#__PURE__*/ // This is only used by the Navigation block for now. It's not ideal having Navigation block specific code here. (0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { onClick: () => selectBlock(parentNavBlockClientId), label: (0,external_wp_i18n_namespaceObject.__)('Go to parent Navigation block'), style: // TODO: This style override is also used in ToolsPanelHeader. // It should be supported out-of-the-box by Button. { minWidth: 24, padding: 0 }, icon: (0,external_wp_i18n_namespaceObject.isRTL)() ? chevron_right : chevron_left, size: "small" }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_icon, { icon: icon, showColors: true }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, { spacing: 1, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("h2", { className: "block-editor-block-card__title", children: title }), description && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, { className: "block-editor-block-card__description", children: description })] })] }); } /* harmony default export */ const block_card = (BlockCard); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/provider/with-registry-provider.js /** * WordPress dependencies */ /** * Internal dependencies */ function getSubRegistry(subRegistries, registry, useSubRegistry) { if (!useSubRegistry) { return registry; } let subRegistry = subRegistries.get(registry); if (!subRegistry) { subRegistry = (0,external_wp_data_namespaceObject.createRegistry)({}, registry); subRegistry.registerStore(STORE_NAME, storeConfig); subRegistries.set(registry, subRegistry); } return subRegistry; } const withRegistryProvider = (0,external_wp_compose_namespaceObject.createHigherOrderComponent)(WrappedComponent => ({ useSubRegistry = true, ...props }) => { const registry = (0,external_wp_data_namespaceObject.useRegistry)(); const [subRegistries] = (0,external_wp_element_namespaceObject.useState)(() => new WeakMap()); const subRegistry = getSubRegistry(subRegistries, registry, useSubRegistry); if (subRegistry === registry) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(WrappedComponent, { registry: registry, ...props }); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_data_namespaceObject.RegistryProvider, { value: subRegistry, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(WrappedComponent, { registry: subRegistry, ...props }) }); }, 'withRegistryProvider'); /* harmony default export */ const with_registry_provider = (withRegistryProvider); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/provider/use-block-sync.js /** * WordPress dependencies */ /** * Internal dependencies */ const use_block_sync_noop = () => {}; /** * A function to call when the block value has been updated in the block-editor * store. * * @callback onBlockUpdate * @param {Object[]} blocks The updated blocks. * @param {Object} options The updated block options, such as selectionStart * and selectionEnd. */ /** * useBlockSync is a side effect which handles bidirectional sync between the * block-editor store and a controlling data source which provides blocks. This * is most commonly used by the BlockEditorProvider to synchronize the contents * of the block-editor store with the root entity, like a post. * * Another example would be the template part block, which provides blocks from * a separate entity data source than a root entity. This hook syncs edits to * the template part in the block editor back to the entity and vice-versa. * * Here are some of its basic functions: * - Initalizes the block-editor store for the given clientID to the blocks * given via props. * - Adds incoming changes (like undo) to the block-editor store. * - Adds outgoing changes (like editing content) to the controlling entity, * determining if a change should be considered persistent or not. * - Handles edge cases and race conditions which occur in those operations. * - Ignores changes which happen to other entities (like nested inner block * controllers. * - Passes selection state from the block-editor store to the controlling entity. * * @param {Object} props Props for the block sync hook * @param {string} props.clientId The client ID of the inner block controller. * If none is passed, then it is assumed to be a * root controller rather than an inner block * controller. * @param {Object[]} props.value The control value for the blocks. This value * is used to initalize the block-editor store * and for resetting the blocks to incoming * changes like undo. * @param {Object} props.selection The selection state responsible to restore the selection on undo/redo. * @param {onBlockUpdate} props.onChange Function to call when a persistent * change has been made in the block-editor blocks * for the given clientId. For example, after * this function is called, an entity is marked * dirty because it has changes to save. * @param {onBlockUpdate} props.onInput Function to call when a non-persistent * change has been made in the block-editor blocks * for the given clientId. When this is called, * controlling sources do not become dirty. */ function useBlockSync({ clientId = null, value: controlledBlocks, selection: controlledSelection, onChange = use_block_sync_noop, onInput = use_block_sync_noop }) { const registry = (0,external_wp_data_namespaceObject.useRegistry)(); const { resetBlocks, resetSelection, replaceInnerBlocks, setHasControlledInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = registry.dispatch(store); const { getBlockName, getBlocks, getSelectionStart, getSelectionEnd } = registry.select(store); const isControlled = (0,external_wp_data_namespaceObject.useSelect)(select => { return !clientId || select(store).areInnerBlocksControlled(clientId); }, [clientId]); const pendingChanges = (0,external_wp_element_namespaceObject.useRef)({ incoming: null, outgoing: [] }); const subscribed = (0,external_wp_element_namespaceObject.useRef)(false); const setControlledBlocks = () => { if (!controlledBlocks) { return; } // We don't need to persist this change because we only replace // controlled inner blocks when the change was caused by an entity, // and so it would already be persisted. __unstableMarkNextChangeAsNotPersistent(); if (clientId) { // It is important to batch here because otherwise, // as soon as `setHasControlledInnerBlocks` is called // the effect to restore might be triggered // before the actual blocks get set properly in state. registry.batch(() => { setHasControlledInnerBlocks(clientId, true); const storeBlocks = controlledBlocks.map(block => (0,external_wp_blocks_namespaceObject.cloneBlock)(block)); if (subscribed.current) { pendingChanges.current.incoming = storeBlocks; } __unstableMarkNextChangeAsNotPersistent(); replaceInnerBlocks(clientId, storeBlocks); }); } else { if (subscribed.current) { pendingChanges.current.incoming = controlledBlocks; } resetBlocks(controlledBlocks); } }; // Clean up the changes made by setControlledBlocks() when the component // containing useBlockSync() unmounts. const unsetControlledBlocks = () => { __unstableMarkNextChangeAsNotPersistent(); if (clientId) { setHasControlledInnerBlocks(clientId, false); __unstableMarkNextChangeAsNotPersistent(); replaceInnerBlocks(clientId, []); } else { resetBlocks([]); } }; // Add a subscription to the block-editor registry to detect when changes // have been made. This lets us inform the data source of changes. This // is an effect so that the subscriber can run synchronously without // waiting for React renders for changes. const onInputRef = (0,external_wp_element_namespaceObject.useRef)(onInput); const onChangeRef = (0,external_wp_element_namespaceObject.useRef)(onChange); (0,external_wp_element_namespaceObject.useEffect)(() => { onInputRef.current = onInput; onChangeRef.current = onChange; }, [onInput, onChange]); // Determine if blocks need to be reset when they change. (0,external_wp_element_namespaceObject.useEffect)(() => { if (pendingChanges.current.outgoing.includes(controlledBlocks)) { // Skip block reset if the value matches expected outbound sync // triggered by this component by a preceding change detection. // Only skip if the value matches expectation, since a reset should // still occur if the value is modified (not equal by reference), // to allow that the consumer may apply modifications to reflect // back on the editor. if (pendingChanges.current.outgoing[pendingChanges.current.outgoing.length - 1] === controlledBlocks) { pendingChanges.current.outgoing = []; } } else if (getBlocks(clientId) !== controlledBlocks) { // Reset changing value in all other cases than the sync described // above. Since this can be reached in an update following an out- // bound sync, unset the outbound value to avoid considering it in // subsequent renders. pendingChanges.current.outgoing = []; setControlledBlocks(); if (controlledSelection) { resetSelection(controlledSelection.selectionStart, controlledSelection.selectionEnd, controlledSelection.initialPosition); } } }, [controlledBlocks, clientId]); const isMounted = (0,external_wp_element_namespaceObject.useRef)(false); (0,external_wp_element_namespaceObject.useEffect)(() => { // On mount, controlled blocks are already set in the effect above. if (!isMounted.current) { isMounted.current = true; return; } // When the block becomes uncontrolled, it means its inner state has been reset // we need to take the blocks again from the external value property. if (!isControlled) { pendingChanges.current.outgoing = []; setControlledBlocks(); } }, [isControlled]); (0,external_wp_element_namespaceObject.useEffect)(() => { const { getSelectedBlocksInitialCaretPosition, isLastBlockChangePersistent, __unstableIsLastBlockChangeIgnored, areInnerBlocksControlled } = registry.select(store); let blocks = getBlocks(clientId); let isPersistent = isLastBlockChangePersistent(); let previousAreBlocksDifferent = false; subscribed.current = true; const unsubscribe = registry.subscribe(() => { // Sometimes, when changing block lists, lingering subscriptions // might trigger before they are cleaned up. If the block for which // the subscription runs is no longer in the store, this would clear // its parent entity's block list. To avoid this, we bail out if // the subscription is triggering for a block (`clientId !== null`) // and its block name can't be found because it's not on the list. // (`getBlockName( clientId ) === null`). if (clientId !== null && getBlockName(clientId) === null) { return; } // When RESET_BLOCKS on parent blocks get called, the controlled blocks // can reset to uncontrolled, in these situations, it means we need to populate // the blocks again from the external blocks (the value property here) // and we should stop triggering onChange const isStillControlled = !clientId || areInnerBlocksControlled(clientId); if (!isStillControlled) { return; } const newIsPersistent = isLastBlockChangePersistent(); const newBlocks = getBlocks(clientId); const areBlocksDifferent = newBlocks !== blocks; blocks = newBlocks; if (areBlocksDifferent && (pendingChanges.current.incoming || __unstableIsLastBlockChangeIgnored())) { pendingChanges.current.incoming = null; isPersistent = newIsPersistent; return; } // Since we often dispatch an action to mark the previous action as // persistent, we need to make sure that the blocks changed on the // previous action before committing the change. const didPersistenceChange = previousAreBlocksDifferent && !areBlocksDifferent && newIsPersistent && !isPersistent; if (areBlocksDifferent || didPersistenceChange) { isPersistent = newIsPersistent; // We know that onChange/onInput will update controlledBlocks. // We need to be aware that it was caused by an outgoing change // so that we do not treat it as an incoming change later on, // which would cause a block reset. pendingChanges.current.outgoing.push(blocks); // Inform the controlling entity that changes have been made to // the block-editor store they should be aware about. const updateParent = isPersistent ? onChangeRef.current : onInputRef.current; const undoIgnore = undoIgnoreBlocks.has(blocks); if (undoIgnore) { undoIgnoreBlocks.delete(blocks); } updateParent(blocks, { selection: { selectionStart: getSelectionStart(), selectionEnd: getSelectionEnd(), initialPosition: getSelectedBlocksInitialCaretPosition() }, undoIgnore }); } previousAreBlocksDifferent = areBlocksDifferent; }, store); return () => { subscribed.current = false; unsubscribe(); }; }, [registry, clientId]); (0,external_wp_element_namespaceObject.useEffect)(() => { return () => { unsetControlledBlocks(); }; }, []); } ;// CONCATENATED MODULE: external ["wp","keyboardShortcuts"] const external_wp_keyboardShortcuts_namespaceObject = window["wp"]["keyboardShortcuts"]; ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/keyboard-shortcuts/index.js /** * WordPress dependencies */ function KeyboardShortcuts() { return null; } function KeyboardShortcutsRegister() { // Registering the shortcuts. const { registerShortcut } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_keyboardShortcuts_namespaceObject.store); (0,external_wp_element_namespaceObject.useEffect)(() => { registerShortcut({ name: 'core/block-editor/duplicate', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Duplicate the selected block(s).'), keyCombination: { modifier: 'primaryShift', character: 'd' } }); registerShortcut({ name: 'core/block-editor/remove', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Remove the selected block(s).'), keyCombination: { modifier: 'access', character: 'z' } }); registerShortcut({ name: 'core/block-editor/insert-before', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Insert a new block before the selected block(s).'), keyCombination: { modifier: 'primaryAlt', character: 't' } }); registerShortcut({ name: 'core/block-editor/insert-after', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Insert a new block after the selected block(s).'), keyCombination: { modifier: 'primaryAlt', character: 'y' } }); registerShortcut({ name: 'core/block-editor/delete-multi-selection', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Delete selection.'), keyCombination: { character: 'del' }, aliases: [{ character: 'backspace' }] }); registerShortcut({ name: 'core/block-editor/select-all', category: 'selection', description: (0,external_wp_i18n_namespaceObject.__)('Select all text when typing. Press again to select all blocks.'), keyCombination: { modifier: 'primary', character: 'a' } }); registerShortcut({ name: 'core/block-editor/unselect', category: 'selection', description: (0,external_wp_i18n_namespaceObject.__)('Clear selection.'), keyCombination: { character: 'escape' } }); registerShortcut({ name: 'core/block-editor/multi-text-selection', category: 'selection', description: (0,external_wp_i18n_namespaceObject.__)('Select text across multiple blocks.'), keyCombination: { modifier: 'shift', character: 'arrow' } }); registerShortcut({ name: 'core/block-editor/focus-toolbar', category: 'global', description: (0,external_wp_i18n_namespaceObject.__)('Navigate to the nearest toolbar.'), keyCombination: { modifier: 'alt', character: 'F10' } }); registerShortcut({ name: 'core/block-editor/move-up', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Move the selected block(s) up.'), keyCombination: { modifier: 'secondary', character: 't' } }); registerShortcut({ name: 'core/block-editor/move-down', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Move the selected block(s) down.'), keyCombination: { modifier: 'secondary', character: 'y' } }); // List view shortcuts. registerShortcut({ name: 'core/block-editor/collapse-list-view', category: 'list-view', description: (0,external_wp_i18n_namespaceObject.__)('Collapse all other items.'), keyCombination: { modifier: 'alt', character: 'l' } }); registerShortcut({ name: 'core/block-editor/group', category: 'block', description: (0,external_wp_i18n_namespaceObject.__)('Create a group block from the selected multiple blocks.'), keyCombination: { modifier: 'primary', character: 'g' } }); }, [registerShortcut]); return null; } KeyboardShortcuts.Register = KeyboardShortcutsRegister; /* harmony default export */ const keyboard_shortcuts = (KeyboardShortcuts); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/provider/index.js /** * WordPress dependencies */ /** * Internal dependencies */ /** @typedef {import('@wordpress/data').WPDataRegistry} WPDataRegistry */ const ExperimentalBlockEditorProvider = with_registry_provider(props => { const { children, settings, stripExperimentalSettings = false } = props; const { __experimentalUpdateSettings } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store)); (0,external_wp_element_namespaceObject.useEffect)(() => { __experimentalUpdateSettings({ ...settings, __internalIsInitialized: true }, { stripExperimentalSettings, reset: true }); }, [settings, stripExperimentalSettings, __experimentalUpdateSettings]); // Syncs the entity provider with changes in the block-editor store. useBlockSync(props); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.SlotFillProvider, { passthrough: true, children: [!settings?.__unstableIsPreviewMode && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(keyboard_shortcuts.Register, {}), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockRefsProvider, { children: children })] }); }); const BlockEditorProvider = props => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ExperimentalBlockEditorProvider, { ...props, stripExperimentalSettings: true, children: props.children }); }; /* harmony default export */ const provider = (BlockEditorProvider); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-selection-clearer/index.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Pass the returned ref callback to an element that should clear block * selection. Selection will only be cleared if the element is clicked directly, * not if a child element is clicked. * * @return {import('react').RefCallback} Ref callback. */ function useBlockSelectionClearer() { const { getSettings, hasSelectedBlock, hasMultiSelection } = (0,external_wp_data_namespaceObject.useSelect)(store); const { clearSelectedBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); const { clearBlockSelection: isEnabled } = getSettings(); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { if (!isEnabled) { return; } function onMouseDown(event) { if (!hasSelectedBlock() && !hasMultiSelection()) { return; } // Only handle clicks on the element, not the children. if (event.target !== node) { return; } clearSelectedBlock(); } node.addEventListener('mousedown', onMouseDown); return () => { node.removeEventListener('mousedown', onMouseDown); }; }, [hasSelectedBlock, hasMultiSelection, clearSelectedBlock, isEnabled]); } function BlockSelectionClearer(props) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { ref: useBlockSelectionClearer(), ...props }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-multi-selection.js /** * WordPress dependencies */ /** * Internal dependencies */ function selector(select) { const { isMultiSelecting, getMultiSelectedBlockClientIds, hasMultiSelection, getSelectedBlockClientId, getSelectedBlocksInitialCaretPosition, __unstableIsFullySelected } = select(store); return { isMultiSelecting: isMultiSelecting(), multiSelectedBlockClientIds: getMultiSelectedBlockClientIds(), hasMultiSelection: hasMultiSelection(), selectedBlockClientId: getSelectedBlockClientId(), initialPosition: getSelectedBlocksInitialCaretPosition(), isFullSelection: __unstableIsFullySelected() }; } function useMultiSelection() { const { initialPosition, isMultiSelecting, multiSelectedBlockClientIds, hasMultiSelection, selectedBlockClientId, isFullSelection } = (0,external_wp_data_namespaceObject.useSelect)(selector, []); /** * When the component updates, and there is multi selection, we need to * select the entire block contents. */ return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { const { ownerDocument } = node; const { defaultView } = ownerDocument; // Allow initialPosition to bypass focus behavior. This is useful // for the list view or other areas where we don't want to transfer // focus to the editor canvas. if (initialPosition === undefined || initialPosition === null) { return; } if (!hasMultiSelection || isMultiSelecting) { return; } const { length } = multiSelectedBlockClientIds; if (length < 2) { return; } if (!isFullSelection) { return; } // Allow cross contentEditable selection by temporarily making // all content editable. We can't rely on using the store and // React because re-rending happens too slowly. We need to be // able to select across instances immediately. node.contentEditable = true; // For some browsers, like Safari, it is important that focus // happens BEFORE selection removal. node.focus(); defaultView.getSelection().removeAllRanges(); }, [hasMultiSelection, isMultiSelecting, multiSelectedBlockClientIds, selectedBlockClientId, initialPosition, isFullSelection]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-tab-nav.js /** * WordPress dependencies */ /** * Internal dependencies */ function useTabNav() { const container = (0,external_wp_element_namespaceObject.useRef)(); const focusCaptureBeforeRef = (0,external_wp_element_namespaceObject.useRef)(); const focusCaptureAfterRef = (0,external_wp_element_namespaceObject.useRef)(); const { hasMultiSelection, getSelectedBlockClientId, getBlockCount } = (0,external_wp_data_namespaceObject.useSelect)(store); const { setNavigationMode, setLastFocus } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store)); const isNavigationMode = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).isNavigationMode(), []); const { getLastFocus } = unlock((0,external_wp_data_namespaceObject.useSelect)(store)); // Don't allow tabbing to this element in Navigation mode. const focusCaptureTabIndex = !isNavigationMode ? '0' : undefined; // Reference that holds the a flag for enabling or disabling // capturing on the focus capture elements. const noCapture = (0,external_wp_element_namespaceObject.useRef)(); function onFocusCapture(event) { // Do not capture incoming focus if set by us in WritingFlow. if (noCapture.current) { noCapture.current = null; } else if (hasMultiSelection()) { container.current.focus(); } else if (getSelectedBlockClientId()) { if (getLastFocus()?.current) { getLastFocus().current.focus(); } else { // Handles when the last focus has not been set yet, or has been cleared by new blocks being added via the inserter. container.current.querySelector(`[data-block="${getSelectedBlockClientId()}"]`).focus(); } } else { setNavigationMode(true); const canvasElement = container.current.ownerDocument === event.target.ownerDocument ? container.current : container.current.ownerDocument.defaultView.frameElement; const isBefore = // eslint-disable-next-line no-bitwise event.target.compareDocumentPosition(canvasElement) & event.target.DOCUMENT_POSITION_FOLLOWING; const tabbables = external_wp_dom_namespaceObject.focus.tabbable.find(container.current); if (tabbables.length) { const next = isBefore ? tabbables[0] : tabbables[tabbables.length - 1]; next.focus(); } } } const before = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { ref: focusCaptureBeforeRef, tabIndex: focusCaptureTabIndex, onFocus: onFocusCapture }); const after = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { ref: focusCaptureAfterRef, tabIndex: focusCaptureTabIndex, onFocus: onFocusCapture }); const ref = (0,external_wp_compose_namespaceObject.useRefEffect)(node => { function onKeyDown(event) { if (event.defaultPrevented) { return; } if (event.keyCode === external_wp_keycodes_namespaceObject.ESCAPE && !hasMultiSelection()) { event.preventDefault(); setNavigationMode(true); return; } // In Edit mode, Tab should focus the first tabbable element after // the content, which is normally the sidebar (with block controls) // and Shift+Tab should focus the first tabbable element before the // content, which is normally the block toolbar. // Arrow keys can be used, and Tab and arrow keys can be used in // Navigation mode (press Esc), to navigate through blocks. if (event.keyCode !== external_wp_keycodes_namespaceObject.TAB) { return; } const isShift = event.shiftKey; const direction = isShift ? 'findPrevious' : 'findNext'; if (!hasMultiSelection() && !getSelectedBlockClientId()) { // Preserve the behaviour of entering navigation mode when // tabbing into the content without a block selection. // `onFocusCapture` already did this previously, but we need to // do it again here because after clearing block selection, // focus land on the writing flow container and pressing Tab // will no longer send focus through the focus capture element. if (event.target === node) { setNavigationMode(true); } return; } const nextTabbable = external_wp_dom_namespaceObject.focus.tabbable[direction](event.target); // We want to constrain the tabbing to the block and its child blocks. // If the preceding form element is within a different block, // such as two sibling image blocks in the placeholder state, // we want shift + tab from the first form element to move to the image // block toolbar and not the previous image block's form element. const currentBlock = event.target.closest('[data-block]'); const isElementPartOfSelectedBlock = currentBlock && nextTabbable && (isInSameBlock(currentBlock, nextTabbable) || isInsideRootBlock(currentBlock, nextTabbable)); // Allow tabbing from the block wrapper to a form element, // and between form elements rendered in a block and its child blocks, // such as inside a placeholder. Form elements are generally // meant to be UI rather than part of the content. Ideally // these are not rendered in the content and perhaps in the // future they can be rendered in an iframe or shadow DOM. if ((0,external_wp_dom_namespaceObject.isFormElement)(nextTabbable) && isElementPartOfSelectedBlock) { return; } const next = isShift ? focusCaptureBeforeRef : focusCaptureAfterRef; // Disable focus capturing on the focus capture element, so it // doesn't refocus this block and so it allows default behaviour // (moving focus to the next tabbable element). noCapture.current = true; // Focusing the focus capture element, which is located above and // below the editor, should not scroll the page all the way up or // down. next.current.focus({ preventScroll: true }); } function onFocusOut(event) { setLastFocus({ ...getLastFocus(), current: event.target }); const { ownerDocument } = node; // If focus disappears due to there being no blocks, move focus to // the writing flow wrapper. if (!event.relatedTarget && ownerDocument.activeElement === ownerDocument.body && getBlockCount() === 0) { node.focus(); } } // When tabbing back to an element in block list, this event handler prevents scrolling if the // focus capture divs (before/after) are outside of the viewport. (For example shift+tab back to a paragraph // when focus is on a sidebar element. This prevents the scrollable writing area from jumping either to the // top or bottom of the document. // // Note that it isn't possible to disable scrolling in the onFocus event. We need to intercept this // earlier in the keypress handler, and call focus( { preventScroll: true } ) instead. // https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus#parameters function preventScrollOnTab(event) { if (event.keyCode !== external_wp_keycodes_namespaceObject.TAB) { return; } if (event.target?.getAttribute('role') === 'region') { return; } if (container.current === event.target) { return; } const isShift = event.shiftKey; const direction = isShift ? 'findPrevious' : 'findNext'; const target = external_wp_dom_namespaceObject.focus.tabbable[direction](event.target); // Only do something when the next tabbable is a focus capture div (before/after) if (target === focusCaptureBeforeRef.current || target === focusCaptureAfterRef.current) { event.preventDefault(); target.focus({ preventScroll: true }); } } const { ownerDocument } = node; const { defaultView } = ownerDocument; defaultView.addEventListener('keydown', preventScrollOnTab); node.addEventListener('keydown', onKeyDown); node.addEventListener('focusout', onFocusOut); return () => { defaultView.removeEventListener('keydown', preventScrollOnTab); node.removeEventListener('keydown', onKeyDown); node.removeEventListener('focusout', onFocusOut); }; }, []); const mergedRefs = (0,external_wp_compose_namespaceObject.useMergeRefs)([container, ref]); return [before, mergedRefs, after]; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-arrow-nav.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Returns true if the element should consider edge navigation upon a keyboard * event of the given directional key code, or false otherwise. * * @param {Element} element HTML element to test. * @param {number} keyCode KeyboardEvent keyCode to test. * @param {boolean} hasModifier Whether a modifier is pressed. * * @return {boolean} Whether element should consider edge navigation. */ function isNavigationCandidate(element, keyCode, hasModifier) { const isVertical = keyCode === external_wp_keycodes_namespaceObject.UP || keyCode === external_wp_keycodes_namespaceObject.DOWN; const { tagName } = element; const elementType = element.getAttribute('type'); // Native inputs should not navigate vertically, unless they are simple types that don't need up/down arrow keys. if (isVertical && !hasModifier) { if (tagName === 'INPUT') { const verticalInputTypes = ['date', 'datetime-local', 'month', 'number', 'range', 'time', 'week']; return !verticalInputTypes.includes(elementType); } return true; } // Native inputs should not navigate horizontally, unless they are simple types that don't need left/right arrow keys. if (tagName === 'INPUT') { const simpleInputTypes = ['button', 'checkbox', 'number', 'color', 'file', 'image', 'radio', 'reset', 'submit']; return simpleInputTypes.includes(elementType); } // Native textareas should not navigate horizontally. return tagName !== 'TEXTAREA'; } /** * Returns the optimal tab target from the given focused element in the desired * direction. A preference is made toward text fields, falling back to the block * focus stop if no other candidates exist for the block. * * @param {Element} target Currently focused text field. * @param {boolean} isReverse True if considering as the first field. * @param {Element} containerElement Element containing all blocks. * @param {boolean} onlyVertical Whether to only consider tabbable elements * that are visually above or under the * target. * * @return {?Element} Optimal tab target, if one exists. */ function getClosestTabbable(target, isReverse, containerElement, onlyVertical) { // Since the current focus target is not guaranteed to be a text field, find // all focusables. Tabbability is considered later. let focusableNodes = external_wp_dom_namespaceObject.focus.focusable.find(containerElement); if (isReverse) { focusableNodes.reverse(); } // Consider as candidates those focusables after the current target. It's // assumed this can only be reached if the target is focusable (on its // keydown event), so no need to verify it exists in the set. focusableNodes = focusableNodes.slice(focusableNodes.indexOf(target) + 1); let targetRect; if (onlyVertical) { targetRect = target.getBoundingClientRect(); } function isTabCandidate(node) { if (node.closest('[inert]')) { return; } // Skip if there's only one child that is content editable (and thus a // better candidate). if (node.children.length === 1 && isInSameBlock(node, node.firstElementChild) && node.firstElementChild.getAttribute('contenteditable') === 'true') { return; } // Not a candidate if the node is not tabbable. if (!external_wp_dom_namespaceObject.focus.tabbable.isTabbableIndex(node)) { return false; } // Skip focusable elements such as links within content editable nodes. if (node.isContentEditable && node.contentEditable !== 'true') { return false; } if (onlyVertical) { const nodeRect = node.getBoundingClientRect(); if (nodeRect.left >= targetRect.right || nodeRect.right <= targetRect.left) { return false; } } return true; } return focusableNodes.find(isTabCandidate); } function useArrowNav() { const { getMultiSelectedBlocksStartClientId, getMultiSelectedBlocksEndClientId, getSettings, hasMultiSelection, __unstableIsFullySelected } = (0,external_wp_data_namespaceObject.useSelect)(store); const { selectBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { // Here a DOMRect is stored while moving the caret vertically so // vertical position of the start position can be restored. This is to // recreate browser behaviour across blocks. let verticalRect; function onMouseDown() { verticalRect = null; } function isClosestTabbableABlock(target, isReverse) { const closestTabbable = getClosestTabbable(target, isReverse, node); return closestTabbable && getBlockClientId(closestTabbable); } function onKeyDown(event) { // Abort if navigation has already been handled (e.g. RichText // inline boundaries). if (event.defaultPrevented) { return; } const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } = event; const isUp = keyCode === external_wp_keycodes_namespaceObject.UP; const isDown = keyCode === external_wp_keycodes_namespaceObject.DOWN; const isLeft = keyCode === external_wp_keycodes_namespaceObject.LEFT; const isRight = keyCode === external_wp_keycodes_namespaceObject.RIGHT; const isReverse = isUp || isLeft; const isHorizontal = isLeft || isRight; const isVertical = isUp || isDown; const isNav = isHorizontal || isVertical; const hasModifier = shiftKey || ctrlKey || altKey || metaKey; const isNavEdge = isVertical ? external_wp_dom_namespaceObject.isVerticalEdge : external_wp_dom_namespaceObject.isHorizontalEdge; const { ownerDocument } = node; const { defaultView } = ownerDocument; if (!isNav) { return; } // If there is a multi-selection, the arrow keys should collapse the // selection to the start or end of the selection. if (hasMultiSelection()) { if (shiftKey) { return; } // Only handle if we have a full selection (not a native partial // selection). if (!__unstableIsFullySelected()) { return; } event.preventDefault(); if (isReverse) { selectBlock(getMultiSelectedBlocksStartClientId()); } else { selectBlock(getMultiSelectedBlocksEndClientId(), -1); } return; } // Abort if our current target is not a candidate for navigation // (e.g. preserve native input behaviors). if (!isNavigationCandidate(target, keyCode, hasModifier)) { return; } // When presing any key other than up or down, the initial vertical // position must ALWAYS be reset. The vertical position is saved so // it can be restored as well as possible on sebsequent vertical // arrow key presses. It may not always be possible to restore the // exact same position (such as at an empty line), so it wouldn't be // good to compute the position right before any vertical arrow key // press. if (!isVertical) { verticalRect = null; } else if (!verticalRect) { verticalRect = (0,external_wp_dom_namespaceObject.computeCaretRect)(defaultView); } // In the case of RTL scripts, right means previous and left means // next, which is the exact reverse of LTR. const isReverseDir = (0,external_wp_dom_namespaceObject.isRTL)(target) ? !isReverse : isReverse; const { keepCaretInsideBlock } = getSettings(); if (shiftKey) { if (isClosestTabbableABlock(target, isReverse) && isNavEdge(target, isReverse)) { node.contentEditable = true; // Firefox doesn't automatically move focus. node.focus(); } } else if (isVertical && (0,external_wp_dom_namespaceObject.isVerticalEdge)(target, isReverse) && ( // When Alt is pressed, only intercept if the caret is also at // the horizontal edge. altKey ? (0,external_wp_dom_namespaceObject.isHorizontalEdge)(target, isReverseDir) : true) && !keepCaretInsideBlock) { const closestTabbable = getClosestTabbable(target, isReverse, node, true); if (closestTabbable) { (0,external_wp_dom_namespaceObject.placeCaretAtVerticalEdge)(closestTabbable, // When Alt is pressed, place the caret at the furthest // horizontal edge and the furthest vertical edge. altKey ? !isReverse : isReverse, altKey ? undefined : verticalRect); event.preventDefault(); } } else if (isHorizontal && defaultView.getSelection().isCollapsed && (0,external_wp_dom_namespaceObject.isHorizontalEdge)(target, isReverseDir) && !keepCaretInsideBlock) { const closestTabbable = getClosestTabbable(target, isReverseDir, node); (0,external_wp_dom_namespaceObject.placeCaretAtHorizontalEdge)(closestTabbable, isReverse); event.preventDefault(); } } node.addEventListener('mousedown', onMouseDown); node.addEventListener('keydown', onKeyDown); return () => { node.removeEventListener('mousedown', onMouseDown); node.removeEventListener('keydown', onKeyDown); }; }, []); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-select-all.js /** * WordPress dependencies */ /** * Internal dependencies */ function useSelectAll() { const { getBlockOrder, getSelectedBlockClientIds, getBlockRootClientId } = (0,external_wp_data_namespaceObject.useSelect)(store); const { multiSelect, selectBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); const isMatch = (0,external_wp_keyboardShortcuts_namespaceObject.__unstableUseShortcutEventMatch)(); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { function onKeyDown(event) { if (!isMatch('core/block-editor/select-all', event)) { return; } const selectedClientIds = getSelectedBlockClientIds(); if (selectedClientIds.length < 2 && !(0,external_wp_dom_namespaceObject.isEntirelySelected)(event.target)) { return; } event.preventDefault(); const [firstSelectedClientId] = selectedClientIds; const rootClientId = getBlockRootClientId(firstSelectedClientId); const blockClientIds = getBlockOrder(rootClientId); // If we have selected all sibling nested blocks, try selecting up a // level. See: https://github.com/WordPress/gutenberg/pull/31859/ if (selectedClientIds.length === blockClientIds.length) { if (rootClientId) { node.ownerDocument.defaultView.getSelection().removeAllRanges(); selectBlock(rootClientId); } return; } multiSelect(blockClientIds[0], blockClientIds[blockClientIds.length - 1]); } node.addEventListener('keydown', onKeyDown); return () => { node.removeEventListener('keydown', onKeyDown); }; }, []); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-drag-selection.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Sets the `contenteditable` wrapper element to `value`. * * @param {HTMLElement} node Block element. * @param {boolean} value `contentEditable` value (true or false) */ function setContentEditableWrapper(node, value) { node.contentEditable = value; // Firefox doesn't automatically move focus. if (value) { node.focus(); } } /** * Sets a multi-selection based on the native selection across blocks. */ function useDragSelection() { const { startMultiSelect, stopMultiSelect } = (0,external_wp_data_namespaceObject.useDispatch)(store); const { isSelectionEnabled, hasSelectedBlock, isDraggingBlocks, isMultiSelecting } = (0,external_wp_data_namespaceObject.useSelect)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { const { ownerDocument } = node; const { defaultView } = ownerDocument; let anchorElement; let rafId; function onMouseUp() { stopMultiSelect(); // Equivalent to attaching the listener once. defaultView.removeEventListener('mouseup', onMouseUp); // The browser selection won't have updated yet at this point, // so wait until the next animation frame to get the browser // selection. rafId = defaultView.requestAnimationFrame(() => { if (!hasSelectedBlock()) { return; } // If the selection is complete (on mouse up), and no // multiple blocks have been selected, set focus back to the // anchor element. if the anchor element contains the // selection. Additionally, the contentEditable wrapper can // now be disabled again. setContentEditableWrapper(node, false); const selection = defaultView.getSelection(); if (selection.rangeCount) { const range = selection.getRangeAt(0); const { commonAncestorContainer } = range; const clonedRange = range.cloneRange(); if (anchorElement.contains(commonAncestorContainer)) { anchorElement.focus(); selection.removeAllRanges(); selection.addRange(clonedRange); } } }); } function onMouseLeave({ buttons, target, relatedTarget }) { // If we're moving into a child element, ignore. We're tracking // the mouse leaving the element to a parent, no a child. if (target.contains(relatedTarget)) { return; } // Avoid triggering a multi-selection if the user is already // dragging blocks. if (isDraggingBlocks()) { return; } // The primary button must be pressed to initiate selection. // See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons if (buttons !== 1) { return; } // Abort if we are already multi-selecting. if (isMultiSelecting()) { return; } // Abort if selection is leaving writing flow. if (node === target) { return; } // Check the attribute, not the contentEditable attribute. All // child elements of the content editable wrapper are editable // and return true for this property. We only want to start // multi selecting when the mouse leaves the wrapper. if (target.getAttribute('contenteditable') !== 'true') { return; } if (!isSelectionEnabled()) { return; } // Do not rely on the active element because it may change after // the mouse leaves for the first time. See // https://github.com/WordPress/gutenberg/issues/48747. anchorElement = target; startMultiSelect(); // `onSelectionStart` is called after `mousedown` and // `mouseleave` (from a block). The selection ends when // `mouseup` happens anywhere in the window. defaultView.addEventListener('mouseup', onMouseUp); // Allow cross contentEditable selection by temporarily making // all content editable. We can't rely on using the store and // React because re-rending happens too slowly. We need to be // able to select across instances immediately. setContentEditableWrapper(node, true); } node.addEventListener('mouseout', onMouseLeave); return () => { node.removeEventListener('mouseout', onMouseLeave); defaultView.removeEventListener('mouseup', onMouseUp); defaultView.cancelAnimationFrame(rafId); }; }, [startMultiSelect, stopMultiSelect, isSelectionEnabled, hasSelectedBlock]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-selection-observer.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Extract the selection start node from the selection. When the anchor node is * not a text node, the selection offset is the index of a child node. * * @param {Selection} selection The selection. * * @return {Element} The selection start node. */ function extractSelectionStartNode(selection) { const { anchorNode, anchorOffset } = selection; if (anchorNode.nodeType === anchorNode.TEXT_NODE) { return anchorNode; } if (anchorOffset === 0) { return anchorNode; } return anchorNode.childNodes[anchorOffset - 1]; } /** * Extract the selection end node from the selection. When the focus node is not * a text node, the selection offset is the index of a child node. The selection * reaches up to but excluding that child node. * * @param {Selection} selection The selection. * * @return {Element} The selection start node. */ function extractSelectionEndNode(selection) { const { focusNode, focusOffset } = selection; if (focusNode.nodeType === focusNode.TEXT_NODE) { return focusNode; } if (focusOffset === focusNode.childNodes.length) { return focusNode; } return focusNode.childNodes[focusOffset]; } function findDepth(a, b) { let depth = 0; while (a[depth] === b[depth]) { depth++; } return depth; } /** * Sets the `contenteditable` wrapper element to `value`. * * @param {HTMLElement} node Block element. * @param {boolean} value `contentEditable` value (true or false) */ function use_selection_observer_setContentEditableWrapper(node, value) { // Since we are calling this on every selection change, check if the value // needs to be updated first because it trigger the browser to recalculate // style. if (node.contentEditable !== String(value)) { node.contentEditable = value; // Firefox doesn't automatically move focus. if (value) { node.focus(); } } } function getRichTextElement(node) { const element = node.nodeType === node.ELEMENT_NODE ? node : node.parentElement; return element?.closest('[data-wp-block-attribute-key]'); } /** * Sets a multi-selection based on the native selection across blocks. */ function useSelectionObserver() { const { multiSelect, selectBlock, selectionChange } = (0,external_wp_data_namespaceObject.useDispatch)(store); const { getBlockParents, getBlockSelectionStart, isMultiSelecting } = (0,external_wp_data_namespaceObject.useSelect)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { const { ownerDocument } = node; const { defaultView } = ownerDocument; function onSelectionChange(event) { const selection = defaultView.getSelection(); if (!selection.rangeCount) { return; } const startNode = extractSelectionStartNode(selection); const endNode = extractSelectionEndNode(selection); if (!node.contains(startNode) || !node.contains(endNode)) { return; } // If selection is collapsed and we haven't used `shift+click`, // end multi selection and disable the contentEditable wrapper. // We have to check about `shift+click` case because elements // that don't support text selection might be involved, and we might // update the clientIds to multi-select blocks. // For now we check if the event is a `mouse` event. const isClickShift = event.shiftKey && event.type === 'mouseup'; if (selection.isCollapsed && !isClickShift) { if (node.contentEditable === 'true' && !isMultiSelecting()) { use_selection_observer_setContentEditableWrapper(node, false); let element = startNode.nodeType === startNode.ELEMENT_NODE ? startNode : startNode.parentElement; element = element?.closest('[contenteditable]'); element?.focus(); } return; } let startClientId = getBlockClientId(startNode); let endClientId = getBlockClientId(endNode); // If the selection has changed and we had pressed `shift+click`, // we need to check if in an element that doesn't support // text selection has been clicked. if (isClickShift) { const selectedClientId = getBlockSelectionStart(); const clickedClientId = getBlockClientId(event.target); // `endClientId` is not defined if we end the selection by clicking a non-selectable block. // We need to check if there was already a selection with a non-selectable focusNode. const focusNodeIsNonSelectable = clickedClientId !== endClientId; if (startClientId === endClientId && selection.isCollapsed || !endClientId || focusNodeIsNonSelectable) { endClientId = clickedClientId; } // Handle the case when we have a non-selectable block // selected and click another one. if (startClientId !== selectedClientId) { startClientId = selectedClientId; } } // If the selection did not involve a block, return. if (startClientId === undefined && endClientId === undefined) { use_selection_observer_setContentEditableWrapper(node, false); return; } const isSingularSelection = startClientId === endClientId; if (isSingularSelection) { if (!isMultiSelecting()) { selectBlock(startClientId); } else { multiSelect(startClientId, startClientId); } } else { const startPath = [...getBlockParents(startClientId), startClientId]; const endPath = [...getBlockParents(endClientId), endClientId]; const depth = findDepth(startPath, endPath); if (startPath[depth] !== startClientId || endPath[depth] !== endClientId) { multiSelect(startPath[depth], endPath[depth]); return; } const richTextElementStart = getRichTextElement(startNode); const richTextElementEnd = getRichTextElement(endNode); if (richTextElementStart && richTextElementEnd) { var _richTextDataStart$st, _richTextDataEnd$star; const range = selection.getRangeAt(0); const richTextDataStart = (0,external_wp_richText_namespaceObject.create)({ element: richTextElementStart, range, __unstableIsEditableTree: true }); const richTextDataEnd = (0,external_wp_richText_namespaceObject.create)({ element: richTextElementEnd, range, __unstableIsEditableTree: true }); const startOffset = (_richTextDataStart$st = richTextDataStart.start) !== null && _richTextDataStart$st !== void 0 ? _richTextDataStart$st : richTextDataStart.end; const endOffset = (_richTextDataEnd$star = richTextDataEnd.start) !== null && _richTextDataEnd$star !== void 0 ? _richTextDataEnd$star : richTextDataEnd.end; selectionChange({ start: { clientId: startClientId, attributeKey: richTextElementStart.dataset.wpBlockAttributeKey, offset: startOffset }, end: { clientId: endClientId, attributeKey: richTextElementEnd.dataset.wpBlockAttributeKey, offset: endOffset } }); } else { multiSelect(startClientId, endClientId); } } } ownerDocument.addEventListener('selectionchange', onSelectionChange); defaultView.addEventListener('mouseup', onSelectionChange); return () => { ownerDocument.removeEventListener('selectionchange', onSelectionChange); defaultView.removeEventListener('mouseup', onSelectionChange); }; }, [multiSelect, selectBlock, selectionChange, getBlockParents]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-click-selection.js /** * WordPress dependencies */ /** * Internal dependencies */ function useClickSelection() { const { selectBlock } = (0,external_wp_data_namespaceObject.useDispatch)(store); const { isSelectionEnabled, getBlockSelectionStart, hasMultiSelection } = (0,external_wp_data_namespaceObject.useSelect)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { function onMouseDown(event) { // The main button. // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button if (!isSelectionEnabled() || event.button !== 0) { return; } const startClientId = getBlockSelectionStart(); const clickedClientId = getBlockClientId(event.target); if (event.shiftKey) { if (startClientId !== clickedClientId) { node.contentEditable = true; // Firefox doesn't automatically move focus. node.focus(); } } else if (hasMultiSelection()) { // Allow user to escape out of a multi-selection to a // singular selection of a block via click. This is handled // here since focus handling excludes blocks when there is // multiselection, as focus can be incurred by starting a // multiselection (focus moved to first block's multi- // controls). selectBlock(clickedClientId); } } node.addEventListener('mousedown', onMouseDown); return () => { node.removeEventListener('mousedown', onMouseDown); }; }, [selectBlock, isSelectionEnabled, getBlockSelectionStart, hasMultiSelection]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-input.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Handles input for selections across blocks. */ function useInput() { const { __unstableIsFullySelected, getSelectedBlockClientIds, getSelectedBlockClientId, __unstableIsSelectionMergeable, hasMultiSelection, getBlockName, canInsertBlockType, getBlockRootClientId, getSelectionStart, getSelectionEnd, getBlockAttributes } = (0,external_wp_data_namespaceObject.useSelect)(store); const { replaceBlocks, __unstableSplitSelection, removeBlocks, __unstableDeleteSelection, __unstableExpandSelection, __unstableMarkAutomaticChange } = (0,external_wp_data_namespaceObject.useDispatch)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { function onBeforeInput(event) { // If writing flow is editable, NEVER allow the browser to alter the // DOM. This will cause React errors (and the DOM should only be // altered in a controlled fashion). if (node.contentEditable === 'true') { event.preventDefault(); } } function onKeyDown(event) { if (event.defaultPrevented) { return; } if (!hasMultiSelection()) { if (event.keyCode === external_wp_keycodes_namespaceObject.ENTER) { if (event.shiftKey || __unstableIsFullySelected()) { return; } const clientId = getSelectedBlockClientId(); const blockName = getBlockName(clientId); const selectionStart = getSelectionStart(); const selectionEnd = getSelectionEnd(); if (selectionStart.attributeKey === selectionEnd.attributeKey) { const selectedAttributeValue = getBlockAttributes(clientId)[selectionStart.attributeKey]; const transforms = (0,external_wp_blocks_namespaceObject.getBlockTransforms)('from').filter(({ type }) => type === 'enter'); const transformation = (0,external_wp_blocks_namespaceObject.findTransform)(transforms, item => { return item.regExp.test(selectedAttributeValue); }); if (transformation) { replaceBlocks(clientId, transformation.transform({ content: selectedAttributeValue })); __unstableMarkAutomaticChange(); return; } } if (!(0,external_wp_blocks_namespaceObject.hasBlockSupport)(blockName, 'splitting', false) && !event.__deprecatedOnSplit) { return; } // Ensure template is not locked. if (canInsertBlockType(blockName, getBlockRootClientId(clientId))) { __unstableSplitSelection(); event.preventDefault(); } } return; } if (event.keyCode === external_wp_keycodes_namespaceObject.ENTER) { node.contentEditable = false; event.preventDefault(); if (__unstableIsFullySelected()) { replaceBlocks(getSelectedBlockClientIds(), (0,external_wp_blocks_namespaceObject.createBlock)((0,external_wp_blocks_namespaceObject.getDefaultBlockName)())); } else { __unstableSplitSelection(); } } else if (event.keyCode === external_wp_keycodes_namespaceObject.BACKSPACE || event.keyCode === external_wp_keycodes_namespaceObject.DELETE) { node.contentEditable = false; event.preventDefault(); if (__unstableIsFullySelected()) { removeBlocks(getSelectedBlockClientIds()); } else if (__unstableIsSelectionMergeable()) { __unstableDeleteSelection(event.keyCode === external_wp_keycodes_namespaceObject.DELETE); } else { __unstableExpandSelection(); } } else if ( // If key.length is longer than 1, it's a control key that doesn't // input anything. event.key.length === 1 && !(event.metaKey || event.ctrlKey)) { node.contentEditable = false; if (__unstableIsSelectionMergeable()) { __unstableDeleteSelection(event.keyCode === external_wp_keycodes_namespaceObject.DELETE); } else { event.preventDefault(); // Safari does not stop default behaviour with either // event.preventDefault() or node.contentEditable = false, so // remove the selection to stop browser manipulation. node.ownerDocument.defaultView.getSelection().removeAllRanges(); } } } function onCompositionStart(event) { if (!hasMultiSelection()) { return; } node.contentEditable = false; if (__unstableIsSelectionMergeable()) { __unstableDeleteSelection(); } else { event.preventDefault(); // Safari does not stop default behaviour with either // event.preventDefault() or node.contentEditable = false, so // remove the selection to stop browser manipulation. node.ownerDocument.defaultView.getSelection().removeAllRanges(); } } node.addEventListener('beforeinput', onBeforeInput); node.addEventListener('keydown', onKeyDown); node.addEventListener('compositionstart', onCompositionStart); return () => { node.removeEventListener('beforeinput', onBeforeInput); node.removeEventListener('keydown', onKeyDown); node.removeEventListener('compositionstart', onCompositionStart); }; }, []); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/utils/use-notify-copy.js /** * WordPress dependencies */ /** * Internal dependencies */ function useNotifyCopy() { const { getBlockName } = (0,external_wp_data_namespaceObject.useSelect)(store); const { getBlockType } = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blocks_namespaceObject.store); const { createSuccessNotice } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store); return (0,external_wp_element_namespaceObject.useCallback)((eventType, selectedBlockClientIds) => { let notice = ''; if (selectedBlockClientIds.length === 1) { const clientId = selectedBlockClientIds[0]; const title = getBlockType(getBlockName(clientId))?.title; notice = eventType === 'copy' ? (0,external_wp_i18n_namespaceObject.sprintf)( // Translators: Name of the block being copied, e.g. "Paragraph". (0,external_wp_i18n_namespaceObject.__)('Copied "%s" to clipboard.'), title) : (0,external_wp_i18n_namespaceObject.sprintf)( // Translators: Name of the block being cut, e.g. "Paragraph". (0,external_wp_i18n_namespaceObject.__)('Moved "%s" to clipboard.'), title); } else { notice = eventType === 'copy' ? (0,external_wp_i18n_namespaceObject.sprintf)( // Translators: %d: Number of blocks being copied. (0,external_wp_i18n_namespaceObject._n)('Copied %d block to clipboard.', 'Copied %d blocks to clipboard.', selectedBlockClientIds.length), selectedBlockClientIds.length) : (0,external_wp_i18n_namespaceObject.sprintf)( // Translators: %d: Number of blocks being cut. (0,external_wp_i18n_namespaceObject._n)('Moved %d block to clipboard.', 'Moved %d blocks to clipboard.', selectedBlockClientIds.length), selectedBlockClientIds.length); } createSuccessNotice(notice, { type: 'snackbar' }); }, []); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/utils/pasting.js /** * WordPress dependencies */ /** * Normalizes a given string of HTML to remove the Windows-specific "Fragment" * comments and any preceding and trailing content. * * @param {string} html the html to be normalized * @return {string} the normalized html */ function removeWindowsFragments(html) { const startStr = '<!--StartFragment-->'; const startIdx = html.indexOf(startStr); if (startIdx > -1) { html = html.substring(startIdx + startStr.length); } else { // No point looking for EndFragment return html; } const endStr = '<!--EndFragment-->'; const endIdx = html.indexOf(endStr); if (endIdx > -1) { html = html.substring(0, endIdx); } return html; } /** * Removes the charset meta tag inserted by Chromium. * See: * - https://github.com/WordPress/gutenberg/issues/33585 * - https://bugs.chromium.org/p/chromium/issues/detail?id=1264616#c4 * * @param {string} html the html to be stripped of the meta tag. * @return {string} the cleaned html */ function removeCharsetMetaTag(html) { const metaTag = `<meta charset='utf-8'>`; if (html.startsWith(metaTag)) { return html.slice(metaTag.length); } return html; } function getPasteEventData({ clipboardData }) { let plainText = ''; let html = ''; // IE11 only supports `Text` as an argument for `getData` and will // otherwise throw an invalid argument error, so we try the standard // arguments first, then fallback to `Text` if they fail. try { plainText = clipboardData.getData('text/plain'); html = clipboardData.getData('text/html'); } catch (error1) { try { html = clipboardData.getData('Text'); } catch (error2) { // Some browsers like UC Browser paste plain text by default and // don't support clipboardData at all, so allow default // behaviour. return; } } // Remove Windows-specific metadata appended within copied HTML text. html = removeWindowsFragments(html); // Strip meta tag. html = removeCharsetMetaTag(html); const files = (0,external_wp_dom_namespaceObject.getFilesFromDataTransfer)(clipboardData); if (files.length && !shouldDismissPastedFiles(files, html)) { return { files }; } return { html, plainText, files: [] }; } /** * Given a collection of DataTransfer files and HTML and plain text strings, * determine whether the files are to be dismissed in favor of the HTML. * * Certain office-type programs, like Microsoft Word or Apple Numbers, * will, upon copy, generate a screenshot of the content being copied and * attach it to the clipboard alongside the actual rich text that the user * sought to copy. In those cases, we should let Gutenberg handle the rich text * content and not the screenshot, since this allows Gutenberg to insert * meaningful blocks, like paragraphs, lists or even tables. * * @param {File[]} files File objects obtained from a paste event * @param {string} html HTML content obtained from a paste event * @return {boolean} True if the files should be dismissed */ function shouldDismissPastedFiles(files, html /*, plainText */) { // The question is only relevant when there is actual HTML content and when // there is exactly one image file. if (html && files?.length === 1 && files[0].type.indexOf('image/') === 0) { // A single <img> tag found in the HTML source suggests that the // content being pasted revolves around an image. Sometimes there are // other elements found, like <figure>, but we assume that the user's // intention is to paste the actual image file. const IMAGE_TAG = /<\s*img\b/gi; if (html.match(IMAGE_TAG)?.length !== 1) { return true; } // Even when there is exactly one <img> tag in the HTML payload, we // choose to weed out local images, i.e. those whose source starts with // "file://". These payloads occur in specific configurations, such as // when copying an entire document from Microsoft Word, that contains // text and exactly one image, and pasting that content using Google // Chrome. const IMG_WITH_LOCAL_SRC = /<\s*img\b[^>]*\bsrc="file:\/\//i; if (html.match(IMG_WITH_LOCAL_SRC)) { return true; } } return false; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/utils.js /** * WordPress dependencies */ /** * Internal dependencies */ const requiresWrapperOnCopy = Symbol('requiresWrapperOnCopy'); /** * Sets the clipboard data for the provided blocks, with both HTML and plain * text representations. * * @param {ClipboardEvent} event Clipboard event. * @param {WPBlock[]} blocks Blocks to set as clipboard data. * @param {Object} registry The registry to select from. */ function setClipboardBlocks(event, blocks, registry) { let _blocks = blocks; const [firstBlock] = blocks; if (firstBlock) { const firstBlockType = registry.select(external_wp_blocks_namespaceObject.store).getBlockType(firstBlock.name); if (firstBlockType[requiresWrapperOnCopy]) { const { getBlockRootClientId, getBlockName, getBlockAttributes } = registry.select(store); const wrapperBlockClientId = getBlockRootClientId(firstBlock.clientId); const wrapperBlockName = getBlockName(wrapperBlockClientId); if (wrapperBlockName) { _blocks = (0,external_wp_blocks_namespaceObject.createBlock)(wrapperBlockName, getBlockAttributes(wrapperBlockClientId), _blocks); } } } const serialized = (0,external_wp_blocks_namespaceObject.serialize)(_blocks); event.clipboardData.setData('text/plain', toPlainText(serialized)); event.clipboardData.setData('text/html', serialized); } /** * Returns the blocks to be pasted from the clipboard event. * * @param {ClipboardEvent} event The clipboard event. * @param {boolean} canUserUseUnfilteredHTML Whether the user can or can't post unfiltered HTML. * @return {Array|string} A list of blocks or a string, depending on `handlerMode`. */ function getPasteBlocks(event, canUserUseUnfilteredHTML) { const { plainText, html, files } = getPasteEventData(event); let blocks = []; if (files.length) { const fromTransforms = (0,external_wp_blocks_namespaceObject.getBlockTransforms)('from'); blocks = files.reduce((accumulator, file) => { const transformation = (0,external_wp_blocks_namespaceObject.findTransform)(fromTransforms, transform => transform.type === 'files' && transform.isMatch([file])); if (transformation) { accumulator.push(transformation.transform([file])); } return accumulator; }, []).flat(); } else { blocks = (0,external_wp_blocks_namespaceObject.pasteHandler)({ HTML: html, plainText, mode: 'BLOCKS', canUserUseUnfilteredHTML }); } return blocks; } /** * Given a string of HTML representing serialized blocks, returns the plain * text extracted after stripping the HTML of any tags and fixing line breaks. * * @param {string} html Serialized blocks. * @return {string} The plain-text content with any html removed. */ function toPlainText(html) { // Manually handle BR tags as line breaks prior to `stripHTML` call html = html.replace(/<br>/g, '\n'); const plainText = (0,external_wp_dom_namespaceObject.__unstableStripHTML)(html).trim(); // Merge any consecutive line breaks return plainText.replace(/\n\n+/g, '\n\n'); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-clipboard-handler.js /** * WordPress dependencies */ /** * Internal dependencies */ function useClipboardHandler() { const registry = (0,external_wp_data_namespaceObject.useRegistry)(); const { getBlocksByClientId, getSelectedBlockClientIds, hasMultiSelection, getSettings, getBlockName, __unstableIsFullySelected, __unstableIsSelectionCollapsed, __unstableIsSelectionMergeable, __unstableGetSelectedBlocksWithPartialSelection, canInsertBlockType, getBlockRootClientId } = (0,external_wp_data_namespaceObject.useSelect)(store); const { flashBlock, removeBlocks, replaceBlocks, __unstableDeleteSelection, __unstableExpandSelection, __unstableSplitSelection } = (0,external_wp_data_namespaceObject.useDispatch)(store); const notifyCopy = useNotifyCopy(); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { function handler(event) { if (event.defaultPrevented) { // This was likely already handled in rich-text/use-paste-handler.js. return; } const selectedBlockClientIds = getSelectedBlockClientIds(); if (selectedBlockClientIds.length === 0) { return; } // Let native copy/paste behaviour take over in input fields. // But always handle multiple selected blocks. if (!hasMultiSelection()) { const { target } = event; const { ownerDocument } = target; // If copying, only consider actual text selection as selection. // Otherwise, any focus on an input field is considered. const hasSelection = event.type === 'copy' || event.type === 'cut' ? (0,external_wp_dom_namespaceObject.documentHasUncollapsedSelection)(ownerDocument) : (0,external_wp_dom_namespaceObject.documentHasSelection)(ownerDocument) && !ownerDocument.activeElement.isContentEditable; // Let native copy behaviour take over in input fields. if (hasSelection) { return; } } const { activeElement } = event.target.ownerDocument; if (!node.contains(activeElement)) { return; } const isSelectionMergeable = __unstableIsSelectionMergeable(); const shouldHandleWholeBlocks = __unstableIsSelectionCollapsed() || __unstableIsFullySelected(); const expandSelectionIsNeeded = !shouldHandleWholeBlocks && !isSelectionMergeable; if (event.type === 'copy' || event.type === 'cut') { event.preventDefault(); if (selectedBlockClientIds.length === 1) { flashBlock(selectedBlockClientIds[0]); } // If we have a partial selection that is not mergeable, just // expand the selection to the whole blocks. if (expandSelectionIsNeeded) { __unstableExpandSelection(); } else { notifyCopy(event.type, selectedBlockClientIds); let blocks; // Check if we have partial selection. if (shouldHandleWholeBlocks) { blocks = getBlocksByClientId(selectedBlockClientIds); } else { const [head, tail] = __unstableGetSelectedBlocksWithPartialSelection(); const inBetweenBlocks = getBlocksByClientId(selectedBlockClientIds.slice(1, selectedBlockClientIds.length - 1)); blocks = [head, ...inBetweenBlocks, tail]; } setClipboardBlocks(event, blocks, registry); } } if (event.type === 'cut') { // We need to also check if at the start we needed to // expand the selection, as in this point we might have // programmatically fully selected the blocks above. if (shouldHandleWholeBlocks && !expandSelectionIsNeeded) { removeBlocks(selectedBlockClientIds); } else { event.target.ownerDocument.activeElement.contentEditable = false; __unstableDeleteSelection(); } } else if (event.type === 'paste') { const { __experimentalCanUserUseUnfilteredHTML: canUserUseUnfilteredHTML } = getSettings(); const isInternal = event.clipboardData.getData('rich-text') === 'true'; if (isInternal) { return; } const { plainText, html, files } = getPasteEventData(event); const isFullySelected = __unstableIsFullySelected(); let blocks = []; if (files.length) { const fromTransforms = (0,external_wp_blocks_namespaceObject.getBlockTransforms)('from'); blocks = files.reduce((accumulator, file) => { const transformation = (0,external_wp_blocks_namespaceObject.findTransform)(fromTransforms, transform => transform.type === 'files' && transform.isMatch([file])); if (transformation) { accumulator.push(transformation.transform([file])); } return accumulator; }, []).flat(); } else { blocks = (0,external_wp_blocks_namespaceObject.pasteHandler)({ HTML: html, plainText, mode: isFullySelected ? 'BLOCKS' : 'AUTO', canUserUseUnfilteredHTML }); } // Inline paste: let rich text handle it. if (typeof blocks === 'string') { return; } if (isFullySelected) { replaceBlocks(selectedBlockClientIds, blocks, blocks.length - 1, -1); event.preventDefault(); return; } // If a block doesn't support splitting, let rich text paste // inline. if (!hasMultiSelection() && !(0,external_wp_blocks_namespaceObject.hasBlockSupport)(getBlockName(selectedBlockClientIds[0]), 'splitting', false) && !event.__deprecatedOnSplit) { return; } const [firstSelectedClientId] = selectedBlockClientIds; const rootClientId = getBlockRootClientId(firstSelectedClientId); const newBlocks = []; for (const block of blocks) { if (canInsertBlockType(block.name, rootClientId)) { newBlocks.push(block); } else { // If a block cannot be inserted in a root block, try // converting it to that root block type and insert the // inner blocks. // Example: paragraphs cannot be inserted into a list, // so convert the paragraphs to a list for list items. const rootBlockName = getBlockName(rootClientId); const switchedBlocks = block.name !== rootBlockName ? (0,external_wp_blocks_namespaceObject.switchToBlockType)(block, rootBlockName) : [block]; if (!switchedBlocks) { return; } for (const switchedBlock of switchedBlocks) { for (const innerBlock of switchedBlock.innerBlocks) { newBlocks.push(innerBlock); } } } } __unstableSplitSelection(newBlocks); event.preventDefault(); } } node.ownerDocument.addEventListener('copy', handler); node.ownerDocument.addEventListener('cut', handler); node.ownerDocument.addEventListener('paste', handler); return () => { node.ownerDocument.removeEventListener('copy', handler); node.ownerDocument.removeEventListener('cut', handler); node.ownerDocument.removeEventListener('paste', handler); }; }, []); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function useWritingFlow() { const [before, ref, after] = useTabNav(); const hasMultiSelection = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).hasMultiSelection(), []); return [before, (0,external_wp_compose_namespaceObject.useMergeRefs)([ref, useClipboardHandler(), useInput(), useDragSelection(), useSelectionObserver(), useClickSelection(), useMultiSelection(), useSelectAll(), useArrowNav(), (0,external_wp_compose_namespaceObject.useRefEffect)(node => { node.tabIndex = 0; if (!hasMultiSelection) { return; } node.classList.add('has-multi-selection'); node.setAttribute('aria-label', (0,external_wp_i18n_namespaceObject.__)('Multiple selected blocks')); return () => { node.classList.remove('has-multi-selection'); node.removeAttribute('aria-label'); }; }, [hasMultiSelection])]), after]; } function WritingFlow({ children, ...props }, forwardedRef) { const [before, ref, after] = useWritingFlow(); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [before, /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { ...props, ref: (0,external_wp_compose_namespaceObject.useMergeRefs)([ref, forwardedRef]), className: dist_clsx(props.className, 'block-editor-writing-flow'), children: children }), after] }); } /** * Handles selection and navigation across blocks. This component should be * wrapped around BlockList. * * @param {Object} props Component properties. * @param {Element} props.children Children to be rendered. */ /* harmony default export */ const writing_flow = ((0,external_wp_element_namespaceObject.forwardRef)(WritingFlow)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/iframe/get-compatibility-styles.js let compatibilityStyles = null; /** * Returns a list of stylesheets that target the editor canvas. A stylesheet is * considered targetting the editor a canvas if it contains the * `editor-styles-wrapper`, `wp-block`, or `wp-block-*` class selectors. * * Ideally, this hook should be removed in the future and styles should be added * explicitly as editor styles. */ function getCompatibilityStyles() { if (compatibilityStyles) { return compatibilityStyles; } // Only memoize the result once on load, since these stylesheets should not // change. compatibilityStyles = Array.from(document.styleSheets).reduce((accumulator, styleSheet) => { try { // May fail for external styles. // eslint-disable-next-line no-unused-expressions styleSheet.cssRules; } catch (e) { return accumulator; } const { ownerNode, cssRules } = styleSheet; // Stylesheet is added by another stylesheet. See // https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet/ownerNode#notes. if (ownerNode === null) { return accumulator; } if (!cssRules) { return accumulator; } // Don't try to add the reset styles, which were removed as a dependency // from `edit-blocks` for the iframe since we don't need to reset admin // styles. if (ownerNode.id === 'wp-reset-editor-styles-css') { return accumulator; } // Don't try to add styles without ID. Styles enqueued via the WP dependency system will always have IDs. if (!ownerNode.id) { return accumulator; } function matchFromRules(_cssRules) { return Array.from(_cssRules).find(({ selectorText, conditionText, cssRules: __cssRules }) => { // If the rule is conditional then it will not have selector text. // Recurse into child CSS ruleset to determine selector eligibility. if (conditionText) { return matchFromRules(__cssRules); } return selectorText && (selectorText.includes('.editor-styles-wrapper') || selectorText.includes('.wp-block')); }); } if (matchFromRules(cssRules)) { const isInline = ownerNode.tagName === 'STYLE'; if (isInline) { // If the current target is inline, // it could be a dependency of an existing stylesheet. // Look for that dependency and add it BEFORE the current target. const mainStylesCssId = ownerNode.id.replace('-inline-css', '-css'); const mainStylesElement = document.getElementById(mainStylesCssId); if (mainStylesElement) { accumulator.push(mainStylesElement.cloneNode(true)); } } accumulator.push(ownerNode.cloneNode(true)); if (!isInline) { // If the current target is not inline, // we still look for inline styles that could be relevant for the current target. // If they exist, add them AFTER the current target. const inlineStylesCssId = ownerNode.id.replace('-css', '-inline-css'); const inlineStylesElement = document.getElementById(inlineStylesCssId); if (inlineStylesElement) { accumulator.push(inlineStylesElement.cloneNode(true)); } } } return accumulator; }, []); return compatibilityStyles; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/iframe/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function bubbleEvent(event, Constructor, frame) { const init = {}; for (const key in event) { init[key] = event[key]; } // Check if the event is a MouseEvent generated within the iframe. // If so, adjust the coordinates to be relative to the position of // the iframe. This ensures that components such as Draggable // receive coordinates relative to the window, instead of relative // to the iframe. Without this, the Draggable event handler would // result in components "jumping" position as soon as the user // drags over the iframe. if (event instanceof frame.contentDocument.defaultView.MouseEvent) { const rect = frame.getBoundingClientRect(); init.clientX += rect.left; init.clientY += rect.top; } const newEvent = new Constructor(event.type, init); if (init.defaultPrevented) { newEvent.preventDefault(); } const cancelled = !frame.dispatchEvent(newEvent); if (cancelled) { event.preventDefault(); } } /** * Bubbles some event types (keydown, keypress, and dragover) to parent document * document to ensure that the keyboard shortcuts and drag and drop work. * * Ideally, we should remove event bubbling in the future. Keyboard shortcuts * should be context dependent, e.g. actions on blocks like Cmd+A should not * work globally outside the block editor. * * @param {Document} iframeDocument Document to attach listeners to. */ function useBubbleEvents(iframeDocument) { return (0,external_wp_compose_namespaceObject.useRefEffect)(() => { const { defaultView } = iframeDocument; if (!defaultView) { return; } const { frameElement } = defaultView; const html = iframeDocument.documentElement; const eventTypes = ['dragover', 'mousemove']; const handlers = {}; for (const name of eventTypes) { handlers[name] = event => { const prototype = Object.getPrototypeOf(event); const constructorName = prototype.constructor.name; const Constructor = window[constructorName]; bubbleEvent(event, Constructor, frameElement); }; html.addEventListener(name, handlers[name]); } return () => { for (const name of eventTypes) { html.removeEventListener(name, handlers[name]); } }; }); } function Iframe({ contentRef, children, tabIndex = 0, scale = 1, frameSize = 0, readonly, forwardedRef: ref, title = (0,external_wp_i18n_namespaceObject.__)('Editor canvas'), ...props }) { const { resolvedAssets, isPreviewMode } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getSettings } = select(store); const settings = getSettings(); return { resolvedAssets: settings.__unstableResolvedAssets, isPreviewMode: settings.__unstableIsPreviewMode }; }, []); const { styles = '', scripts = '' } = resolvedAssets; const [iframeDocument, setIframeDocument] = (0,external_wp_element_namespaceObject.useState)(); const prevContainerWidth = (0,external_wp_element_namespaceObject.useRef)(); const [bodyClasses, setBodyClasses] = (0,external_wp_element_namespaceObject.useState)([]); const clearerRef = useBlockSelectionClearer(); const [before, writingFlowRef, after] = useWritingFlow(); const [contentResizeListener, { height: contentHeight }] = (0,external_wp_compose_namespaceObject.useResizeObserver)(); const [containerResizeListener, { width: containerWidth }] = (0,external_wp_compose_namespaceObject.useResizeObserver)(); const setRef = (0,external_wp_compose_namespaceObject.useRefEffect)(node => { node._load = () => { setIframeDocument(node.contentDocument); }; let iFrameDocument; // Prevent the default browser action for files dropped outside of dropzones. function preventFileDropDefault(event) { event.preventDefault(); } function onLoad() { const { contentDocument, ownerDocument } = node; const { documentElement } = contentDocument; iFrameDocument = contentDocument; documentElement.classList.add('block-editor-iframe__html'); clearerRef(documentElement); // Ideally ALL classes that are added through get_body_class should // be added in the editor too, which we'll somehow have to get from // the server in the future (which will run the PHP filters). setBodyClasses(Array.from(ownerDocument.body.classList).filter(name => name.startsWith('admin-color-') || name.startsWith('post-type-') || name === 'wp-embed-responsive')); contentDocument.dir = ownerDocument.dir; for (const compatStyle of getCompatibilityStyles()) { if (contentDocument.getElementById(compatStyle.id)) { continue; } contentDocument.head.appendChild(compatStyle.cloneNode(true)); if (!isPreviewMode) { // eslint-disable-next-line no-console console.warn(`${compatStyle.id} was added to the iframe incorrectly. Please use block.json or enqueue_block_assets to add styles to the iframe.`, compatStyle); } } iFrameDocument.addEventListener('dragover', preventFileDropDefault, false); iFrameDocument.addEventListener('drop', preventFileDropDefault, false); } node.addEventListener('load', onLoad); return () => { delete node._load; node.removeEventListener('load', onLoad); iFrameDocument?.removeEventListener('dragover', preventFileDropDefault); iFrameDocument?.removeEventListener('drop', preventFileDropDefault); }; }, []); const [iframeWindowInnerHeight, setIframeWindowInnerHeight] = (0,external_wp_element_namespaceObject.useState)(); const iframeResizeRef = (0,external_wp_compose_namespaceObject.useRefEffect)(node => { const nodeWindow = node.ownerDocument.defaultView; setIframeWindowInnerHeight(nodeWindow.innerHeight); const onResize = () => { setIframeWindowInnerHeight(nodeWindow.innerHeight); }; nodeWindow.addEventListener('resize', onResize); return () => { nodeWindow.removeEventListener('resize', onResize); }; }, []); const [windowInnerWidth, setWindowInnerWidth] = (0,external_wp_element_namespaceObject.useState)(); const windowResizeRef = (0,external_wp_compose_namespaceObject.useRefEffect)(node => { const nodeWindow = node.ownerDocument.defaultView; setWindowInnerWidth(nodeWindow.innerWidth); const onResize = () => { setWindowInnerWidth(nodeWindow.innerWidth); }; nodeWindow.addEventListener('resize', onResize); return () => { nodeWindow.removeEventListener('resize', onResize); }; }, []); const isZoomedOut = scale !== 1; (0,external_wp_element_namespaceObject.useEffect)(() => { if (!isZoomedOut) { prevContainerWidth.current = containerWidth; } }, [containerWidth, isZoomedOut]); const disabledRef = (0,external_wp_compose_namespaceObject.useDisabled)({ isDisabled: !readonly }); const bodyRef = (0,external_wp_compose_namespaceObject.useMergeRefs)([useBubbleEvents(iframeDocument), contentRef, clearerRef, writingFlowRef, disabledRef, // Avoid resize listeners when not needed, these will trigger // unnecessary re-renders when animating the iframe width, or when // expanding preview iframes. isZoomedOut ? iframeResizeRef : null]); // Correct doctype is required to enable rendering in standards // mode. Also preload the styles to avoid a flash of unstyled // content. const html = `<!doctype html> <html> <head> <meta charset="utf-8"> <script>window.frameElement._load()</script> <style> html{ height: auto !important; min-height: 100%; } /* Lowest specificity to not override global styles */ :where(body) { margin: 0; /* Default background color in case zoom out mode background colors the html element */ background-color: white; } </style> ${styles} ${scripts} </head> <body> <script>document.currentScript.parentElement.remove()</script> </body> </html>`; const [src, cleanup] = (0,external_wp_element_namespaceObject.useMemo)(() => { const _src = URL.createObjectURL(new window.Blob([html], { type: 'text/html' })); return [_src, () => URL.revokeObjectURL(_src)]; }, [html]); (0,external_wp_element_namespaceObject.useEffect)(() => cleanup, [cleanup]); (0,external_wp_element_namespaceObject.useEffect)(() => { if (!iframeDocument || !isZoomedOut) { return; } iframeDocument.documentElement.classList.add('is-zoomed-out'); const maxWidth = 800; iframeDocument.documentElement.style.setProperty('--wp-block-editor-iframe-zoom-out-scale', scale === 'default' ? Math.min(containerWidth, maxWidth) / prevContainerWidth.current : scale); iframeDocument.documentElement.style.setProperty('--wp-block-editor-iframe-zoom-out-frame-size', typeof frameSize === 'number' ? `${frameSize}px` : frameSize); iframeDocument.documentElement.style.setProperty('--wp-block-editor-iframe-zoom-out-content-height', `${contentHeight}px`); iframeDocument.documentElement.style.setProperty('--wp-block-editor-iframe-zoom-out-inner-height', `${iframeWindowInnerHeight}px`); iframeDocument.documentElement.style.setProperty('--wp-block-editor-iframe-zoom-out-container-width', `${containerWidth}px`); iframeDocument.documentElement.style.setProperty('--wp-block-editor-iframe-zoom-out-prev-container-width', `${prevContainerWidth.current}px`); return () => { iframeDocument.documentElement.classList.remove('is-zoomed-out'); iframeDocument.documentElement.style.removeProperty('--wp-block-editor-iframe-zoom-out-scale'); iframeDocument.documentElement.style.removeProperty('--wp-block-editor-iframe-zoom-out-frame-size'); iframeDocument.documentElement.style.removeProperty('--wp-block-editor-iframe-zoom-out-content-height'); iframeDocument.documentElement.style.removeProperty('--wp-block-editor-iframe-zoom-out-inner-height'); iframeDocument.documentElement.style.removeProperty('--wp-block-editor-iframe-zoom-out-container-width'); iframeDocument.documentElement.style.removeProperty('--wp-block-editor-iframe-zoom-out-prev-container-width'); }; }, [scale, frameSize, iframeDocument, iframeWindowInnerHeight, contentHeight, containerWidth, windowInnerWidth, isZoomedOut]); // Make sure to not render the before and after focusable div elements in view // mode. They're only needed to capture focus in edit mode. const shouldRenderFocusCaptureElements = tabIndex >= 0 && !isPreviewMode; const iframe = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [shouldRenderFocusCaptureElements && before, /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("iframe", { ...props, style: { border: 0, ...props.style, height: props.style?.height, transition: 'all .3s' }, ref: (0,external_wp_compose_namespaceObject.useMergeRefs)([ref, setRef]), tabIndex: tabIndex // Correct doctype is required to enable rendering in standards // mode. Also preload the styles to avoid a flash of unstyled // content. , src: src, title: title, onKeyDown: event => { if (props.onKeyDown) { props.onKeyDown(event); } // If the event originates from inside the iframe, it means // it bubbled through the portal, but only with React // events. We need to to bubble native events as well, // though by doing so we also trigger another React event, // so we need to stop the propagation of this event to avoid // duplication. if (event.currentTarget.ownerDocument !== event.target.ownerDocument) { // We should only stop propagation of the React event, // the native event should further bubble inside the // iframe to the document and window. // Alternatively, we could consider redispatching the // native event in the iframe. const { stopPropagation } = event.nativeEvent; event.nativeEvent.stopPropagation = () => {}; event.stopPropagation(); event.nativeEvent.stopPropagation = stopPropagation; bubbleEvent(event, window.KeyboardEvent, event.currentTarget); } }, children: iframeDocument && (0,external_wp_element_namespaceObject.createPortal)( /*#__PURE__*/ // We want to prevent React events from bubbling throught the iframe // we bubble these manually. /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */ (0,external_ReactJSXRuntime_namespaceObject.jsxs)("body", { ref: bodyRef, className: dist_clsx('block-editor-iframe__body', 'editor-styles-wrapper', ...bodyClasses), children: [contentResizeListener, /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalStyleProvider, { document: iframeDocument, children: children })] }), iframeDocument.documentElement) }), shouldRenderFocusCaptureElements && after] }); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-iframe__container", ref: windowResizeRef, children: [containerResizeListener, /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: dist_clsx('block-editor-iframe__scale-container', isZoomedOut && 'is-zoomed-out'), style: { '--wp-block-editor-iframe-zoom-out-container-width': isZoomedOut && `${containerWidth}px`, '--wp-block-editor-iframe-zoom-out-prev-container-width': isZoomedOut && `${prevContainerWidth.current}px` }, children: iframe })] }); } function IframeIfReady(props, ref) { const isInitialised = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).getSettings().__internalIsInitialized, []); // We shouldn't render the iframe until the editor settings are initialised. // The initial settings are needed to get the styles for the srcDoc, which // cannot be changed after the iframe is mounted. srcDoc is used to to set // the initial iframe HTML, which is required to avoid a flash of unstyled // content. if (!isInitialised) { return null; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Iframe, { ...props, forwardedRef: ref }); } /* harmony default export */ const iframe = ((0,external_wp_element_namespaceObject.forwardRef)(IframeIfReady)); // EXTERNAL MODULE: ./node_modules/postcss/lib/postcss.js var postcss = __webpack_require__(4529); ;// CONCATENATED MODULE: ./node_modules/postcss/lib/postcss.mjs /* harmony default export */ const lib_postcss = (postcss); const stringify = postcss.stringify const fromJSON = postcss.fromJSON const postcss_plugin = postcss.plugin const parse = postcss.parse const list = postcss.list const postcss_document = postcss.document const comment = postcss.comment const atRule = postcss.atRule const rule = postcss.rule const decl = postcss.decl const root = postcss.root const CssSyntaxError = postcss.CssSyntaxError const Declaration = postcss.Declaration const Container = postcss.Container const Processor = postcss.Processor const Document = postcss.Document const Comment = postcss.Comment const postcss_Warning = postcss.Warning const AtRule = postcss.AtRule const Result = postcss.Result const Input = postcss.Input const Rule = postcss.Rule const Root = postcss.Root const Node = postcss.Node // EXTERNAL MODULE: ./node_modules/postcss-prefixwrap/build/index.js var build = __webpack_require__(8036); var build_default = /*#__PURE__*/__webpack_require__.n(build); // EXTERNAL MODULE: ./node_modules/postcss-urlrebase/index.js var postcss_urlrebase = __webpack_require__(5404); var postcss_urlrebase_default = /*#__PURE__*/__webpack_require__.n(postcss_urlrebase); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/utils/transform-styles/index.js /** * External dependencies */ const cacheByWrapperSelector = new Map(); function transformStyle({ css, ignoredSelectors = [], baseURL }, wrapperSelector = '') { // When there is no wrapper selector or base URL, there is no need // to transform the CSS. This is most cases because in the default // iframed editor, no wrapping is needed, and not many styles // provide a base URL. if (!wrapperSelector && !baseURL) { return css; } const postcssFriendlyCSS = css.replace(/:root :where\(body\)/g, 'body').replace(/:where\(body\)/g, 'body'); try { return lib_postcss([wrapperSelector && build_default()(wrapperSelector, { ignoredSelectors: [...ignoredSelectors, wrapperSelector] }), baseURL && postcss_urlrebase_default()({ rootUrl: baseURL })].filter(Boolean)).process(postcssFriendlyCSS, {}).css; // use sync PostCSS API } catch (error) { if (error instanceof CssSyntaxError) { // eslint-disable-next-line no-console console.warn('wp.blockEditor.transformStyles Failed to transform CSS.', error.message + '\n' + error.showSourceCode(false)); } else { // eslint-disable-next-line no-console console.warn('wp.blockEditor.transformStyles Failed to transform CSS.', error); } return null; } } /** * Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed. * * @typedef {Object} EditorStyle * @property {string} css the CSS block(s), as a single string. * @property {?string} baseURL the base URL to be used as the reference when rewritting urls. * @property {?string[]} ignoredSelectors the selectors not to wrap. * * @param {EditorStyle[]} styles CSS rules. * @param {string} wrapperSelector Wrapper selector. * @return {Array} converted rules. */ const transform_styles_transformStyles = (styles, wrapperSelector = '') => { let cache = cacheByWrapperSelector.get(wrapperSelector); if (!cache) { cache = new WeakMap(); cacheByWrapperSelector.set(wrapperSelector, cache); } return styles.map(style => { let css = cache.get(style); if (!css) { css = transformStyle(style, wrapperSelector); cache.set(style, css); } return css; }); }; /* harmony default export */ const transform_styles = (transform_styles_transformStyles); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/editor-styles/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ k([names, a11y]); function useDarkThemeBodyClassName(styles, scope) { return (0,external_wp_element_namespaceObject.useCallback)(node => { if (!node) { return; } const { ownerDocument } = node; const { defaultView, body } = ownerDocument; const canvas = scope ? ownerDocument.querySelector(scope) : body; let backgroundColor; if (!canvas) { // The real .editor-styles-wrapper element might not exist in the // DOM, so calculate the background color by creating a fake // wrapper. const tempCanvas = ownerDocument.createElement('div'); tempCanvas.classList.add('editor-styles-wrapper'); body.appendChild(tempCanvas); backgroundColor = defaultView?.getComputedStyle(tempCanvas, null).getPropertyValue('background-color'); body.removeChild(tempCanvas); } else { backgroundColor = defaultView?.getComputedStyle(canvas, null).getPropertyValue('background-color'); } const colordBackgroundColor = w(backgroundColor); // If background is transparent, it should be treated as light color. if (colordBackgroundColor.luminance() > 0.5 || colordBackgroundColor.alpha() === 0) { body.classList.remove('is-dark-theme'); } else { body.classList.add('is-dark-theme'); } }, [styles, scope]); } function EditorStyles({ styles, scope }) { const overrides = (0,external_wp_data_namespaceObject.useSelect)(select => unlock(select(store)).getStyleOverrides(), []); const [transformedStyles, transformedSvgs] = (0,external_wp_element_namespaceObject.useMemo)(() => { const _styles = Object.values(styles !== null && styles !== void 0 ? styles : []); for (const [id, override] of overrides) { const index = _styles.findIndex(({ id: _id }) => id === _id); const overrideWithId = { ...override, id }; if (index === -1) { _styles.push(overrideWithId); } else { _styles[index] = overrideWithId; } } return [transform_styles(_styles.filter(style => style?.css), scope), _styles.filter(style => style.__unstableType === 'svgs').map(style => style.assets).join('')]; }, [styles, overrides, scope]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("style", { ref: useDarkThemeBodyClassName(transformedStyles, scope) }), transformedStyles.map((css, index) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("style", { children: css }, index)), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 0 0", width: "0", height: "0", role: "none", style: { visibility: 'hidden', position: 'absolute', left: '-9999px', overflow: 'hidden' }, dangerouslySetInnerHTML: { __html: transformedSvgs } })] }); } /* harmony default export */ const editor_styles = ((0,external_wp_element_namespaceObject.memo)(EditorStyles)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-preview/auto.js /** * WordPress dependencies */ /** * Internal dependencies */ // This is used to avoid rendering the block list if the sizes change. let MemoizedBlockList; const MAX_HEIGHT = 2000; const EMPTY_ADDITIONAL_STYLES = []; function ScaledBlockPreview({ viewportWidth, containerWidth, minHeight, additionalStyles = EMPTY_ADDITIONAL_STYLES }) { if (!viewportWidth) { viewportWidth = containerWidth; } const [contentResizeListener, { height: contentHeight }] = (0,external_wp_compose_namespaceObject.useResizeObserver)(); const { styles } = (0,external_wp_data_namespaceObject.useSelect)(select => { const settings = select(store).getSettings(); return { styles: settings.styles }; }, []); // Avoid scrollbars for pattern previews. const editorStyles = (0,external_wp_element_namespaceObject.useMemo)(() => { if (styles) { return [...styles, { css: 'body{height:auto;overflow:hidden;border:none;padding:0;}', __unstableType: 'presets' }, ...additionalStyles]; } return styles; }, [styles, additionalStyles]); // Initialize on render instead of module top level, to avoid circular dependency issues. MemoizedBlockList = MemoizedBlockList || (0,external_wp_element_namespaceObject.memo)(BlockList); const scale = containerWidth / viewportWidth; const aspectRatio = contentHeight ? containerWidth / (contentHeight * scale) : 0; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Disabled, { className: "block-editor-block-preview__content", style: { transform: `scale(${scale})`, // Using width + aspect-ratio instead of height here triggers browsers' native // handling of scrollbar's visibility. It prevents the flickering issue seen // in https://github.com/WordPress/gutenberg/issues/52027. // See https://github.com/WordPress/gutenberg/pull/52921 for more info. aspectRatio, maxHeight: contentHeight > MAX_HEIGHT ? MAX_HEIGHT * scale : undefined, minHeight }, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(iframe, { contentRef: (0,external_wp_compose_namespaceObject.useRefEffect)(bodyElement => { const { ownerDocument: { documentElement } } = bodyElement; documentElement.classList.add('block-editor-block-preview__content-iframe'); documentElement.style.position = 'absolute'; documentElement.style.width = '100%'; // Necessary for contentResizeListener to work. bodyElement.style.boxSizing = 'border-box'; bodyElement.style.position = 'absolute'; bodyElement.style.width = '100%'; }, []), "aria-hidden": true, tabIndex: -1, style: { position: 'absolute', width: viewportWidth, height: contentHeight, pointerEvents: 'none', // This is a catch-all max-height for patterns. // See: https://github.com/WordPress/gutenberg/pull/38175. maxHeight: MAX_HEIGHT, minHeight: scale !== 0 && scale < 1 && minHeight ? minHeight / scale : minHeight }, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(editor_styles, { styles: editorStyles }), contentResizeListener, /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MemoizedBlockList, { renderAppender: false })] }) }); } function AutoBlockPreview(props) { const [containerResizeListener, { width: containerWidth }] = (0,external_wp_compose_namespaceObject.useResizeObserver)(); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { style: { position: 'relative', width: '100%', height: 0 }, children: containerResizeListener }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-preview__container", children: !!containerWidth && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ScaledBlockPreview, { ...props, containerWidth: containerWidth }) })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-preview/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const block_preview_EMPTY_ADDITIONAL_STYLES = []; function BlockPreview({ blocks, viewportWidth = 1200, minHeight, additionalStyles = block_preview_EMPTY_ADDITIONAL_STYLES, // Deprecated props: __experimentalMinHeight, __experimentalPadding }) { if (__experimentalMinHeight) { minHeight = __experimentalMinHeight; external_wp_deprecated_default()('The __experimentalMinHeight prop', { since: '6.2', version: '6.4', alternative: 'minHeight' }); } if (__experimentalPadding) { additionalStyles = [...additionalStyles, { css: `body { padding: ${__experimentalPadding}px; }` }]; external_wp_deprecated_default()('The __experimentalPadding prop of BlockPreview', { since: '6.2', version: '6.4', alternative: 'additionalStyles' }); } const originalSettings = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).getSettings(), []); const settings = (0,external_wp_element_namespaceObject.useMemo)(() => ({ ...originalSettings, focusMode: false, // Disable "Spotlight mode". __unstableIsPreviewMode: true }), [originalSettings]); const renderedBlocks = (0,external_wp_element_namespaceObject.useMemo)(() => Array.isArray(blocks) ? blocks : [blocks], [blocks]); if (!blocks || blocks.length === 0) { return null; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ExperimentalBlockEditorProvider, { value: renderedBlocks, settings: settings, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(AutoBlockPreview, { viewportWidth: viewportWidth, minHeight: minHeight, additionalStyles: additionalStyles }) }); } /** * BlockPreview renders a preview of a block or array of blocks. * * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/block-preview/README.md * * @param {Object} preview options for how the preview should be shown * @param {Array|Object} preview.blocks A block instance (object) or an array of blocks to be previewed. * @param {number} preview.viewportWidth Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview. Default: 700. * * @return {Component} The component to be rendered. */ /* harmony default export */ const block_preview = ((0,external_wp_element_namespaceObject.memo)(BlockPreview)); /** * This hook is used to lightly mark an element as a block preview wrapper * element. Call this hook and pass the returned props to the element to mark as * a block preview wrapper, automatically rendering inner blocks as children. If * you define a ref for the element, it is important to pass the ref to this * hook, which the hook in turn will pass to the component through the props it * returns. Optionally, you can also pass any other props through this hook, and * they will be merged and returned. * * @param {Object} options Preview options. * @param {WPBlock[]} options.blocks Block objects. * @param {Object} options.props Optional. Props to pass to the element. Must contain * the ref if one is defined. * @param {Object} options.layout Layout settings to be used in the preview. */ function useBlockPreview({ blocks, props = {}, layout }) { const originalSettings = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).getSettings(), []); const settings = (0,external_wp_element_namespaceObject.useMemo)(() => ({ ...originalSettings, styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles. focusMode: false, // Disable "Spotlight mode". __unstableIsPreviewMode: true }), [originalSettings]); const disabledRef = (0,external_wp_compose_namespaceObject.useDisabled)(); const ref = (0,external_wp_compose_namespaceObject.useMergeRefs)([props.ref, disabledRef]); const renderedBlocks = (0,external_wp_element_namespaceObject.useMemo)(() => Array.isArray(blocks) ? blocks : [blocks], [blocks]); const children = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(ExperimentalBlockEditorProvider, { value: renderedBlocks, settings: settings, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(editor_styles, {}), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockListItems, { renderAppender: false, layout: layout })] }); return { ...props, ref, className: dist_clsx(props.className, 'block-editor-block-preview__live-content', 'components-disabled'), children: blocks?.length ? children : null }; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/preview-panel.js /** * WordPress dependencies */ /** * Internal dependencies */ function InserterPreviewPanel({ item }) { var _example$viewportWidt; const { name, title, icon, description, initialAttributes, example } = item; const isReusable = (0,external_wp_blocks_namespaceObject.isReusableBlock)(item); const blocks = (0,external_wp_element_namespaceObject.useMemo)(() => { if (!example) { return (0,external_wp_blocks_namespaceObject.createBlock)(name, initialAttributes); } return (0,external_wp_blocks_namespaceObject.getBlockFromExample)(name, { attributes: { ...example.attributes, ...initialAttributes }, innerBlocks: example.innerBlocks }); }, [name, example, initialAttributes]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__preview-container", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__preview", children: isReusable || example ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__preview-content", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_preview, { blocks: blocks, viewportWidth: (_example$viewportWidt = example?.viewportWidth) !== null && _example$viewportWidt !== void 0 ? _example$viewportWidt : 500, additionalStyles: [{ css: 'body { padding: 24px; }' }] }) }) : /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__preview-content-missing", children: (0,external_wp_i18n_namespaceObject.__)('No preview available.') }) }), !isReusable && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_card, { title: title, icon: icon, description: description })] }); } /* harmony default export */ const preview_panel = (InserterPreviewPanel); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-listbox/item.js /** * WordPress dependencies */ /** * Internal dependencies */ const { CompositeItemV2: item_CompositeItem } = unlock(external_wp_components_namespaceObject.privateApis); function InserterListboxItem({ isFirst, as: Component, children, ...props }, ref) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(item_CompositeItem, { ref: ref, role: "option" // Use the CompositeItem `accessibleWhenDisabled` prop // over Button's `isFocusable`. The latter was shown to // cause an issue with tab order in the inserter list. , accessibleWhenDisabled: true, ...props, render: htmlProps => { const propsWithTabIndex = { ...htmlProps, tabIndex: isFirst ? 0 : htmlProps.tabIndex }; if (Component) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Component, { ...propsWithTabIndex, children: children }); } if (typeof children === 'function') { return children(propsWithTabIndex); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { ...propsWithTabIndex, children: children }); } }); } /* harmony default export */ const inserter_listbox_item = ((0,external_wp_element_namespaceObject.forwardRef)(InserterListboxItem)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/drag-handle.js /** * WordPress dependencies */ const dragHandle = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, { width: "24", height: "24", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, { d: "M8 7h2V5H8v2zm0 6h2v-2H8v2zm0 6h2v-2H8v2zm6-14v2h2V5h-2zm0 8h2v-2h-2v2zm0 6h2v-2h-2v2z" }) }); /* harmony default export */ const drag_handle = (dragHandle); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-draggable/draggable-chip.js /** * WordPress dependencies */ /** * Internal dependencies */ function BlockDraggableChip({ count, icon, isPattern, fadeWhenDisabled }) { const patternLabel = isPattern && (0,external_wp_i18n_namespaceObject.__)('Pattern'); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-draggable-chip-wrapper", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-draggable-chip", "data-testid": "block-draggable-chip", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.Flex, { justify: "center", className: "block-editor-block-draggable-chip__content", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexItem, { children: icon ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_icon, { icon: icon }) : patternLabel || (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %d: Number of blocks. */ (0,external_wp_i18n_namespaceObject._n)('%d block', '%d blocks', count), count) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexItem, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_icon, { icon: drag_handle }) }), fadeWhenDisabled && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexItem, { className: "block-editor-block-draggable-chip__disabled", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { className: "block-editor-block-draggable-chip__disabled-icon" }) })] }) }) }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-draggable-blocks/index.js /** * WordPress dependencies */ /** * Internal dependencies */ const InserterDraggableBlocks = ({ isEnabled, blocks, icon, children, pattern }) => { const transferData = { type: 'inserter', blocks }; const blockTypeIcon = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockType } = select(external_wp_blocks_namespaceObject.store); return blocks.length === 1 && getBlockType(blocks[0].name)?.icon; }, [blocks]); const { startDragging, stopDragging } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store)); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Draggable, { __experimentalTransferDataType: "wp-blocks", transferData: transferData, onDragStart: event => { startDragging(); const parsedBlocks = pattern?.type === INSERTER_PATTERN_TYPES.user && pattern?.syncStatus !== 'unsynced' ? [(0,external_wp_blocks_namespaceObject.createBlock)('core/block', { ref: pattern.id })] : blocks; event.dataTransfer.setData('text/html', (0,external_wp_blocks_namespaceObject.serialize)(parsedBlocks)); }, onDragEnd: () => { stopDragging(); }, __experimentalDragComponent: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockDraggableChip, { count: blocks.length, icon: icon || !pattern && blockTypeIcon, isPattern: !!pattern }), children: ({ onDraggableStart, onDraggableEnd }) => { return children({ draggable: isEnabled, onDragStart: isEnabled ? onDraggableStart : undefined, onDragEnd: isEnabled ? onDraggableEnd : undefined }); } }); }; /* harmony default export */ const inserter_draggable_blocks = (InserterDraggableBlocks); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-list-item/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function InserterListItem({ className, isFirst, item, onSelect, onHover, isDraggable, ...props }) { const isDragging = (0,external_wp_element_namespaceObject.useRef)(false); const itemIconStyle = item.icon ? { backgroundColor: item.icon.background, color: item.icon.foreground } : {}; const blocks = (0,external_wp_element_namespaceObject.useMemo)(() => [(0,external_wp_blocks_namespaceObject.createBlock)(item.name, item.initialAttributes, (0,external_wp_blocks_namespaceObject.createBlocksFromInnerBlocksTemplate)(item.innerBlocks))], [item.name, item.initialAttributes, item.innerBlocks]); const isSynced = (0,external_wp_blocks_namespaceObject.isReusableBlock)(item) && item.syncStatus !== 'unsynced' || (0,external_wp_blocks_namespaceObject.isTemplatePart)(item); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_draggable_blocks, { isEnabled: isDraggable && !item.isDisabled, blocks: blocks, icon: item.icon, children: ({ draggable, onDragStart, onDragEnd }) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: dist_clsx('block-editor-block-types-list__list-item', { 'is-synced': isSynced }), draggable: draggable, onDragStart: event => { isDragging.current = true; if (onDragStart) { onHover(null); onDragStart(event); } }, onDragEnd: event => { isDragging.current = false; if (onDragEnd) { onDragEnd(event); } }, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(inserter_listbox_item, { isFirst: isFirst, className: dist_clsx('block-editor-block-types-list__item', className), disabled: item.isDisabled, onClick: event => { event.preventDefault(); onSelect(item, (0,external_wp_keycodes_namespaceObject.isAppleOS)() ? event.metaKey : event.ctrlKey); onHover(null); }, onKeyDown: event => { const { keyCode } = event; if (keyCode === external_wp_keycodes_namespaceObject.ENTER) { event.preventDefault(); onSelect(item, (0,external_wp_keycodes_namespaceObject.isAppleOS)() ? event.metaKey : event.ctrlKey); onHover(null); } }, onMouseEnter: () => { if (isDragging.current) { return; } onHover(item); }, onMouseLeave: () => onHover(null), ...props, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { className: "block-editor-block-types-list__item-icon", style: itemIconStyle, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_icon, { icon: item.icon, showColors: true }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { className: "block-editor-block-types-list__item-title", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalTruncate, { numberOfLines: 3, children: item.title }) })] }) }) }); } /* harmony default export */ const inserter_list_item = ((0,external_wp_element_namespaceObject.memo)(InserterListItem)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-listbox/group.js /** * WordPress dependencies */ function InserterListboxGroup(props, ref) { const [shouldSpeak, setShouldSpeak] = (0,external_wp_element_namespaceObject.useState)(false); (0,external_wp_element_namespaceObject.useEffect)(() => { if (shouldSpeak) { (0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.__)('Use left and right arrow keys to move through blocks')); } }, [shouldSpeak]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { ref: ref, role: "listbox", "aria-orientation": "horizontal", onFocus: () => { setShouldSpeak(true); }, onBlur: event => { const focusingOutsideGroup = !event.currentTarget.contains(event.relatedTarget); if (focusingOutsideGroup) { setShouldSpeak(false); } }, ...props }); } /* harmony default export */ const group = ((0,external_wp_element_namespaceObject.forwardRef)(InserterListboxGroup)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-listbox/row.js /** * WordPress dependencies */ /** * Internal dependencies */ const { CompositeGroupV2: CompositeGroup } = unlock(external_wp_components_namespaceObject.privateApis); function InserterListboxRow(props, ref) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CompositeGroup, { role: "presentation", ref: ref, ...props }); } /* harmony default export */ const inserter_listbox_row = ((0,external_wp_element_namespaceObject.forwardRef)(InserterListboxRow)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-types-list/index.js /** * WordPress dependencies */ /** * Internal dependencies */ function chunk(array, size) { const chunks = []; for (let i = 0, j = array.length; i < j; i += size) { chunks.push(array.slice(i, i + size)); } return chunks; } function BlockTypesList({ items = [], onSelect, onHover = () => {}, children, label, isDraggable = true }) { const className = 'block-editor-block-types-list'; const listId = (0,external_wp_compose_namespaceObject.useInstanceId)(BlockTypesList, className); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(group, { className: className, "aria-label": label, children: [chunk(items, 3).map((row, i) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_listbox_row, { children: row.map((item, j) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_list_item, { item: item, className: (0,external_wp_blocks_namespaceObject.getBlockMenuDefaultClassName)(item.id), onSelect: onSelect, onHover: onHover, isDraggable: isDraggable && !item.isDisabled, isFirst: i === 0 && j === 0, rowId: `${listId}-${i}` }, item.id)) }, i)), children] }); } /* harmony default export */ const block_types_list = (BlockTypesList); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/panel.js /** * WordPress dependencies */ function InserterPanel({ title, icon, children }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__panel-header", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("h2", { className: "block-editor-inserter__panel-title", children: title }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Icon, { icon: icon })] }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__panel-content", children: children })] }); } /* harmony default export */ const panel = (InserterPanel); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-listbox/index.js /** * WordPress dependencies */ /** * Internal dependencies */ const { CompositeV2: inserter_listbox_Composite, useCompositeStoreV2: inserter_listbox_useCompositeStore } = unlock(external_wp_components_namespaceObject.privateApis); function InserterListbox({ children }) { const store = inserter_listbox_useCompositeStore({ focusShift: true, focusWrap: 'horizontal' }); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_listbox_Composite, { store: store, render: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, {}), children: children }); } /* harmony default export */ const inserter_listbox = (InserterListbox); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/no-results.js /** * WordPress dependencies */ function InserterNoResults() { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__no-results", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_icon, { className: "block-editor-inserter__no-results-icon", icon: block_default }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("p", { children: (0,external_wp_i18n_namespaceObject.__)('No results found.') })] }); } /* harmony default export */ const no_results = (InserterNoResults); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-types-tab.js /** * WordPress dependencies */ /** * Internal dependencies */ const getBlockNamespace = item => item.name.split('/')[0]; const MAX_SUGGESTED_ITEMS = 6; /** * Shared reference to an empty array for cases where it is important to avoid * returning a new array reference on every invocation and rerendering the component. * * @type {Array} */ const block_types_tab_EMPTY_ARRAY = []; function BlockTypesTabPanel({ items, collections, categories, onSelectItem, onHover, showMostUsedBlocks, className }) { const suggestedItems = (0,external_wp_element_namespaceObject.useMemo)(() => { return orderBy(items, 'frecency', 'desc').slice(0, MAX_SUGGESTED_ITEMS); }, [items]); const uncategorizedItems = (0,external_wp_element_namespaceObject.useMemo)(() => { return items.filter(item => !item.category); }, [items]); const itemsPerCollection = (0,external_wp_element_namespaceObject.useMemo)(() => { // Create a new Object to avoid mutating collection. const result = { ...collections }; Object.keys(collections).forEach(namespace => { result[namespace] = items.filter(item => getBlockNamespace(item) === namespace); if (result[namespace].length === 0) { delete result[namespace]; } }); return result; }, [items, collections]); // Hide block preview on unmount. (0,external_wp_element_namespaceObject.useEffect)(() => () => onHover(null), []); /** * The inserter contains a big number of blocks and opening it is a costful operation. * The rendering is the most costful part of it, in order to improve the responsiveness * of the "opening" action, these lazy lists allow us to render the inserter category per category, * once all the categories are rendered, we start rendering the collections and the uncategorized block types. */ const currentlyRenderedCategories = (0,external_wp_compose_namespaceObject.useAsyncList)(categories); const didRenderAllCategories = categories.length === currentlyRenderedCategories.length; // Async List requires an array. const collectionEntries = (0,external_wp_element_namespaceObject.useMemo)(() => { return Object.entries(collections); }, [collections]); const currentlyRenderedCollections = (0,external_wp_compose_namespaceObject.useAsyncList)(didRenderAllCategories ? collectionEntries : block_types_tab_EMPTY_ARRAY); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: className, children: [showMostUsedBlocks && // Only show the most used blocks if the total amount of block // is larger than 1 row, otherwise it is not so useful. items.length > 3 && !!suggestedItems.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(panel, { title: (0,external_wp_i18n_namespaceObject._x)('Most used', 'blocks'), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_types_list, { items: suggestedItems, onSelect: onSelectItem, onHover: onHover, label: (0,external_wp_i18n_namespaceObject._x)('Most used', 'blocks') }) }), currentlyRenderedCategories.map(category => { const categoryItems = items.filter(item => item.category === category.slug); if (!categoryItems || !categoryItems.length) { return null; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(panel, { title: category.title, icon: category.icon, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_types_list, { items: categoryItems, onSelect: onSelectItem, onHover: onHover, label: category.title }) }, category.slug); }), didRenderAllCategories && uncategorizedItems.length > 0 && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(panel, { className: "block-editor-inserter__uncategorized-blocks-panel", title: (0,external_wp_i18n_namespaceObject.__)('Uncategorized'), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_types_list, { items: uncategorizedItems, onSelect: onSelectItem, onHover: onHover, label: (0,external_wp_i18n_namespaceObject.__)('Uncategorized') }) }), currentlyRenderedCollections.map(([namespace, collection]) => { const collectionItems = itemsPerCollection[namespace]; if (!collectionItems || !collectionItems.length) { return null; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(panel, { title: collection.title, icon: collection.icon, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_types_list, { items: collectionItems, onSelect: onSelectItem, onHover: onHover, label: collection.title }) }, namespace); })] }); } function BlockTypesTab({ rootClientId, onInsert, onHover, showMostUsedBlocks }, ref) { const [items, categories, collections, onSelectItem] = use_block_types_state(rootClientId, onInsert); if (!items.length) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(no_results, {}); } const itemsForCurrentRoot = []; const itemsRemaining = []; for (const item of items) { // Skip reusable blocks, they moved to the patterns tab. if (item.category === 'reusable') { continue; } if (rootClientId && item.rootClientId === rootClientId) { itemsForCurrentRoot.push(item); } else { itemsRemaining.push(item); } } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_listbox, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { ref: ref, children: [!!itemsForCurrentRoot.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockTypesTabPanel, { items: itemsForCurrentRoot, categories: categories, collections: collections, onSelectItem: onSelectItem, onHover: onHover, showMostUsedBlocks: showMostUsedBlocks, className: "block-editor-inserter__insertable-blocks-at-selection" }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockTypesTabPanel, { items: itemsRemaining, categories: categories, collections: collections, onSelectItem: onSelectItem, onHover: onHover, showMostUsedBlocks: showMostUsedBlocks, className: "block-editor-inserter__all-blocks" })] }) }); } /* harmony default export */ const block_types_tab = ((0,external_wp_element_namespaceObject.forwardRef)(BlockTypesTab)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-explorer/pattern-explorer-sidebar.js /** * WordPress dependencies */ function PatternCategoriesList({ selectedCategory, patternCategories, onClickCategory }) { const baseClassName = 'block-editor-block-patterns-explorer__sidebar'; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: `${baseClassName}__categories-list`, children: patternCategories.map(({ name, label }) => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { label: label, className: `${baseClassName}__categories-list__item`, isPressed: selectedCategory === name, onClick: () => { onClickCategory(name); }, children: label }, name); }) }); } function PatternsExplorerSearch({ searchValue, setSearchValue }) { const baseClassName = 'block-editor-block-patterns-explorer__search'; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: baseClassName, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.SearchControl, { __nextHasNoMarginBottom: true, onChange: setSearchValue, value: searchValue, label: (0,external_wp_i18n_namespaceObject.__)('Search for patterns'), placeholder: (0,external_wp_i18n_namespaceObject.__)('Search') }) }); } function PatternExplorerSidebar({ selectedCategory, patternCategories, onClickCategory, searchValue, setSearchValue }) { const baseClassName = 'block-editor-block-patterns-explorer__sidebar'; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: baseClassName, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternsExplorerSearch, { searchValue: searchValue, setSearchValue: setSearchValue }), !searchValue && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoriesList, { selectedCategory: selectedCategory, patternCategories: patternCategories, onClickCategory: onClickCategory })] }); } /* harmony default export */ const pattern_explorer_sidebar = (PatternExplorerSidebar); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-patterns-paging/index.js /** * WordPress dependencies */ function Pagination({ currentPage, numPages, changePage, totalItems }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, { className: "block-editor-patterns__grid-pagination-wrapper", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, { variant: "muted", children: // translators: %s: Total number of patterns. (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %s: Total number of patterns. (0,external_wp_i18n_namespaceObject._n)('%s item', '%s items', totalItems), totalItems) }), numPages > 1 && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { expanded: false, spacing: 3, justify: "flex-start", className: "block-editor-patterns__grid-pagination", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { expanded: false, spacing: 1, className: "block-editor-patterns__grid-pagination-previous", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { variant: "tertiary", onClick: () => changePage(1), disabled: currentPage === 1, "aria-label": (0,external_wp_i18n_namespaceObject.__)('First page'), __experimentalIsFocusable: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { children: "\xAB" }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { variant: "tertiary", onClick: () => changePage(currentPage - 1), disabled: currentPage === 1, "aria-label": (0,external_wp_i18n_namespaceObject.__)('Previous page'), __experimentalIsFocusable: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { children: "\u2039" }) })] }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, { variant: "muted", children: (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %1$s: Current page number, %2$s: Total number of pages. (0,external_wp_i18n_namespaceObject._x)('%1$s of %2$s', 'paging'), currentPage, numPages) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { expanded: false, spacing: 1, className: "block-editor-patterns__grid-pagination-next", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { variant: "tertiary", onClick: () => changePage(currentPage + 1), disabled: currentPage === numPages, "aria-label": (0,external_wp_i18n_namespaceObject.__)('Next page'), __experimentalIsFocusable: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { children: "\u203A" }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { variant: "tertiary", onClick: () => changePage(numPages), disabled: currentPage === numPages, "aria-label": (0,external_wp_i18n_namespaceObject.__)('Last page'), size: "default", __experimentalIsFocusable: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", { children: "\xBB" }) })] })] })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-patterns-list/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const { CompositeV2: block_patterns_list_Composite, CompositeItemV2: block_patterns_list_CompositeItem, useCompositeStoreV2: block_patterns_list_useCompositeStore } = unlock(external_wp_components_namespaceObject.privateApis); const WithToolTip = ({ showTooltip, title, children }) => { if (showTooltip) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Tooltip, { text: title, children: children }); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: children }); }; function BlockPattern({ id, isDraggable, pattern, onClick, onHover, showTitle = true, showTooltip, category }) { const [isDragging, setIsDragging] = (0,external_wp_element_namespaceObject.useState)(false); const { blocks, viewportWidth } = pattern; const instanceId = (0,external_wp_compose_namespaceObject.useInstanceId)(BlockPattern); const descriptionId = `block-editor-block-patterns-list__item-description-${instanceId}`; // When we have a selected category and the pattern is draggable, we need to update the // pattern's categories in metadata to only contain the selected category, and pass this to // InserterDraggableBlocks component. We do that because we use this information for pattern // shuffling and it makes more sense to show only the ones from the initially selected category during insertion. const patternBlocks = (0,external_wp_element_namespaceObject.useMemo)(() => { if (!category || !isDraggable) { return blocks; } return (blocks !== null && blocks !== void 0 ? blocks : []).map(block => { const clonedBlock = (0,external_wp_blocks_namespaceObject.cloneBlock)(block); if (clonedBlock.attributes.metadata?.categories?.includes(category)) { clonedBlock.attributes.metadata.categories = [category]; } return clonedBlock; }); }, [blocks, isDraggable, category]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_draggable_blocks, { isEnabled: isDraggable, blocks: patternBlocks, pattern: pattern, children: ({ draggable, onDragStart, onDragEnd }) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-patterns-list__list-item", draggable: draggable, onDragStart: event => { setIsDragging(true); if (onDragStart) { onHover?.(null); onDragStart(event); } }, onDragEnd: event => { setIsDragging(false); if (onDragEnd) { onDragEnd(event); } }, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(WithToolTip, { showTooltip: showTooltip && !pattern.type !== INSERTER_PATTERN_TYPES.user, title: pattern.title, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(block_patterns_list_CompositeItem, { render: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { role: "option", "aria-label": pattern.title, "aria-describedby": pattern.description ? descriptionId : undefined, className: dist_clsx('block-editor-block-patterns-list__item', { 'block-editor-block-patterns-list__list-item-synced': pattern.type === INSERTER_PATTERN_TYPES.user && !pattern.syncStatus }) }), id: id, onClick: () => { onClick(pattern, blocks); onHover?.(null); }, onMouseEnter: () => { if (isDragging) { return; } onHover?.(pattern); }, onMouseLeave: () => onHover?.(null), children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_preview, { blocks: blocks, viewportWidth: viewportWidth }), showTitle && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { className: "block-editor-patterns__pattern-details", spacing: 2, children: [pattern.type === INSERTER_PATTERN_TYPES.user && !pattern.syncStatus && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-patterns__pattern-icon-wrapper", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_icon, { className: "block-editor-patterns__pattern-icon", icon: library_symbol }) }), (!showTooltip || pattern.type === INSERTER_PATTERN_TYPES.user) && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-patterns-list__item-title", children: pattern.title })] }), !!pattern.description && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.VisuallyHidden, { id: descriptionId, children: pattern.description })] }) }) }) }); } function BlockPatternPlaceholder() { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-patterns-list__item is-placeholder" }); } function BlockPatternsList({ isDraggable, blockPatterns, shownPatterns, onHover, onClickPattern, orientation, label = (0,external_wp_i18n_namespaceObject.__)('Block patterns'), category, showTitle = true, showTitlesAsTooltip, pagingProps }, ref) { const compositeStore = block_patterns_list_useCompositeStore({ orientation }); const { setActiveId } = compositeStore; (0,external_wp_element_namespaceObject.useEffect)(() => { // We reset the active composite item whenever the // available patterns change, to make sure that // focus is put back to the start. setActiveId(undefined); }, [setActiveId, shownPatterns, blockPatterns]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(block_patterns_list_Composite, { store: compositeStore, role: "listbox", className: "block-editor-block-patterns-list", "aria-label": label, ref: ref, children: [blockPatterns.map(pattern => { const isShown = shownPatterns.includes(pattern); return isShown ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockPattern, { id: pattern.name, pattern: pattern, onClick: onClickPattern, onHover: onHover, isDraggable: isDraggable, showTitle: showTitle, showTooltip: showTitlesAsTooltip, category: category }, pattern.name) : /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockPatternPlaceholder, {}, pattern.name); }), pagingProps && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Pagination, { ...pagingProps })] }); } /* harmony default export */ const block_patterns_list = ((0,external_wp_element_namespaceObject.forwardRef)(BlockPatternsList)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/hooks/use-insertion-point.js /** * WordPress dependencies */ /** * Internal dependencies */ function getIndex({ destinationRootClientId, destinationIndex, rootClientId, registry }) { if (rootClientId === destinationRootClientId) { return destinationIndex; } const parents = ['', ...registry.select(store).getBlockParents(destinationRootClientId), destinationRootClientId]; const parentIndex = parents.indexOf(rootClientId); if (parentIndex !== -1) { return registry.select(store).getBlockIndex(parents[parentIndex + 1]) + 1; } return registry.select(store).getBlockOrder(rootClientId).length; } /** * @typedef WPInserterConfig * * @property {string=} rootClientId If set, insertion will be into the * block with this ID. * @property {number=} insertionIndex If set, insertion will be into this * explicit position. * @property {string=} clientId If set, insertion will be after the * block with this ID. * @property {boolean=} isAppender Whether the inserter is an appender * or not. * @property {Function=} onSelect Called after insertion. */ /** * Returns the insertion point state given the inserter config. * * @param {WPInserterConfig} config Inserter Config. * @return {Array} Insertion Point State (rootClientID, onInsertBlocks and onToggle). */ function useInsertionPoint({ rootClientId = '', insertionIndex, clientId, isAppender, onSelect, shouldFocusBlock = true, selectBlockOnInsert = true }) { const registry = (0,external_wp_data_namespaceObject.useRegistry)(); const { getSelectedBlock } = (0,external_wp_data_namespaceObject.useSelect)(store); const { destinationRootClientId, destinationIndex } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getSelectedBlockClientId, getBlockRootClientId, getBlockIndex, getBlockOrder } = select(store); const selectedBlockClientId = getSelectedBlockClientId(); let _destinationRootClientId = rootClientId; let _destinationIndex; if (insertionIndex !== undefined) { // Insert into a specific index. _destinationIndex = insertionIndex; } else if (clientId) { // Insert after a specific client ID. _destinationIndex = getBlockIndex(clientId); } else if (!isAppender && selectedBlockClientId) { _destinationRootClientId = getBlockRootClientId(selectedBlockClientId); _destinationIndex = getBlockIndex(selectedBlockClientId) + 1; } else { // Insert at the end of the list. _destinationIndex = getBlockOrder(_destinationRootClientId).length; } return { destinationRootClientId: _destinationRootClientId, destinationIndex: _destinationIndex }; }, [rootClientId, insertionIndex, clientId, isAppender]); const { replaceBlocks, insertBlocks, showInsertionPoint, hideInsertionPoint, setLastFocus } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store)); const onInsertBlocks = (0,external_wp_element_namespaceObject.useCallback)((blocks, meta, shouldForceFocusBlock = false, _rootClientId) => { // When we are trying to move focus or select a new block on insert, we also // need to clear the last focus to avoid the focus being set to the wrong block // when tabbing back into the canvas if the block was added from outside the // editor canvas. if (shouldForceFocusBlock || shouldFocusBlock || selectBlockOnInsert) { setLastFocus(null); } const selectedBlock = getSelectedBlock(); if (!isAppender && selectedBlock && (0,external_wp_blocks_namespaceObject.isUnmodifiedDefaultBlock)(selectedBlock)) { replaceBlocks(selectedBlock.clientId, blocks, null, shouldFocusBlock || shouldForceFocusBlock ? 0 : null, meta); } else { insertBlocks(blocks, isAppender || _rootClientId === undefined ? destinationIndex : getIndex({ destinationRootClientId, destinationIndex, rootClientId: _rootClientId, registry }), isAppender || _rootClientId === undefined ? destinationRootClientId : _rootClientId, selectBlockOnInsert, shouldFocusBlock || shouldForceFocusBlock ? 0 : null, meta); } const blockLength = Array.isArray(blocks) ? blocks.length : 1; const message = (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %d: the name of the block that has been added (0,external_wp_i18n_namespaceObject._n)('%d block added.', '%d blocks added.', blockLength), blockLength); (0,external_wp_a11y_namespaceObject.speak)(message); if (onSelect) { onSelect(blocks); } }, [isAppender, getSelectedBlock, replaceBlocks, insertBlocks, destinationRootClientId, destinationIndex, onSelect, shouldFocusBlock, selectBlockOnInsert]); const onToggleInsertionPoint = (0,external_wp_element_namespaceObject.useCallback)(item => { if (item?.hasOwnProperty('rootClientId')) { showInsertionPoint(item.rootClientId, getIndex({ destinationRootClientId, destinationIndex, rootClientId: item.rootClientId, registry })); } else { hideInsertionPoint(); } }, [showInsertionPoint, hideInsertionPoint, destinationRootClientId, destinationIndex]); return [destinationRootClientId, onInsertBlocks, onToggleInsertionPoint]; } /* harmony default export */ const use_insertion_point = (useInsertionPoint); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/hooks/use-patterns-state.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Retrieves the block patterns inserter state. * * @param {Function} onInsert function called when inserter a list of blocks. * @param {string=} rootClientId Insertion's root client ID. * * @param {string} selectedCategory The selected pattern category. * @return {Array} Returns the patterns state. (patterns, categories, onSelect handler) */ const usePatternsState = (onInsert, rootClientId, selectedCategory) => { const { patternCategories, patterns, userPatternCategories } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { __experimentalGetAllowedPatterns, getSettings } = select(store); const { __experimentalUserPatternCategories, __experimentalBlockPatternCategories } = getSettings(); return { patterns: __experimentalGetAllowedPatterns(rootClientId), userPatternCategories: __experimentalUserPatternCategories, patternCategories: __experimentalBlockPatternCategories }; }, [rootClientId]); const allCategories = (0,external_wp_element_namespaceObject.useMemo)(() => { const categories = [...patternCategories]; userPatternCategories?.forEach(userCategory => { if (!categories.find(existingCategory => existingCategory.name === userCategory.name)) { categories.push(userCategory); } }); return categories; }, [patternCategories, userPatternCategories]); const { createSuccessNotice } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store); const onClickPattern = (0,external_wp_element_namespaceObject.useCallback)((pattern, blocks) => { const patternBlocks = pattern.type === INSERTER_PATTERN_TYPES.user && pattern.syncStatus !== 'unsynced' ? [(0,external_wp_blocks_namespaceObject.createBlock)('core/block', { ref: pattern.id })] : blocks; onInsert((patternBlocks !== null && patternBlocks !== void 0 ? patternBlocks : []).map(block => { const clonedBlock = (0,external_wp_blocks_namespaceObject.cloneBlock)(block); if (clonedBlock.attributes.metadata?.categories?.includes(selectedCategory)) { clonedBlock.attributes.metadata.categories = [selectedCategory]; } return clonedBlock; }), pattern.name); createSuccessNotice((0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %s: block pattern title. */ (0,external_wp_i18n_namespaceObject.__)('Block pattern "%s" inserted.'), pattern.title), { type: 'snackbar', id: 'block-pattern-inserted-notice' }); }, [createSuccessNotice, onInsert, selectedCategory]); return [patterns, allCategories, onClickPattern]; }; /* harmony default export */ const use_patterns_state = (usePatternsState); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/hooks/use-patterns-paging.js /** * WordPress dependencies */ const PAGE_SIZE = 20; const INITIAL_INSERTER_RESULTS = 5; /** * Supplies values needed to page the patterns list client side. * * @param {Array} currentCategoryPatterns An array of the current patterns to display. * @param {string} currentCategory The currently selected category. * @param {Object} scrollContainerRef Ref of container to to find scroll container for when moving between pages. * @param {string} currentFilter The currently search filter. * * @return {Object} Returns the relevant paging values. (totalItems, categoryPatternsList, numPages, changePage, currentPage) */ function usePatternsPaging(currentCategoryPatterns, currentCategory, scrollContainerRef, currentFilter = '') { const [currentPage, setCurrentPage] = (0,external_wp_element_namespaceObject.useState)(1); const previousCategory = (0,external_wp_compose_namespaceObject.usePrevious)(currentCategory); const previousFilter = (0,external_wp_compose_namespaceObject.usePrevious)(currentFilter); if ((previousCategory !== currentCategory || previousFilter !== currentFilter) && currentPage !== 1) { setCurrentPage(1); } const totalItems = currentCategoryPatterns.length; const pageIndex = currentPage - 1; const categoryPatterns = (0,external_wp_element_namespaceObject.useMemo)(() => { return currentCategoryPatterns.slice(pageIndex * PAGE_SIZE, pageIndex * PAGE_SIZE + PAGE_SIZE); }, [pageIndex, currentCategoryPatterns]); const categoryPatternsAsyncList = (0,external_wp_compose_namespaceObject.useAsyncList)(categoryPatterns, { step: INITIAL_INSERTER_RESULTS }); const numPages = Math.ceil(currentCategoryPatterns.length / PAGE_SIZE); const changePage = page => { const scrollContainer = (0,external_wp_dom_namespaceObject.getScrollContainer)(scrollContainerRef?.current); scrollContainer?.scrollTo(0, 0); setCurrentPage(page); }; (0,external_wp_element_namespaceObject.useEffect)(function scrollToTopOnCategoryChange() { const scrollContainer = (0,external_wp_dom_namespaceObject.getScrollContainer)(scrollContainerRef?.current); scrollContainer?.scrollTo(0, 0); }, [currentCategory, scrollContainerRef]); return { totalItems, categoryPatterns, categoryPatternsAsyncList, numPages, changePage, currentPage }; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-explorer/pattern-list.js /** * WordPress dependencies */ /** * Internal dependencies */ function PatternsListHeader({ filterValue, filteredBlockPatternsLength }) { if (!filterValue) { return null; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalHeading, { level: 2, lineHeight: "48px", className: "block-editor-block-patterns-explorer__search-results-count", children: (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %d: number of patterns. */ (0,external_wp_i18n_namespaceObject._n)('%d pattern found', '%d patterns found', filteredBlockPatternsLength), filteredBlockPatternsLength) }); } function PatternList({ searchValue, selectedCategory, patternCategories, rootClientId }) { const container = (0,external_wp_element_namespaceObject.useRef)(); const debouncedSpeak = (0,external_wp_compose_namespaceObject.useDebounce)(external_wp_a11y_namespaceObject.speak, 500); const [destinationRootClientId, onInsertBlocks] = use_insertion_point({ rootClientId, shouldFocusBlock: true }); const [patterns,, onClickPattern] = use_patterns_state(onInsertBlocks, destinationRootClientId, selectedCategory); const registeredPatternCategories = (0,external_wp_element_namespaceObject.useMemo)(() => patternCategories.map(patternCategory => patternCategory.name), [patternCategories]); const filteredBlockPatterns = (0,external_wp_element_namespaceObject.useMemo)(() => { const filteredPatterns = patterns.filter(pattern => { if (selectedCategory === allPatternsCategory.name) { return true; } if (selectedCategory === myPatternsCategory.name && pattern.type === INSERTER_PATTERN_TYPES.user) { return true; } if (selectedCategory === 'uncategorized') { const hasKnownCategory = pattern.categories.some(category => registeredPatternCategories.includes(category)); return !pattern.categories?.length || !hasKnownCategory; } return pattern.categories?.includes(selectedCategory); }); if (!searchValue) { return filteredPatterns; } return searchItems(filteredPatterns, searchValue); }, [searchValue, patterns, selectedCategory, registeredPatternCategories]); // Announce search results on change. (0,external_wp_element_namespaceObject.useEffect)(() => { if (!searchValue) { return; } const count = filteredBlockPatterns.length; const resultsFoundMessage = (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %d: number of results. */ (0,external_wp_i18n_namespaceObject._n)('%d result found.', '%d results found.', count), count); debouncedSpeak(resultsFoundMessage); }, [searchValue, debouncedSpeak, filteredBlockPatterns.length]); const pagingProps = usePatternsPaging(filteredBlockPatterns, selectedCategory, container); // Reset page when search value changes. const [previousSearchValue, setPreviousSearchValue] = (0,external_wp_element_namespaceObject.useState)(searchValue); if (searchValue !== previousSearchValue) { setPreviousSearchValue(searchValue); pagingProps.changePage(1); } const hasItems = !!filteredBlockPatterns?.length; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-block-patterns-explorer__list", ref: container, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternsListHeader, { filterValue: searchValue, filteredBlockPatternsLength: filteredBlockPatterns.length }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_listbox, { children: hasItems && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_patterns_list, { shownPatterns: pagingProps.categoryPatternsAsyncList, blockPatterns: pagingProps.categoryPatterns, onClickPattern: onClickPattern, isDraggable: false }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Pagination, { ...pagingProps })] }) })] }); } /* harmony default export */ const pattern_list = (PatternList); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-tab/use-pattern-categories.js /** * WordPress dependencies */ /** * Internal dependencies */ function hasRegisteredCategory(pattern, allCategories) { if (!pattern.categories || !pattern.categories.length) { return false; } return pattern.categories.some(cat => allCategories.some(category => category.name === cat)); } function usePatternCategories(rootClientId, sourceFilter = 'all') { const [patterns, allCategories] = use_patterns_state(undefined, rootClientId); const filteredPatterns = (0,external_wp_element_namespaceObject.useMemo)(() => sourceFilter === 'all' ? patterns : patterns.filter(pattern => !isPatternFiltered(pattern, sourceFilter)), [sourceFilter, patterns]); // Remove any empty categories. const populatedCategories = (0,external_wp_element_namespaceObject.useMemo)(() => { const categories = allCategories.filter(category => filteredPatterns.some(pattern => pattern.categories?.includes(category.name))).sort((a, b) => a.label.localeCompare(b.label)); if (filteredPatterns.some(pattern => !hasRegisteredCategory(pattern, allCategories)) && !categories.find(category => category.name === 'uncategorized')) { categories.push({ name: 'uncategorized', label: (0,external_wp_i18n_namespaceObject._x)('Uncategorized') }); } if (filteredPatterns.some(pattern => pattern.type === INSERTER_PATTERN_TYPES.user)) { categories.unshift(myPatternsCategory); } if (filteredPatterns.length > 0) { categories.unshift({ name: allPatternsCategory.name, label: allPatternsCategory.label }); } (0,external_wp_a11y_namespaceObject.speak)((0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %d: number of categories . */ (0,external_wp_i18n_namespaceObject._n)('%d category button displayed.', '%d category buttons displayed.', categories.length), categories.length)); return categories; }, [allCategories, filteredPatterns]); return populatedCategories; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-explorer/index.js /** * WordPress dependencies */ /** * Internal dependencies */ function PatternsExplorer({ initialCategory, rootClientId }) { const [searchValue, setSearchValue] = (0,external_wp_element_namespaceObject.useState)(''); const [selectedCategory, setSelectedCategory] = (0,external_wp_element_namespaceObject.useState)(initialCategory?.name); const patternCategories = usePatternCategories(rootClientId); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-block-patterns-explorer", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(pattern_explorer_sidebar, { selectedCategory: selectedCategory, patternCategories: patternCategories, onClickCategory: setSelectedCategory, searchValue: searchValue, setSearchValue: setSearchValue }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(pattern_list, { searchValue: searchValue, selectedCategory: selectedCategory, patternCategories: patternCategories, rootClientId: rootClientId })] }); } function PatternsExplorerModal({ onModalClose, ...restProps }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, { title: (0,external_wp_i18n_namespaceObject.__)('Patterns'), onRequestClose: onModalClose, isFullScreen: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternsExplorer, { ...restProps }) }); } /* harmony default export */ const block_patterns_explorer = (PatternsExplorerModal); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/mobile-tab-navigation.js /** * WordPress dependencies */ function ScreenHeader({ title }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalVStack, { spacing: 0, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalView, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalSpacer, { marginBottom: 0, paddingX: 4, paddingY: 3, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { spacing: 2, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalNavigatorBackButton, { style: // TODO: This style override is also used in ToolsPanelHeader. // It should be supported out-of-the-box by Button. { minWidth: 24, padding: 0 }, icon: (0,external_wp_i18n_namespaceObject.isRTL)() ? chevron_right : chevron_left, size: "small", label: (0,external_wp_i18n_namespaceObject.__)('Back') }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalSpacer, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalHeading, { level: 5, children: title }) })] }) }) }) }); } function MobileTabNavigation({ categories, children }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalNavigatorProvider, { initialPath: "/", className: "block-editor-inserter__mobile-tab-navigation", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalNavigatorScreen, { path: "/", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalItemGroup, { children: categories.map(category => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalNavigatorButton, { path: `/category/${category.name}`, as: external_wp_components_namespaceObject.__experimentalItem, isAction: true, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexBlock, { children: category.label }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_icon, { icon: (0,external_wp_i18n_namespaceObject.isRTL)() ? chevron_left : chevron_right })] }) }, category.name)) }) }), categories.map(category => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalNavigatorScreen, { path: `/category/${category.name}`, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ScreenHeader, { title: (0,external_wp_i18n_namespaceObject.__)('Back') }), children(category)] }, category.name))] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-tab/patterns-filter.js /** * WordPress dependencies */ /** * Internal dependencies */ const getShouldDisableSyncFilter = sourceFilter => sourceFilter !== 'all'; const getShouldDisableNonUserSources = category => { return category.name === myPatternsCategory.name; }; function PatternsFilter({ setPatternSyncFilter, setPatternSourceFilter, patternSyncFilter, patternSourceFilter, scrollContainerRef, category }) { // If the category is `myPatterns` then we need to set the source filter to `user`, but // we do this by deriving from props rather than calling setPatternSourceFilter otherwise // the user may be confused when switching to another category if the haven't explicity set // this filter themselves. const currentPatternSourceFilter = category.name === myPatternsCategory.name ? INSERTER_PATTERN_TYPES.user : patternSourceFilter; // We need to disable the sync filter option if the source filter is not 'all' or 'user' // otherwise applying them will just result in no patterns being shown. const shouldDisableSyncFilter = getShouldDisableSyncFilter(currentPatternSourceFilter); // We also need to disable the directory and theme source filter options if the category // is `myPatterns` otherwise applying them will also just result in no patterns being shown. const shouldDisableNonUserSources = getShouldDisableNonUserSources(category); const patternSyncMenuOptions = (0,external_wp_element_namespaceObject.useMemo)(() => [{ value: 'all', label: (0,external_wp_i18n_namespaceObject._x)('All', 'patterns') }, { value: INSERTER_SYNC_TYPES.full, label: (0,external_wp_i18n_namespaceObject._x)('Synced', 'patterns'), disabled: shouldDisableSyncFilter }, { value: INSERTER_SYNC_TYPES.unsynced, label: (0,external_wp_i18n_namespaceObject._x)('Not synced', 'patterns'), disabled: shouldDisableSyncFilter }], [shouldDisableSyncFilter]); const patternSourceMenuOptions = (0,external_wp_element_namespaceObject.useMemo)(() => [{ value: 'all', label: (0,external_wp_i18n_namespaceObject._x)('All', 'patterns'), disabled: shouldDisableNonUserSources }, { value: INSERTER_PATTERN_TYPES.directory, label: (0,external_wp_i18n_namespaceObject.__)('Pattern Directory'), disabled: shouldDisableNonUserSources }, { value: INSERTER_PATTERN_TYPES.theme, label: (0,external_wp_i18n_namespaceObject.__)('Theme & Plugins'), disabled: shouldDisableNonUserSources }, { value: INSERTER_PATTERN_TYPES.user, label: (0,external_wp_i18n_namespaceObject.__)('User') }], [shouldDisableNonUserSources]); function handleSetSourceFilterChange(newSourceFilter) { setPatternSourceFilter(newSourceFilter); if (getShouldDisableSyncFilter(newSourceFilter)) { setPatternSyncFilter('all'); } } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.DropdownMenu, { popoverProps: { placement: 'right-end' }, label: (0,external_wp_i18n_namespaceObject.__)('Filter patterns'), toggleProps: { size: 'compact' }, icon: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_icon, { icon: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.SVG, { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Path, { d: "M10 17.5H14V16H10V17.5ZM6 6V7.5H18V6H6ZM8 12.5H16V11H8V12.5Z", fill: "currentColor" }) }) }), children: () => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuGroup, { label: (0,external_wp_i18n_namespaceObject.__)('Source'), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItemsChoice, { choices: patternSourceMenuOptions, onSelect: value => { handleSetSourceFilterChange(value); scrollContainerRef.current?.scrollTo(0, 0); }, value: currentPatternSourceFilter }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuGroup, { label: (0,external_wp_i18n_namespaceObject.__)('Type'), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItemsChoice, { choices: patternSyncMenuOptions, onSelect: value => { setPatternSyncFilter(value); scrollContainerRef.current?.scrollTo(0, 0); }, value: patternSyncFilter }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-tool-selector__help", children: (0,external_wp_element_namespaceObject.createInterpolateElement)((0,external_wp_i18n_namespaceObject.__)('Patterns are available from the <Link>WordPress.org Pattern Directory</Link>, bundled in the active theme, or created by users on this site. Only patterns created on this site can be synced.'), { Link: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ExternalLink, { href: (0,external_wp_i18n_namespaceObject.__)('https://wordpress.org/patterns/') }) }) })] }) }) }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-tab/pattern-category-previews.js /** * WordPress dependencies */ /** * Internal dependencies */ const pattern_category_previews_noop = () => {}; function PatternCategoryPreviews({ rootClientId, onInsert, onHover = pattern_category_previews_noop, category, showTitlesAsTooltip }) { const [allPatterns,, onClickPattern] = use_patterns_state(onInsert, rootClientId, category?.name); const [patternSyncFilter, setPatternSyncFilter] = (0,external_wp_element_namespaceObject.useState)('all'); const [patternSourceFilter, setPatternSourceFilter] = (0,external_wp_element_namespaceObject.useState)('all'); const availableCategories = usePatternCategories(rootClientId, patternSourceFilter); const scrollContainerRef = (0,external_wp_element_namespaceObject.useRef)(); const currentCategoryPatterns = (0,external_wp_element_namespaceObject.useMemo)(() => allPatterns.filter(pattern => { if (isPatternFiltered(pattern, patternSourceFilter, patternSyncFilter)) { return false; } if (category.name === allPatternsCategory.name) { return true; } if (category.name === myPatternsCategory.name && pattern.type === INSERTER_PATTERN_TYPES.user) { return true; } if (category.name === 'uncategorized') { // The uncategorized category should show all the patterns without any category... if (!pattern.categories) { return true; } // ...or with no available category. return !pattern.categories.some(catName => availableCategories.some(c => c.name === catName)); } return pattern.categories?.includes(category.name); }), [allPatterns, availableCategories, category.name, patternSourceFilter, patternSyncFilter]); const pagingProps = usePatternsPaging(currentCategoryPatterns, category, scrollContainerRef); const { changePage } = pagingProps; // Hide block pattern preview on unmount. // eslint-disable-next-line react-hooks/exhaustive-deps (0,external_wp_element_namespaceObject.useEffect)(() => () => onHover(null), []); const onSetPatternSyncFilter = (0,external_wp_element_namespaceObject.useCallback)(value => { setPatternSyncFilter(value); changePage(1); }, [setPatternSyncFilter, changePage]); const onSetPatternSourceFilter = (0,external_wp_element_namespaceObject.useCallback)(value => { setPatternSourceFilter(value); changePage(1); }, [setPatternSourceFilter, changePage]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, { spacing: 2, className: "block-editor-inserter__patterns-category-panel-header", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexBlock, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalHeading, { className: "block-editor-inserter__patterns-category-panel-title", size: 13, level: 4, as: "div", children: category.label }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternsFilter, { patternSyncFilter: patternSyncFilter, patternSourceFilter: patternSourceFilter, setPatternSyncFilter: onSetPatternSyncFilter, setPatternSourceFilter: onSetPatternSourceFilter, scrollContainerRef: scrollContainerRef, category: category })] }), !currentCategoryPatterns.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, { variant: "muted", className: "block-editor-inserter__patterns-category-no-results", children: (0,external_wp_i18n_namespaceObject.__)('No results found') })] }), currentCategoryPatterns.length > 0 && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_patterns_list, { ref: scrollContainerRef, shownPatterns: pagingProps.categoryPatternsAsyncList, blockPatterns: pagingProps.categoryPatterns, onClickPattern: onClickPattern, onHover: onHover, label: category.label, orientation: "vertical", category: category.name, isDraggable: true, showTitlesAsTooltip: showTitlesAsTooltip, patternFilter: patternSourceFilter, pagingProps: pagingProps })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/category-tabs/index.js /** * WordPress dependencies */ /** * Internal dependencies */ const { Tabs: category_tabs_Tabs } = unlock(external_wp_components_namespaceObject.privateApis); function CategoryTabs({ categories, selectedCategory, onSelectCategory, children }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(category_tabs_Tabs, { className: "block-editor-inserter__category-tabs", selectOnMove: false, selectedTabId: selectedCategory ? selectedCategory.name : null, orientation: "vertical", onSelect: categoryId => { // Pass the full category object onSelectCategory(categories.find(category => category.name === categoryId)); }, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(category_tabs_Tabs.TabList, { className: "block-editor-inserter__category-tablist", children: categories.map(category => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(category_tabs_Tabs.Tab, { tabId: category.name, className: "block-editor-inserter__category-tab", "aria-label": category.label, "aria-current": category === selectedCategory ? 'true' : undefined, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexBlock, { children: category.label }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_icon, { icon: (0,external_wp_i18n_namespaceObject.isRTL)() ? chevron_left : chevron_right })] }) }, category.name)) }), categories.map(category => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(category_tabs_Tabs.TabPanel, { tabId: category.name, focusable: false, className: "block-editor-inserter__category-panel", children: children }, category.name))] }); } /* harmony default export */ const category_tabs = (CategoryTabs); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-tab/index.js /** * WordPress dependencies */ /** * Internal dependencies */ function BlockPatternsTab({ onSelectCategory, selectedCategory, onInsert, rootClientId, children }) { const [showPatternsExplorer, setShowPatternsExplorer] = (0,external_wp_element_namespaceObject.useState)(false); const categories = usePatternCategories(rootClientId); const isMobile = (0,external_wp_compose_namespaceObject.useViewportMatch)('medium', '<'); const isResolvingPatterns = (0,external_wp_data_namespaceObject.useSelect)(select => unlock(select(store)).isResolvingPatterns(), []); if (isResolvingPatterns) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__patterns-loading", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Spinner, {}) }); } if (!categories.length) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(no_results, {}); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [!isMobile && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__block-patterns-tabs-container", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(category_tabs, { categories: categories, selectedCategory: selectedCategory, onSelectCategory: onSelectCategory, children: children }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { className: "block-editor-inserter__patterns-explore-button", onClick: () => setShowPatternsExplorer(true), variant: "secondary", children: (0,external_wp_i18n_namespaceObject.__)('Explore all patterns') })] }), isMobile && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MobileTabNavigation, { categories: categories, children: category => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__category-panel", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoryPreviews, { onInsert: onInsert, rootClientId: rootClientId, category: category, showTitlesAsTooltip: false }, category.name) }) }), showPatternsExplorer && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_patterns_explorer, { initialCategory: selectedCategory || categories[0], patternCategories: categories, onModalClose: () => setShowPatternsExplorer(false), rootClientId: rootClientId })] }); } /* harmony default export */ const block_patterns_tab = (BlockPatternsTab); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/block-patterns-tab/pattern-category-preview-panel.js /** * Internal dependencies */ function PatternCategoryPreviewPanelInner({ rootClientId, onInsert, onHover, category, showTitlesAsTooltip, patternFilter }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoryPreviews, { rootClientId: rootClientId, onInsert: onInsert, onHover: onHover, category: category, showTitlesAsTooltip: showTitlesAsTooltip, patternFilter: patternFilter }, category.name); } function PatternCategoryPreviewPanelWithZoomOut(props) { useZoomOut(); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoryPreviewPanelInner, { ...props }); } function PatternCategoryPreviewPanel(props) { // When the pattern panel is showing, we want to use zoom out mode if (window.__experimentalEnableZoomedOutPatternsTab) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoryPreviewPanelWithZoomOut, { ...props }); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoryPreviewPanelInner, { ...props }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/external.js /** * WordPress dependencies */ const external = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, { d: "M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z" }) }); /* harmony default export */ const library_external = (external); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/media-tab/utils.js /** * WordPress dependencies */ const mediaTypeTag = { image: 'img', video: 'video', audio: 'audio' }; /** @typedef {import('./hooks').InserterMediaItem} InserterMediaItem */ /** * Creates a block and a preview element from a media object. * * @param {InserterMediaItem} media The media object to create the block from. * @param {('image'|'audio'|'video')} mediaType The media type to create the block for. * @return {[WPBlock, JSX.Element]} An array containing the block and the preview element. */ function getBlockAndPreviewFromMedia(media, mediaType) { // Add the common attributes between the different media types. const attributes = { id: media.id || undefined, caption: media.caption || undefined }; const mediaSrc = media.url; const alt = media.alt || undefined; if (mediaType === 'image') { attributes.url = mediaSrc; attributes.alt = alt; } else if (['video', 'audio'].includes(mediaType)) { attributes.src = mediaSrc; } const PreviewTag = mediaTypeTag[mediaType]; const preview = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PreviewTag, { src: media.previewUrl || mediaSrc, alt: alt, controls: mediaType === 'audio' ? true : undefined, inert: "true", onError: ({ currentTarget }) => { // Fall back to the media source if the preview cannot be loaded. if (currentTarget.src === media.previewUrl) { currentTarget.src = mediaSrc; } } }); return [(0,external_wp_blocks_namespaceObject.createBlock)(`core/${mediaType}`, attributes), preview]; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/media-tab/media-preview.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const ALLOWED_MEDIA_TYPES = ['image']; const MAXIMUM_TITLE_LENGTH = 25; const MEDIA_OPTIONS_POPOVER_PROPS = { position: 'bottom left', className: 'block-editor-inserter__media-list__item-preview-options__popover' }; const { CompositeItemV2: media_preview_CompositeItem } = unlock(external_wp_components_namespaceObject.privateApis); function MediaPreviewOptions({ category, media }) { if (!category.getReportUrl) { return null; } const reportUrl = category.getReportUrl(media); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.DropdownMenu, { className: "block-editor-inserter__media-list__item-preview-options", label: (0,external_wp_i18n_namespaceObject.__)('Options'), popoverProps: MEDIA_OPTIONS_POPOVER_PROPS, icon: more_vertical, children: () => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuGroup, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, { onClick: () => window.open(reportUrl, '_blank').focus(), icon: library_external, children: (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %s: The media type to report e.g: "image", "video", "audio" */ (0,external_wp_i18n_namespaceObject.__)('Report %s'), category.mediaType) }) }) }); } function InsertExternalImageModal({ onClose, onSubmit }) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.Modal, { title: (0,external_wp_i18n_namespaceObject.__)('Insert external image'), onRequestClose: onClose, className: "block-editor-inserter-media-tab-media-preview-inserter-external-image-modal", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, { spacing: 3, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("p", { children: (0,external_wp_i18n_namespaceObject.__)('This image cannot be uploaded to your Media Library, but it can still be inserted as an external image.') }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("p", { children: (0,external_wp_i18n_namespaceObject.__)('External images can be removed by the external provider without warning and could even have legal compliance issues related to privacy legislation.') })] }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.Flex, { className: "block-editor-block-lock-modal__actions", justify: "flex-end", expanded: false, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexItem, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { variant: "tertiary", onClick: onClose, children: (0,external_wp_i18n_namespaceObject.__)('Cancel') }) }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FlexItem, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { variant: "primary", onClick: onSubmit, children: (0,external_wp_i18n_namespaceObject.__)('Insert') }) })] })] }); } function MediaPreview({ media, onClick, category }) { const [showExternalUploadModal, setShowExternalUploadModal] = (0,external_wp_element_namespaceObject.useState)(false); const [isHovered, setIsHovered] = (0,external_wp_element_namespaceObject.useState)(false); const [isInserting, setIsInserting] = (0,external_wp_element_namespaceObject.useState)(false); const [block, preview] = (0,external_wp_element_namespaceObject.useMemo)(() => getBlockAndPreviewFromMedia(media, category.mediaType), [media, category.mediaType]); const { createErrorNotice, createSuccessNotice } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store); const { getSettings } = (0,external_wp_data_namespaceObject.useSelect)(store); const onMediaInsert = (0,external_wp_element_namespaceObject.useCallback)(previewBlock => { // Prevent multiple uploads when we're in the process of inserting. if (isInserting) { return; } const settings = getSettings(); const clonedBlock = (0,external_wp_blocks_namespaceObject.cloneBlock)(previewBlock); const { id, url, caption } = clonedBlock.attributes; // User has no permission to upload media. if (!id && !settings.mediaUpload) { setShowExternalUploadModal(true); return; } // Media item already exists in library, so just insert it. if (!!id) { onClick(clonedBlock); return; } setIsInserting(true); // Media item does not exist in library, so try to upload it. // Fist fetch the image data. This may fail if the image host // doesn't allow CORS with the domain. // If this happens, we insert the image block using the external // URL and let the user know about the possible implications. window.fetch(url).then(response => response.blob()).then(blob => { settings.mediaUpload({ filesList: [blob], additionalData: { caption }, onFileChange([img]) { if ((0,external_wp_blob_namespaceObject.isBlobURL)(img.url)) { return; } onClick({ ...clonedBlock, attributes: { ...clonedBlock.attributes, id: img.id, url: img.url } }); createSuccessNotice((0,external_wp_i18n_namespaceObject.__)('Image uploaded and inserted.'), { type: 'snackbar' }); setIsInserting(false); }, allowedTypes: ALLOWED_MEDIA_TYPES, onError(message) { createErrorNotice(message, { type: 'snackbar' }); setIsInserting(false); } }); }).catch(() => { setShowExternalUploadModal(true); setIsInserting(false); }); }, [isInserting, getSettings, onClick, createSuccessNotice, createErrorNotice]); const title = typeof media.title === 'string' ? media.title : media.title?.rendered || (0,external_wp_i18n_namespaceObject.__)('no title'); let truncatedTitle; if (title.length > MAXIMUM_TITLE_LENGTH) { const omission = '...'; truncatedTitle = title.slice(0, MAXIMUM_TITLE_LENGTH - omission.length) + omission; } const onMouseEnter = (0,external_wp_element_namespaceObject.useCallback)(() => setIsHovered(true), []); const onMouseLeave = (0,external_wp_element_namespaceObject.useCallback)(() => setIsHovered(false), []); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_draggable_blocks, { isEnabled: true, blocks: [block], children: ({ draggable, onDragStart, onDragEnd }) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: dist_clsx('block-editor-inserter__media-list__list-item', { 'is-hovered': isHovered }), draggable: draggable, onDragStart: onDragStart, onDragEnd: onDragEnd, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Tooltip, { text: truncatedTitle || title, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(media_preview_CompositeItem, { render: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { "aria-label": title, role: "option", className: "block-editor-inserter__media-list__item" }), onClick: () => onMediaInsert(block), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__media-list__item-preview", children: [preview, isInserting && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__media-list__item-preview-spinner", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Spinner, {}) })] }) }) }), !isInserting && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MediaPreviewOptions, { category: category, media: media })] }) }) }), showExternalUploadModal && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(InsertExternalImageModal, { onClose: () => setShowExternalUploadModal(false), onSubmit: () => { onClick((0,external_wp_blocks_namespaceObject.cloneBlock)(block)); createSuccessNotice((0,external_wp_i18n_namespaceObject.__)('Image inserted.'), { type: 'snackbar' }); setShowExternalUploadModal(false); } })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/media-tab/media-list.js /** * WordPress dependencies */ /** * Internal dependencies */ const { CompositeV2: media_list_Composite, useCompositeStoreV2: media_list_useCompositeStore } = unlock(external_wp_components_namespaceObject.privateApis); function MediaList({ mediaList, category, onClick, label = (0,external_wp_i18n_namespaceObject.__)('Media List') }) { const compositeStore = media_list_useCompositeStore(); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(media_list_Composite, { store: compositeStore, role: "listbox", className: "block-editor-inserter__media-list", "aria-label": label, children: mediaList.map((media, index) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MediaPreview, { media: media, category: category, onClick: onClick }, media.id || media.sourceId || index)) }); } /* harmony default export */ const media_list = (MediaList); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/media-tab/hooks.js /** * WordPress dependencies */ /** * Internal dependencies */ /** @typedef {import('../../../store/actions').InserterMediaRequest} InserterMediaRequest */ /** @typedef {import('../../../store/actions').InserterMediaItem} InserterMediaItem */ /** * Fetches media items based on the provided category. * Each media category is responsible for providing a `fetch` function. * * @param {Object} category The media category to fetch results for. * @param {InserterMediaRequest} query The query args to use for the request. * @return {InserterMediaItem[]} The media results. */ function useMediaResults(category, query = {}) { const [mediaList, setMediaList] = (0,external_wp_element_namespaceObject.useState)(); const [isLoading, setIsLoading] = (0,external_wp_element_namespaceObject.useState)(false); // We need to keep track of the last request made because // multiple request can be fired without knowing the order // of resolution, and we need to ensure we are showing // the results of the last request. // In the future we could use AbortController to cancel previous // requests, but we don't for now as it involves adding support // for this to `core-data` package. const lastRequest = (0,external_wp_element_namespaceObject.useRef)(); (0,external_wp_element_namespaceObject.useEffect)(() => { (async () => { const key = JSON.stringify({ category: category.name, ...query }); lastRequest.current = key; setIsLoading(true); setMediaList([]); // Empty the previous results. const _media = await category.fetch?.(query); if (key === lastRequest.current) { setMediaList(_media); setIsLoading(false); } })(); }, [category.name, ...Object.values(query)]); return { mediaList, isLoading }; } function useMediaCategories(rootClientId) { const [categories, setCategories] = (0,external_wp_element_namespaceObject.useState)([]); const inserterMediaCategories = (0,external_wp_data_namespaceObject.useSelect)(select => unlock(select(store)).getInserterMediaCategories(), []); const { canInsertImage, canInsertVideo, canInsertAudio } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { canInsertBlockType } = select(store); return { canInsertImage: canInsertBlockType('core/image', rootClientId), canInsertVideo: canInsertBlockType('core/video', rootClientId), canInsertAudio: canInsertBlockType('core/audio', rootClientId) }; }, [rootClientId]); (0,external_wp_element_namespaceObject.useEffect)(() => { (async () => { const _categories = []; // If `inserterMediaCategories` is not defined in // block editor settings, do not show any media categories. if (!inserterMediaCategories) { return; } // Loop through categories to check if they have at least one media item. const categoriesHaveMedia = new Map(await Promise.all(inserterMediaCategories.map(async category => { // Some sources are external and we don't need to make a request. if (category.isExternalResource) { return [category.name, true]; } let results = []; try { results = await category.fetch({ per_page: 1 }); } catch (e) { // If the request fails, we shallow the error and just don't show // the category, in order to not break the media tab. } return [category.name, !!results.length]; }))); // We need to filter out categories that don't have any media items or // whose corresponding block type is not allowed to be inserted, based // on the category's `mediaType`. const canInsertMediaType = { image: canInsertImage, video: canInsertVideo, audio: canInsertAudio }; inserterMediaCategories.forEach(category => { if (canInsertMediaType[category.mediaType] && categoriesHaveMedia.get(category.name)) { _categories.push(category); } }); if (!!_categories.length) { setCategories(_categories); } })(); }, [canInsertImage, canInsertVideo, canInsertAudio, inserterMediaCategories]); return categories; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/media-tab/media-panel.js /** * WordPress dependencies */ /** * Internal dependencies */ const INITIAL_MEDIA_ITEMS_PER_PAGE = 10; function MediaCategoryPanel({ rootClientId, onInsert, category }) { const [search, setSearch, debouncedSearch] = (0,external_wp_compose_namespaceObject.useDebouncedInput)(); const { mediaList, isLoading } = useMediaResults(category, { per_page: !!debouncedSearch ? 20 : INITIAL_MEDIA_ITEMS_PER_PAGE, search: debouncedSearch }); const baseCssClass = 'block-editor-inserter__media-panel'; const searchLabel = category.labels.search_items || (0,external_wp_i18n_namespaceObject.__)('Search'); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: baseCssClass, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.SearchControl, { className: `${baseCssClass}-search`, onChange: setSearch, value: search, label: searchLabel, placeholder: searchLabel }), isLoading && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: `${baseCssClass}-spinner`, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Spinner, {}) }), !isLoading && !mediaList?.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(no_results, {}), !isLoading && !!mediaList?.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(media_list, { rootClientId: rootClientId, onClick: onInsert, mediaList: mediaList, category: category })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/media-tab/media-tab.js /** * WordPress dependencies */ /** * Internal dependencies */ const media_tab_ALLOWED_MEDIA_TYPES = ['image', 'video', 'audio']; function MediaTab({ rootClientId, selectedCategory, onSelectCategory, onInsert, children }) { const mediaCategories = useMediaCategories(rootClientId); const isMobile = (0,external_wp_compose_namespaceObject.useViewportMatch)('medium', '<'); const baseCssClass = 'block-editor-inserter__media-tabs'; const onSelectMedia = (0,external_wp_element_namespaceObject.useCallback)(media => { if (!media?.url) { return; } const [block] = getBlockAndPreviewFromMedia(media, media.type); onInsert(block); }, [onInsert]); const categories = (0,external_wp_element_namespaceObject.useMemo)(() => mediaCategories.map(mediaCategory => ({ ...mediaCategory, label: mediaCategory.labels.name })), [mediaCategories]); if (!categories.length) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(no_results, {}); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [!isMobile && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: `${baseCssClass}-container`, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(category_tabs, { categories: categories, selectedCategory: selectedCategory, onSelectCategory: onSelectCategory, children: children }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(check, { children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(media_upload, { multiple: false, onSelect: onSelectMedia, allowedTypes: media_tab_ALLOWED_MEDIA_TYPES, render: ({ open }) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { onClick: event => { // Safari doesn't emit a focus event on button elements when // clicked and we need to manually focus the button here. // The reason is that core's Media Library modal explicitly triggers a // focus event and therefore a `blur` event is triggered on a different // element, which doesn't contain the `data-unstable-ignore-focus-outside-for-relatedtarget` // attribute making the Inserter dialog to close. event.target.focus(); open(); }, className: "block-editor-inserter__media-library-button", variant: "secondary", "data-unstable-ignore-focus-outside-for-relatedtarget": ".media-modal", children: (0,external_wp_i18n_namespaceObject.__)('Open Media Library') }) }) })] }), isMobile && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MobileTabNavigation, { categories: categories, children: category => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MediaCategoryPanel, { onInsert: onInsert, rootClientId: rootClientId, category: category }) })] }); } /* harmony default export */ const media_tab = (MediaTab); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter-menu-extension/index.js /** * WordPress dependencies */ const { Fill: __unstableInserterMenuExtension, Slot: inserter_menu_extension_Slot } = (0,external_wp_components_namespaceObject.createSlotFill)('__unstableInserterMenuExtension'); __unstableInserterMenuExtension.Slot = inserter_menu_extension_Slot; /* harmony default export */ const inserter_menu_extension = (__unstableInserterMenuExtension); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/search-results.js /** * WordPress dependencies */ /** * Internal dependencies */ const search_results_INITIAL_INSERTER_RESULTS = 9; /** * Shared reference to an empty array for cases where it is important to avoid * returning a new array reference on every invocation and rerendering the component. * * @type {Array} */ const search_results_EMPTY_ARRAY = []; function InserterSearchResults({ filterValue, onSelect, onHover, onHoverPattern, rootClientId, clientId, isAppender, __experimentalInsertionIndex, maxBlockPatterns, maxBlockTypes, showBlockDirectory = false, isDraggable = true, shouldFocusBlock = true, prioritizePatterns, selectBlockOnInsert, isQuick }) { const debouncedSpeak = (0,external_wp_compose_namespaceObject.useDebounce)(external_wp_a11y_namespaceObject.speak, 500); const { prioritizedBlocks } = (0,external_wp_data_namespaceObject.useSelect)(select => { const blockListSettings = select(store).getBlockListSettings(rootClientId); return { prioritizedBlocks: blockListSettings?.prioritizedInserterBlocks || search_results_EMPTY_ARRAY }; }, [rootClientId]); const [destinationRootClientId, onInsertBlocks] = use_insertion_point({ onSelect, rootClientId, clientId, isAppender, insertionIndex: __experimentalInsertionIndex, shouldFocusBlock, selectBlockOnInsert }); const [blockTypes, blockTypeCategories, blockTypeCollections, onSelectBlockType] = use_block_types_state(destinationRootClientId, onInsertBlocks, isQuick); const [patterns,, onClickPattern] = use_patterns_state(onInsertBlocks, destinationRootClientId); const filteredBlockPatterns = (0,external_wp_element_namespaceObject.useMemo)(() => { if (maxBlockPatterns === 0) { return []; } const results = searchItems(patterns, filterValue); return maxBlockPatterns !== undefined ? results.slice(0, maxBlockPatterns) : results; }, [filterValue, patterns, maxBlockPatterns]); let maxBlockTypesToShow = maxBlockTypes; if (prioritizePatterns && filteredBlockPatterns.length > 2) { maxBlockTypesToShow = 0; } const filteredBlockTypes = (0,external_wp_element_namespaceObject.useMemo)(() => { if (maxBlockTypesToShow === 0) { return []; } const nonPatternBlockTypes = blockTypes.filter(blockType => blockType.name !== 'core/block'); let orderedItems = orderBy(nonPatternBlockTypes, 'frecency', 'desc'); if (!filterValue && prioritizedBlocks.length) { orderedItems = orderInserterBlockItems(orderedItems, prioritizedBlocks); } const results = searchBlockItems(orderedItems, blockTypeCategories, blockTypeCollections, filterValue); return maxBlockTypesToShow !== undefined ? results.slice(0, maxBlockTypesToShow) : results; }, [filterValue, blockTypes, blockTypeCategories, blockTypeCollections, maxBlockTypesToShow, prioritizedBlocks]); // Announce search results on change. (0,external_wp_element_namespaceObject.useEffect)(() => { if (!filterValue) { return; } const count = filteredBlockTypes.length + filteredBlockPatterns.length; const resultsFoundMessage = (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %d: number of results. */ (0,external_wp_i18n_namespaceObject._n)('%d result found.', '%d results found.', count), count); debouncedSpeak(resultsFoundMessage); }, [filterValue, debouncedSpeak, filteredBlockTypes, filteredBlockPatterns]); const currentShownBlockTypes = (0,external_wp_compose_namespaceObject.useAsyncList)(filteredBlockTypes, { step: search_results_INITIAL_INSERTER_RESULTS }); const currentShownPatterns = (0,external_wp_compose_namespaceObject.useAsyncList)(currentShownBlockTypes.length === filteredBlockTypes.length ? filteredBlockPatterns : search_results_EMPTY_ARRAY); const hasItems = filteredBlockTypes.length > 0 || filteredBlockPatterns.length > 0; const blocksUI = !!filteredBlockTypes.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(panel, { title: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.VisuallyHidden, { children: (0,external_wp_i18n_namespaceObject.__)('Blocks') }), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_types_list, { items: currentShownBlockTypes, onSelect: onSelectBlockType, onHover: onHover, label: (0,external_wp_i18n_namespaceObject.__)('Blocks'), isDraggable: isDraggable }) }); const patternsUI = !!filteredBlockPatterns.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(panel, { title: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.VisuallyHidden, { children: (0,external_wp_i18n_namespaceObject.__)('Block patterns') }), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__quick-inserter-patterns", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_patterns_list, { shownPatterns: currentShownPatterns, blockPatterns: filteredBlockPatterns, onClickPattern: onClickPattern, onHover: onHoverPattern, isDraggable: isDraggable }) }) }); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(inserter_listbox, { children: [!showBlockDirectory && !hasItems && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(no_results, {}), prioritizePatterns ? patternsUI : blocksUI, !!filteredBlockTypes.length && !!filteredBlockPatterns.length && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__quick-inserter-separator" }), prioritizePatterns ? blocksUI : patternsUI, showBlockDirectory && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter_menu_extension.Slot, { fillProps: { onSelect: onSelectBlockType, onHover, filterValue, hasItems, rootClientId: destinationRootClientId }, children: fills => { if (fills.length) { return fills; } if (!hasItems) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(no_results, {}); } return null; } })] }); } /* harmony default export */ const search_results = (InserterSearchResults); ;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/close-small.js /** * WordPress dependencies */ const closeSmall = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, { d: "M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z" }) }); /* harmony default export */ const close_small = (closeSmall); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/tabs.js /** * WordPress dependencies */ /** * Internal dependencies */ const { Tabs: tabs_Tabs } = unlock(external_wp_components_namespaceObject.privateApis); const blocksTab = { name: 'blocks', /* translators: Blocks tab title in the block inserter. */ title: (0,external_wp_i18n_namespaceObject.__)('Blocks') }; const patternsTab = { name: 'patterns', /* translators: Theme and Directory Patterns tab title in the block inserter. */ title: (0,external_wp_i18n_namespaceObject.__)('Patterns') }; const mediaTab = { name: 'media', /* translators: Media tab title in the block inserter. */ title: (0,external_wp_i18n_namespaceObject.__)('Media') }; function InserterTabs({ onSelect, children, onClose, selectedTab }, ref) { const tabs = [blocksTab, patternsTab, mediaTab]; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__tabs", ref: ref, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(tabs_Tabs, { onSelect: onSelect, selectedTabId: selectedTab, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__tablist-and-close-button", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { className: "block-editor-inserter__close-button", icon: close_small, label: (0,external_wp_i18n_namespaceObject.__)('Close block inserter'), onClick: () => onClose(), size: "small" }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(tabs_Tabs.TabList, { className: "block-editor-inserter__tablist", children: tabs.map(tab => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(tabs_Tabs.Tab, { tabId: tab.name, className: "block-editor-inserter__tab", children: tab.title }, tab.name)) })] }), tabs.map(tab => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(tabs_Tabs.TabPanel, { tabId: tab.name, focusable: false, className: "block-editor-inserter__tabpanel", children: children }, tab.name))] }) }); } /* harmony default export */ const tabs = ((0,external_wp_element_namespaceObject.forwardRef)(InserterTabs)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/menu.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const NOOP = () => {}; function InserterMenu({ rootClientId, clientId, isAppender, __experimentalInsertionIndex, onSelect, showInserterHelpPanel, showMostUsedBlocks, __experimentalFilterValue = '', shouldFocusBlock = true, onPatternCategorySelection, onClose, __experimentalInitialTab, __experimentalInitialCategory }, ref) { const isZoomOutMode = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).__unstableGetEditorMode() === 'zoom-out', []); const [filterValue, setFilterValue, delayedFilterValue] = (0,external_wp_compose_namespaceObject.useDebouncedInput)(__experimentalFilterValue); const [hoveredItem, setHoveredItem] = (0,external_wp_element_namespaceObject.useState)(null); const [selectedPatternCategory, setSelectedPatternCategory] = (0,external_wp_element_namespaceObject.useState)(__experimentalInitialCategory); const [patternFilter, setPatternFilter] = (0,external_wp_element_namespaceObject.useState)('all'); const [selectedMediaCategory, setSelectedMediaCategory] = (0,external_wp_element_namespaceObject.useState)(null); const [selectedTab, setSelectedTab] = (0,external_wp_element_namespaceObject.useState)(__experimentalInitialTab); const [destinationRootClientId, onInsertBlocks, onToggleInsertionPoint] = use_insertion_point({ rootClientId, clientId, isAppender, insertionIndex: __experimentalInsertionIndex, shouldFocusBlock }); const blockTypesTabRef = (0,external_wp_element_namespaceObject.useRef)(); const onInsert = (0,external_wp_element_namespaceObject.useCallback)((blocks, meta, shouldForceFocusBlock, _rootClientId) => { onInsertBlocks(blocks, meta, shouldForceFocusBlock, _rootClientId); onSelect(); // Check for focus loss due to filtering blocks by selected block type window.requestAnimationFrame(() => { if (!shouldFocusBlock && !blockTypesTabRef?.current.contains(ref.current.ownerDocument.activeElement)) { // There has been a focus loss, so focus the first button in the block types tab blockTypesTabRef?.current.querySelector('button').focus(); } }); }, [onInsertBlocks, onSelect, shouldFocusBlock]); const onInsertPattern = (0,external_wp_element_namespaceObject.useCallback)((blocks, patternName) => { onInsertBlocks(blocks, { patternName }); onSelect(); }, [onInsertBlocks, onSelect]); const onHover = (0,external_wp_element_namespaceObject.useCallback)(item => { onToggleInsertionPoint(item); setHoveredItem(item); }, [onToggleInsertionPoint, setHoveredItem]); const onHoverPattern = (0,external_wp_element_namespaceObject.useCallback)(item => { onToggleInsertionPoint(!!item); }, [onToggleInsertionPoint]); const onClickPatternCategory = (0,external_wp_element_namespaceObject.useCallback)((patternCategory, filter) => { setSelectedPatternCategory(patternCategory); setPatternFilter(filter); onPatternCategorySelection?.(); }, [setSelectedPatternCategory, onPatternCategorySelection]); const showPatternPanel = selectedTab === 'patterns' && !delayedFilterValue && !!selectedPatternCategory; const showMediaPanel = selectedTab === 'media' && !!selectedMediaCategory; const inserterSearch = (0,external_wp_element_namespaceObject.useMemo)(() => { if (selectedTab === 'media') { return null; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.SearchControl, { __nextHasNoMarginBottom: true, className: "block-editor-inserter__search", onChange: value => { if (hoveredItem) { setHoveredItem(null); } setFilterValue(value); }, value: filterValue, label: (0,external_wp_i18n_namespaceObject.__)('Search for blocks and patterns'), placeholder: (0,external_wp_i18n_namespaceObject.__)('Search') }), !!delayedFilterValue && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(search_results, { filterValue: delayedFilterValue, onSelect: onSelect, onHover: onHover, onHoverPattern: onHoverPattern, rootClientId: rootClientId, clientId: clientId, isAppender: isAppender, __experimentalInsertionIndex: __experimentalInsertionIndex, showBlockDirectory: true, shouldFocusBlock: shouldFocusBlock, prioritizePatterns: selectedTab === 'patterns' })] }); }, [selectedTab, hoveredItem, setHoveredItem, setFilterValue, filterValue, delayedFilterValue, onSelect, onHover, onHoverPattern, shouldFocusBlock, clientId, rootClientId, __experimentalInsertionIndex, isAppender]); const blocksTab = (0,external_wp_element_namespaceObject.useMemo)(() => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, { children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__block-list", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_types_tab, { ref: blockTypesTabRef, rootClientId: destinationRootClientId, onInsert: onInsert, onHover: onHover, showMostUsedBlocks: showMostUsedBlocks }) }), showInserterHelpPanel && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: "block-editor-inserter__tips", children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.VisuallyHidden, { as: "h2", children: (0,external_wp_i18n_namespaceObject.__)('A tip for using the block editor') }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(tips, {})] })] }); }, [destinationRootClientId, onInsert, onHover, showMostUsedBlocks, showInserterHelpPanel]); const patternsTab = (0,external_wp_element_namespaceObject.useMemo)(() => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_patterns_tab, { rootClientId: destinationRootClientId, onInsert: onInsertPattern, onSelectCategory: onClickPatternCategory, selectedCategory: selectedPatternCategory, children: showPatternPanel && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternCategoryPreviewPanel, { rootClientId: destinationRootClientId, onInsert: onInsertPattern, onHover: onHoverPattern, category: selectedPatternCategory, patternFilter: patternFilter, showTitlesAsTooltip: true }) }); }, [destinationRootClientId, onHoverPattern, onInsertPattern, onClickPatternCategory, patternFilter, selectedPatternCategory, showPatternPanel]); const mediaTab = (0,external_wp_element_namespaceObject.useMemo)(() => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(media_tab, { rootClientId: destinationRootClientId, selectedCategory: selectedMediaCategory, onSelectCategory: setSelectedMediaCategory, onInsert: onInsert, children: showMediaPanel && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(MediaCategoryPanel, { rootClientId: destinationRootClientId, onInsert: onInsert, category: selectedMediaCategory }) }); }, [destinationRootClientId, onInsert, selectedMediaCategory, setSelectedMediaCategory, showMediaPanel]); const handleSetSelectedTab = value => { // If no longer on patterns tab remove the category setting. if (value !== 'patterns') { setSelectedPatternCategory(null); } setSelectedTab(value); }; // Focus first active tab, if any const tabsRef = (0,external_wp_element_namespaceObject.useRef)(); (0,external_wp_element_namespaceObject.useLayoutEffect)(() => { if (tabsRef.current) { window.requestAnimationFrame(() => { tabsRef.current.querySelector('[role="tab"][aria-selected="true"]')?.focus(); }); } }, []); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: dist_clsx('block-editor-inserter__menu', { 'show-panel': showPatternPanel || showMediaPanel, 'is-zoom-out': isZoomOutMode }), ref: ref, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__main-area", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(tabs, { ref: tabsRef, onSelect: handleSetSelectedTab, onClose: onClose, selectedTab: selectedTab, children: [inserterSearch, selectedTab === 'blocks' && !delayedFilterValue && blocksTab, selectedTab === 'patterns' && !delayedFilterValue && patternsTab, selectedTab === 'media' && mediaTab] }) }), showInserterHelpPanel && hoveredItem && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Popover, { className: "block-editor-inserter__preview-container__popover", placement: "right-start", offset: 16, focusOnMount: false, animate: false, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(preview_panel, { item: hoveredItem }) })] }); } const PrivateInserterMenu = (0,external_wp_element_namespaceObject.forwardRef)(InserterMenu); function PublicInserterMenu(props, ref) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PrivateInserterMenu, { ...props, onPatternCategorySelection: NOOP, ref: ref }); } /* harmony default export */ const menu = ((0,external_wp_element_namespaceObject.forwardRef)(PublicInserterMenu)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/quick-inserter.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const SEARCH_THRESHOLD = 6; const quick_inserter_SHOWN_BLOCK_TYPES = 6; const SHOWN_BLOCK_PATTERNS = 2; const SHOWN_BLOCK_PATTERNS_WITH_PRIORITIZATION = 4; function QuickInserter({ onSelect, rootClientId, clientId, isAppender, prioritizePatterns, selectBlockOnInsert, hasSearch = true }) { const [filterValue, setFilterValue] = (0,external_wp_element_namespaceObject.useState)(''); const [destinationRootClientId, onInsertBlocks] = use_insertion_point({ onSelect, rootClientId, clientId, isAppender, selectBlockOnInsert }); const [blockTypes] = use_block_types_state(destinationRootClientId, onInsertBlocks, true); const [patterns] = use_patterns_state(onInsertBlocks, destinationRootClientId); const { setInserterIsOpened, insertionIndex } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getSettings, getBlockIndex, getBlockCount } = select(store); const settings = getSettings(); const index = getBlockIndex(clientId); const blockCount = getBlockCount(); return { setInserterIsOpened: settings.__experimentalSetIsInserterOpened, insertionIndex: index === -1 ? blockCount : index }; }, [clientId]); const showPatterns = patterns.length && (!!filterValue || prioritizePatterns); const showSearch = hasSearch && (showPatterns && patterns.length > SEARCH_THRESHOLD || blockTypes.length > SEARCH_THRESHOLD); (0,external_wp_element_namespaceObject.useEffect)(() => { if (setInserterIsOpened) { setInserterIsOpened(false); } }, [setInserterIsOpened]); // When clicking Browse All select the appropriate block so as // the insertion point can work as expected. const onBrowseAll = () => { setInserterIsOpened({ rootClientId, insertionIndex, filterValue }); }; let maxBlockPatterns = 0; if (showPatterns) { maxBlockPatterns = prioritizePatterns ? SHOWN_BLOCK_PATTERNS_WITH_PRIORITIZATION : SHOWN_BLOCK_PATTERNS; } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { className: dist_clsx('block-editor-inserter__quick-inserter', { 'has-search': showSearch, 'has-expand': setInserterIsOpened }), children: [showSearch && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.SearchControl, { __nextHasNoMarginBottom: true, className: "block-editor-inserter__search", value: filterValue, onChange: value => { setFilterValue(value); }, label: (0,external_wp_i18n_namespaceObject.__)('Search for blocks and patterns'), placeholder: (0,external_wp_i18n_namespaceObject.__)('Search') }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-inserter__quick-inserter-results", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(search_results, { filterValue: filterValue, onSelect: onSelect, rootClientId: rootClientId, clientId: clientId, isAppender: isAppender, maxBlockPatterns: maxBlockPatterns, maxBlockTypes: quick_inserter_SHOWN_BLOCK_TYPES, isDraggable: false, prioritizePatterns: prioritizePatterns, selectBlockOnInsert: selectBlockOnInsert, isQuick: true }) }), setInserterIsOpened && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, { className: "block-editor-inserter__quick-inserter-expand", onClick: onBrowseAll, "aria-label": (0,external_wp_i18n_namespaceObject.__)('Browse all. This will open the main inserter panel in the editor toolbar.'), children: (0,external_wp_i18n_namespaceObject.__)('Browse all') })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inserter/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const defaultRenderToggle = ({ onToggle, disabled, isOpen, blockTitle, hasSingleBlockType, toggleProps = {}, prioritizePatterns }) => { const { as: Wrapper = external_wp_components_namespaceObject.Button, label: labelProp, onClick, ...rest } = toggleProps; let label = labelProp; if (!label && hasSingleBlockType) { label = (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %s: the name of the block when there is only one (0,external_wp_i18n_namespaceObject._x)('Add %s', 'directly add the only allowed block'), blockTitle); } else if (!label && prioritizePatterns) { label = (0,external_wp_i18n_namespaceObject.__)('Add pattern'); } else if (!label) { label = (0,external_wp_i18n_namespaceObject._x)('Add block', 'Generic label for block inserter button'); } // Handle both onClick functions from the toggle and the parent component. function handleClick(event) { if (onToggle) { onToggle(event); } if (onClick) { onClick(event); } } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Wrapper, { icon: library_plus, label: label, tooltipPosition: "bottom", onClick: handleClick, className: "block-editor-inserter__toggle", "aria-haspopup": !hasSingleBlockType ? 'true' : false, "aria-expanded": !hasSingleBlockType ? isOpen : false, disabled: disabled, ...rest }); }; class PrivateInserter extends external_wp_element_namespaceObject.Component { constructor() { super(...arguments); this.onToggle = this.onToggle.bind(this); this.renderToggle = this.renderToggle.bind(this); this.renderContent = this.renderContent.bind(this); } onToggle(isOpen) { const { onToggle } = this.props; // Surface toggle callback to parent component. if (onToggle) { onToggle(isOpen); } } /** * Render callback to display Dropdown toggle element. * * @param {Object} options * @param {Function} options.onToggle Callback to invoke when toggle is * pressed. * @param {boolean} options.isOpen Whether dropdown is currently open. * * @return {Element} Dropdown toggle element. */ renderToggle({ onToggle, isOpen }) { const { disabled, blockTitle, hasSingleBlockType, directInsertBlock, toggleProps, hasItems, renderToggle = defaultRenderToggle, prioritizePatterns } = this.props; return renderToggle({ onToggle, isOpen, disabled: disabled || !hasItems, blockTitle, hasSingleBlockType, directInsertBlock, toggleProps, prioritizePatterns }); } /** * Render callback to display Dropdown content element. * * @param {Object} options * @param {Function} options.onClose Callback to invoke when dropdown is * closed. * * @return {Element} Dropdown content element. */ renderContent({ onClose }) { const { rootClientId, clientId, isAppender, showInserterHelpPanel, // This prop is experimental to give some time for the quick inserter to mature // Feel free to make them stable after a few releases. __experimentalIsQuick: isQuick, prioritizePatterns, onSelectOrClose, selectBlockOnInsert } = this.props; if (isQuick) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(QuickInserter, { onSelect: blocks => { const firstBlock = Array.isArray(blocks) && blocks?.length ? blocks[0] : blocks; if (onSelectOrClose && typeof onSelectOrClose === 'function') { onSelectOrClose(firstBlock); } onClose(); }, rootClientId: rootClientId, clientId: clientId, isAppender: isAppender, prioritizePatterns: prioritizePatterns, selectBlockOnInsert: selectBlockOnInsert }); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(menu, { onSelect: () => { onClose(); }, rootClientId: rootClientId, clientId: clientId, isAppender: isAppender, showInserterHelpPanel: showInserterHelpPanel }); } render() { const { position, hasSingleBlockType, directInsertBlock, insertOnlyAllowedBlock, __experimentalIsQuick: isQuick, onSelectOrClose } = this.props; if (hasSingleBlockType || directInsertBlock) { return this.renderToggle({ onToggle: insertOnlyAllowedBlock }); } return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Dropdown, { className: "block-editor-inserter", contentClassName: dist_clsx('block-editor-inserter__popover', { 'is-quick': isQuick }), popoverProps: { position, shift: true }, onToggle: this.onToggle, expandOnMobile: true, headerTitle: (0,external_wp_i18n_namespaceObject.__)('Add a block'), renderToggle: this.renderToggle, renderContent: this.renderContent, onClose: onSelectOrClose }); } } const ComposedPrivateInserter = (0,external_wp_compose_namespaceObject.compose)([(0,external_wp_data_namespaceObject.withSelect)((select, { clientId, rootClientId, shouldDirectInsert = true }) => { const { getBlockRootClientId, hasInserterItems, getAllowedBlocks, getDirectInsertBlock, getSettings } = select(store); const { getBlockVariations } = select(external_wp_blocks_namespaceObject.store); rootClientId = rootClientId || getBlockRootClientId(clientId) || undefined; const allowedBlocks = getAllowedBlocks(rootClientId); const directInsertBlock = shouldDirectInsert && getDirectInsertBlock(rootClientId); const settings = getSettings(); const hasSingleBlockType = allowedBlocks?.length === 1 && getBlockVariations(allowedBlocks[0].name, 'inserter')?.length === 0; let allowedBlockType = false; if (hasSingleBlockType) { allowedBlockType = allowedBlocks[0]; } return { hasItems: hasInserterItems(rootClientId), hasSingleBlockType, blockTitle: allowedBlockType ? allowedBlockType.title : '', allowedBlockType, directInsertBlock, rootClientId, prioritizePatterns: settings.__experimentalPreferPatternsOnRoot && !rootClientId }; }), (0,external_wp_data_namespaceObject.withDispatch)((dispatch, ownProps, { select }) => { return { insertOnlyAllowedBlock() { const { rootClientId, clientId, isAppender, hasSingleBlockType, allowedBlockType, directInsertBlock, onSelectOrClose, selectBlockOnInsert } = ownProps; if (!hasSingleBlockType && !directInsertBlock) { return; } function getAdjacentBlockAttributes(attributesToCopy) { const { getBlock, getPreviousBlockClientId } = select(store); if (!attributesToCopy || !clientId && !rootClientId) { return {}; } const result = {}; let adjacentAttributes = {}; // If there is no clientId, then attempt to get attributes // from the last block within innerBlocks of the root block. if (!clientId) { const parentBlock = getBlock(rootClientId); if (parentBlock?.innerBlocks?.length) { const lastInnerBlock = parentBlock.innerBlocks[parentBlock.innerBlocks.length - 1]; if (directInsertBlock && directInsertBlock?.name === lastInnerBlock.name) { adjacentAttributes = lastInnerBlock.attributes; } } } else { // Otherwise, attempt to get attributes from the // previous block relative to the current clientId. const currentBlock = getBlock(clientId); const previousBlock = getBlock(getPreviousBlockClientId(clientId)); if (currentBlock?.name === previousBlock?.name) { adjacentAttributes = previousBlock?.attributes || {}; } } // Copy over only those attributes flagged to be copied. attributesToCopy.forEach(attribute => { if (adjacentAttributes.hasOwnProperty(attribute)) { result[attribute] = adjacentAttributes[attribute]; } }); return result; } function getInsertionIndex() { const { getBlockIndex, getBlockSelectionEnd, getBlockOrder, getBlockRootClientId } = select(store); // If the clientId is defined, we insert at the position of the block. if (clientId) { return getBlockIndex(clientId); } // If there a selected block, we insert after the selected block. const end = getBlockSelectionEnd(); if (!isAppender && end && getBlockRootClientId(end) === rootClientId) { return getBlockIndex(end) + 1; } // Otherwise, we insert at the end of the current rootClientId. return getBlockOrder(rootClientId).length; } const { insertBlock } = dispatch(store); let blockToInsert; // Attempt to augment the directInsertBlock with attributes from an adjacent block. // This ensures styling from nearby blocks is preserved in the newly inserted block. // See: https://github.com/WordPress/gutenberg/issues/37904 if (directInsertBlock) { const newAttributes = getAdjacentBlockAttributes(directInsertBlock.attributesToCopy); blockToInsert = (0,external_wp_blocks_namespaceObject.createBlock)(directInsertBlock.name, { ...(directInsertBlock.attributes || {}), ...newAttributes }); } else { blockToInsert = (0,external_wp_blocks_namespaceObject.createBlock)(allowedBlockType.name); } insertBlock(blockToInsert, getInsertionIndex(), rootClientId, selectBlockOnInsert); if (onSelectOrClose) { onSelectOrClose({ clientId: blockToInsert?.clientId }); } const message = (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %s: the name of the block that has been added (0,external_wp_i18n_namespaceObject.__)('%s block added'), allowedBlockType.title); (0,external_wp_a11y_namespaceObject.speak)(message); } }; }), // The global inserter should always be visible, we are using ( ! isAppender && ! rootClientId && ! clientId ) as // a way to detect the global Inserter. (0,external_wp_compose_namespaceObject.ifCondition)(({ hasItems, isAppender, rootClientId, clientId }) => hasItems || !isAppender && !rootClientId && !clientId)])(PrivateInserter); const Inserter = (0,external_wp_element_namespaceObject.forwardRef)((props, ref) => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(ComposedPrivateInserter, { ref: ref, ...props }); }); /* harmony default export */ const inserter = (Inserter); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/default-block-appender/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Zero width non-breaking space, used as padding for the paragraph when it is * empty. */ const ZWNBSP = '\ufeff'; function DefaultBlockAppender({ rootClientId }) { const { showPrompt, isLocked, placeholder } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockCount, getSettings, getTemplateLock } = select(store); const isEmpty = !getBlockCount(rootClientId); const { bodyPlaceholder } = getSettings(); return { showPrompt: isEmpty, isLocked: !!getTemplateLock(rootClientId), placeholder: bodyPlaceholder }; }, [rootClientId]); const { insertDefaultBlock, startTyping } = (0,external_wp_data_namespaceObject.useDispatch)(store); if (isLocked) { return null; } const value = (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(placeholder) || (0,external_wp_i18n_namespaceObject.__)('Type / to choose a block'); const onAppend = () => { insertDefaultBlock(undefined, rootClientId); startTyping(); }; return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)("div", { "data-root-client-id": rootClientId || '', className: dist_clsx('block-editor-default-block-appender', { 'has-visible-prompt': showPrompt }), children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("p", { tabIndex: "0" // We want this element to be styled as a paragraph by themes. // eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role , role: "button", "aria-label": (0,external_wp_i18n_namespaceObject.__)('Add default block') // A wrapping container for this one already has the wp-block className. , className: "block-editor-default-block-appender__content", onKeyDown: event => { if (external_wp_keycodes_namespaceObject.ENTER === event.keyCode || external_wp_keycodes_namespaceObject.SPACE === event.keyCode) { onAppend(); } }, onClick: () => onAppend(), onFocus: () => { if (showPrompt) { onAppend(); } }, children: showPrompt ? value : ZWNBSP }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter, { rootClientId: rootClientId, position: "bottom right", isAppender: true, __experimentalIsQuick: true })] }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/button-block-appender/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function ButtonBlockAppender({ rootClientId, className, onFocus, tabIndex }, ref) { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter, { position: "bottom center", rootClientId: rootClientId, __experimentalIsQuick: true, renderToggle: ({ onToggle, disabled, isOpen, blockTitle, hasSingleBlockType }) => { let label; if (hasSingleBlockType) { label = (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %s: the name of the block when there is only one (0,external_wp_i18n_namespaceObject._x)('Add %s', 'directly add the only allowed block'), blockTitle); } else { label = (0,external_wp_i18n_namespaceObject._x)('Add block', 'Generic label for block inserter button'); } const isToggleButton = !hasSingleBlockType; let inserterButton = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.Button, { ref: ref, onFocus: onFocus, tabIndex: tabIndex, className: dist_clsx(className, 'block-editor-button-block-appender'), onClick: onToggle, "aria-haspopup": isToggleButton ? 'true' : undefined, "aria-expanded": isToggleButton ? isOpen : undefined // Disable reason: There shouldn't be a case where this button is disabled but not visually hidden. // eslint-disable-next-line no-restricted-syntax , disabled: disabled, label: label, children: [!hasSingleBlockType && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.VisuallyHidden, { as: "span", children: label }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(build_module_icon, { icon: library_plus })] }); if (isToggleButton || hasSingleBlockType) { inserterButton = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Tooltip, { text: label, children: inserterButton }); } return inserterButton; }, isAppender: true }); } /** * Use `ButtonBlockAppender` instead. * * @deprecated */ const ButtonBlockerAppender = (0,external_wp_element_namespaceObject.forwardRef)((props, ref) => { external_wp_deprecated_default()(`wp.blockEditor.ButtonBlockerAppender`, { alternative: 'wp.blockEditor.ButtonBlockAppender', since: '5.9' }); return ButtonBlockAppender(props, ref); }); /** * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/button-block-appender/README.md */ /* harmony default export */ const button_block_appender = ((0,external_wp_element_namespaceObject.forwardRef)(ButtonBlockAppender)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list-appender/index.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function DefaultAppender({ rootClientId }) { const canInsertDefaultBlock = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).canInsertBlockType((0,external_wp_blocks_namespaceObject.getDefaultBlockName)(), rootClientId)); if (canInsertDefaultBlock) { // Render the default block appender if the context supports use // of the default appender. return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(DefaultBlockAppender, { rootClientId: rootClientId }); } // Fallback in case the default block can't be inserted. return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(button_block_appender, { rootClientId: rootClientId, className: "block-list-appender__toggle" }); } function BlockListAppender({ rootClientId, CustomAppender, className, tagName: TagName = 'div' }) { const isDragOver = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockInsertionPoint, isBlockInsertionPointVisible, getBlockCount } = select(store); const insertionPoint = getBlockInsertionPoint(); // Ideally we should also check for `isDragging` but currently it // requires a lot more setup. We can revisit this once we refactor // the DnD utility hooks. return isBlockInsertionPointVisible() && rootClientId === insertionPoint?.rootClientId && getBlockCount(rootClientId) === 0; }, [rootClientId]); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(TagName // A `tabIndex` is used on the wrapping `div` element in order to // force a focus event to occur when an appender `button` element // is clicked. In some browsers (Firefox, Safari), button clicks do // not emit a focus event, which could cause this event to propagate // unexpectedly. The `tabIndex` ensures that the interaction is // captured as a focus, without also adding an extra tab stop. // // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus , { tabIndex: -1, className: dist_clsx('block-list-appender wp-block', className, { 'is-drag-over': isDragOver }) // Needed in case the whole editor is content editable (for multi // selection). It fixes an edge case where ArrowDown and ArrowRight // should collapse the selection to the end of that selection and // not into the appender. , contentEditable: false // The appender exists to let you add the first Paragraph before // any is inserted. To that end, this appender should visually be // presented as a block. That means theme CSS should style it as if // it were an empty paragraph block. That means a `wp-block` class to // ensure the width is correct, and a [data-block] attribute to ensure // the correct margin is applied, especially for classic themes which // have commonly targeted that attribute for margins. , "data-block": true, children: CustomAppender ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CustomAppender, {}) : /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(DefaultAppender, { rootClientId: rootClientId }) }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-popover/inbetween.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const inbetween_MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; const InsertionPointOpenRef = (0,external_wp_element_namespaceObject.createContext)(); function BlockPopoverInbetween({ previousClientId, nextClientId, children, __unstablePopoverSlot, __unstableContentRef, operation = 'insert', nearestSide = 'right', ...props }) { // This is a temporary hack to get the inbetween inserter to recompute properly. const [popoverRecomputeCounter, forcePopoverRecompute] = (0,external_wp_element_namespaceObject.useReducer)( // Module is there to make sure that the counter doesn't overflow. s => (s + 1) % inbetween_MAX_POPOVER_RECOMPUTE_COUNTER, 0); const { orientation, rootClientId, isVisible } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockListSettings, getBlockRootClientId, isBlockVisible } = select(store); const _rootClientId = getBlockRootClientId(previousClientId !== null && previousClientId !== void 0 ? previousClientId : nextClientId); return { orientation: getBlockListSettings(_rootClientId)?.orientation || 'vertical', rootClientId: _rootClientId, isVisible: isBlockVisible(previousClientId) && isBlockVisible(nextClientId) }; }, [previousClientId, nextClientId]); const previousElement = useBlockElement(previousClientId); const nextElement = useBlockElement(nextClientId); const isVertical = orientation === 'vertical'; const popoverAnchor = (0,external_wp_element_namespaceObject.useMemo)(() => { if ( // popoverRecomputeCounter is by definition always equal or greater than 0. // This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. popoverRecomputeCounter < 0 || !previousElement && !nextElement || !isVisible) { return undefined; } const contextElement = operation === 'group' ? nextElement || previousElement : previousElement || nextElement; return { contextElement, getBoundingClientRect() { const previousRect = previousElement ? previousElement.getBoundingClientRect() : null; const nextRect = nextElement ? nextElement.getBoundingClientRect() : null; let left = 0; let top = 0; let width = 0; let height = 0; if (operation === 'group') { const targetRect = nextRect || previousRect; top = targetRect.top; // No spacing is likely around blocks in this operation. // So width of the inserter containing rect is set to 0. width = 0; height = targetRect.bottom - targetRect.top; // Popover calculates its distance from mid-block so some // adjustments are needed to make it appear in the right place. left = nearestSide === 'left' ? targetRect.left - 2 : targetRect.right - 2; } else if (isVertical) { // vertical top = previousRect ? previousRect.bottom : nextRect.top; width = previousRect ? previousRect.width : nextRect.width; height = nextRect && previousRect ? nextRect.top - previousRect.bottom : 0; left = previousRect ? previousRect.left : nextRect.left; } else { top = previousRect ? previousRect.top : nextRect.top; height = previousRect ? previousRect.height : nextRect.height; if ((0,external_wp_i18n_namespaceObject.isRTL)()) { // non vertical, rtl left = nextRect ? nextRect.right : previousRect.left; width = previousRect && nextRect ? previousRect.left - nextRect.right : 0; } else { // non vertical, ltr left = previousRect ? previousRect.right : nextRect.left; width = previousRect && nextRect ? nextRect.left - previousRect.right : 0; } } return new window.DOMRect(left, top, width, height); } }; }, [previousElement, nextElement, popoverRecomputeCounter, isVertical, isVisible, operation, nearestSide]); const popoverScrollRef = use_popover_scroll(__unstableContentRef); // This is only needed for a smooth transition when moving blocks. // When blocks are moved up/down, their position can be set by // updating the `transform` property manually (i.e. without using CSS // transitions or animations). The animation, which can also scroll the block // editor, can sometimes cause the position of the Popover to get out of sync. // A MutationObserver is therefore used to make sure that changes to the // selectedElement's attribute (i.e. `transform`) can be tracked and used to // trigger the Popover to rerender. (0,external_wp_element_namespaceObject.useLayoutEffect)(() => { if (!previousElement) { return; } const observer = new window.MutationObserver(forcePopoverRecompute); observer.observe(previousElement, { attributes: true }); return () => { observer.disconnect(); }; }, [previousElement]); (0,external_wp_element_namespaceObject.useLayoutEffect)(() => { if (!nextElement) { return; } const observer = new window.MutationObserver(forcePopoverRecompute); observer.observe(nextElement, { attributes: true }); return () => { observer.disconnect(); }; }, [nextElement]); (0,external_wp_element_namespaceObject.useLayoutEffect)(() => { if (!previousElement) { return; } previousElement.ownerDocument.defaultView.addEventListener('resize', forcePopoverRecompute); return () => { previousElement.ownerDocument.defaultView?.removeEventListener('resize', forcePopoverRecompute); }; }, [previousElement]); // If there's either a previous or a next element, show the inbetween popover. // Note that drag and drop uses the inbetween popover to show the drop indicator // before the first block and after the last block. if (!previousElement && !nextElement || !isVisible) { return null; } /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ // While ideally it would be enough to capture the // bubbling focus event from the Inserter, due to the // characteristics of click focusing of `button`s in // Firefox and Safari, it is not reliable. // // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Popover, { ref: popoverScrollRef, animate: false, anchor: popoverAnchor, focusOnMount: false // Render in the old slot if needed for backward compatibility, // otherwise render in place (not in the default popover slot). , __unstableSlotName: __unstablePopoverSlot, inline: !__unstablePopoverSlot // Forces a remount of the popover when its position changes // This makes sure the popover doesn't animate from its previous position. , ...props, className: dist_clsx('block-editor-block-popover', 'block-editor-block-popover__inbetween', props.className), resize: false, flip: false, placement: "overlay", variant: "unstyled", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", { className: "block-editor-block-popover__inbetween-container", children: children }) }, nextClientId + '--' + rootClientId); /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ } /* harmony default export */ const inbetween = (BlockPopoverInbetween); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-popover/drop-zone.js /** * WordPress dependencies */ /** * Internal dependencies */ const animateVariants = { hide: { opacity: 0, scaleY: 0.75 }, show: { opacity: 1, scaleY: 1 }, exit: { opacity: 0, scaleY: 0.9 } }; function BlockDropZonePopover({ __unstablePopoverSlot, __unstableContentRef }) { const { clientId } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockOrder, getBlockInsertionPoint } = select(store); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder(insertionPoint.rootClientId); if (!order.length) { return {}; } return { clientId: order[insertionPoint.index] }; }, []); const reducedMotion = (0,external_wp_compose_namespaceObject.useReducedMotion)(); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(cover, { clientId: clientId, __unstablePopoverSlot: __unstablePopoverSlot, __unstableContentRef: __unstableContentRef, className: "block-editor-block-popover__drop-zone", children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__unstableMotion.div, { "data-testid": "block-popover-drop-zone", initial: reducedMotion ? animateVariants.show : animateVariants.hide, animate: animateVariants.show, exit: reducedMotion ? animateVariants.show : animateVariants.exit, className: "block-editor-block-popover__drop-zone-foreground" }) }); } /* harmony default export */ const drop_zone = (BlockDropZonePopover); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-tools/insertion-point.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const insertion_point_InsertionPointOpenRef = (0,external_wp_element_namespaceObject.createContext)(); function InbetweenInsertionPointPopover({ __unstablePopoverSlot, __unstableContentRef, operation = 'insert', nearestSide = 'right' }) { const { selectBlock, hideInsertionPoint } = (0,external_wp_data_namespaceObject.useDispatch)(store); const openRef = (0,external_wp_element_namespaceObject.useContext)(insertion_point_InsertionPointOpenRef); const ref = (0,external_wp_element_namespaceObject.useRef)(); const { orientation, previousClientId, nextClientId, rootClientId, isInserterShown, isDistractionFree, isNavigationMode } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockOrder, getBlockListSettings, getBlockInsertionPoint, isBlockBeingDragged, getPreviousBlockClientId, getNextBlockClientId, getSettings, isNavigationMode: _isNavigationMode } = select(store); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder(insertionPoint.rootClientId); if (!order.length) { return {}; } let _previousClientId = order[insertionPoint.index - 1]; let _nextClientId = order[insertionPoint.index]; while (isBlockBeingDragged(_previousClientId)) { _previousClientId = getPreviousBlockClientId(_previousClientId); } while (isBlockBeingDragged(_nextClientId)) { _nextClientId = getNextBlockClientId(_nextClientId); } const settings = getSettings(); return { previousClientId: _previousClientId, nextClientId: _nextClientId, orientation: getBlockListSettings(insertionPoint.rootClientId)?.orientation || 'vertical', rootClientId: insertionPoint.rootClientId, isNavigationMode: _isNavigationMode(), isDistractionFree: settings.isDistractionFree, isInserterShown: insertionPoint?.__unstableWithInserter }; }, []); const { getBlockEditingMode } = (0,external_wp_data_namespaceObject.useSelect)(store); const disableMotion = (0,external_wp_compose_namespaceObject.useReducedMotion)(); function onClick(event) { if (event.target === ref.current && nextClientId && getBlockEditingMode(nextClientId) !== 'disabled') { selectBlock(nextClientId, -1); } } function maybeHideInserterPoint(event) { // Only hide the inserter if it's triggered on the wrapper, // and the inserter is not open. if (event.target === ref.current && !openRef.current) { hideInsertionPoint(); } } function onFocus(event) { // Only handle click on the wrapper specifically, and not an event // bubbled from the inserter itself. if (event.target !== ref.current) { openRef.current = true; } } const lineVariants = { // Initial position starts from the center and invisible. start: { opacity: 0, scale: 0 }, // The line expands to fill the container. If the inserter is visible it // is delayed so it appears orchestrated. rest: { opacity: 1, scale: 1, transition: { delay: isInserterShown ? 0.5 : 0, type: 'tween' } }, hover: { opacity: 1, scale: 1, transition: { delay: 0.5, type: 'tween' } } }; const inserterVariants = { start: { scale: disableMotion ? 1 : 0 }, rest: { scale: 1, transition: { delay: 0.4, type: 'tween' } } }; if (isDistractionFree && !isNavigationMode) { return null; } const orientationClassname = orientation === 'horizontal' || operation === 'group' ? 'is-horizontal' : 'is-vertical'; const className = dist_clsx('block-editor-block-list__insertion-point', orientationClassname); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inbetween, { previousClientId: previousClientId, nextClientId: nextClientId, __unstablePopoverSlot: __unstablePopoverSlot, __unstableContentRef: __unstableContentRef, operation: operation, nearestSide: nearestSide, children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__unstableMotion.div, { layout: !disableMotion, initial: disableMotion ? 'rest' : 'start', animate: "rest", whileHover: "hover", whileTap: "pressed", exit: "start", ref: ref, tabIndex: -1, onClick: onClick, onFocus: onFocus, className: dist_clsx(className, { 'is-with-inserter': isInserterShown }), onHoverEnd: maybeHideInserterPoint, children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__unstableMotion.div, { variants: lineVariants, className: "block-editor-block-list__insertion-point-indicator", "data-testid": "block-list-insertion-point-indicator" }), isInserterShown && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__unstableMotion.div, { variants: inserterVariants, className: dist_clsx('block-editor-block-list__insertion-point-inserter'), children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(inserter, { position: "bottom center", clientId: nextClientId, rootClientId: rootClientId, __experimentalIsQuick: true, onToggle: isOpen => { openRef.current = isOpen; }, onSelectOrClose: () => { openRef.current = false; } }) })] }) }); } function InsertionPoint(props) { const { insertionPoint, isVisible, isBlockListEmpty } = (0,external_wp_data_namespaceObject.useSelect)(select => { const { getBlockInsertionPoint, isBlockInsertionPointVisible, getBlockCount } = select(store); const blockInsertionPoint = getBlockInsertionPoint(); return { insertionPoint: blockInsertionPoint, isVisible: isBlockInsertionPointVisible(), isBlockListEmpty: getBlockCount(blockInsertionPoint?.rootClientId) === 0 }; }, []); if (!isVisible || // Don't render the insertion point if the block list is empty. // The insertion point will be represented by the appender instead. isBlockListEmpty) { return null; } /** * Render a popover that overlays the block when the desired operation is to replace it. * Otherwise, render a popover in between blocks for the indication of inserting between them. */ return insertionPoint.operation === 'replace' ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(drop_zone // Force remount to trigger the animation. , { ...props }, `${insertionPoint.rootClientId}-${insertionPoint.index}`) : /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(InbetweenInsertionPointPopover, { operation: insertionPoint.operation, nearestSide: insertionPoint.nearestSide, ...props }); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/use-in-between-inserter.js /** * WordPress dependencies */ /** * Internal dependencies */ function useInBetweenInserter() { const openRef = (0,external_wp_element_namespaceObject.useContext)(insertion_point_InsertionPointOpenRef); const isInBetweenInserterDisabled = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).getSettings().isDistractionFree || select(store).__unstableGetEditorMode() === 'zoom-out', []); const { getBlockListSettings, getBlockIndex, isMultiSelecting, getSelectedBlockClientIds, getTemplateLock, __unstableIsWithinBlockOverlay, getBlockEditingMode, getBlockName } = (0,external_wp_data_namespaceObject.useSelect)(store); const { showInsertionPoint, hideInsertionPoint } = (0,external_wp_data_namespaceObject.useDispatch)(store); return (0,external_wp_compose_namespaceObject.useRefEffect)(node => { if (isInBetweenInserterDisabled) { return; } function onMouseMove(event) { // openRef is the reference to the insertion point between blocks. // If the reference is not set or the insertion point is already open, return. if (openRef === undefined || openRef.current) { return; } // Ignore text nodes sometimes detected in FireFox. if (event.target.nodeType === event.target.TEXT_NODE) { return; } if (isMultiSelecting()) { return; } if (!event.target.classList.contains('block-editor-block-list__layout')) { hideInsertionPoint(); return; } let rootClientId; if (!event.target.classList.contains('is-root-container')) { const blockElement = !!event.target.getAttribute('data-block') ? event.target : event.target.closest('[data-block]'); rootClientId = blockElement.getAttribute('data-block'); } if (getTemplateLock(rootClientId) || getBlockEditingMode(rootClientId) === 'disabled' || getBlockName(rootClientId) === 'core/block') { return; } const orientation = getBlockListSettings(rootClientId)?.orientation || 'vertical'; const offsetTop = event.clientY; const offsetLeft = event.clientX; const children = Array.from(event.target.children); let element = children.find(blockEl => { const blockElRect = blockEl.getBoundingClientRect(); return blockEl.classList.contains('wp-block') && orientation === 'vertical' && blockElRect.top > offsetTop || blockEl.classList.contains('wp-block') && orientation === 'horizontal' && ((0,external_wp_i18n_namespaceObject.isRTL)() ? blockElRect.right < offsetLeft : blockElRect.left > offsetLeft); }); if (!element) { hideInsertionPoint(); return; } // The block may be in an alignment wrapper, so check the first direct // child if the element has no ID. if (!element.id) { element = element.firstElementChild; if (!element) { hideInsertionPoint(); return; } } // Don't show the insertion point if a parent block has an "overlay" // See https://github.com/WordPress/gutenberg/pull/34012#pullrequestreview-727762337 const clientId = element.id.slice('block-'.length); if (!clientId || __unstableIsWithinBlockOverlay(clientId)) { return; } // Don't show the inserter when hovering above (conflicts with // block toolbar) or inside selected block(s). if (getSelectedBlockClientIds().includes(clientId)) { return; } const elementRect = element.getBoundingClientRect(); if (orientation === 'horizontal' && (event.clientY > elementRect.bottom || event.clientY < elementRect.top) || orientation === 'vertical' && (event.clientX > elementRect.right || event.clientX < elementRect.left)) { hideInsertionPoint(); return; } const index = getBlockIndex(clientId); // Don't show the in-between inserter before the first block in // the list (preserves the original behaviour). if (index === 0) { hideInsertionPoint(); return; } showInsertionPoint(rootClientId, index, { __unstableWithInserter: true }); } node.addEventListener('mousemove', onMouseMove); return () => { node.removeEventListener('mousemove', onMouseMove); }; }, [openRef, getBlockListSettings, getBlockIndex, isMultiSelecting, showInsertionPoint, hideInsertionPoint, getSelectedBlockClientIds, isInBetweenInserterDisabled]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/with-client-id.js /** * WordPress dependencies */ /** * Internal dependencies */ const withClientId = (0,external_wp_compose_namespaceObject.createHigherOrderComponent)(WrappedComponent => props => { const { clientId } = useBlockEditContext(); return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(WrappedComponent, { ...props, clientId: clientId }); }, 'withClientId'); /* harmony default export */ const with_client_id = (withClientId); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/button-block-appender.js /** * External dependencies */ /** * Internal dependencies */ const button_block_appender_ButtonBlockAppender = ({ clientId, showSeparator, isFloating, onAddBlock, isToggle }) => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(button_block_appender, { className: dist_clsx({ 'block-list-appender__toggle': isToggle }), rootClientId: clientId, showSeparator: showSeparator, isFloating: isFloating, onAddBlock: onAddBlock }); }; /* harmony default export */ const inner_blocks_button_block_appender = (with_client_id(button_block_appender_ButtonBlockAppender)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/default-block-appender.js /** * WordPress dependencies */ /** * Internal dependencies */ const default_block_appender_DefaultBlockAppender = ({ clientId }) => { return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(DefaultBlockAppender, { rootClientId: clientId }); }; /* harmony default export */ const default_block_appender = ((0,external_wp_compose_namespaceObject.compose)([with_client_id, (0,external_wp_data_namespaceObject.withSelect)((select, { clientId }) => { const { getBlockOrder } = select(store); const blockClientIds = getBlockOrder(clientId); return { lastBlockClientId: blockClientIds[blockClientIds.length - 1] }; })])(default_block_appender_DefaultBlockAppender)); ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/use-nested-settings-update.js /** * WordPress dependencies */ /** * Internal dependencies */ /** @typedef {import('../../selectors').WPDirectInsertBlock } WPDirectInsertBlock */ const pendingSettingsUpdates = new WeakMap(); function useShallowMemo(value) { const [prevValue, setPrevValue] = (0,external_wp_element_namespaceObject.useState)(value); if (!external_wp_isShallowEqual_default()(prevValue, value)) { setPrevValue(value); } return prevValue; } /** * This hook is a side effect which updates the block-editor store when changes * happen to inner block settings. The given props are transformed into a * settings object, and if that is different from the current settings object in * the block-editor store, then the store is updated with the new settings which * came from props. * * @param {string} clientId The client ID of the block to update. * @param {string} parentLock * @param {string[]} allowedBlocks An array of block names which are permitted * in inner blocks. * @param {string[]} prioritizedInserterBlocks Block names and/or block variations to be prioritized in the inserter, in the format {blockName}/{variationName}. * @param {?WPDirectInsertBlock} defaultBlock The default block to insert: [ blockName, { blockAttributes } ]. * @param {?boolean} directInsert If a default block should be inserted directly by the appender. * * @param {?WPDirectInsertBlock} __experimentalDefaultBlock A deprecated prop for the default block to insert: [ blockName, { blockAttributes } ]. Use `defaultBlock` instead. * * @param {?boolean} __experimentalDirectInsert A deprecated prop for whether a default block should be inserted directly by the appender. Use `directInsert` instead. * * @param {string} [templateLock] The template lock specified for the inner * blocks component. (e.g. "all") * @param {boolean} captureToolbars Whether or children toolbars should be shown * in the inner blocks component rather than on * the child block. * @param {string} orientation The direction in which the block * should face. * @param {Object} layout The layout object for the block container. */ function useNestedSettingsUpdate(clientId, parentLock, allowedBlocks, prioritizedInserterBlocks, defaultBlock, directInsert, __experimentalDefaultBlock, __experimentalDirectInsert, templateLock, captureToolbars, orientation, layout) { // Instead of adding a useSelect mapping here, please add to the useSelect // mapping in InnerBlocks! Every subscription impacts performance. const registry = (0,external_wp_data_namespaceObject.useRegistry)(); // Implementors often pass a new array on every render, // and the contents of the arrays are just strings, so the entire array // can be passed as dependencies but We need to include the length of the array, // otherwise if the arrays change length but the first elements are equal the comparison, // does not works as expected. const _allowedBlocks = useShallowMemo(allowedBlocks); const _prioritizedInserterBlocks = (0,external_wp_element_namespaceObject.useMemo)(() => prioritizedInserterBlocks, // eslint-disable-next-line react-hooks/exhaustive-deps prioritizedInserterBlocks); const _templateLock = templateLock === undefined || parentLock === 'contentOnly' ? parentLock : templateLock; (0,external_wp_element_namespaceObject.useLayoutEffect)(() => { const newSettings = { allowedBlocks: _allowedBlocks, prioritizedInserterBlocks: _prioritizedInserterBlocks, templateLock: _templateLock }; // These values are not defined for RN, so only include them if they // are defined. if (captureToolbars !== undefined) { newSettings.__experimentalCaptureToolbars = captureToolbars; } // Orientation depends on layout, // ideally the separate orientation prop should be deprecated. if (orientation !== undefined) { newSettings.orientation = orientation; } else { const layoutType = getLayoutType(layout?.type); newSettings.orientation = layoutType.getOrientation(layout); } if (__experimentalDefaultBlock !== undefined) { external_wp_deprecated_default()('__experimentalDefaultBlock', { alternative: 'defaultBlock', since: '6.3', version: '6.4' }); newSettings.defaultBlock = __experimentalDefaultBlock; } if (defaultBlock !== undefined) { newSettings.defaultBlock = defaultBlock; } if (__experimentalDirectInsert !== undefined) { external_wp_deprecated_default()('__experimentalDirectInsert', { alternative: 'directInsert', since: '6.3', version: '6.4' }); newSettings.directInsert = __experimentalDirectInsert; } if (directInsert !== undefined) { newSettings.directInsert = directInsert; } if (newSettings.directInsert !== undefined && typeof newSettings.directInsert !== 'boolean') { external_wp_deprecated_default()('Using `Function` as a `directInsert` argument', { alternative: '`boolean` values', since: '6.5' }); } // Batch updates to block list settings to avoid triggering cascading renders // for each container block included in a tree and optimize initial render. // To avoid triggering updateBlockListSettings for each container block // causing X re-renderings for X container blocks, // we batch all the updatedBlockListSettings in a single "data" batch // which results in a single re-render. if (!pendingSettingsUpdates.get(registry)) { pendingSettingsUpdates.set(registry, {}); } pendingSettingsUpdates.get(registry)[clientId] = newSettings; window.queueMicrotask(() => { const settings = pendingSettingsUpdates.get(registry); if (Object.keys(settings).length) { const { updateBlockListSettings } = registry.dispatch(store); updateBlockListSettings(settings); pendingSettingsUpdates.set(registry, {}); } }); }, [clientId, _allowedBlocks, _prioritizedInserterBlocks, _templateLock, defaultBlock, directInsert, __experimentalDefaultBlock, __experimentalDirectInsert, captureToolbars, orientation, layout, registry]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/use-inner-block-template-sync.js /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * This hook makes sure that a block's inner blocks stay in sync with the given * block "template". The template is a block hierarchy to which inner blocks must * conform. If the blocks get "out of sync" with the template and the template * is meant to be locked (e.g. templateLock = "all" or templateLock = "contentOnly"), * then we replace the inner blocks with the correct value after synchronizing it with the template. * * @param {string} clientId The block client ID. * @param {Object} template The template to match. * @param {string} templateLock The template lock state for the inner blocks. For * example, if the template lock is set to "all", * then the inner blocks will stay in sync with the * template. If not defined or set to false, then * the inner blocks will not be synchronized with * the given template. * @param {boolean} templateInsertUpdatesSelection Whether or not to update the * block-editor selection state when inner blocks * are replaced after template synchronization. */ function useInnerBlockTemplateSync(clientId, template, templateLock, templateInsertUpdatesSelection) { // Instead of adding a useSelect mapping here, please add to the useSelect // mapping in InnerBlocks! Every subscription impacts performance. const { getBlocks, getSelectedBlocksInitialCaretPosition, isBlockSelected } = (0,external_wp_data_namespaceObject.useSelect)(store); const { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = (0,external_wp_data_namespaceObject.useDispatch)(store); // Maintain a reference to the previous value so we can do a deep equality check. const existingTemplate = (0,external_wp_element_namespaceObject.useRef)(null); (0,external_wp_element_namespaceObject.useLayoutEffect)(() => { let isCancelled = false; // There's an implicit dependency between useInnerBlockTemplateSync and useNestedSettingsUpdate // The former needs to happen after the latter and since the latter is using microtasks to batch updates (performance optimization), // we need to schedule this one in a microtask as well. // Example: If you remove queueMicrotask here, ctrl + click to insert quote block won't close the inserter. window.queueMicrotask(() => { if (isCancelled) { return; } // Only synchronize innerBlocks with template if innerBlocks are empty // or a locking "all" or "contentOnly" exists directly on the block. const currentInnerBlocks = getBlocks(clientId); const shouldApplyTemplate = currentInnerBlocks.length === 0 || templateLock === 'all' || templateLock === 'contentOnly'; const hasTemplateChanged = !es6_default()(template, existingTemplate.current); if (!shouldApplyTemplate || !hasTemplateChanged) { return; } existingTemplate.current = template; const nextBlocks = (0,external_wp_blocks_namespaceObject.synchronizeBlocksWithTemplate)(currentInnerBlocks, template); if (!es6_default()(nextBlocks, currentInnerBlocks)) { __unstableMarkNextChangeAsNotPersistent(); replaceInnerBlocks(clientId, nextBlocks, currentInnerBlocks.length === 0 && templateInsertUpdatesSelection && nextBlocks.length !== 0 && isBlockSelected(clientId), // This ensures the "initialPosition" doesn't change when applying the template // If we're supposed to focus the block, we'll focus the first inner block // otherwise, we won't apply any auto-focus. // This ensures for instance that the focus stays in the inserter when inserting the "buttons" block. getSelectedBlocksInitialCaretPosition()); } }); return () => { isCancelled = true; }; }, [template, templateLock, clientId]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/inner-blocks/use-block-context.js /** * WordPress dependencies */ /** * Internal dependencies */ /** * Returns a context object for a given block. * * @param {string} clientId The block client ID. * * @return {Record<string,*>} Context value. */ function useBlockContext(clientId) { return (0,external_wp_data_namespaceObject.useSelect)(select => { const block = select(store).getBlock(clientId); if (!block) { return undefined; } const blockType = select(external_wp_blocks_namespaceObject.store).getBlockType(block.name); if (!blockType) { return undefined; } if (Object.keys(blockType.providesContext).length === 0) { return undefined; } return Object.fromEntries(Object.entries(blockType.providesContext).map(([contextName, attributeName]) => [contextName, block.attributes[attributeName]])); }, [clientId]); } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/use-on-block-drop/index.js /** * WordPress dependencies */ /** * Internal dependencies */ /** @typedef {import('react').SyntheticEvent} SyntheticEvent */ /** @typedef {import('./types').WPDropOperation} WPDropOperation */ /** * Retrieve the data for a block drop event. * * @param {SyntheticEvent} event The drop event. * * @return {Object} An object with block drag and drop data. */ function parseDropEvent(event) { let result = { srcRootClientId: null, srcClientIds: null, srcIndex: null, type: null, blocks: null }; if (!event.dataTransfer) { return result; } try { result = Object.assign(result, JSON.parse(event.dataTransfer.getData('wp-blocks'))); } catch (err) { return result; } return result; } /** * A function that returns an event handler function for block drop events. * * @param {string} targetRootClientId The root client id where the block(s) will be inserted. * @param {number} targetBlockIndex The index where the block(s) will be inserted. * @param {Function} getBlockIndex A function that gets the index of a block. * @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks. * @param {Function} moveBlocks A function that moves blocks. * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks. * @param {Function} clearSelectedBlock A function that clears block selection. * @param {string} operation The type of operation to perform on drop. Could be `insert` or `replace` or `group`. * @param {Function} getBlock A function that returns a block given its client id. * @return {Function} The event handler for a block drop event. */ function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants, moveBlocks, insertOrReplaceBlocks, clearSelectedBlock, operation, getBlock) { return event => { const { srcRootClientId: sourceRootClientId, srcClientIds: sourceClientIds, type: dropType, blocks } = parseDropEvent(event); // If the user is inserting a block. if (dropType === 'inserter') { clearSelectedBlock(); const blocksToInsert = blocks.map(block => (0,external_wp_blocks_namespaceObject.cloneBlock)(block)); insertOrReplaceBlocks(blocksToInsert, true, null); } // If the user is moving a block. if (dropType === 'block') { const sourceBlockIndex = getBlockIndex(sourceClientIds[0]); // If the user is dropping to the same position, return early. if (sourceRootClientId === targetRootClientId && sourceBlockIndex === targetBlockIndex) { return; } // If the user is attempting to drop a block within its own // nested blocks, return early as this would create infinite // recursion. if (sourceClientIds.includes(targetRootClientId) || getClientIdsOfDescendants(sourceClientIds).some(id => id === targetRootClientId)) { return; } // If the user is dropping a block over another block, replace both blocks // with a group block containing them if (operation === 'group') { const blocksToInsert = sourceClientIds.map(clientId => getBlock(clientId)); insertOrReplaceBlocks(blocksToInsert, true, null, sourceClientIds); return; } const isAtSameLevel = sourceRootClientId === targetRootClientId; const draggedBlockCount = sourceClientIds.length; // If the block is kept at the same level and moved downwards, // subtract to take into account that the blocks being dragged // were removed from the block list above the insertion point. const insertIndex = isAtSameLevel && sourceBlockIndex < targetBlockIndex ? targetBlockIndex - draggedBlockCount : targetBlockIndex; moveBlocks(sourceClientIds, sourceRootClientId, insertIndex); } }; } /** * A function that returns an event handler function for block-related file drop events. * * @param {string} targetRootClientId The root client id where the block(s) will be inserted. * @param {Function} getSettings A function that gets the block editor settings. * @param {Function} updateBlockAttributes A function that updates a block's attributes. * @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted. * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks. * * @return {Function} The event handler for a block-related file drop event. */ function onFilesDrop(targetRootClientId, getSettings, updateBlockAttributes, canInsertBlockType, insertOrReplaceBlocks) { return files => { if (!getSettings().mediaUpload) { return; } const transformation = (0,external_wp_blocks_namespaceObject.findTransform)((0,external_wp_blocks_namespaceObject.getBlockTransforms)('from'), transform => transform.type === 'files' && canInsertBlockType(transform.blockName, targetRootClientId) && transform.isMatch(files)); if (transformation) { const blocks = transformation.transform(files, updateBlockAttributes); insertOrReplaceBlocks(blocks); } }; } /** * A function that returns an event handler function for block-related HTML drop events. * * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks. * * @return {Function} The event handler for a block-related HTML drop event. */ function onHTMLDrop(insertOrReplaceBlocks) { return HTML => { const blocks = (0,external_wp_blocks_namespaceObject.pasteHandler)({ HTML, mode: 'BLOCKS' }); if (blocks.length) { insertOrReplaceBlocks(blocks); } }; } /** * A React hook for handling block drop events. * * @param {string} targetRootClientId The root client id where the block(s) will be inserted. * @param {number} targetBlockIndex The index where the block(s) will be inserted. * @param {Object} options The optional options. * @param {WPDropOperation} [options.operation] The type of operation to perform on drop. Could be `insert` or `replace` for now. * * @return {Function} A function to be passed to the onDrop handler. */ function useOnBlockDrop(targetRootClientId, targetBlockIndex, options = {}) { const { operation = 'insert', nearestSide = 'right' } = options; const { canInsertBlockType, getBlockIndex, getClientIdsOfDescendants, getBlockOrder, getBlocksByClientId, getSettings, getBlock, isGroupable } = (0,external_wp_data_namespaceObject.useSelect)(store); const { getGroupingBlockName } = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blocks_namespaceObject.store); const { insertBlocks, moveBlocksToPosition, updateBlockAttributes, clearSelectedBlock, replaceBlocks, removeBlocks } = (0,external_wp_data_namespaceObject.useDispatch)(store); const registry = (0,external_wp_data_namespaceObject.useRegistry)(); const insertOrReplaceBlocks = (0,external_wp_element_namespaceObject.useCallback)((blocks, updateSelection = true, initialPosition = 0, clientIdsToReplace = []) => { if (!Array.isArray(blocks)) { blocks = [blocks]; } const clientIds = getBlockOrder(targetRootClientId); const clientId = clientIds[targetBlockIndex]; const blocksClientIds = blocks.map(block => block.clientId); const areGroupableBlocks = isGroupable([...blocksClientIds, clientId]); if (operation === 'replace') { replaceBlocks(clientId, blocks, undefined, initialPosition); } else if (operation === 'group' && areGroupableBlocks) { const targetBlock = getBlock(clientId); if (nearestSide === 'left') { blocks.push(targetBlock); } else { blocks.unshift(targetBlock); } const groupInnerBlocks = blocks.map(block => { return (0,external_wp_blocks_namespaceObject.createBlock)(block.name, block.attributes, block.innerBlocks); }); const areAllImages = blocks.every(block => { return block.name === 'core/image'; }); const galleryBlock = canInsertBlockType('core/gallery', targetRootClientId); const wrappedBlocks = (0,external_wp_blocks_namespaceObject.createBlock)(areAllImages && galleryBlock ? 'core/gallery' : getGroupingBlockName(), { layout: { type: 'flex', flexWrap: areAllImages && galleryBlock ? null : 'nowrap' } }, groupInnerBlocks); // Need to make sure both the target block and the block being dragged are replaced // otherwise the dragged block will be duplicated. replaceBlocks([clientId, ...clientIdsToReplace], wrappedBlocks, undefined, initialPosition); } else { insertBlocks(blocks, targetBlockIndex, targetRootClientId, updateSelection, initialPosition); } }, [getBlockOrder, targetRootClientId, targetBlockIndex, isGroupable, operation, replaceBlocks, getBlock, nearestSide, canInsertBlockType, getGroupingBlockName, insertBlocks]); const moveBlocks = (0,external_wp_element_namespaceObject.useCallback)((sourceClientIds, sourceRootClientId, insertIndex) => { if (operation === 'replace') { const sourceBlocks = getBlocksByClientId(sourceClientIds); const targetBlockClientIds = getBlockOrder(targetRootClientId); const targetBlockClientId = targetBlockClientIds[targetBlockIndex]; registry.batch(() => { // Remove the source blocks. removeBlocks(sourceClientIds, false); // Replace the target block with the source blocks. replaceBlocks(targetBlockClientId, sourceBlocks, undefined, 0); }); } else { moveBlocksToPosition(sourceClientIds, sourceRootClientId, targetRootClientId, insertIndex); } }, [operation, getBlockOrder, getBlocksByClientId, moveBlocksToPosition, registry, removeBlocks, replaceBlocks, targetBlockIndex, targetRootClientId]); const _onDrop = onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants, moveBlocks, insertOrReplaceBlocks, clearSelectedBlock, operation, getBlock); const _onFilesDrop = onFilesDrop(targetRootClientId, getSettings, updateBlockAttributes, canInsertBlockType, insertOrReplaceBlocks); const _onHTMLDrop = onHTMLDrop(insertOrReplaceBlocks); return event => { const files = (0,external_wp_dom_namespaceObject.getFilesFromDataTransfer)(event.dataTransfer); const html = event.dataTransfer.getData('text/html'); /** * From Windows Chrome 96, the `event.dataTransfer` returns both file object and HTML. * The order of the checks is important to recognise the HTML drop. */ if (html) { _onHTMLDrop(html); } else if (files.length) { _onFilesDrop(files); } else { _onDrop(event); } }; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/utils/math.js /** * A string representing the name of an edge. * * @typedef {'top'|'right'|'bottom'|'left'} WPEdgeName */ /** * @typedef {Object} WPPoint * @property {number} x The horizontal position. * @property {number} y The vertical position. */ /** * Given a point, a DOMRect and the name of an edge, returns the distance to * that edge of the rect. * * This function works for edges that are horizontal or vertical (e.g. not * rotated), the following terms are used so that the function works in both * orientations: * * - Forward, meaning the axis running horizontally when an edge is vertical * and vertically when an edge is horizontal. * - Lateral, meaning the axis running vertically when an edge is vertical * and horizontally when an edge is horizontal. * * @param {WPPoint} point The point to measure distance from. * @param {DOMRect} rect A DOM Rect containing edge positions. * @param {WPEdgeName} edge The edge to measure to. */ function getDistanceFromPointToEdge(point, rect, edge) { const isHorizontal = edge === 'top' || edge === 'bottom'; const { x, y } = point; const pointLateralPosition = isHorizontal ? x : y; const pointForwardPosition = isHorizontal ? y : x; const edgeStart = isHorizontal ? rect.left : rect.top; const edgeEnd = isHorizontal ? rect.right : rect.bottom; const edgeForwardPosition = rect[edge]; // Measure the straight line distance to the edge of the rect, when the // point is adjacent to the edge. // Else, if the point is positioned diagonally to the edge of the rect, // measure diagonally to the nearest corner that the edge meets. let edgeLateralPosition; if (pointLateralPosition >= edgeStart && pointLateralPosition <= edgeEnd) { edgeLateralPosition = pointLateralPosition; } else if (pointLateralPosition < edgeEnd) { edgeLateralPosition = edgeStart; } else { edgeLateralPosition = edgeEnd; } return Math.sqrt((pointLateralPosition - edgeLateralPosition) ** 2 + (pointForwardPosition - edgeForwardPosition) ** 2); } /** * Given a point, a DOMRect and a list of allowed edges returns the name of and * distance to the nearest edge. * * @param {WPPoint} point The point to measure distance from. * @param {DOMRect} rect A DOM Rect containing edge positions. * @param {WPEdgeName[]} allowedEdges A list of the edges included in the * calculation. Defaults to all edges. * * @return {[number, string]} An array where the first value is the distance * and a second is the edge name. */ function getDistanceToNearestEdge(point, rect, allowedEdges = ['top', 'bottom', 'left', 'right']) { let candidateDistance; let candidateEdge; allowedEdges.forEach(edge => { const distance = getDistanceFromPointToEdge(point, rect, edge); if (candidateDistance === undefined || distance < candidateDistance) { candidateDistance = distance; candidateEdge = edge; } }); return [candidateDistance, candidateEdge]; } /** * Is the point contained by the rectangle. * * @param {WPPoint} point The point. * @param {DOMRect} rect The rectangle. * * @return {boolean} True if the point is contained by the rectangle, false otherwise. */ function isPointContainedByRect(point, rect) { return rect.left <= point.x && rect.right >= point.x && rect.top <= point.y && rect.bottom >= point.y; } /** * Is the point within the top and bottom boundaries of the rectangle. * * @param {WPPoint} point The point. * @param {DOMRect} rect The rectangle. * * @return {boolean} True if the point is within top and bottom of rectangle, false otherwise. */ function isPointWithinTopAndBottomBoundariesOfRect(point, rect) { return rect.top <= point.y && rect.bottom >= point.y; } ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/use-block-drop-zone/index.js /** * WordPress dependencies */ /** * Internal dependencies */ const THRESHOLD_DISTANCE = 30; const MINIMUM_HEIGHT_FOR_THRESHOLD = 120; const MINIMUM_WIDTH_FOR_THRESHOLD = 120; /** @typedef {import('../../utils/math').WPPoint} WPPoint */ /** @typedef {import('../use-on-block-drop/types').WPDropOperation} WPDropOperation */ /** * The orientation of a block list. * * @typedef {'horizontal'|'vertical'|undefined} WPBlockListOrientation */ /** * The insert position when dropping a block. * * @typedef {'before'|'after'} WPInsertPosition */ /** * @typedef {Object} WPBlockData * @property {boolean} isUnmodifiedDefaultBlock Is the block unmodified default block. * @property {() => DOMRect} getBoundingClientRect Get the bounding client rect of the block. * @property {number} blockIndex The index of the block. */ /** * Get the drop target position from a given drop point and the orientation. * * @param {WPBlockData[]} blocksData The block data list. * @param {WPPoint} position The position of the item being dragged. * @param {WPBlockListOrientation} orientation The orientation of the block list. * @param {Object} options Additional options. * @return {[number, WPDropOperation]} The drop target position. */ function getDropTargetPosition(blocksData, position, orientation = 'vertical', options = {}) { const allowedEdges = orientation === 'horizontal' ? ['left', 'right'] : ['top', 'bottom']; let nearestIndex = 0; let insertPosition = 'before'; let minDistance = Infinity; let targetBlockIndex = null; let nearestSide = 'right'; const { dropZoneElement, parentBlockOrientation, rootBlockIndex = 0 } = options; // Allow before/after when dragging over the top/bottom edges of the drop zone. if (dropZoneElement && parentBlockOrientation !== 'horizontal') { const rect = dropZoneElement.getBoundingClientRect(); const [distance, edge] = getDistanceToNearestEdge(position, rect, ['top', 'bottom']); // If dragging over the top or bottom of the drop zone, insert the block // before or after the parent block. This only applies to blocks that use // a drop zone element, typically container blocks such as Group or Cover. if (rect.height > MINIMUM_HEIGHT_FOR_THRESHOLD && distance < THRESHOLD_DISTANCE) { if (edge === 'top') { return [rootBlockIndex, 'before']; } if (edge === 'bottom') { return [rootBlockIndex + 1, 'after']; } } } const isRightToLeft = (0,external_wp_i18n_namespaceObject.isRTL)(); // Allow before/after when dragging over the left/right edges of the drop zone.
•
Search:
•
Replace:
1
2
3
4
5
6
7
8
Function
Edit by line
Download
Information
Rename
Copy
Move
Delete
Chmod
List