wp/wp-includes/js/dist/patterns.js
changeset 21 48c4eec2b7e6
child 22 8c2e4d02f4ef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wp/wp-includes/js/dist/patterns.js	Fri Sep 05 18:40:08 2025 +0200
@@ -0,0 +1,1748 @@
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	// The require scope
+/******/ 	var __webpack_require__ = {};
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+var __webpack_exports__ = {};
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, {
+  privateApis: () => (/* reexport */ privateApis),
+  store: () => (/* reexport */ store)
+});
+
+// NAMESPACE OBJECT: ./node_modules/@wordpress/patterns/build-module/store/actions.js
+var actions_namespaceObject = {};
+__webpack_require__.r(actions_namespaceObject);
+__webpack_require__.d(actions_namespaceObject, {
+  convertSyncedPatternToStatic: () => (convertSyncedPatternToStatic),
+  createPattern: () => (createPattern),
+  createPatternFromFile: () => (createPatternFromFile),
+  setEditingPattern: () => (setEditingPattern)
+});
+
+// NAMESPACE OBJECT: ./node_modules/@wordpress/patterns/build-module/store/selectors.js
+var selectors_namespaceObject = {};
+__webpack_require__.r(selectors_namespaceObject);
+__webpack_require__.d(selectors_namespaceObject, {
+  isEditingPattern: () => (selectors_isEditingPattern)
+});
+
+;// CONCATENATED MODULE: external ["wp","data"]
+const external_wp_data_namespaceObject = window["wp"]["data"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/store/reducer.js
+/**
+ * WordPress dependencies
+ */
+
+function isEditingPattern(state = {}, action) {
+  if (action?.type === 'SET_EDITING_PATTERN') {
+    return {
+      ...state,
+      [action.clientId]: action.isEditing
+    };
+  }
+  return state;
+}
+/* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
+  isEditingPattern
+}));
+
+;// CONCATENATED MODULE: external ["wp","blocks"]
+const external_wp_blocks_namespaceObject = window["wp"]["blocks"];
+;// CONCATENATED MODULE: external ["wp","coreData"]
+const external_wp_coreData_namespaceObject = window["wp"]["coreData"];
+;// CONCATENATED MODULE: external ["wp","blockEditor"]
+const external_wp_blockEditor_namespaceObject = window["wp"]["blockEditor"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/constants.js
+const PATTERN_TYPES = {
+  theme: 'pattern',
+  user: 'wp_block'
+};
+const PATTERN_DEFAULT_CATEGORY = 'all-patterns';
+const PATTERN_USER_CATEGORY = 'my-patterns';
+const EXCLUDED_PATTERN_SOURCES = ['core', 'pattern-directory/core', 'pattern-directory/featured'];
+const PATTERN_SYNC_TYPES = {
+  full: 'fully',
+  unsynced: 'unsynced'
+};
+
+// TODO: This should not be hardcoded. Maybe there should be a config and/or an UI.
+const PARTIAL_SYNCING_SUPPORTED_BLOCKS = {
+  'core/paragraph': ['content'],
+  'core/heading': ['content'],
+  'core/button': ['text', 'url', 'linkTarget', 'rel'],
+  'core/image': ['id', 'url', 'title', 'alt']
+};
+const PATTERN_OVERRIDES_BINDING_SOURCE = 'core/pattern-overrides';
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/store/actions.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Returns a generator converting one or more static blocks into a pattern, or creating a new empty pattern.
+ *
+ * @param {string}             title        Pattern title.
+ * @param {'full'|'unsynced'}  syncType     They way block is synced, 'full' or 'unsynced'.
+ * @param {string|undefined}   [content]    Optional serialized content of blocks to convert to pattern.
+ * @param {number[]|undefined} [categories] Ids of any selected categories.
+ */
+const createPattern = (title, syncType, content, categories) => async ({
+  registry
+}) => {
+  const meta = syncType === PATTERN_SYNC_TYPES.unsynced ? {
+    wp_pattern_sync_status: syncType
+  } : undefined;
+  const reusableBlock = {
+    title,
+    content,
+    status: 'publish',
+    meta,
+    wp_pattern_category: categories
+  };
+  const updatedRecord = await registry.dispatch(external_wp_coreData_namespaceObject.store).saveEntityRecord('postType', 'wp_block', reusableBlock);
+  return updatedRecord;
+};
+
+/**
+ * Create a pattern from a JSON file.
+ * @param {File}               file         The JSON file instance of the pattern.
+ * @param {number[]|undefined} [categories] Ids of any selected categories.
+ */
+const createPatternFromFile = (file, categories) => async ({
+  dispatch
+}) => {
+  const fileContent = await file.text();
+  /** @type {import('./types').PatternJSON} */
+  let parsedContent;
+  try {
+    parsedContent = JSON.parse(fileContent);
+  } catch (e) {
+    throw new Error('Invalid JSON file');
+  }
+  if (parsedContent.__file !== 'wp_block' || !parsedContent.title || !parsedContent.content || typeof parsedContent.title !== 'string' || typeof parsedContent.content !== 'string' || parsedContent.syncStatus && typeof parsedContent.syncStatus !== 'string') {
+    throw new Error('Invalid pattern JSON file');
+  }
+  const pattern = await dispatch.createPattern(parsedContent.title, parsedContent.syncStatus, parsedContent.content, categories);
+  return pattern;
+};
+
+/**
+ * Returns a generator converting a synced pattern block into a static block.
+ *
+ * @param {string} clientId The client ID of the block to attach.
+ */
+const convertSyncedPatternToStatic = clientId => ({
+  registry
+}) => {
+  const patternBlock = registry.select(external_wp_blockEditor_namespaceObject.store).getBlock(clientId);
+  const existingOverrides = patternBlock.attributes?.content;
+  function cloneBlocksAndRemoveBindings(blocks) {
+    return blocks.map(block => {
+      let metadata = block.attributes.metadata;
+      if (metadata) {
+        metadata = {
+          ...metadata
+        };
+        delete metadata.id;
+        delete metadata.bindings;
+        // Use overridden values of the pattern block if they exist.
+        if (existingOverrides?.[metadata.name]) {
+          // Iterate over each overriden attribute.
+          for (const [attributeName, value] of Object.entries(existingOverrides[metadata.name])) {
+            // Skip if the attribute does not exist in the block type.
+            if (!(0,external_wp_blocks_namespaceObject.getBlockType)(block.name)?.attributes[attributeName]) {
+              continue;
+            }
+            // Update the block attribute with the override value.
+            block.attributes[attributeName] = value;
+          }
+        }
+      }
+      return (0,external_wp_blocks_namespaceObject.cloneBlock)(block, {
+        metadata: metadata && Object.keys(metadata).length > 0 ? metadata : undefined
+      }, cloneBlocksAndRemoveBindings(block.innerBlocks));
+    });
+  }
+  const patternInnerBlocks = registry.select(external_wp_blockEditor_namespaceObject.store).getBlocks(patternBlock.clientId);
+  registry.dispatch(external_wp_blockEditor_namespaceObject.store).replaceBlocks(patternBlock.clientId, cloneBlocksAndRemoveBindings(patternInnerBlocks));
+};
+
+/**
+ * Returns an action descriptor for SET_EDITING_PATTERN action.
+ *
+ * @param {string}  clientId  The clientID of the pattern to target.
+ * @param {boolean} isEditing Whether the block should be in editing state.
+ * @return {Object} Action descriptor.
+ */
+function setEditingPattern(clientId, isEditing) {
+  return {
+    type: 'SET_EDITING_PATTERN',
+    clientId,
+    isEditing
+  };
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/store/constants.js
+/**
+ * Module Constants
+ */
+const STORE_NAME = 'core/patterns';
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/store/selectors.js
+/**
+ * Returns true if pattern is in the editing state.
+ *
+ * @param {Object} state    Global application state.
+ * @param {number} clientId the clientID of the block.
+ * @return {boolean} Whether the pattern is in the editing state.
+ */
+function selectors_isEditingPattern(state, clientId) {
+  return state.isEditingPattern[clientId];
+}
+
+;// CONCATENATED MODULE: external ["wp","privateApis"]
+const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/lock-unlock.js
+/**
+ * WordPress dependencies
+ */
+
+const {
+  lock,
+  unlock
+} = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/patterns');
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/store/index.js
+/**
+ * WordPress dependencies
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+
+/**
+ * Post editor data store configuration.
+ *
+ * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore
+ *
+ * @type {Object}
+ */
+const storeConfig = {
+  reducer: reducer
+};
+
+/**
+ * Store definition for the editor namespace.
+ *
+ * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
+ *
+ * @type {Object}
+ */
+const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
+  ...storeConfig
+});
+(0,external_wp_data_namespaceObject.register)(store);
+unlock(store).registerPrivateActions(actions_namespaceObject);
+unlock(store).registerPrivateSelectors(selectors_namespaceObject);
+
+;// CONCATENATED MODULE: external ["wp","components"]
+const external_wp_components_namespaceObject = window["wp"]["components"];
+;// CONCATENATED MODULE: external ["wp","element"]
+const external_wp_element_namespaceObject = window["wp"]["element"];
+;// CONCATENATED MODULE: external ["wp","i18n"]
+const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/api/index.js
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Determines whether a block is overridable.
+ *
+ * @param {WPBlock} block The block to test.
+ *
+ * @return {boolean} `true` if a block is overridable, `false` otherwise.
+ */
+function isOverridableBlock(block) {
+  return Object.keys(PARTIAL_SYNCING_SUPPORTED_BLOCKS).includes(block.name) && !!block.attributes.metadata?.name && !!block.attributes.metadata?.bindings && Object.values(block.attributes.metadata.bindings).some(binding => binding.source === 'core/pattern-overrides');
+}
+
+/**
+ * Determines whether the blocks list has overridable blocks.
+ *
+ * @param {WPBlock[]} blocks The blocks list.
+ *
+ * @return {boolean} `true` if the list has overridable blocks, `false` otherwise.
+ */
+function hasOverridableBlocks(blocks) {
+  return blocks.some(block => {
+    if (isOverridableBlock(block)) {
+      return true;
+    }
+    return hasOverridableBlocks(block.innerBlocks);
+  });
+}
+
+;// CONCATENATED MODULE: external "ReactJSXRuntime"
+const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/overrides-panel.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+const {
+  BlockQuickNavigation
+} = unlock(external_wp_blockEditor_namespaceObject.privateApis);
+function OverridesPanel() {
+  const allClientIds = (0,external_wp_data_namespaceObject.useSelect)(select => select(external_wp_blockEditor_namespaceObject.store).getClientIdsWithDescendants(), []);
+  const {
+    getBlock
+  } = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blockEditor_namespaceObject.store);
+  const clientIdsWithOverrides = (0,external_wp_element_namespaceObject.useMemo)(() => allClientIds.filter(clientId => {
+    const block = getBlock(clientId);
+    return isOverridableBlock(block);
+  }), [allClientIds, getBlock]);
+  if (!clientIdsWithOverrides?.length) {
+    return null;
+  }
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.PanelBody, {
+    title: (0,external_wp_i18n_namespaceObject.__)('Overrides'),
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockQuickNavigation, {
+      clientIds: clientIdsWithOverrides
+    })
+  });
+}
+
+;// CONCATENATED MODULE: external ["wp","notices"]
+const external_wp_notices_namespaceObject = window["wp"]["notices"];
+;// CONCATENATED MODULE: external ["wp","compose"]
+const external_wp_compose_namespaceObject = window["wp"]["compose"];
+;// CONCATENATED MODULE: external ["wp","htmlEntities"]
+const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/category-selector.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+const unescapeString = arg => {
+  return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(arg);
+};
+const CATEGORY_SLUG = 'wp_pattern_category';
+function CategorySelector({
+  categoryTerms,
+  onChange,
+  categoryMap
+}) {
+  const [search, setSearch] = (0,external_wp_element_namespaceObject.useState)('');
+  const debouncedSearch = (0,external_wp_compose_namespaceObject.useDebounce)(setSearch, 500);
+  const suggestions = (0,external_wp_element_namespaceObject.useMemo)(() => {
+    return Array.from(categoryMap.values()).map(category => unescapeString(category.label)).filter(category => {
+      if (search !== '') {
+        return category.toLowerCase().includes(search.toLowerCase());
+      }
+      return true;
+    }).sort((a, b) => a.localeCompare(b));
+  }, [search, categoryMap]);
+  function handleChange(termNames) {
+    const uniqueTerms = termNames.reduce((terms, newTerm) => {
+      if (!terms.some(term => term.toLowerCase() === newTerm.toLowerCase())) {
+        terms.push(newTerm);
+      }
+      return terms;
+    }, []);
+    onChange(uniqueTerms);
+  }
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FormTokenField, {
+    className: "patterns-menu-items__convert-modal-categories",
+    value: categoryTerms,
+    suggestions: suggestions,
+    onChange: handleChange,
+    onInputChange: debouncedSearch,
+    label: (0,external_wp_i18n_namespaceObject.__)('Categories'),
+    tokenizeOnBlur: true,
+    __experimentalExpandOnFocus: true,
+    __next40pxDefaultSize: true,
+    __nextHasNoMarginBottom: true
+  });
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/private-hooks.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+/**
+ * Helper hook that creates a Map with the core and user patterns categories
+ * and removes any duplicates. It's used when we need to create new user
+ * categories when creating or importing patterns.
+ * This hook also provides a function to find or create a pattern category.
+ *
+ * @return {Object} The merged categories map and the callback function to find or create a category.
+ */
+function useAddPatternCategory() {
+  const {
+    saveEntityRecord,
+    invalidateResolution
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_coreData_namespaceObject.store);
+  const {
+    corePatternCategories,
+    userPatternCategories
+  } = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    const {
+      getUserPatternCategories,
+      getBlockPatternCategories
+    } = select(external_wp_coreData_namespaceObject.store);
+    return {
+      corePatternCategories: getBlockPatternCategories(),
+      userPatternCategories: getUserPatternCategories()
+    };
+  }, []);
+  const categoryMap = (0,external_wp_element_namespaceObject.useMemo)(() => {
+    // Merge the user and core pattern categories and remove any duplicates.
+    const uniqueCategories = new Map();
+    userPatternCategories.forEach(category => {
+      uniqueCategories.set(category.label.toLowerCase(), {
+        label: category.label,
+        name: category.name,
+        id: category.id
+      });
+    });
+    corePatternCategories.forEach(category => {
+      if (!uniqueCategories.has(category.label.toLowerCase()) &&
+      // There are two core categories with `Post` label so explicitly remove the one with
+      // the `query` slug to avoid any confusion.
+      category.name !== 'query') {
+        uniqueCategories.set(category.label.toLowerCase(), {
+          label: category.label,
+          name: category.name
+        });
+      }
+    });
+    return uniqueCategories;
+  }, [userPatternCategories, corePatternCategories]);
+  async function findOrCreateTerm(term) {
+    try {
+      const existingTerm = categoryMap.get(term.toLowerCase());
+      if (existingTerm?.id) {
+        return existingTerm.id;
+      }
+      // If we have an existing core category we need to match the new user category to the
+      // correct slug rather than autogenerating it to prevent duplicates, eg. the core `Headers`
+      // category uses the singular `header` as the slug.
+      const termData = existingTerm ? {
+        name: existingTerm.label,
+        slug: existingTerm.name
+      } : {
+        name: term
+      };
+      const newTerm = await saveEntityRecord('taxonomy', CATEGORY_SLUG, termData, {
+        throwOnError: true
+      });
+      invalidateResolution('getUserPatternCategories');
+      return newTerm.id;
+    } catch (error) {
+      if (error.code !== 'term_exists') {
+        throw error;
+      }
+      return error.data.term_id;
+    }
+  }
+  return {
+    categoryMap,
+    findOrCreateTerm
+  };
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/create-pattern-modal.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+
+
+function CreatePatternModal({
+  className = 'patterns-menu-items__convert-modal',
+  modalTitle,
+  ...restProps
+}) {
+  const defaultModalTitle = (0,external_wp_data_namespaceObject.useSelect)(select => select(external_wp_coreData_namespaceObject.store).getPostType(PATTERN_TYPES.user)?.labels?.add_new_item, []);
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
+    title: modalTitle || defaultModalTitle,
+    onRequestClose: restProps.onClose,
+    overlayClassName: className,
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CreatePatternModalContents, {
+      ...restProps
+    })
+  });
+}
+function CreatePatternModalContents({
+  confirmLabel = (0,external_wp_i18n_namespaceObject.__)('Add'),
+  defaultCategories = [],
+  content,
+  onClose,
+  onError,
+  onSuccess,
+  defaultSyncType = PATTERN_SYNC_TYPES.full,
+  defaultTitle = ''
+}) {
+  const [syncType, setSyncType] = (0,external_wp_element_namespaceObject.useState)(defaultSyncType);
+  const [categoryTerms, setCategoryTerms] = (0,external_wp_element_namespaceObject.useState)(defaultCategories);
+  const [title, setTitle] = (0,external_wp_element_namespaceObject.useState)(defaultTitle);
+  const [isSaving, setIsSaving] = (0,external_wp_element_namespaceObject.useState)(false);
+  const {
+    createPattern
+  } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
+  const {
+    createErrorNotice
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
+  const {
+    categoryMap,
+    findOrCreateTerm
+  } = useAddPatternCategory();
+  async function onCreate(patternTitle, sync) {
+    if (!title || isSaving) {
+      return;
+    }
+    try {
+      setIsSaving(true);
+      const categories = await Promise.all(categoryTerms.map(termName => findOrCreateTerm(termName)));
+      const newPattern = await createPattern(patternTitle, sync, typeof content === 'function' ? content() : content, categories);
+      onSuccess({
+        pattern: newPattern,
+        categoryId: PATTERN_DEFAULT_CATEGORY
+      });
+    } catch (error) {
+      createErrorNotice(error.message, {
+        type: 'snackbar',
+        id: 'pattern-create'
+      });
+      onError?.();
+    } finally {
+      setIsSaving(false);
+      setCategoryTerms([]);
+      setTitle('');
+    }
+  }
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
+    onSubmit: event => {
+      event.preventDefault();
+      onCreate(title, syncType);
+    },
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
+      spacing: "5",
+      children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
+        label: (0,external_wp_i18n_namespaceObject.__)('Name'),
+        value: title,
+        onChange: setTitle,
+        placeholder: (0,external_wp_i18n_namespaceObject.__)('My pattern'),
+        className: "patterns-create-modal__name-input",
+        __nextHasNoMarginBottom: true,
+        __next40pxDefaultSize: true
+      }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CategorySelector, {
+        categoryTerms: categoryTerms,
+        onChange: setCategoryTerms,
+        categoryMap: categoryMap
+      }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToggleControl, {
+        label: (0,external_wp_i18n_namespaceObject._x)('Synced', 'pattern (singular)'),
+        help: (0,external_wp_i18n_namespaceObject.__)('Sync this pattern across multiple locations.'),
+        checked: syncType === PATTERN_SYNC_TYPES.full,
+        onChange: () => {
+          setSyncType(syncType === PATTERN_SYNC_TYPES.full ? PATTERN_SYNC_TYPES.unsynced : PATTERN_SYNC_TYPES.full);
+        }
+      }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
+        justify: "right",
+        children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+          __next40pxDefaultSize: true,
+          variant: "tertiary",
+          onClick: () => {
+            onClose();
+            setTitle('');
+          },
+          children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
+        }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+          __next40pxDefaultSize: true,
+          variant: "primary",
+          type: "submit",
+          "aria-disabled": !title || isSaving,
+          isBusy: isSaving,
+          children: confirmLabel
+        })]
+      })]
+    })
+  });
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/duplicate-pattern-modal.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+function getTermLabels(pattern, categories) {
+  // Theme patterns rely on core pattern categories.
+  if (pattern.type !== PATTERN_TYPES.user) {
+    return categories.core?.filter(category => pattern.categories.includes(category.name)).map(category => category.label);
+  }
+  return categories.user?.filter(category => pattern.wp_pattern_category.includes(category.id)).map(category => category.label);
+}
+function useDuplicatePatternProps({
+  pattern,
+  onSuccess
+}) {
+  const {
+    createSuccessNotice
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
+  const categories = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    const {
+      getUserPatternCategories,
+      getBlockPatternCategories
+    } = select(external_wp_coreData_namespaceObject.store);
+    return {
+      core: getBlockPatternCategories(),
+      user: getUserPatternCategories()
+    };
+  });
+  if (!pattern) {
+    return null;
+  }
+  return {
+    content: pattern.content,
+    defaultCategories: getTermLabels(pattern, categories),
+    defaultSyncType: pattern.type !== PATTERN_TYPES.user // Theme patterns are unsynced by default.
+    ? PATTERN_SYNC_TYPES.unsynced : pattern.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full,
+    defaultTitle: (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %s: Existing pattern title */
+    (0,external_wp_i18n_namespaceObject.__)('%s (Copy)'), typeof pattern.title === 'string' ? pattern.title : pattern.title.raw),
+    onSuccess: ({
+      pattern: newPattern
+    }) => {
+      createSuccessNotice((0,external_wp_i18n_namespaceObject.sprintf)(
+      // translators: %s: The new pattern's title e.g. 'Call to action (copy)'.
+      (0,external_wp_i18n_namespaceObject.__)('"%s" duplicated.'), newPattern.title.raw), {
+        type: 'snackbar',
+        id: 'patterns-create'
+      });
+      onSuccess?.({
+        pattern: newPattern
+      });
+    }
+  };
+}
+function DuplicatePatternModal({
+  pattern,
+  onClose,
+  onSuccess
+}) {
+  const duplicatedProps = useDuplicatePatternProps({
+    pattern,
+    onSuccess
+  });
+  if (!pattern) {
+    return null;
+  }
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CreatePatternModal, {
+    modalTitle: (0,external_wp_i18n_namespaceObject.__)('Duplicate pattern'),
+    confirmLabel: (0,external_wp_i18n_namespaceObject.__)('Duplicate'),
+    onClose: onClose,
+    onError: onClose,
+    ...duplicatedProps
+  });
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/rename-pattern-modal.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+
+
+
+function RenamePatternModal({
+  onClose,
+  onError,
+  onSuccess,
+  pattern,
+  ...props
+}) {
+  const originalName = (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(pattern.title);
+  const [name, setName] = (0,external_wp_element_namespaceObject.useState)(originalName);
+  const [isSaving, setIsSaving] = (0,external_wp_element_namespaceObject.useState)(false);
+  const {
+    editEntityRecord,
+    __experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_coreData_namespaceObject.store);
+  const {
+    createSuccessNotice,
+    createErrorNotice
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
+  const onRename = async event => {
+    event.preventDefault();
+    if (!name || name === pattern.title || isSaving) {
+      return;
+    }
+    try {
+      await editEntityRecord('postType', pattern.type, pattern.id, {
+        title: name
+      });
+      setIsSaving(true);
+      setName('');
+      onClose?.();
+      const savedRecord = await saveSpecifiedEntityEdits('postType', pattern.type, pattern.id, ['title'], {
+        throwOnError: true
+      });
+      onSuccess?.(savedRecord);
+      createSuccessNotice((0,external_wp_i18n_namespaceObject.__)('Pattern renamed'), {
+        type: 'snackbar',
+        id: 'pattern-update'
+      });
+    } catch (error) {
+      onError?.();
+      const errorMessage = error.message && error.code !== 'unknown_error' ? error.message : (0,external_wp_i18n_namespaceObject.__)('An error occurred while renaming the pattern.');
+      createErrorNotice(errorMessage, {
+        type: 'snackbar',
+        id: 'pattern-update'
+      });
+    } finally {
+      setIsSaving(false);
+      setName('');
+    }
+  };
+  const onRequestClose = () => {
+    onClose?.();
+    setName('');
+  };
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
+    title: (0,external_wp_i18n_namespaceObject.__)('Rename'),
+    ...props,
+    onRequestClose: onClose,
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
+      onSubmit: onRename,
+      children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
+        spacing: "5",
+        children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
+          __nextHasNoMarginBottom: true,
+          __next40pxDefaultSize: true,
+          label: (0,external_wp_i18n_namespaceObject.__)('Name'),
+          value: name,
+          onChange: setName,
+          required: true
+        }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
+          justify: "right",
+          children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "tertiary",
+            onClick: onRequestClose,
+            children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
+          }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "primary",
+            type: "submit",
+            children: (0,external_wp_i18n_namespaceObject.__)('Save')
+          })]
+        })]
+      })
+    })
+  });
+}
+
+;// CONCATENATED MODULE: external ["wp","primitives"]
+const external_wp_primitives_namespaceObject = window["wp"]["primitives"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/symbol.js
+/**
+ * WordPress dependencies
+ */
+
+
+const symbol = /*#__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: "M21.3 10.8l-5.6-5.6c-.7-.7-1.8-.7-2.5 0l-5.6 5.6c-.7.7-.7 1.8 0 2.5l5.6 5.6c.3.3.8.5 1.2.5s.9-.2 1.2-.5l5.6-5.6c.8-.7.8-1.9.1-2.5zm-1 1.4l-5.6 5.6c-.1.1-.3.1-.4 0l-5.6-5.6c-.1-.1-.1-.3 0-.4l5.6-5.6s.1-.1.2-.1.1 0 .2.1l5.6 5.6c.1.1.1.3 0 .4zm-16.6-.4L10 5.5l-1-1-6.3 6.3c-.7.7-.7 1.8 0 2.5L9 19.5l1.1-1.1-6.3-6.3c-.2 0-.2-.2-.1-.3z"
+  })
+});
+/* harmony default export */ const library_symbol = (symbol);
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/pattern-convert-button.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+/**
+ * Menu control to convert block(s) to a pattern block.
+ *
+ * @param {Object}   props                        Component props.
+ * @param {string[]} props.clientIds              Client ids of selected blocks.
+ * @param {string}   props.rootClientId           ID of the currently selected top-level block.
+ * @param {()=>void} props.closeBlockSettingsMenu Callback to close the block settings menu dropdown.
+ * @return {import('react').ComponentType} The menu control or null.
+ */
+
+
+
+function PatternConvertButton({
+  clientIds,
+  rootClientId,
+  closeBlockSettingsMenu
+}) {
+  const {
+    createSuccessNotice
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
+  const {
+    replaceBlocks
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_blockEditor_namespaceObject.store);
+  // Ignore reason: false positive of the lint rule.
+  // eslint-disable-next-line @wordpress/no-unused-vars-before-return
+  const {
+    setEditingPattern
+  } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
+  const [isModalOpen, setIsModalOpen] = (0,external_wp_element_namespaceObject.useState)(false);
+  const canConvert = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    var _getBlocksByClientId;
+    const {
+      canUser
+    } = select(external_wp_coreData_namespaceObject.store);
+    const {
+      getBlocksByClientId,
+      canInsertBlockType,
+      getBlockRootClientId
+    } = select(external_wp_blockEditor_namespaceObject.store);
+    const rootId = rootClientId || (clientIds.length > 0 ? getBlockRootClientId(clientIds[0]) : undefined);
+    const blocks = (_getBlocksByClientId = getBlocksByClientId(clientIds)) !== null && _getBlocksByClientId !== void 0 ? _getBlocksByClientId : [];
+    const isReusable = blocks.length === 1 && blocks[0] && (0,external_wp_blocks_namespaceObject.isReusableBlock)(blocks[0]) && !!select(external_wp_coreData_namespaceObject.store).getEntityRecord('postType', 'wp_block', blocks[0].attributes.ref);
+    const _canConvert =
+    // Hide when this is already a synced pattern.
+    !isReusable &&
+    // Hide when patterns are disabled.
+    canInsertBlockType('core/block', rootId) && blocks.every(block =>
+    // Guard against the case where a regular block has *just* been converted.
+    !!block &&
+    // Hide on invalid blocks.
+    block.isValid &&
+    // Hide when block doesn't support being made into a pattern.
+    (0,external_wp_blocks_namespaceObject.hasBlockSupport)(block.name, 'reusable', true)) &&
+    // Hide when current doesn't have permission to do that.
+    !!canUser('create', 'blocks');
+    return _canConvert;
+  }, [clientIds, rootClientId]);
+  const {
+    getBlocksByClientId
+  } = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blockEditor_namespaceObject.store);
+  const getContent = (0,external_wp_element_namespaceObject.useCallback)(() => (0,external_wp_blocks_namespaceObject.serialize)(getBlocksByClientId(clientIds)), [getBlocksByClientId, clientIds]);
+  if (!canConvert) {
+    return null;
+  }
+  const handleSuccess = ({
+    pattern
+  }) => {
+    if (pattern.wp_pattern_sync_status !== PATTERN_SYNC_TYPES.unsynced) {
+      const newBlock = (0,external_wp_blocks_namespaceObject.createBlock)('core/block', {
+        ref: pattern.id
+      });
+      replaceBlocks(clientIds, newBlock);
+      setEditingPattern(newBlock.clientId, true);
+      closeBlockSettingsMenu();
+    }
+    createSuccessNotice(pattern.wp_pattern_sync_status === PATTERN_SYNC_TYPES.unsynced ? (0,external_wp_i18n_namespaceObject.sprintf)(
+    // translators: %s: the name the user has given to the pattern.
+    (0,external_wp_i18n_namespaceObject.__)('Unsynced pattern created: %s'), pattern.title.raw) : (0,external_wp_i18n_namespaceObject.sprintf)(
+    // translators: %s: the name the user has given to the pattern.
+    (0,external_wp_i18n_namespaceObject.__)('Synced pattern created: %s'), pattern.title.raw), {
+      type: 'snackbar',
+      id: 'convert-to-pattern-success'
+    });
+    setIsModalOpen(false);
+  };
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
+    children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, {
+      icon: library_symbol,
+      onClick: () => setIsModalOpen(true),
+      "aria-expanded": isModalOpen,
+      "aria-haspopup": "dialog",
+      children: (0,external_wp_i18n_namespaceObject.__)('Create pattern')
+    }), isModalOpen && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CreatePatternModal, {
+      content: getContent,
+      onSuccess: pattern => {
+        handleSuccess(pattern);
+      },
+      onError: () => {
+        setIsModalOpen(false);
+      },
+      onClose: () => {
+        setIsModalOpen(false);
+      }
+    })]
+  });
+}
+
+;// CONCATENATED MODULE: external ["wp","url"]
+const external_wp_url_namespaceObject = window["wp"]["url"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/patterns-manage-button.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+function PatternsManageButton({
+  clientId
+}) {
+  const {
+    canRemove,
+    isVisible,
+    managePatternsUrl
+  } = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    const {
+      getBlock,
+      canRemoveBlock,
+      getBlockCount
+    } = select(external_wp_blockEditor_namespaceObject.store);
+    const {
+      canUser
+    } = select(external_wp_coreData_namespaceObject.store);
+    const reusableBlock = getBlock(clientId);
+    return {
+      canRemove: canRemoveBlock(clientId),
+      isVisible: !!reusableBlock && (0,external_wp_blocks_namespaceObject.isReusableBlock)(reusableBlock) && !!canUser('update', 'blocks', reusableBlock.attributes.ref),
+      innerBlockCount: getBlockCount(clientId),
+      // The site editor and templates both check whether the user
+      // has edit_theme_options capabilities. We can leverage that here
+      // and omit the manage patterns link if the user can't access it.
+      managePatternsUrl: canUser('create', 'templates') ? (0,external_wp_url_namespaceObject.addQueryArgs)('site-editor.php', {
+        path: '/patterns'
+      }) : (0,external_wp_url_namespaceObject.addQueryArgs)('edit.php', {
+        post_type: 'wp_block'
+      })
+    };
+  }, [clientId]);
+
+  // Ignore reason: false positive of the lint rule.
+  // eslint-disable-next-line @wordpress/no-unused-vars-before-return
+  const {
+    convertSyncedPatternToStatic
+  } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
+  if (!isVisible) {
+    return null;
+  }
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
+    children: [canRemove && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, {
+      onClick: () => convertSyncedPatternToStatic(clientId),
+      children: (0,external_wp_i18n_namespaceObject.__)('Detach')
+    }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, {
+      href: managePatternsUrl,
+      children: (0,external_wp_i18n_namespaceObject.__)('Manage patterns')
+    })]
+  });
+}
+/* harmony default export */ const patterns_manage_button = (PatternsManageButton);
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/index.js
+/**
+ * WordPress dependencies
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+function PatternsMenuItems({
+  rootClientId
+}) {
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.BlockSettingsMenuControls, {
+    children: ({
+      selectedClientIds,
+      onClose
+    }) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
+      children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternConvertButton, {
+        clientIds: selectedClientIds,
+        rootClientId: rootClientId,
+        closeBlockSettingsMenu: onClose
+      }), selectedClientIds.length === 1 && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(patterns_manage_button, {
+        clientId: selectedClientIds[0]
+      })]
+    })
+  });
+}
+
+;// CONCATENATED MODULE: external ["wp","a11y"]
+const external_wp_a11y_namespaceObject = window["wp"]["a11y"];
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/rename-pattern-category-modal.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+function RenamePatternCategoryModal({
+  category,
+  existingCategories,
+  onClose,
+  onError,
+  onSuccess,
+  ...props
+}) {
+  const id = (0,external_wp_element_namespaceObject.useId)();
+  const textControlRef = (0,external_wp_element_namespaceObject.useRef)();
+  const [name, setName] = (0,external_wp_element_namespaceObject.useState)((0,external_wp_htmlEntities_namespaceObject.decodeEntities)(category.name));
+  const [isSaving, setIsSaving] = (0,external_wp_element_namespaceObject.useState)(false);
+  const [validationMessage, setValidationMessage] = (0,external_wp_element_namespaceObject.useState)(false);
+  const validationMessageId = validationMessage ? `patterns-rename-pattern-category-modal__validation-message-${id}` : undefined;
+  const {
+    saveEntityRecord,
+    invalidateResolution
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_coreData_namespaceObject.store);
+  const {
+    createErrorNotice,
+    createSuccessNotice
+  } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
+  const onChange = newName => {
+    if (validationMessage) {
+      setValidationMessage(undefined);
+    }
+    setName(newName);
+  };
+  const onSave = async event => {
+    event.preventDefault();
+    if (isSaving) {
+      return;
+    }
+    if (!name || name === category.name) {
+      const message = (0,external_wp_i18n_namespaceObject.__)('Please enter a new name for this category.');
+      (0,external_wp_a11y_namespaceObject.speak)(message, 'assertive');
+      setValidationMessage(message);
+      textControlRef.current?.focus();
+      return;
+    }
+
+    // Check existing categories to avoid creating duplicates.
+    if (existingCategories.patternCategories.find(existingCategory => {
+      // Compare the id so that the we don't disallow the user changing the case of their current category
+      // (i.e. renaming 'test' to 'Test').
+      return existingCategory.id !== category.id && existingCategory.label.toLowerCase() === name.toLowerCase();
+    })) {
+      const message = (0,external_wp_i18n_namespaceObject.__)('This category already exists. Please use a different name.');
+      (0,external_wp_a11y_namespaceObject.speak)(message, 'assertive');
+      setValidationMessage(message);
+      textControlRef.current?.focus();
+      return;
+    }
+    try {
+      setIsSaving(true);
+
+      // User pattern category properties may differ as they can be
+      // normalized for use alongside template part areas, core pattern
+      // categories etc. As a result we won't just destructure the passed
+      // category object.
+      const savedRecord = await saveEntityRecord('taxonomy', CATEGORY_SLUG, {
+        id: category.id,
+        slug: category.slug,
+        name
+      });
+      invalidateResolution('getUserPatternCategories');
+      onSuccess?.(savedRecord);
+      onClose();
+      createSuccessNotice((0,external_wp_i18n_namespaceObject.__)('Pattern category renamed.'), {
+        type: 'snackbar',
+        id: 'pattern-category-update'
+      });
+    } catch (error) {
+      onError?.();
+      createErrorNotice(error.message, {
+        type: 'snackbar',
+        id: 'pattern-category-update'
+      });
+    } finally {
+      setIsSaving(false);
+      setName('');
+    }
+  };
+  const onRequestClose = () => {
+    onClose();
+    setName('');
+  };
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
+    title: (0,external_wp_i18n_namespaceObject.__)('Rename'),
+    onRequestClose: onRequestClose,
+    ...props,
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
+      onSubmit: onSave,
+      children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
+        spacing: "5",
+        children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
+          spacing: "2",
+          children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
+            ref: textControlRef,
+            __nextHasNoMarginBottom: true,
+            __next40pxDefaultSize: true,
+            label: (0,external_wp_i18n_namespaceObject.__)('Name'),
+            value: name,
+            onChange: onChange,
+            "aria-describedby": validationMessageId,
+            required: true
+          }), validationMessage && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", {
+            className: "patterns-rename-pattern-category-modal__validation-message",
+            id: validationMessageId,
+            children: validationMessage
+          })]
+        }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
+          justify: "right",
+          children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "tertiary",
+            onClick: onRequestClose,
+            children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
+          }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "primary",
+            type: "submit",
+            "aria-disabled": !name || name === category.name || isSaving,
+            isBusy: isSaving,
+            children: (0,external_wp_i18n_namespaceObject.__)('Save')
+          })]
+        })]
+      })
+    })
+  });
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/allow-overrides-modal.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+function AllowOverridesModal({
+  placeholder,
+  initialName = '',
+  onClose,
+  onSave
+}) {
+  const [editedBlockName, setEditedBlockName] = (0,external_wp_element_namespaceObject.useState)(initialName);
+  const descriptionId = (0,external_wp_element_namespaceObject.useId)();
+  const isNameValid = !!editedBlockName.trim();
+  const handleSubmit = () => {
+    if (editedBlockName !== initialName) {
+      const message = (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %s: new name/label for the block */
+      (0,external_wp_i18n_namespaceObject.__)('Block name changed to: "%s".'), editedBlockName);
+
+      // Must be assertive to immediately announce change.
+      (0,external_wp_a11y_namespaceObject.speak)(message, 'assertive');
+    }
+    onSave(editedBlockName);
+
+    // Immediate close avoids ability to hit save multiple times.
+    onClose();
+  };
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
+    title: (0,external_wp_i18n_namespaceObject.__)('Enable overrides'),
+    onRequestClose: onClose,
+    focusOnMount: "firstContentElement",
+    aria: {
+      describedby: descriptionId
+    },
+    size: "small",
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
+      onSubmit: event => {
+        event.preventDefault();
+        if (!isNameValid) {
+          return;
+        }
+        handleSubmit();
+      },
+      children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
+        spacing: "6",
+        children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, {
+          id: descriptionId,
+          children: (0,external_wp_i18n_namespaceObject.__)('Overrides are changes you make to a block within a synced pattern instance. Use overrides to customize a synced pattern instance to suit its new context. Name this block to specify an override.')
+        }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
+          __nextHasNoMarginBottom: true,
+          __next40pxDefaultSize: true,
+          value: editedBlockName,
+          label: (0,external_wp_i18n_namespaceObject.__)('Name'),
+          help: (0,external_wp_i18n_namespaceObject.__)('For example, if you are creating a recipe pattern, you use "Recipe Title", "Recipe Description", etc.'),
+          placeholder: placeholder,
+          onChange: setEditedBlockName
+        }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
+          justify: "right",
+          children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "tertiary",
+            onClick: onClose,
+            children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
+          }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            "aria-disabled": !isNameValid,
+            variant: "primary",
+            type: "submit",
+            children: (0,external_wp_i18n_namespaceObject.__)('Enable')
+          })]
+        })]
+      })
+    })
+  });
+}
+function DisallowOverridesModal({
+  onClose,
+  onSave
+}) {
+  const descriptionId = (0,external_wp_element_namespaceObject.useId)();
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
+    title: (0,external_wp_i18n_namespaceObject.__)('Disable overrides'),
+    onRequestClose: onClose,
+    aria: {
+      describedby: descriptionId
+    },
+    size: "small",
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
+      onSubmit: event => {
+        event.preventDefault();
+        onSave();
+        onClose();
+      },
+      children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
+        spacing: "6",
+        children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, {
+          id: descriptionId,
+          children: (0,external_wp_i18n_namespaceObject.__)('Are you sure you want to disable overrides? Disabling overrides will revert all applied overrides for this block throughout instances of this pattern.')
+        }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
+          justify: "right",
+          children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "tertiary",
+            onClick: onClose,
+            children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
+          }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+            __next40pxDefaultSize: true,
+            variant: "primary",
+            type: "submit",
+            children: (0,external_wp_i18n_namespaceObject.__)('Disable')
+          })]
+        })]
+      })
+    })
+  });
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/pattern-overrides-controls.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+function removeBindings(bindings) {
+  let updatedBindings = {
+    ...bindings
+  };
+  delete updatedBindings.__default;
+  if (!Object.keys(updatedBindings).length) {
+    updatedBindings = undefined;
+  }
+  return updatedBindings;
+}
+function addBindings(bindings) {
+  return {
+    ...bindings,
+    __default: {
+      source: PATTERN_OVERRIDES_BINDING_SOURCE
+    }
+  };
+}
+function PatternOverridesControls({
+  attributes,
+  setAttributes,
+  name: blockName
+}) {
+  const controlId = (0,external_wp_element_namespaceObject.useId)();
+  const [showAllowOverridesModal, setShowAllowOverridesModal] = (0,external_wp_element_namespaceObject.useState)(false);
+  const [showDisallowOverridesModal, setShowDisallowOverridesModal] = (0,external_wp_element_namespaceObject.useState)(false);
+  const hasName = !!attributes.metadata?.name;
+  const defaultBindings = attributes.metadata?.bindings?.__default;
+  const hasOverrides = hasName && defaultBindings?.source === PATTERN_OVERRIDES_BINDING_SOURCE;
+  const isConnectedToOtherSources = defaultBindings?.source && defaultBindings.source !== PATTERN_OVERRIDES_BINDING_SOURCE;
+  function updateBindings(isChecked, customName) {
+    const prevBindings = attributes?.metadata?.bindings;
+    const updatedBindings = isChecked ? addBindings(prevBindings) : removeBindings(prevBindings);
+    const updatedMetadata = {
+      ...attributes.metadata,
+      bindings: updatedBindings
+    };
+    if (customName) {
+      updatedMetadata.name = customName;
+    }
+    setAttributes({
+      metadata: updatedMetadata
+    });
+  }
+
+  // Avoid overwriting other (e.g. meta) bindings.
+  if (isConnectedToOtherSources) {
+    return null;
+  }
+  const hasUnsupportedImageAttributes = blockName === 'core/image' && (!!attributes.caption?.length || !!attributes.href?.length);
+  const helpText = !hasOverrides && hasUnsupportedImageAttributes ? (0,external_wp_i18n_namespaceObject.__)(`Overrides currently don't support image captions or links. Remove the caption or link first before enabling overrides.`) : (0,external_wp_i18n_namespaceObject.__)('Allow changes to this block throughout instances of this pattern.');
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
+    children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.InspectorControls, {
+      group: "advanced",
+      children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.BaseControl, {
+        id: controlId,
+        label: (0,external_wp_i18n_namespaceObject.__)('Overrides'),
+        help: helpText,
+        children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
+          __next40pxDefaultSize: true,
+          className: "pattern-overrides-control__allow-overrides-button",
+          variant: "secondary",
+          "aria-haspopup": "dialog",
+          onClick: () => {
+            if (hasOverrides) {
+              setShowDisallowOverridesModal(true);
+            } else {
+              setShowAllowOverridesModal(true);
+            }
+          },
+          disabled: !hasOverrides && hasUnsupportedImageAttributes,
+          __experimentalIsFocusable: true,
+          children: hasOverrides ? (0,external_wp_i18n_namespaceObject.__)('Disable overrides') : (0,external_wp_i18n_namespaceObject.__)('Enable overrides')
+        })
+      })
+    }), showAllowOverridesModal && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(AllowOverridesModal, {
+      initialName: attributes.metadata?.name,
+      onClose: () => setShowAllowOverridesModal(false),
+      onSave: newName => {
+        updateBindings(true, newName);
+      }
+    }), showDisallowOverridesModal && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(DisallowOverridesModal, {
+      onClose: () => setShowDisallowOverridesModal(false),
+      onSave: () => updateBindings(false)
+    })]
+  });
+}
+/* harmony default export */ const pattern_overrides_controls = (PatternOverridesControls);
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/reset-overrides-control.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+const CONTENT = 'content';
+function ResetOverridesControl(props) {
+  const name = props.attributes.metadata?.name;
+  const registry = (0,external_wp_data_namespaceObject.useRegistry)();
+  const isOverriden = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    if (!name) {
+      return;
+    }
+    const {
+      getBlockAttributes,
+      getBlockParentsByBlockName
+    } = select(external_wp_blockEditor_namespaceObject.store);
+    const [patternClientId] = getBlockParentsByBlockName(props.clientId, 'core/block', true);
+    if (!patternClientId) {
+      return;
+    }
+    const overrides = getBlockAttributes(patternClientId)[CONTENT];
+    if (!overrides) {
+      return;
+    }
+    return overrides.hasOwnProperty(name);
+  }, [props.clientId, name]);
+  function onClick() {
+    const {
+      getBlockAttributes,
+      getBlockParentsByBlockName
+    } = registry.select(external_wp_blockEditor_namespaceObject.store);
+    const [patternClientId] = getBlockParentsByBlockName(props.clientId, 'core/block', true);
+    if (!patternClientId) {
+      return;
+    }
+    const overrides = getBlockAttributes(patternClientId)[CONTENT];
+    if (!overrides.hasOwnProperty(name)) {
+      return;
+    }
+    const {
+      updateBlockAttributes,
+      __unstableMarkLastChangeAsPersistent
+    } = registry.dispatch(external_wp_blockEditor_namespaceObject.store);
+    __unstableMarkLastChangeAsPersistent();
+    let newOverrides = {
+      ...overrides
+    };
+    delete newOverrides[name];
+    if (!Object.keys(newOverrides).length) {
+      newOverrides = undefined;
+    }
+    updateBlockAttributes(patternClientId, {
+      [CONTENT]: newOverrides
+    });
+  }
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.__unstableBlockToolbarLastItem, {
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToolbarGroup, {
+      children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToolbarButton, {
+        onClick: onClick,
+        disabled: !isOverriden,
+        __experimentalIsFocusable: true,
+        children: (0,external_wp_i18n_namespaceObject.__)('Reset')
+      })
+    })
+  });
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/icons/build-module/library/copy.js
+/**
+ * WordPress dependencies
+ */
+
+
+const copy = /*#__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, {
+    fillRule: "evenodd",
+    clipRule: "evenodd",
+    d: "M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"
+  })
+});
+/* harmony default export */ const library_copy = (copy);
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/components/pattern-overrides-block-controls.js
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+
+
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+const {
+  useBlockDisplayTitle
+} = unlock(external_wp_blockEditor_namespaceObject.privateApis);
+function PatternOverridesToolbarIndicator({
+  clientIds
+}) {
+  const isSingleBlockSelected = clientIds.length === 1;
+  const {
+    icon,
+    firstBlockName
+  } = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    const {
+      getBlockAttributes,
+      getBlockNamesByClientId
+    } = select(external_wp_blockEditor_namespaceObject.store);
+    const {
+      getBlockType,
+      getActiveBlockVariation
+    } = select(external_wp_blocks_namespaceObject.store);
+    const blockTypeNames = getBlockNamesByClientId(clientIds);
+    const _firstBlockTypeName = blockTypeNames[0];
+    const firstBlockType = getBlockType(_firstBlockTypeName);
+    let _icon;
+    if (isSingleBlockSelected) {
+      const match = getActiveBlockVariation(_firstBlockTypeName, getBlockAttributes(clientIds[0]));
+      // Take into account active block variations.
+      _icon = match?.icon || firstBlockType.icon;
+    } else {
+      const isSelectionOfSameType = new Set(blockTypeNames).size === 1;
+      // When selection consists of blocks of multiple types, display an
+      // appropriate icon to communicate the non-uniformity.
+      _icon = isSelectionOfSameType ? firstBlockType.icon : library_copy;
+    }
+    return {
+      icon: _icon,
+      firstBlockName: getBlockAttributes(clientIds[0]).metadata.name
+    };
+  }, [clientIds, isSingleBlockSelected]);
+  const firstBlockTitle = useBlockDisplayTitle({
+    clientId: clientIds[0],
+    maximumLength: 35
+  });
+  const blockDescription = isSingleBlockSelected ? (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %1s: The block type's name; %2s: The block's user-provided name (the same as the override name). */
+  (0,external_wp_i18n_namespaceObject.__)('This %1$s is editable using the "%2$s" override.'), firstBlockTitle.toLowerCase(), firstBlockName) : (0,external_wp_i18n_namespaceObject.__)('These blocks are editable using overrides.');
+  const descriptionId = (0,external_wp_element_namespaceObject.useId)();
+  return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToolbarItem, {
+    children: toggleProps => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.DropdownMenu, {
+      className: "patterns-pattern-overrides-toolbar-indicator",
+      label: firstBlockTitle,
+      popoverProps: {
+        placement: 'bottom-start',
+        className: 'patterns-pattern-overrides-toolbar-indicator__popover'
+      },
+      icon: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, {
+        children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.BlockIcon, {
+          icon: icon,
+          className: "patterns-pattern-overrides-toolbar-indicator-icon",
+          showColors: true
+        })
+      }),
+      toggleProps: {
+        describedBy: blockDescription,
+        ...toggleProps
+      },
+      menuProps: {
+        orientation: 'both',
+        'aria-describedby': descriptionId
+      },
+      children: () => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, {
+        id: descriptionId,
+        children: blockDescription
+      })
+    })
+  });
+}
+function PatternOverridesBlockControls() {
+  const {
+    clientIds,
+    hasPatternOverrides,
+    hasParentPattern
+  } = (0,external_wp_data_namespaceObject.useSelect)(select => {
+    const {
+      getBlockAttributes,
+      getSelectedBlockClientIds,
+      getBlockParentsByBlockName
+    } = select(external_wp_blockEditor_namespaceObject.store);
+    const selectedClientIds = getSelectedBlockClientIds();
+    const _hasPatternOverrides = selectedClientIds.every(clientId => {
+      var _getBlockAttributes$m;
+      return Object.values((_getBlockAttributes$m = getBlockAttributes(clientId)?.metadata?.bindings) !== null && _getBlockAttributes$m !== void 0 ? _getBlockAttributes$m : {}).some(binding => binding?.source === PATTERN_OVERRIDES_BINDING_SOURCE);
+    });
+    const _hasParentPattern = selectedClientIds.every(clientId => getBlockParentsByBlockName(clientId, 'core/block', true).length > 0);
+    return {
+      clientIds: selectedClientIds,
+      hasPatternOverrides: _hasPatternOverrides,
+      hasParentPattern: _hasParentPattern
+    };
+  }, []);
+  return hasPatternOverrides && hasParentPattern ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.BlockControls, {
+    group: "parent",
+    children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternOverridesToolbarIndicator, {
+      clientIds: clientIds
+    })
+  }) : null;
+}
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/private-apis.js
+/**
+ * Internal dependencies
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+const privateApis = {};
+lock(privateApis, {
+  OverridesPanel: OverridesPanel,
+  CreatePatternModal: CreatePatternModal,
+  CreatePatternModalContents: CreatePatternModalContents,
+  DuplicatePatternModal: DuplicatePatternModal,
+  isOverridableBlock: isOverridableBlock,
+  hasOverridableBlocks: hasOverridableBlocks,
+  useDuplicatePatternProps: useDuplicatePatternProps,
+  RenamePatternModal: RenamePatternModal,
+  PatternsMenuItems: PatternsMenuItems,
+  RenamePatternCategoryModal: RenamePatternCategoryModal,
+  PatternOverridesControls: pattern_overrides_controls,
+  ResetOverridesControl: ResetOverridesControl,
+  PatternOverridesBlockControls: PatternOverridesBlockControls,
+  useAddPatternCategory: useAddPatternCategory,
+  PATTERN_TYPES: PATTERN_TYPES,
+  PATTERN_DEFAULT_CATEGORY: PATTERN_DEFAULT_CATEGORY,
+  PATTERN_USER_CATEGORY: PATTERN_USER_CATEGORY,
+  EXCLUDED_PATTERN_SOURCES: EXCLUDED_PATTERN_SOURCES,
+  PATTERN_SYNC_TYPES: PATTERN_SYNC_TYPES,
+  PARTIAL_SYNCING_SUPPORTED_BLOCKS: PARTIAL_SYNCING_SUPPORTED_BLOCKS
+});
+
+;// CONCATENATED MODULE: ./node_modules/@wordpress/patterns/build-module/index.js
+/**
+ * Internal dependencies
+ */
+
+
+
+(window.wp = window.wp || {}).patterns = __webpack_exports__;
+/******/ })()
+;
\ No newline at end of file