[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/ -> patterns.js (source)

   1  var wp;
   2  (wp ||= {}).patterns = (() => {
   3    var __create = Object.create;
   4    var __defProp = Object.defineProperty;
   5    var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
   6    var __getOwnPropNames = Object.getOwnPropertyNames;
   7    var __getProtoOf = Object.getPrototypeOf;
   8    var __hasOwnProp = Object.prototype.hasOwnProperty;
   9    var __commonJS = (cb, mod) => function __require() {
  10      return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  11    };
  12    var __export = (target, all) => {
  13      for (var name in all)
  14        __defProp(target, name, { get: all[name], enumerable: true });
  15    };
  16    var __copyProps = (to, from, except, desc) => {
  17      if (from && typeof from === "object" || typeof from === "function") {
  18        for (let key of __getOwnPropNames(from))
  19          if (!__hasOwnProp.call(to, key) && key !== except)
  20            __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  21      }
  22      return to;
  23    };
  24    var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  25      // If the importer is in node compatibility mode or this is not an ESM
  26      // file that has been converted to a CommonJS file using a Babel-
  27      // compatible transform (i.e. "__esModule" has not been set), then set
  28      // "default" to the CommonJS "module.exports" for node compatibility.
  29      isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  30      mod
  31    ));
  32    var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  33  
  34    // package-external:@wordpress/data
  35    var require_data = __commonJS({
  36      "package-external:@wordpress/data"(exports, module) {
  37        module.exports = window.wp.data;
  38      }
  39    });
  40  
  41    // package-external:@wordpress/blocks
  42    var require_blocks = __commonJS({
  43      "package-external:@wordpress/blocks"(exports, module) {
  44        module.exports = window.wp.blocks;
  45      }
  46    });
  47  
  48    // package-external:@wordpress/core-data
  49    var require_core_data = __commonJS({
  50      "package-external:@wordpress/core-data"(exports, module) {
  51        module.exports = window.wp.coreData;
  52      }
  53    });
  54  
  55    // package-external:@wordpress/block-editor
  56    var require_block_editor = __commonJS({
  57      "package-external:@wordpress/block-editor"(exports, module) {
  58        module.exports = window.wp.blockEditor;
  59      }
  60    });
  61  
  62    // package-external:@wordpress/private-apis
  63    var require_private_apis = __commonJS({
  64      "package-external:@wordpress/private-apis"(exports, module) {
  65        module.exports = window.wp.privateApis;
  66      }
  67    });
  68  
  69    // package-external:@wordpress/components
  70    var require_components = __commonJS({
  71      "package-external:@wordpress/components"(exports, module) {
  72        module.exports = window.wp.components;
  73      }
  74    });
  75  
  76    // package-external:@wordpress/element
  77    var require_element = __commonJS({
  78      "package-external:@wordpress/element"(exports, module) {
  79        module.exports = window.wp.element;
  80      }
  81    });
  82  
  83    // package-external:@wordpress/i18n
  84    var require_i18n = __commonJS({
  85      "package-external:@wordpress/i18n"(exports, module) {
  86        module.exports = window.wp.i18n;
  87      }
  88    });
  89  
  90    // vendor-external:react/jsx-runtime
  91    var require_jsx_runtime = __commonJS({
  92      "vendor-external:react/jsx-runtime"(exports, module) {
  93        module.exports = window.ReactJSXRuntime;
  94      }
  95    });
  96  
  97    // package-external:@wordpress/notices
  98    var require_notices = __commonJS({
  99      "package-external:@wordpress/notices"(exports, module) {
 100        module.exports = window.wp.notices;
 101      }
 102    });
 103  
 104    // package-external:@wordpress/compose
 105    var require_compose = __commonJS({
 106      "package-external:@wordpress/compose"(exports, module) {
 107        module.exports = window.wp.compose;
 108      }
 109    });
 110  
 111    // package-external:@wordpress/html-entities
 112    var require_html_entities = __commonJS({
 113      "package-external:@wordpress/html-entities"(exports, module) {
 114        module.exports = window.wp.htmlEntities;
 115      }
 116    });
 117  
 118    // package-external:@wordpress/primitives
 119    var require_primitives = __commonJS({
 120      "package-external:@wordpress/primitives"(exports, module) {
 121        module.exports = window.wp.primitives;
 122      }
 123    });
 124  
 125    // package-external:@wordpress/url
 126    var require_url = __commonJS({
 127      "package-external:@wordpress/url"(exports, module) {
 128        module.exports = window.wp.url;
 129      }
 130    });
 131  
 132    // package-external:@wordpress/a11y
 133    var require_a11y = __commonJS({
 134      "package-external:@wordpress/a11y"(exports, module) {
 135        module.exports = window.wp.a11y;
 136      }
 137    });
 138  
 139    // packages/patterns/build-module/index.js
 140    var index_exports = {};
 141    __export(index_exports, {
 142      privateApis: () => privateApis,
 143      store: () => store
 144    });
 145  
 146    // packages/patterns/build-module/store/index.js
 147    var import_data2 = __toESM(require_data());
 148  
 149    // packages/patterns/build-module/store/reducer.js
 150    var import_data = __toESM(require_data());
 151    function isEditingPattern(state = {}, action) {
 152      if (action?.type === "SET_EDITING_PATTERN") {
 153        return {
 154          ...state,
 155          [action.clientId]: action.isEditing
 156        };
 157      }
 158      return state;
 159    }
 160    var reducer_default = (0, import_data.combineReducers)({
 161      isEditingPattern
 162    });
 163  
 164    // packages/patterns/build-module/store/actions.js
 165    var actions_exports = {};
 166    __export(actions_exports, {
 167      convertSyncedPatternToStatic: () => convertSyncedPatternToStatic,
 168      createPattern: () => createPattern,
 169      createPatternFromFile: () => createPatternFromFile,
 170      setEditingPattern: () => setEditingPattern
 171    });
 172    var import_blocks = __toESM(require_blocks());
 173    var import_core_data = __toESM(require_core_data());
 174    var import_block_editor = __toESM(require_block_editor());
 175  
 176    // packages/patterns/build-module/constants.js
 177    var PATTERN_TYPES = {
 178      theme: "pattern",
 179      user: "wp_block"
 180    };
 181    var PATTERN_DEFAULT_CATEGORY = "all-patterns";
 182    var PATTERN_USER_CATEGORY = "my-patterns";
 183    var EXCLUDED_PATTERN_SOURCES = [
 184      "core",
 185      "pattern-directory/core",
 186      "pattern-directory/featured"
 187    ];
 188    var PATTERN_SYNC_TYPES = {
 189      full: "fully",
 190      unsynced: "unsynced"
 191    };
 192    var PARTIAL_SYNCING_SUPPORTED_BLOCKS = {
 193      "core/paragraph": ["content"],
 194      "core/heading": ["content"],
 195      "core/button": ["text", "url", "linkTarget", "rel"],
 196      "core/image": ["id", "url", "title", "alt", "caption"]
 197    };
 198    var PATTERN_OVERRIDES_BINDING_SOURCE = "core/pattern-overrides";
 199  
 200    // packages/patterns/build-module/store/actions.js
 201    var createPattern = (title, syncType, content, categories) => async ({ registry }) => {
 202      const meta = syncType === PATTERN_SYNC_TYPES.unsynced ? {
 203        wp_pattern_sync_status: syncType
 204      } : void 0;
 205      const reusableBlock = {
 206        title,
 207        content,
 208        status: "publish",
 209        meta,
 210        wp_pattern_category: categories
 211      };
 212      const updatedRecord = await registry.dispatch(import_core_data.store).saveEntityRecord("postType", "wp_block", reusableBlock);
 213      return updatedRecord;
 214    };
 215    var createPatternFromFile = (file, categories) => async ({ dispatch }) => {
 216      const fileContent = await file.text();
 217      let parsedContent;
 218      try {
 219        parsedContent = JSON.parse(fileContent);
 220      } catch (e) {
 221        throw new Error("Invalid JSON file");
 222      }
 223      if (parsedContent.__file !== "wp_block" || !parsedContent.title || !parsedContent.content || typeof parsedContent.title !== "string" || typeof parsedContent.content !== "string" || parsedContent.syncStatus && typeof parsedContent.syncStatus !== "string") {
 224        throw new Error("Invalid pattern JSON file");
 225      }
 226      const pattern = await dispatch.createPattern(
 227        parsedContent.title,
 228        parsedContent.syncStatus,
 229        parsedContent.content,
 230        categories
 231      );
 232      return pattern;
 233    };
 234    var convertSyncedPatternToStatic = (clientId) => ({ registry }) => {
 235      const patternBlock = registry.select(import_block_editor.store).getBlock(clientId);
 236      const existingOverrides = patternBlock.attributes?.content;
 237      function cloneBlocksAndRemoveBindings(blocks) {
 238        return blocks.map((block) => {
 239          let metadata = block.attributes.metadata;
 240          if (metadata) {
 241            metadata = { ...metadata };
 242            delete metadata.id;
 243            delete metadata.bindings;
 244            if (existingOverrides?.[metadata.name]) {
 245              for (const [attributeName, value] of Object.entries(
 246                existingOverrides[metadata.name]
 247              )) {
 248                if (!(0, import_blocks.getBlockType)(block.name)?.attributes[attributeName]) {
 249                  continue;
 250                }
 251                block.attributes[attributeName] = value;
 252              }
 253            }
 254          }
 255          return (0, import_blocks.cloneBlock)(
 256            block,
 257            {
 258              metadata: metadata && Object.keys(metadata).length > 0 ? metadata : void 0
 259            },
 260            cloneBlocksAndRemoveBindings(block.innerBlocks)
 261          );
 262        });
 263      }
 264      const patternInnerBlocks = registry.select(import_block_editor.store).getBlocks(patternBlock.clientId);
 265      registry.dispatch(import_block_editor.store).replaceBlocks(
 266        patternBlock.clientId,
 267        cloneBlocksAndRemoveBindings(patternInnerBlocks)
 268      );
 269    };
 270    function setEditingPattern(clientId, isEditing) {
 271      return {
 272        type: "SET_EDITING_PATTERN",
 273        clientId,
 274        isEditing
 275      };
 276    }
 277  
 278    // packages/patterns/build-module/store/constants.js
 279    var STORE_NAME = "core/patterns";
 280  
 281    // packages/patterns/build-module/store/selectors.js
 282    var selectors_exports = {};
 283    __export(selectors_exports, {
 284      isEditingPattern: () => isEditingPattern2
 285    });
 286    function isEditingPattern2(state, clientId) {
 287      return state.isEditingPattern[clientId];
 288    }
 289  
 290    // packages/patterns/build-module/lock-unlock.js
 291    var import_private_apis = __toESM(require_private_apis());
 292    var { lock, unlock } = (0, import_private_apis.__dangerousOptInToUnstableAPIsOnlyForCoreModules)(
 293      "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.",
 294      "@wordpress/patterns"
 295    );
 296  
 297    // packages/patterns/build-module/store/index.js
 298    var storeConfig = {
 299      reducer: reducer_default
 300    };
 301    var store = (0, import_data2.createReduxStore)(STORE_NAME, {
 302      ...storeConfig
 303    });
 304    (0, import_data2.register)(store);
 305    unlock(store).registerPrivateActions(actions_exports);
 306    unlock(store).registerPrivateSelectors(selectors_exports);
 307  
 308    // packages/patterns/build-module/components/overrides-panel.js
 309    var import_block_editor2 = __toESM(require_block_editor());
 310    var import_components = __toESM(require_components());
 311    var import_data3 = __toESM(require_data());
 312    var import_element = __toESM(require_element());
 313    var import_i18n = __toESM(require_i18n());
 314  
 315    // packages/patterns/build-module/api/index.js
 316    function isOverridableBlock(block) {
 317      return Object.keys(PARTIAL_SYNCING_SUPPORTED_BLOCKS).includes(
 318        block.name
 319      ) && !!block.attributes.metadata?.name && !!block.attributes.metadata?.bindings && Object.values(block.attributes.metadata.bindings).some(
 320        (binding) => binding.source === "core/pattern-overrides"
 321      );
 322    }
 323    function hasOverridableBlocks(blocks) {
 324      return blocks.some((block) => {
 325        if (isOverridableBlock(block)) {
 326          return true;
 327        }
 328        return hasOverridableBlocks(block.innerBlocks);
 329      });
 330    }
 331  
 332    // packages/patterns/build-module/components/overrides-panel.js
 333    var import_jsx_runtime = __toESM(require_jsx_runtime());
 334    var { BlockQuickNavigation } = unlock(import_block_editor2.privateApis);
 335    function OverridesPanel() {
 336      const allClientIds = (0, import_data3.useSelect)(
 337        (select) => select(import_block_editor2.store).getClientIdsWithDescendants(),
 338        []
 339      );
 340      const { getBlock } = (0, import_data3.useSelect)(import_block_editor2.store);
 341      const clientIdsWithOverrides = (0, import_element.useMemo)(
 342        () => allClientIds.filter((clientId) => {
 343          const block = getBlock(clientId);
 344          return isOverridableBlock(block);
 345        }),
 346        [allClientIds, getBlock]
 347      );
 348      if (!clientIdsWithOverrides?.length) {
 349        return null;
 350      }
 351      return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.PanelBody, { title: (0, import_i18n.__)("Overrides"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BlockQuickNavigation, { clientIds: clientIdsWithOverrides }) });
 352    }
 353  
 354    // packages/patterns/build-module/components/create-pattern-modal.js
 355    var import_components3 = __toESM(require_components());
 356    var import_i18n3 = __toESM(require_i18n());
 357    var import_element4 = __toESM(require_element());
 358    var import_data5 = __toESM(require_data());
 359    var import_notices = __toESM(require_notices());
 360    var import_core_data3 = __toESM(require_core_data());
 361  
 362    // packages/patterns/build-module/components/category-selector.js
 363    var import_i18n2 = __toESM(require_i18n());
 364    var import_element2 = __toESM(require_element());
 365    var import_components2 = __toESM(require_components());
 366    var import_compose = __toESM(require_compose());
 367    var import_html_entities = __toESM(require_html_entities());
 368    var import_jsx_runtime2 = __toESM(require_jsx_runtime());
 369    var unescapeString = (arg) => {
 370      return (0, import_html_entities.decodeEntities)(arg);
 371    };
 372    var CATEGORY_SLUG = "wp_pattern_category";
 373    function CategorySelector({
 374      categoryTerms,
 375      onChange,
 376      categoryMap
 377    }) {
 378      const [search, setSearch] = (0, import_element2.useState)("");
 379      const debouncedSearch = (0, import_compose.useDebounce)(setSearch, 500);
 380      const suggestions = (0, import_element2.useMemo)(() => {
 381        return Array.from(categoryMap.values()).map((category) => unescapeString(category.label)).filter((category) => {
 382          if (search !== "") {
 383            return category.toLowerCase().includes(search.toLowerCase());
 384          }
 385          return true;
 386        }).sort((a, b) => a.localeCompare(b));
 387      }, [search, categoryMap]);
 388      function handleChange(termNames) {
 389        const uniqueTerms = termNames.reduce((terms, newTerm) => {
 390          if (!terms.some(
 391            (term) => term.toLowerCase() === newTerm.toLowerCase()
 392          )) {
 393            terms.push(newTerm);
 394          }
 395          return terms;
 396        }, []);
 397        onChange(uniqueTerms);
 398      }
 399      return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
 400        import_components2.FormTokenField,
 401        {
 402          className: "patterns-menu-items__convert-modal-categories",
 403          value: categoryTerms,
 404          suggestions,
 405          onChange: handleChange,
 406          onInputChange: debouncedSearch,
 407          label: (0, import_i18n2.__)("Categories"),
 408          tokenizeOnBlur: true,
 409          __experimentalExpandOnFocus: true,
 410          __next40pxDefaultSize: true
 411        }
 412      );
 413    }
 414  
 415    // packages/patterns/build-module/private-hooks.js
 416    var import_data4 = __toESM(require_data());
 417    var import_core_data2 = __toESM(require_core_data());
 418    var import_element3 = __toESM(require_element());
 419    function useAddPatternCategory() {
 420      const { saveEntityRecord, invalidateResolution } = (0, import_data4.useDispatch)(import_core_data2.store);
 421      const { corePatternCategories, userPatternCategories } = (0, import_data4.useSelect)(
 422        (select) => {
 423          const { getUserPatternCategories, getBlockPatternCategories } = select(import_core_data2.store);
 424          return {
 425            corePatternCategories: getBlockPatternCategories(),
 426            userPatternCategories: getUserPatternCategories()
 427          };
 428        },
 429        []
 430      );
 431      const categoryMap = (0, import_element3.useMemo)(() => {
 432        const uniqueCategories = /* @__PURE__ */ new Map();
 433        userPatternCategories.forEach((category) => {
 434          uniqueCategories.set(category.label.toLowerCase(), {
 435            label: category.label,
 436            name: category.name,
 437            id: category.id
 438          });
 439        });
 440        corePatternCategories.forEach((category) => {
 441          if (!uniqueCategories.has(category.label.toLowerCase()) && // There are two core categories with `Post` label so explicitly remove the one with
 442          // the `query` slug to avoid any confusion.
 443          category.name !== "query") {
 444            uniqueCategories.set(category.label.toLowerCase(), {
 445              label: category.label,
 446              name: category.name
 447            });
 448          }
 449        });
 450        return uniqueCategories;
 451      }, [userPatternCategories, corePatternCategories]);
 452      async function findOrCreateTerm(term) {
 453        try {
 454          const existingTerm = categoryMap.get(term.toLowerCase());
 455          if (existingTerm?.id) {
 456            return existingTerm.id;
 457          }
 458          const termData = existingTerm ? { name: existingTerm.label, slug: existingTerm.name } : { name: term };
 459          const newTerm = await saveEntityRecord(
 460            "taxonomy",
 461            CATEGORY_SLUG,
 462            termData,
 463            { throwOnError: true }
 464          );
 465          invalidateResolution("getUserPatternCategories");
 466          return newTerm.id;
 467        } catch (error) {
 468          if (error.code !== "term_exists") {
 469            throw error;
 470          }
 471          return error.data.term_id;
 472        }
 473      }
 474      return { categoryMap, findOrCreateTerm };
 475    }
 476  
 477    // packages/patterns/build-module/components/create-pattern-modal.js
 478    var import_jsx_runtime3 = __toESM(require_jsx_runtime());
 479    function CreatePatternModal({
 480      className = "patterns-menu-items__convert-modal",
 481      modalTitle,
 482      ...restProps
 483    }) {
 484      const defaultModalTitle = (0, import_data5.useSelect)(
 485        (select) => select(import_core_data3.store).getPostType(PATTERN_TYPES.user)?.labels?.add_new_item,
 486        []
 487      );
 488      return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 489        import_components3.Modal,
 490        {
 491          title: modalTitle || defaultModalTitle,
 492          onRequestClose: restProps.onClose,
 493          overlayClassName: className,
 494          focusOnMount: "firstContentElement",
 495          size: "small",
 496          children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CreatePatternModalContents, { ...restProps })
 497        }
 498      );
 499    }
 500    function CreatePatternModalContents({
 501      confirmLabel = (0, import_i18n3.__)("Add"),
 502      defaultCategories = [],
 503      content,
 504      onClose,
 505      onError,
 506      onSuccess,
 507      defaultSyncType = PATTERN_SYNC_TYPES.full,
 508      defaultTitle = ""
 509    }) {
 510      const [syncType, setSyncType] = (0, import_element4.useState)(defaultSyncType);
 511      const [categoryTerms, setCategoryTerms] = (0, import_element4.useState)(defaultCategories);
 512      const [title, setTitle] = (0, import_element4.useState)(defaultTitle);
 513      const [isSaving, setIsSaving] = (0, import_element4.useState)(false);
 514      const { createPattern: createPattern2 } = unlock((0, import_data5.useDispatch)(store));
 515      const { createErrorNotice } = (0, import_data5.useDispatch)(import_notices.store);
 516      const { categoryMap, findOrCreateTerm } = useAddPatternCategory();
 517      async function onCreate(patternTitle, sync) {
 518        if (!title || isSaving) {
 519          return;
 520        }
 521        try {
 522          setIsSaving(true);
 523          const categories = await Promise.all(
 524            categoryTerms.map(
 525              (termName) => findOrCreateTerm(termName)
 526            )
 527          );
 528          const newPattern = await createPattern2(
 529            patternTitle,
 530            sync,
 531            typeof content === "function" ? content() : content,
 532            categories
 533          );
 534          onSuccess({
 535            pattern: newPattern,
 536            categoryId: PATTERN_DEFAULT_CATEGORY
 537          });
 538        } catch (error) {
 539          createErrorNotice(error.message, {
 540            type: "snackbar",
 541            id: "pattern-create"
 542          });
 543          onError?.();
 544        } finally {
 545          setIsSaving(false);
 546          setCategoryTerms([]);
 547          setTitle("");
 548        }
 549      }
 550      return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 551        "form",
 552        {
 553          onSubmit: (event) => {
 554            event.preventDefault();
 555            onCreate(title, syncType);
 556          },
 557          children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_components3.__experimentalVStack, { spacing: "5", children: [
 558            /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 559              import_components3.TextControl,
 560              {
 561                label: (0, import_i18n3.__)("Name"),
 562                value: title,
 563                onChange: setTitle,
 564                placeholder: (0, import_i18n3.__)("My pattern"),
 565                className: "patterns-create-modal__name-input",
 566                __next40pxDefaultSize: true
 567              }
 568            ),
 569            /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 570              CategorySelector,
 571              {
 572                categoryTerms,
 573                onChange: setCategoryTerms,
 574                categoryMap
 575              }
 576            ),
 577            /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 578              import_components3.ToggleControl,
 579              {
 580                label: (0, import_i18n3._x)("Synced", "pattern (singular)"),
 581                help: (0, import_i18n3.__)(
 582                  "Sync this pattern across multiple locations."
 583                ),
 584                checked: syncType === PATTERN_SYNC_TYPES.full,
 585                onChange: () => {
 586                  setSyncType(
 587                    syncType === PATTERN_SYNC_TYPES.full ? PATTERN_SYNC_TYPES.unsynced : PATTERN_SYNC_TYPES.full
 588                  );
 589                }
 590              }
 591            ),
 592            /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_components3.__experimentalHStack, { justify: "right", children: [
 593              /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 594                import_components3.Button,
 595                {
 596                  __next40pxDefaultSize: true,
 597                  variant: "tertiary",
 598                  onClick: () => {
 599                    onClose();
 600                    setTitle("");
 601                  },
 602                  children: (0, import_i18n3.__)("Cancel")
 603                }
 604              ),
 605              /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 606                import_components3.Button,
 607                {
 608                  __next40pxDefaultSize: true,
 609                  variant: "primary",
 610                  type: "submit",
 611                  "aria-disabled": !title || isSaving,
 612                  isBusy: isSaving,
 613                  children: confirmLabel
 614                }
 615              )
 616            ] })
 617          ] })
 618        }
 619      );
 620    }
 621  
 622    // packages/patterns/build-module/components/duplicate-pattern-modal.js
 623    var import_core_data4 = __toESM(require_core_data());
 624    var import_data6 = __toESM(require_data());
 625    var import_i18n4 = __toESM(require_i18n());
 626    var import_notices2 = __toESM(require_notices());
 627    var import_jsx_runtime4 = __toESM(require_jsx_runtime());
 628    function getTermLabels(pattern, categories) {
 629      if (pattern.type !== PATTERN_TYPES.user) {
 630        return categories.core?.filter(
 631          (category) => pattern.categories?.includes(category.name)
 632        ).map((category) => category.label);
 633      }
 634      return categories.user?.filter(
 635        (category) => pattern.wp_pattern_category?.includes(category.id)
 636      ).map((category) => category.label);
 637    }
 638    function useDuplicatePatternProps({ pattern, onSuccess }) {
 639      const { createSuccessNotice } = (0, import_data6.useDispatch)(import_notices2.store);
 640      const categories = (0, import_data6.useSelect)((select) => {
 641        const { getUserPatternCategories, getBlockPatternCategories } = select(import_core_data4.store);
 642        return {
 643          core: getBlockPatternCategories(),
 644          user: getUserPatternCategories()
 645        };
 646      });
 647      if (!pattern) {
 648        return null;
 649      }
 650      return {
 651        content: pattern.content,
 652        defaultCategories: getTermLabels(pattern, categories),
 653        defaultSyncType: pattern.type !== PATTERN_TYPES.user ? PATTERN_SYNC_TYPES.unsynced : pattern.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full,
 654        defaultTitle: (0, import_i18n4.sprintf)(
 655          /* translators: %s: Existing pattern title */
 656          (0, import_i18n4._x)("%s (Copy)", "pattern"),
 657          typeof pattern.title === "string" ? pattern.title : pattern.title.raw
 658        ),
 659        onSuccess: ({ pattern: newPattern }) => {
 660          createSuccessNotice(
 661            (0, import_i18n4.sprintf)(
 662              // translators: %s: The new pattern's title e.g. 'Call to action (copy)'.
 663              (0, import_i18n4._x)('"%s" duplicated.', "pattern"),
 664              newPattern.title.raw
 665            ),
 666            {
 667              type: "snackbar",
 668              id: "patterns-create"
 669            }
 670          );
 671          onSuccess?.({ pattern: newPattern });
 672        }
 673      };
 674    }
 675    function DuplicatePatternModal({
 676      pattern,
 677      onClose,
 678      onSuccess
 679    }) {
 680      const duplicatedProps = useDuplicatePatternProps({ pattern, onSuccess });
 681      if (!pattern) {
 682        return null;
 683      }
 684      return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
 685        CreatePatternModal,
 686        {
 687          modalTitle: (0, import_i18n4.__)("Duplicate pattern"),
 688          confirmLabel: (0, import_i18n4.__)("Duplicate"),
 689          onClose,
 690          onError: onClose,
 691          ...duplicatedProps
 692        }
 693      );
 694    }
 695  
 696    // packages/patterns/build-module/components/rename-pattern-modal.js
 697    var import_components4 = __toESM(require_components());
 698    var import_core_data5 = __toESM(require_core_data());
 699    var import_data7 = __toESM(require_data());
 700    var import_element5 = __toESM(require_element());
 701    var import_html_entities2 = __toESM(require_html_entities());
 702    var import_i18n5 = __toESM(require_i18n());
 703    var import_notices3 = __toESM(require_notices());
 704    var import_jsx_runtime5 = __toESM(require_jsx_runtime());
 705    function RenamePatternModal({
 706      onClose,
 707      onError,
 708      onSuccess,
 709      pattern,
 710      ...props
 711    }) {
 712      const originalName = (0, import_html_entities2.decodeEntities)(pattern.title);
 713      const [name, setName] = (0, import_element5.useState)(originalName);
 714      const [isSaving, setIsSaving] = (0, import_element5.useState)(false);
 715      const {
 716        editEntityRecord,
 717        __experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits
 718      } = (0, import_data7.useDispatch)(import_core_data5.store);
 719      const { createSuccessNotice, createErrorNotice } = (0, import_data7.useDispatch)(import_notices3.store);
 720      const onRename = async (event) => {
 721        event.preventDefault();
 722        if (!name || name === pattern.title || isSaving) {
 723          return;
 724        }
 725        try {
 726          await editEntityRecord("postType", pattern.type, pattern.id, {
 727            title: name
 728          });
 729          setIsSaving(true);
 730          setName("");
 731          onClose?.();
 732          const savedRecord = await saveSpecifiedEntityEdits(
 733            "postType",
 734            pattern.type,
 735            pattern.id,
 736            ["title"],
 737            { throwOnError: true }
 738          );
 739          onSuccess?.(savedRecord);
 740          createSuccessNotice((0, import_i18n5.__)("Pattern renamed"), {
 741            type: "snackbar",
 742            id: "pattern-update"
 743          });
 744        } catch (error) {
 745          onError?.();
 746          const errorMessage = error.message && error.code !== "unknown_error" ? error.message : (0, import_i18n5.__)("An error occurred while renaming the pattern.");
 747          createErrorNotice(errorMessage, {
 748            type: "snackbar",
 749            id: "pattern-update"
 750          });
 751        } finally {
 752          setIsSaving(false);
 753          setName("");
 754        }
 755      };
 756      const onRequestClose = () => {
 757        onClose?.();
 758        setName("");
 759      };
 760      return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
 761        import_components4.Modal,
 762        {
 763          title: (0, import_i18n5.__)("Rename"),
 764          ...props,
 765          onRequestClose: onClose,
 766          focusOnMount: "firstContentElement",
 767          size: "small",
 768          children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("form", { onSubmit: onRename, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_components4.__experimentalVStack, { spacing: "5", children: [
 769            /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
 770              import_components4.TextControl,
 771              {
 772                __next40pxDefaultSize: true,
 773                label: (0, import_i18n5.__)("Name"),
 774                value: name,
 775                onChange: setName,
 776                required: true
 777              }
 778            ),
 779            /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_components4.__experimentalHStack, { justify: "right", children: [
 780              /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
 781                import_components4.Button,
 782                {
 783                  __next40pxDefaultSize: true,
 784                  variant: "tertiary",
 785                  onClick: onRequestClose,
 786                  children: (0, import_i18n5.__)("Cancel")
 787                }
 788              ),
 789              /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
 790                import_components4.Button,
 791                {
 792                  __next40pxDefaultSize: true,
 793                  variant: "primary",
 794                  type: "submit",
 795                  children: (0, import_i18n5.__)("Save")
 796                }
 797              )
 798            ] })
 799          ] }) })
 800        }
 801      );
 802    }
 803  
 804    // packages/patterns/build-module/components/index.js
 805    var import_block_editor5 = __toESM(require_block_editor());
 806  
 807    // packages/patterns/build-module/components/pattern-convert-button.js
 808    var import_blocks2 = __toESM(require_blocks());
 809    var import_block_editor3 = __toESM(require_block_editor());
 810    var import_element6 = __toESM(require_element());
 811    var import_components5 = __toESM(require_components());
 812  
 813    // packages/icons/build-module/library/symbol.js
 814    var import_primitives = __toESM(require_primitives());
 815    var import_jsx_runtime6 = __toESM(require_jsx_runtime());
 816    var symbol_default = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_primitives.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_primitives.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" }) });
 817  
 818    // packages/patterns/build-module/components/pattern-convert-button.js
 819    var import_data8 = __toESM(require_data());
 820    var import_core_data6 = __toESM(require_core_data());
 821    var import_i18n6 = __toESM(require_i18n());
 822    var import_notices4 = __toESM(require_notices());
 823    var import_jsx_runtime7 = __toESM(require_jsx_runtime());
 824    function PatternConvertButton({
 825      clientIds,
 826      rootClientId,
 827      closeBlockSettingsMenu
 828    }) {
 829      const { createSuccessNotice } = (0, import_data8.useDispatch)(import_notices4.store);
 830      const { replaceBlocks, updateBlockAttributes } = (0, import_data8.useDispatch)(import_block_editor3.store);
 831      const { setEditingPattern: setEditingPattern2 } = unlock((0, import_data8.useDispatch)(store));
 832      const [isModalOpen, setIsModalOpen] = (0, import_element6.useState)(false);
 833      const { getBlockAttributes } = (0, import_data8.useSelect)(import_block_editor3.store);
 834      const canConvert = (0, import_data8.useSelect)(
 835        (select) => {
 836          const { canUser } = select(import_core_data6.store);
 837          const {
 838            getBlocksByClientId: getBlocksByClientId2,
 839            canInsertBlockType,
 840            getBlockRootClientId
 841          } = select(import_block_editor3.store);
 842          const rootId = rootClientId || (clientIds.length > 0 ? getBlockRootClientId(clientIds[0]) : void 0);
 843          const blocks = getBlocksByClientId2(clientIds) ?? [];
 844          const hasReusableBlockSupport = (blockName) => {
 845            const blockType = (0, import_blocks2.getBlockType)(blockName);
 846            const hasParent = blockType && "parent" in blockType;
 847            return (0, import_blocks2.hasBlockSupport)(blockName, "reusable", !hasParent);
 848          };
 849          const isSyncedPattern = blocks.length === 1 && blocks[0] && (0, import_blocks2.isReusableBlock)(blocks[0]) && !!select(import_core_data6.store).getEntityRecord(
 850            "postType",
 851            "wp_block",
 852            blocks[0].attributes.ref
 853          );
 854          const isUnsyncedPattern = window?.__experimentalContentOnlyPatternInsertion && blocks.length === 1 && blocks?.[0]?.attributes?.metadata?.patternName;
 855          const _canConvert = (
 856            // Hide when this is already a pattern.
 857            !isUnsyncedPattern && !isSyncedPattern && // Hide when patterns are disabled.
 858            canInsertBlockType("core/block", rootId) && blocks.every(
 859              (block) => (
 860                // Guard against the case where a regular block has *just* been converted.
 861                !!block && // Hide on invalid blocks.
 862                block.isValid && // Hide when block doesn't support being made into a pattern.
 863                hasReusableBlockSupport(block.name)
 864              )
 865            ) && // Hide when current doesn't have permission to do that.
 866            // Blocks refers to the wp_block post type, this checks the ability to create a post of that type.
 867            !!canUser("create", {
 868              kind: "postType",
 869              name: "wp_block"
 870            })
 871          );
 872          return _canConvert;
 873        },
 874        [clientIds, rootClientId]
 875      );
 876      const { getBlocksByClientId } = (0, import_data8.useSelect)(import_block_editor3.store);
 877      const getContent = (0, import_element6.useCallback)(
 878        () => (0, import_blocks2.serialize)(getBlocksByClientId(clientIds)),
 879        [getBlocksByClientId, clientIds]
 880      );
 881      if (!canConvert) {
 882        return null;
 883      }
 884      const handleSuccess = ({ pattern }) => {
 885        if (pattern.wp_pattern_sync_status === PATTERN_SYNC_TYPES.unsynced) {
 886          if (clientIds?.length === 1) {
 887            const existingAttributes = getBlockAttributes(clientIds[0]);
 888            updateBlockAttributes(clientIds[0], {
 889              metadata: {
 890                ...existingAttributes?.metadata ? existingAttributes.metadata : {},
 891                patternName: `core/block/$pattern.id}`,
 892                name: pattern.title.raw
 893              }
 894            });
 895          }
 896        } else {
 897          const newBlock = (0, import_blocks2.createBlock)("core/block", {
 898            ref: pattern.id
 899          });
 900          replaceBlocks(clientIds, newBlock);
 901          setEditingPattern2(newBlock.clientId, true);
 902          closeBlockSettingsMenu();
 903        }
 904        createSuccessNotice(
 905          pattern.wp_pattern_sync_status === PATTERN_SYNC_TYPES.unsynced ? (0, import_i18n6.sprintf)(
 906            // translators: %s: the name the user has given to the pattern.
 907            (0, import_i18n6.__)("Unsynced pattern created: %s"),
 908            pattern.title.raw
 909          ) : (0, import_i18n6.sprintf)(
 910            // translators: %s: the name the user has given to the pattern.
 911            (0, import_i18n6.__)("Synced pattern created: %s"),
 912            pattern.title.raw
 913          ),
 914          {
 915            type: "snackbar",
 916            id: "convert-to-pattern-success"
 917          }
 918        );
 919        setIsModalOpen(false);
 920      };
 921      return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
 922        /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
 923          import_components5.MenuItem,
 924          {
 925            icon: symbol_default,
 926            onClick: () => setIsModalOpen(true),
 927            "aria-expanded": isModalOpen,
 928            "aria-haspopup": "dialog",
 929            children: (0, import_i18n6.__)("Create pattern")
 930          }
 931        ),
 932        isModalOpen && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
 933          CreatePatternModal,
 934          {
 935            content: getContent,
 936            onSuccess: (pattern) => {
 937              handleSuccess(pattern);
 938            },
 939            onError: () => {
 940              setIsModalOpen(false);
 941            },
 942            onClose: () => {
 943              setIsModalOpen(false);
 944            }
 945          }
 946        )
 947      ] });
 948    }
 949  
 950    // packages/patterns/build-module/components/patterns-manage-button.js
 951    var import_components6 = __toESM(require_components());
 952    var import_i18n7 = __toESM(require_i18n());
 953    var import_blocks3 = __toESM(require_blocks());
 954    var import_data9 = __toESM(require_data());
 955    var import_block_editor4 = __toESM(require_block_editor());
 956    var import_url = __toESM(require_url());
 957    var import_core_data7 = __toESM(require_core_data());
 958    var import_jsx_runtime8 = __toESM(require_jsx_runtime());
 959    function PatternsManageButton({ clientId }) {
 960      const {
 961        attributes,
 962        canDetach,
 963        isVisible,
 964        managePatternsUrl,
 965        isSyncedPattern,
 966        isUnsyncedPattern
 967      } = (0, import_data9.useSelect)(
 968        (select) => {
 969          const { canRemoveBlock, getBlock } = select(import_block_editor4.store);
 970          const { canUser } = select(import_core_data7.store);
 971          const block = getBlock(clientId);
 972          const _isUnsyncedPattern = window?.__experimentalContentOnlyPatternInsertion && !!block?.attributes?.metadata?.patternName;
 973          const _isSyncedPattern = !!block && (0, import_blocks3.isReusableBlock)(block) && !!canUser("update", {
 974            kind: "postType",
 975            name: "wp_block",
 976            id: block.attributes.ref
 977          });
 978          return {
 979            attributes: block.attributes,
 980            // For unsynced patterns, detaching is simply removing the `patternName` attribute.
 981            // For synced patterns, the `core:block` block is replaced with its inner blocks,
 982            // so checking whether `canRemoveBlock` is possible is required.
 983            canDetach: _isUnsyncedPattern || _isSyncedPattern && canRemoveBlock(clientId),
 984            isUnsyncedPattern: _isUnsyncedPattern,
 985            isSyncedPattern: _isSyncedPattern,
 986            isVisible: _isUnsyncedPattern || _isSyncedPattern,
 987            // The site editor and templates both check whether the user
 988            // has edit_theme_options capabilities. We can leverage that here
 989            // and omit the manage patterns link if the user can't access it.
 990            managePatternsUrl: canUser("create", {
 991              kind: "postType",
 992              name: "wp_template"
 993            }) ? (0, import_url.addQueryArgs)("site-editor.php", {
 994              p: "/pattern"
 995            }) : (0, import_url.addQueryArgs)("edit.php", {
 996              post_type: "wp_block"
 997            })
 998          };
 999        },
1000        [clientId]
1001      );
1002      const { updateBlockAttributes } = (0, import_data9.useDispatch)(import_block_editor4.store);
1003      const { convertSyncedPatternToStatic: convertSyncedPatternToStatic2 } = unlock(
1004        (0, import_data9.useDispatch)(store)
1005      );
1006      if (!isVisible) {
1007        return null;
1008      }
1009      return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1010        canDetach && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1011          import_components6.MenuItem,
1012          {
1013            onClick: () => {
1014              if (isSyncedPattern) {
1015                convertSyncedPatternToStatic2(clientId);
1016              }
1017              if (isUnsyncedPattern) {
1018                const {
1019                  patternName,
1020                  ...attributesWithoutPatternName
1021                } = attributes?.metadata ?? {};
1022                updateBlockAttributes(clientId, {
1023                  metadata: attributesWithoutPatternName
1024                });
1025              }
1026            },
1027            children: (0, import_i18n7.__)("Disconnect pattern")
1028          }
1029        ),
1030        /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.MenuItem, { href: managePatternsUrl, children: (0, import_i18n7.__)("Manage patterns") })
1031      ] });
1032    }
1033    var patterns_manage_button_default = PatternsManageButton;
1034  
1035    // packages/patterns/build-module/components/index.js
1036    var import_jsx_runtime9 = __toESM(require_jsx_runtime());
1037    function PatternsMenuItems({ rootClientId }) {
1038      return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_block_editor5.BlockSettingsMenuControls, { children: ({ selectedClientIds, onClose }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1039        /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1040          PatternConvertButton,
1041          {
1042            clientIds: selectedClientIds,
1043            rootClientId,
1044            closeBlockSettingsMenu: onClose
1045          }
1046        ),
1047        selectedClientIds.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1048          patterns_manage_button_default,
1049          {
1050            clientId: selectedClientIds[0]
1051          }
1052        )
1053      ] }) });
1054    }
1055  
1056    // packages/patterns/build-module/components/rename-pattern-category-modal.js
1057    var import_components7 = __toESM(require_components());
1058    var import_core_data8 = __toESM(require_core_data());
1059    var import_data10 = __toESM(require_data());
1060    var import_element7 = __toESM(require_element());
1061    var import_html_entities3 = __toESM(require_html_entities());
1062    var import_i18n8 = __toESM(require_i18n());
1063    var import_notices5 = __toESM(require_notices());
1064    var import_a11y = __toESM(require_a11y());
1065    var import_jsx_runtime10 = __toESM(require_jsx_runtime());
1066    function RenamePatternCategoryModal({
1067      category,
1068      existingCategories,
1069      onClose,
1070      onError,
1071      onSuccess,
1072      ...props
1073    }) {
1074      const id = (0, import_element7.useId)();
1075      const textControlRef = (0, import_element7.useRef)();
1076      const [name, setName] = (0, import_element7.useState)((0, import_html_entities3.decodeEntities)(category.name));
1077      const [isSaving, setIsSaving] = (0, import_element7.useState)(false);
1078      const [validationMessage, setValidationMessage] = (0, import_element7.useState)(false);
1079      const validationMessageId = validationMessage ? `patterns-rename-pattern-category-modal__validation-message-$id}` : void 0;
1080      const { saveEntityRecord, invalidateResolution } = (0, import_data10.useDispatch)(import_core_data8.store);
1081      const { createErrorNotice, createSuccessNotice } = (0, import_data10.useDispatch)(import_notices5.store);
1082      const onChange = (newName) => {
1083        if (validationMessage) {
1084          setValidationMessage(void 0);
1085        }
1086        setName(newName);
1087      };
1088      const onSave = async (event) => {
1089        event.preventDefault();
1090        if (isSaving) {
1091          return;
1092        }
1093        if (!name || name === category.name) {
1094          const message = (0, import_i18n8.__)("Please enter a new name for this category.");
1095          (0, import_a11y.speak)(message, "assertive");
1096          setValidationMessage(message);
1097          textControlRef.current?.focus();
1098          return;
1099        }
1100        if (existingCategories.patternCategories.find((existingCategory) => {
1101          return existingCategory.id !== category.id && existingCategory.label.toLowerCase() === name.toLowerCase();
1102        })) {
1103          const message = (0, import_i18n8.__)(
1104            "This category already exists. Please use a different name."
1105          );
1106          (0, import_a11y.speak)(message, "assertive");
1107          setValidationMessage(message);
1108          textControlRef.current?.focus();
1109          return;
1110        }
1111        try {
1112          setIsSaving(true);
1113          const savedRecord = await saveEntityRecord(
1114            "taxonomy",
1115            CATEGORY_SLUG,
1116            {
1117              id: category.id,
1118              slug: category.slug,
1119              name
1120            }
1121          );
1122          invalidateResolution("getUserPatternCategories");
1123          onSuccess?.(savedRecord);
1124          onClose();
1125          createSuccessNotice((0, import_i18n8.__)("Pattern category renamed."), {
1126            type: "snackbar",
1127            id: "pattern-category-update"
1128          });
1129        } catch (error) {
1130          onError?.();
1131          createErrorNotice(error.message, {
1132            type: "snackbar",
1133            id: "pattern-category-update"
1134          });
1135        } finally {
1136          setIsSaving(false);
1137          setName("");
1138        }
1139      };
1140      const onRequestClose = () => {
1141        onClose();
1142        setName("");
1143      };
1144      return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1145        import_components7.Modal,
1146        {
1147          title: (0, import_i18n8.__)("Rename"),
1148          onRequestClose,
1149          ...props,
1150          children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("form", { onSubmit: onSave, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_components7.__experimentalVStack, { spacing: "5", children: [
1151            /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_components7.__experimentalVStack, { spacing: "2", children: [
1152              /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1153                import_components7.TextControl,
1154                {
1155                  ref: textControlRef,
1156                  __next40pxDefaultSize: true,
1157                  label: (0, import_i18n8.__)("Name"),
1158                  value: name,
1159                  onChange,
1160                  "aria-describedby": validationMessageId,
1161                  required: true
1162                }
1163              ),
1164              validationMessage && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1165                "span",
1166                {
1167                  className: "patterns-rename-pattern-category-modal__validation-message",
1168                  id: validationMessageId,
1169                  children: validationMessage
1170                }
1171              )
1172            ] }),
1173            /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_components7.__experimentalHStack, { justify: "right", children: [
1174              /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1175                import_components7.Button,
1176                {
1177                  __next40pxDefaultSize: true,
1178                  variant: "tertiary",
1179                  onClick: onRequestClose,
1180                  children: (0, import_i18n8.__)("Cancel")
1181                }
1182              ),
1183              /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1184                import_components7.Button,
1185                {
1186                  __next40pxDefaultSize: true,
1187                  variant: "primary",
1188                  type: "submit",
1189                  "aria-disabled": !name || name === category.name || isSaving,
1190                  isBusy: isSaving,
1191                  children: (0, import_i18n8.__)("Save")
1192                }
1193              )
1194            ] })
1195          ] }) })
1196        }
1197      );
1198    }
1199  
1200    // packages/patterns/build-module/components/pattern-overrides-controls.js
1201    var import_element9 = __toESM(require_element());
1202    var import_block_editor6 = __toESM(require_block_editor());
1203    var import_components9 = __toESM(require_components());
1204    var import_i18n10 = __toESM(require_i18n());
1205  
1206    // packages/patterns/build-module/components/allow-overrides-modal.js
1207    var import_components8 = __toESM(require_components());
1208    var import_i18n9 = __toESM(require_i18n());
1209    var import_element8 = __toESM(require_element());
1210    var import_a11y2 = __toESM(require_a11y());
1211    var import_jsx_runtime11 = __toESM(require_jsx_runtime());
1212    function AllowOverridesModal({
1213      placeholder,
1214      initialName = "",
1215      onClose,
1216      onSave
1217    }) {
1218      const [editedBlockName, setEditedBlockName] = (0, import_element8.useState)(initialName);
1219      const descriptionId = (0, import_element8.useId)();
1220      const isNameValid = !!editedBlockName.trim();
1221      const handleSubmit = () => {
1222        if (editedBlockName !== initialName) {
1223          const message = (0, import_i18n9.sprintf)(
1224            /* translators: %s: new name/label for the block */
1225            (0, import_i18n9.__)('Block name changed to: "%s".'),
1226            editedBlockName
1227          );
1228          (0, import_a11y2.speak)(message, "assertive");
1229        }
1230        onSave(editedBlockName);
1231        onClose();
1232      };
1233      return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1234        import_components8.Modal,
1235        {
1236          title: (0, import_i18n9.__)("Enable overrides"),
1237          onRequestClose: onClose,
1238          focusOnMount: "firstContentElement",
1239          aria: { describedby: descriptionId },
1240          size: "small",
1241          children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1242            "form",
1243            {
1244              onSubmit: (event) => {
1245                event.preventDefault();
1246                if (!isNameValid) {
1247                  return;
1248                }
1249                handleSubmit();
1250              },
1251              children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_components8.__experimentalVStack, { spacing: "6", children: [
1252                /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_components8.__experimentalText, { id: descriptionId, children: (0, import_i18n9.__)(
1253                  "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."
1254                ) }),
1255                /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1256                  import_components8.TextControl,
1257                  {
1258                    __next40pxDefaultSize: true,
1259                    value: editedBlockName,
1260                    label: (0, import_i18n9.__)("Name"),
1261                    help: (0, import_i18n9.__)(
1262                      'For example, if you are creating a recipe pattern, you use "Recipe Title", "Recipe Description", etc.'
1263                    ),
1264                    placeholder,
1265                    onChange: setEditedBlockName
1266                  }
1267                ),
1268                /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_components8.__experimentalHStack, { justify: "right", children: [
1269                  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1270                    import_components8.Button,
1271                    {
1272                      __next40pxDefaultSize: true,
1273                      variant: "tertiary",
1274                      onClick: onClose,
1275                      children: (0, import_i18n9.__)("Cancel")
1276                    }
1277                  ),
1278                  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1279                    import_components8.Button,
1280                    {
1281                      __next40pxDefaultSize: true,
1282                      "aria-disabled": !isNameValid,
1283                      variant: "primary",
1284                      type: "submit",
1285                      children: (0, import_i18n9.__)("Enable")
1286                    }
1287                  )
1288                ] })
1289              ] })
1290            }
1291          )
1292        }
1293      );
1294    }
1295    function DisallowOverridesModal({ onClose, onSave }) {
1296      const descriptionId = (0, import_element8.useId)();
1297      return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1298        import_components8.Modal,
1299        {
1300          title: (0, import_i18n9.__)("Disable overrides"),
1301          onRequestClose: onClose,
1302          aria: { describedby: descriptionId },
1303          size: "small",
1304          children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1305            "form",
1306            {
1307              onSubmit: (event) => {
1308                event.preventDefault();
1309                onSave();
1310                onClose();
1311              },
1312              children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_components8.__experimentalVStack, { spacing: "6", children: [
1313                /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_components8.__experimentalText, { id: descriptionId, children: (0, import_i18n9.__)(
1314                  "Are you sure you want to disable overrides? Disabling overrides will revert all applied overrides for this block throughout instances of this pattern."
1315                ) }),
1316                /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_components8.__experimentalHStack, { justify: "right", children: [
1317                  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1318                    import_components8.Button,
1319                    {
1320                      __next40pxDefaultSize: true,
1321                      variant: "tertiary",
1322                      onClick: onClose,
1323                      children: (0, import_i18n9.__)("Cancel")
1324                    }
1325                  ),
1326                  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1327                    import_components8.Button,
1328                    {
1329                      __next40pxDefaultSize: true,
1330                      variant: "primary",
1331                      type: "submit",
1332                      children: (0, import_i18n9.__)("Disable")
1333                    }
1334                  )
1335                ] })
1336              ] })
1337            }
1338          )
1339        }
1340      );
1341    }
1342  
1343    // packages/patterns/build-module/components/pattern-overrides-controls.js
1344    var import_jsx_runtime12 = __toESM(require_jsx_runtime());
1345    function PatternOverridesControls({
1346      attributes,
1347      setAttributes,
1348      name: blockName
1349    }) {
1350      const controlId = (0, import_element9.useId)();
1351      const [showAllowOverridesModal, setShowAllowOverridesModal] = (0, import_element9.useState)(false);
1352      const [showDisallowOverridesModal, setShowDisallowOverridesModal] = (0, import_element9.useState)(false);
1353      const hasName = !!attributes.metadata?.name;
1354      const defaultBindings = attributes.metadata?.bindings?.__default;
1355      const hasOverrides = hasName && defaultBindings?.source === PATTERN_OVERRIDES_BINDING_SOURCE;
1356      const isConnectedToOtherSources = defaultBindings?.source && defaultBindings.source !== PATTERN_OVERRIDES_BINDING_SOURCE;
1357      const { updateBlockBindings } = (0, import_block_editor6.useBlockBindingsUtils)();
1358      function updateBindings(isChecked, customName) {
1359        if (customName) {
1360          setAttributes({
1361            metadata: {
1362              ...attributes.metadata,
1363              name: customName
1364            }
1365          });
1366        }
1367        updateBlockBindings({
1368          __default: isChecked ? { source: PATTERN_OVERRIDES_BINDING_SOURCE } : void 0
1369        });
1370      }
1371      if (isConnectedToOtherSources) {
1372        return null;
1373      }
1374      const hasUnsupportedImageAttributes = blockName === "core/image" && !!attributes.href?.length;
1375      const helpText = !hasOverrides && hasUnsupportedImageAttributes ? (0, import_i18n10.__)(
1376        `Overrides currently don't support image links. Remove the link first before enabling overrides.`
1377      ) : (0, import_i18n10.__)(
1378        "Allow changes to this block throughout instances of this pattern."
1379      );
1380      return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1381        /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_block_editor6.InspectorControls, { group: "advanced", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1382          import_components9.BaseControl,
1383          {
1384            id: controlId,
1385            label: (0, import_i18n10.__)("Overrides"),
1386            help: helpText,
1387            children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1388              import_components9.Button,
1389              {
1390                __next40pxDefaultSize: true,
1391                className: "pattern-overrides-control__allow-overrides-button",
1392                variant: "secondary",
1393                "aria-haspopup": "dialog",
1394                onClick: () => {
1395                  if (hasOverrides) {
1396                    setShowDisallowOverridesModal(true);
1397                  } else {
1398                    setShowAllowOverridesModal(true);
1399                  }
1400                },
1401                disabled: !hasOverrides && hasUnsupportedImageAttributes,
1402                accessibleWhenDisabled: true,
1403                children: hasOverrides ? (0, import_i18n10.__)("Disable overrides") : (0, import_i18n10.__)("Enable overrides")
1404              }
1405            )
1406          }
1407        ) }),
1408        showAllowOverridesModal && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1409          AllowOverridesModal,
1410          {
1411            initialName: attributes.metadata?.name,
1412            onClose: () => setShowAllowOverridesModal(false),
1413            onSave: (newName) => {
1414              updateBindings(true, newName);
1415            }
1416          }
1417        ),
1418        showDisallowOverridesModal && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1419          DisallowOverridesModal,
1420          {
1421            onClose: () => setShowDisallowOverridesModal(false),
1422            onSave: () => updateBindings(false)
1423          }
1424        )
1425      ] });
1426    }
1427    var pattern_overrides_controls_default = PatternOverridesControls;
1428  
1429    // packages/patterns/build-module/components/reset-overrides-control.js
1430    var import_block_editor7 = __toESM(require_block_editor());
1431    var import_components10 = __toESM(require_components());
1432    var import_data11 = __toESM(require_data());
1433    var import_i18n11 = __toESM(require_i18n());
1434    var import_jsx_runtime13 = __toESM(require_jsx_runtime());
1435    var CONTENT = "content";
1436    function ResetOverridesControl(props) {
1437      const name = props.attributes.metadata?.name;
1438      const registry = (0, import_data11.useRegistry)();
1439      const isOverridden = (0, import_data11.useSelect)(
1440        (select) => {
1441          if (!name) {
1442            return;
1443          }
1444          const { getBlockAttributes, getBlockParentsByBlockName } = select(import_block_editor7.store);
1445          const [patternClientId] = getBlockParentsByBlockName(
1446            props.clientId,
1447            "core/block",
1448            true
1449          );
1450          if (!patternClientId) {
1451            return;
1452          }
1453          const overrides = getBlockAttributes(patternClientId)[CONTENT];
1454          if (!overrides) {
1455            return;
1456          }
1457          return overrides.hasOwnProperty(name);
1458        },
1459        [props.clientId, name]
1460      );
1461      function onClick() {
1462        const { getBlockAttributes, getBlockParentsByBlockName } = registry.select(import_block_editor7.store);
1463        const [patternClientId] = getBlockParentsByBlockName(
1464          props.clientId,
1465          "core/block",
1466          true
1467        );
1468        if (!patternClientId) {
1469          return;
1470        }
1471        const overrides = getBlockAttributes(patternClientId)[CONTENT];
1472        if (!overrides.hasOwnProperty(name)) {
1473          return;
1474        }
1475        const { updateBlockAttributes, __unstableMarkLastChangeAsPersistent } = registry.dispatch(import_block_editor7.store);
1476        __unstableMarkLastChangeAsPersistent();
1477        let newOverrides = { ...overrides };
1478        delete newOverrides[name];
1479        if (!Object.keys(newOverrides).length) {
1480          newOverrides = void 0;
1481        }
1482        updateBlockAttributes(patternClientId, {
1483          [CONTENT]: newOverrides
1484        });
1485      }
1486      return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_block_editor7.__unstableBlockToolbarLastItem, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components10.ToolbarButton, { onClick, disabled: !isOverridden, children: (0, import_i18n11.__)("Reset") }) }) });
1487    }
1488  
1489    // packages/patterns/build-module/private-apis.js
1490    var privateApis = {};
1491    lock(privateApis, {
1492      OverridesPanel,
1493      CreatePatternModal,
1494      CreatePatternModalContents,
1495      DuplicatePatternModal,
1496      isOverridableBlock,
1497      hasOverridableBlocks,
1498      useDuplicatePatternProps,
1499      RenamePatternModal,
1500      PatternsMenuItems,
1501      RenamePatternCategoryModal,
1502      PatternOverridesControls: pattern_overrides_controls_default,
1503      ResetOverridesControl,
1504      useAddPatternCategory,
1505      PATTERN_TYPES,
1506      PATTERN_DEFAULT_CATEGORY,
1507      PATTERN_USER_CATEGORY,
1508      EXCLUDED_PATTERN_SOURCES,
1509      PATTERN_SYNC_TYPES,
1510      PARTIAL_SYNCING_SUPPORTED_BLOCKS
1511    });
1512    return __toCommonJS(index_exports);
1513  })();


Generated : Sat Apr 18 08:20:10 2026 Cross-referenced by PHPXref