PluginProbe
Gutenberg / 18.9.0
Gutenberg v18.9.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / build / patterns / index.js

index.js in Gutenberg 18.9.0, at build/patterns/index.js

1,762 lines 62.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ "use strict";
3 /******/ // The require scope
4 /******/ var __webpack_require__ = {};
5 /******/
6 /************************************************************************/
7 /******/ /* webpack/runtime/define property getters */
8 /******/ (() => {
9 /******/ // define getter functions for harmony exports
10 /******/ __webpack_require__.d = (exports, definition) => {
11 /******/ for(var key in definition) {
12 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
13 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
14 /******/ }
15 /******/ }
16 /******/ };
17 /******/ })();
18 /******/
19 /******/ /* webpack/runtime/hasOwnProperty shorthand */
20 /******/ (() => {
21 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
22 /******/ })();
23 /******/
24 /******/ /* webpack/runtime/make namespace object */
25 /******/ (() => {
26 /******/ // define __esModule on exports
27 /******/ __webpack_require__.r = (exports) => {
28 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
29 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
30 /******/ }
31 /******/ Object.defineProperty(exports, '__esModule', { value: true });
32 /******/ };
33 /******/ })();
34 /******/
35 /************************************************************************/
36 var __webpack_exports__ = {};
37 // ESM COMPAT FLAG
38 __webpack_require__.r(__webpack_exports__);
39
40 // EXPORTS
41 __webpack_require__.d(__webpack_exports__, {
42 privateApis: () => (/* reexport */ privateApis),
43 store: () => (/* reexport */ store)
44 });
45
46 // NAMESPACE OBJECT: ./packages/patterns/build-module/store/actions.js
47 var actions_namespaceObject = {};
48 __webpack_require__.r(actions_namespaceObject);
49 __webpack_require__.d(actions_namespaceObject, {
50 convertSyncedPatternToStatic: () => (convertSyncedPatternToStatic),
51 createPattern: () => (createPattern),
52 createPatternFromFile: () => (createPatternFromFile),
53 setEditingPattern: () => (setEditingPattern)
54 });
55
56 // NAMESPACE OBJECT: ./packages/patterns/build-module/store/selectors.js
57 var selectors_namespaceObject = {};
58 __webpack_require__.r(selectors_namespaceObject);
59 __webpack_require__.d(selectors_namespaceObject, {
60 isEditingPattern: () => (selectors_isEditingPattern)
61 });
62
63 ;// CONCATENATED MODULE: external ["wp","data"]
64 const external_wp_data_namespaceObject = window["wp"]["data"];
65 ;// CONCATENATED MODULE: ./packages/patterns/build-module/store/reducer.js
66 /**
67 * WordPress dependencies
68 */
69
70 function isEditingPattern(state = {}, action) {
71 if (action?.type === 'SET_EDITING_PATTERN') {
72 return {
73 ...state,
74 [action.clientId]: action.isEditing
75 };
76 }
77 return state;
78 }
79 /* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
80 isEditingPattern
81 }));
82
83 ;// CONCATENATED MODULE: external ["wp","blocks"]
84 const external_wp_blocks_namespaceObject = window["wp"]["blocks"];
85 ;// CONCATENATED MODULE: external ["wp","coreData"]
86 const external_wp_coreData_namespaceObject = window["wp"]["coreData"];
87 ;// CONCATENATED MODULE: external ["wp","blockEditor"]
88 const external_wp_blockEditor_namespaceObject = window["wp"]["blockEditor"];
89 ;// CONCATENATED MODULE: ./packages/patterns/build-module/constants.js
90 const PATTERN_TYPES = {
91 theme: 'pattern',
92 user: 'wp_block'
93 };
94 const PATTERN_DEFAULT_CATEGORY = 'all-patterns';
95 const PATTERN_USER_CATEGORY = 'my-patterns';
96 const EXCLUDED_PATTERN_SOURCES = ['core', 'pattern-directory/core', 'pattern-directory/featured'];
97 const PATTERN_SYNC_TYPES = {
98 full: 'fully',
99 unsynced: 'unsynced'
100 };
101
102 // TODO: This should not be hardcoded. Maybe there should be a config and/or an UI.
103 const PARTIAL_SYNCING_SUPPORTED_BLOCKS = {
104 'core/paragraph': ['content'],
105 'core/heading': ['content'],
106 'core/button': ['text', 'url', 'linkTarget', 'rel'],
107 'core/image': ['id', 'url', 'title', 'alt']
108 };
109 const PATTERN_OVERRIDES_BINDING_SOURCE = 'core/pattern-overrides';
110
111 ;// CONCATENATED MODULE: ./packages/patterns/build-module/store/actions.js
112 /**
113 * WordPress dependencies
114 */
115
116
117
118
119
120 /**
121 * Internal dependencies
122 */
123
124
125 /**
126 * Returns a generator converting one or more static blocks into a pattern, or creating a new empty pattern.
127 *
128 * @param {string} title Pattern title.
129 * @param {'full'|'unsynced'} syncType They way block is synced, 'full' or 'unsynced'.
130 * @param {string|undefined} [content] Optional serialized content of blocks to convert to pattern.
131 * @param {number[]|undefined} [categories] Ids of any selected categories.
132 */
133 const createPattern = (title, syncType, content, categories) => async ({
134 registry
135 }) => {
136 const meta = syncType === PATTERN_SYNC_TYPES.unsynced ? {
137 wp_pattern_sync_status: syncType
138 } : undefined;
139 const reusableBlock = {
140 title,
141 content,
142 status: 'publish',
143 meta,
144 wp_pattern_category: categories
145 };
146 const updatedRecord = await registry.dispatch(external_wp_coreData_namespaceObject.store).saveEntityRecord('postType', 'wp_block', reusableBlock);
147 return updatedRecord;
148 };
149
150 /**
151 * Create a pattern from a JSON file.
152 * @param {File} file The JSON file instance of the pattern.
153 * @param {number[]|undefined} [categories] Ids of any selected categories.
154 */
155 const createPatternFromFile = (file, categories) => async ({
156 dispatch
157 }) => {
158 const fileContent = await file.text();
159 /** @type {import('./types').PatternJSON} */
160 let parsedContent;
161 try {
162 parsedContent = JSON.parse(fileContent);
163 } catch (e) {
164 throw new Error('Invalid JSON file');
165 }
166 if (parsedContent.__file !== 'wp_block' || !parsedContent.title || !parsedContent.content || typeof parsedContent.title !== 'string' || typeof parsedContent.content !== 'string' || parsedContent.syncStatus && typeof parsedContent.syncStatus !== 'string') {
167 throw new Error('Invalid pattern JSON file');
168 }
169 const pattern = await dispatch.createPattern(parsedContent.title, parsedContent.syncStatus, parsedContent.content, categories);
170 return pattern;
171 };
172
173 /**
174 * Returns a generator converting a synced pattern block into a static block.
175 *
176 * @param {string} clientId The client ID of the block to attach.
177 */
178 const convertSyncedPatternToStatic = clientId => ({
179 registry
180 }) => {
181 const patternBlock = registry.select(external_wp_blockEditor_namespaceObject.store).getBlock(clientId);
182 const existingOverrides = patternBlock.attributes?.content;
183 function cloneBlocksAndRemoveBindings(blocks) {
184 return blocks.map(block => {
185 let metadata = block.attributes.metadata;
186 if (metadata) {
187 metadata = {
188 ...metadata
189 };
190 delete metadata.id;
191 delete metadata.bindings;
192 // Use overridden values of the pattern block if they exist.
193 if (existingOverrides?.[metadata.name]) {
194 // Iterate over each overriden attribute.
195 for (const [attributeName, value] of Object.entries(existingOverrides[metadata.name])) {
196 // Skip if the attribute does not exist in the block type.
197 if (!(0,external_wp_blocks_namespaceObject.getBlockType)(block.name)?.attributes[attributeName]) {
198 continue;
199 }
200 // Update the block attribute with the override value.
201 block.attributes[attributeName] = value;
202 }
203 }
204 }
205 return (0,external_wp_blocks_namespaceObject.cloneBlock)(block, {
206 metadata: metadata && Object.keys(metadata).length > 0 ? metadata : undefined
207 }, cloneBlocksAndRemoveBindings(block.innerBlocks));
208 });
209 }
210 const patternInnerBlocks = registry.select(external_wp_blockEditor_namespaceObject.store).getBlocks(patternBlock.clientId);
211 registry.dispatch(external_wp_blockEditor_namespaceObject.store).replaceBlocks(patternBlock.clientId, cloneBlocksAndRemoveBindings(patternInnerBlocks));
212 };
213
214 /**
215 * Returns an action descriptor for SET_EDITING_PATTERN action.
216 *
217 * @param {string} clientId The clientID of the pattern to target.
218 * @param {boolean} isEditing Whether the block should be in editing state.
219 * @return {Object} Action descriptor.
220 */
221 function setEditingPattern(clientId, isEditing) {
222 return {
223 type: 'SET_EDITING_PATTERN',
224 clientId,
225 isEditing
226 };
227 }
228
229 ;// CONCATENATED MODULE: ./packages/patterns/build-module/store/constants.js
230 /**
231 * Module Constants
232 */
233 const STORE_NAME = 'core/patterns';
234
235 ;// CONCATENATED MODULE: ./packages/patterns/build-module/store/selectors.js
236 /**
237 * Returns true if pattern is in the editing state.
238 *
239 * @param {Object} state Global application state.
240 * @param {number} clientId the clientID of the block.
241 * @return {boolean} Whether the pattern is in the editing state.
242 */
243 function selectors_isEditingPattern(state, clientId) {
244 return state.isEditingPattern[clientId];
245 }
246
247 ;// CONCATENATED MODULE: external ["wp","privateApis"]
248 const external_wp_privateApis_namespaceObject = window["wp"]["privateApis"];
249 ;// CONCATENATED MODULE: ./packages/patterns/build-module/lock-unlock.js
250 /**
251 * WordPress dependencies
252 */
253
254 const {
255 lock,
256 unlock
257 } = (0,external_wp_privateApis_namespaceObject.__dangerousOptInToUnstableAPIsOnlyForCoreModules)('I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.', '@wordpress/patterns');
258
259 ;// CONCATENATED MODULE: ./packages/patterns/build-module/store/index.js
260 /**
261 * WordPress dependencies
262 */
263
264
265 /**
266 * Internal dependencies
267 */
268
269
270
271
272
273
274 /**
275 * Post editor data store configuration.
276 *
277 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#registerStore
278 *
279 * @type {Object}
280 */
281 const storeConfig = {
282 reducer: reducer
283 };
284
285 /**
286 * Store definition for the editor namespace.
287 *
288 * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore
289 *
290 * @type {Object}
291 */
292 const store = (0,external_wp_data_namespaceObject.createReduxStore)(STORE_NAME, {
293 ...storeConfig
294 });
295 (0,external_wp_data_namespaceObject.register)(store);
296 unlock(store).registerPrivateActions(actions_namespaceObject);
297 unlock(store).registerPrivateSelectors(selectors_namespaceObject);
298
299 ;// CONCATENATED MODULE: external ["wp","components"]
300 const external_wp_components_namespaceObject = window["wp"]["components"];
301 ;// CONCATENATED MODULE: external ["wp","element"]
302 const external_wp_element_namespaceObject = window["wp"]["element"];
303 ;// CONCATENATED MODULE: external ["wp","i18n"]
304 const external_wp_i18n_namespaceObject = window["wp"]["i18n"];
305 ;// CONCATENATED MODULE: ./packages/patterns/build-module/api/index.js
306 /**
307 * Internal dependencies
308 */
309
310
311 /**
312 * Determines whether a block is overridable.
313 *
314 * @param {WPBlock} block The block to test.
315 *
316 * @return {boolean} `true` if a block is overridable, `false` otherwise.
317 */
318 function isOverridableBlock(block) {
319 return Object.keys(PARTIAL_SYNCING_SUPPORTED_BLOCKS).includes(block.name) && !!block.attributes.metadata?.name && !!block.attributes.metadata?.bindings && Object.values(block.attributes.metadata.bindings).some(binding => binding.source === 'core/pattern-overrides');
320 }
321
322 /**
323 * Determines whether the blocks list has overridable blocks.
324 *
325 * @param {WPBlock[]} blocks The blocks list.
326 *
327 * @return {boolean} `true` if the list has overridable blocks, `false` otherwise.
328 */
329 function hasOverridableBlocks(blocks) {
330 return blocks.some(block => {
331 if (isOverridableBlock(block)) {
332 return true;
333 }
334 return hasOverridableBlocks(block.innerBlocks);
335 });
336 }
337
338 ;// CONCATENATED MODULE: external "ReactJSXRuntime"
339 const external_ReactJSXRuntime_namespaceObject = window["ReactJSXRuntime"];
340 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/overrides-panel.js
341 /**
342 * WordPress dependencies
343 */
344
345
346
347
348
349
350 /**
351 * Internal dependencies
352 */
353
354
355
356 const {
357 BlockQuickNavigation
358 } = unlock(external_wp_blockEditor_namespaceObject.privateApis);
359 function OverridesPanel() {
360 const allClientIds = (0,external_wp_data_namespaceObject.useSelect)(select => select(external_wp_blockEditor_namespaceObject.store).getClientIdsWithDescendants(), []);
361 const {
362 getBlock
363 } = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blockEditor_namespaceObject.store);
364 const clientIdsWithOverrides = (0,external_wp_element_namespaceObject.useMemo)(() => allClientIds.filter(clientId => {
365 const block = getBlock(clientId);
366 return isOverridableBlock(block);
367 }), [allClientIds, getBlock]);
368 if (!clientIdsWithOverrides?.length) {
369 return null;
370 }
371 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.PanelBody, {
372 title: (0,external_wp_i18n_namespaceObject.__)('Overrides'),
373 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockQuickNavigation, {
374 clientIds: clientIdsWithOverrides
375 })
376 });
377 }
378
379 ;// CONCATENATED MODULE: external ["wp","notices"]
380 const external_wp_notices_namespaceObject = window["wp"]["notices"];
381 ;// CONCATENATED MODULE: external ["wp","compose"]
382 const external_wp_compose_namespaceObject = window["wp"]["compose"];
383 ;// CONCATENATED MODULE: external ["wp","htmlEntities"]
384 const external_wp_htmlEntities_namespaceObject = window["wp"]["htmlEntities"];
385 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/category-selector.js
386 /**
387 * WordPress dependencies
388 */
389
390
391
392
393
394
395 const unescapeString = arg => {
396 return (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(arg);
397 };
398 const CATEGORY_SLUG = 'wp_pattern_category';
399 function CategorySelector({
400 categoryTerms,
401 onChange,
402 categoryMap
403 }) {
404 const [search, setSearch] = (0,external_wp_element_namespaceObject.useState)('');
405 const debouncedSearch = (0,external_wp_compose_namespaceObject.useDebounce)(setSearch, 500);
406 const suggestions = (0,external_wp_element_namespaceObject.useMemo)(() => {
407 return Array.from(categoryMap.values()).map(category => unescapeString(category.label)).filter(category => {
408 if (search !== '') {
409 return category.toLowerCase().includes(search.toLowerCase());
410 }
411 return true;
412 }).sort((a, b) => a.localeCompare(b));
413 }, [search, categoryMap]);
414 function handleChange(termNames) {
415 const uniqueTerms = termNames.reduce((terms, newTerm) => {
416 if (!terms.some(term => term.toLowerCase() === newTerm.toLowerCase())) {
417 terms.push(newTerm);
418 }
419 return terms;
420 }, []);
421 onChange(uniqueTerms);
422 }
423 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.FormTokenField, {
424 className: "patterns-menu-items__convert-modal-categories",
425 value: categoryTerms,
426 suggestions: suggestions,
427 onChange: handleChange,
428 onInputChange: debouncedSearch,
429 label: (0,external_wp_i18n_namespaceObject.__)('Categories'),
430 tokenizeOnBlur: true,
431 __experimentalExpandOnFocus: true,
432 __next40pxDefaultSize: true,
433 __nextHasNoMarginBottom: true
434 });
435 }
436
437 ;// CONCATENATED MODULE: ./packages/patterns/build-module/private-hooks.js
438 /**
439 * WordPress dependencies
440 */
441
442
443
444
445 /**
446 * Internal dependencies
447 */
448
449
450 /**
451 * Helper hook that creates a Map with the core and user patterns categories
452 * and removes any duplicates. It's used when we need to create new user
453 * categories when creating or importing patterns.
454 * This hook also provides a function to find or create a pattern category.
455 *
456 * @return {Object} The merged categories map and the callback function to find or create a category.
457 */
458 function useAddPatternCategory() {
459 const {
460 saveEntityRecord,
461 invalidateResolution
462 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_coreData_namespaceObject.store);
463 const {
464 corePatternCategories,
465 userPatternCategories
466 } = (0,external_wp_data_namespaceObject.useSelect)(select => {
467 const {
468 getUserPatternCategories,
469 getBlockPatternCategories
470 } = select(external_wp_coreData_namespaceObject.store);
471 return {
472 corePatternCategories: getBlockPatternCategories(),
473 userPatternCategories: getUserPatternCategories()
474 };
475 }, []);
476 const categoryMap = (0,external_wp_element_namespaceObject.useMemo)(() => {
477 // Merge the user and core pattern categories and remove any duplicates.
478 const uniqueCategories = new Map();
479 userPatternCategories.forEach(category => {
480 uniqueCategories.set(category.label.toLowerCase(), {
481 label: category.label,
482 name: category.name,
483 id: category.id
484 });
485 });
486 corePatternCategories.forEach(category => {
487 if (!uniqueCategories.has(category.label.toLowerCase()) &&
488 // There are two core categories with `Post` label so explicitly remove the one with
489 // the `query` slug to avoid any confusion.
490 category.name !== 'query') {
491 uniqueCategories.set(category.label.toLowerCase(), {
492 label: category.label,
493 name: category.name
494 });
495 }
496 });
497 return uniqueCategories;
498 }, [userPatternCategories, corePatternCategories]);
499 async function findOrCreateTerm(term) {
500 try {
501 const existingTerm = categoryMap.get(term.toLowerCase());
502 if (existingTerm?.id) {
503 return existingTerm.id;
504 }
505 // If we have an existing core category we need to match the new user category to the
506 // correct slug rather than autogenerating it to prevent duplicates, eg. the core `Headers`
507 // category uses the singular `header` as the slug.
508 const termData = existingTerm ? {
509 name: existingTerm.label,
510 slug: existingTerm.name
511 } : {
512 name: term
513 };
514 const newTerm = await saveEntityRecord('taxonomy', CATEGORY_SLUG, termData, {
515 throwOnError: true
516 });
517 invalidateResolution('getUserPatternCategories');
518 return newTerm.id;
519 } catch (error) {
520 if (error.code !== 'term_exists') {
521 throw error;
522 }
523 return error.data.term_id;
524 }
525 }
526 return {
527 categoryMap,
528 findOrCreateTerm
529 };
530 }
531
532 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/create-pattern-modal.js
533 /**
534 * WordPress dependencies
535 */
536
537
538
539
540
541
542
543 /**
544 * Internal dependencies
545 */
546
547
548
549
550
551
552
553 function CreatePatternModal({
554 className = 'patterns-menu-items__convert-modal',
555 modalTitle,
556 ...restProps
557 }) {
558 const defaultModalTitle = (0,external_wp_data_namespaceObject.useSelect)(select => select(external_wp_coreData_namespaceObject.store).getPostType(PATTERN_TYPES.user)?.labels?.add_new_item, []);
559 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
560 title: modalTitle || defaultModalTitle,
561 onRequestClose: restProps.onClose,
562 overlayClassName: className,
563 focusOnMount: "firstContentElement",
564 size: "small",
565 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CreatePatternModalContents, {
566 ...restProps
567 })
568 });
569 }
570 function CreatePatternModalContents({
571 confirmLabel = (0,external_wp_i18n_namespaceObject.__)('Add'),
572 defaultCategories = [],
573 content,
574 onClose,
575 onError,
576 onSuccess,
577 defaultSyncType = PATTERN_SYNC_TYPES.full,
578 defaultTitle = ''
579 }) {
580 const [syncType, setSyncType] = (0,external_wp_element_namespaceObject.useState)(defaultSyncType);
581 const [categoryTerms, setCategoryTerms] = (0,external_wp_element_namespaceObject.useState)(defaultCategories);
582 const [title, setTitle] = (0,external_wp_element_namespaceObject.useState)(defaultTitle);
583 const [isSaving, setIsSaving] = (0,external_wp_element_namespaceObject.useState)(false);
584 const {
585 createPattern
586 } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
587 const {
588 createErrorNotice
589 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
590 const {
591 categoryMap,
592 findOrCreateTerm
593 } = useAddPatternCategory();
594 async function onCreate(patternTitle, sync) {
595 if (!title || isSaving) {
596 return;
597 }
598 try {
599 setIsSaving(true);
600 const categories = await Promise.all(categoryTerms.map(termName => findOrCreateTerm(termName)));
601 const newPattern = await createPattern(patternTitle, sync, typeof content === 'function' ? content() : content, categories);
602 onSuccess({
603 pattern: newPattern,
604 categoryId: PATTERN_DEFAULT_CATEGORY
605 });
606 } catch (error) {
607 createErrorNotice(error.message, {
608 type: 'snackbar',
609 id: 'pattern-create'
610 });
611 onError?.();
612 } finally {
613 setIsSaving(false);
614 setCategoryTerms([]);
615 setTitle('');
616 }
617 }
618 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
619 onSubmit: event => {
620 event.preventDefault();
621 onCreate(title, syncType);
622 },
623 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
624 spacing: "5",
625 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
626 label: (0,external_wp_i18n_namespaceObject.__)('Name'),
627 value: title,
628 onChange: setTitle,
629 placeholder: (0,external_wp_i18n_namespaceObject.__)('My pattern'),
630 className: "patterns-create-modal__name-input",
631 __nextHasNoMarginBottom: true,
632 __next40pxDefaultSize: true
633 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CategorySelector, {
634 categoryTerms: categoryTerms,
635 onChange: setCategoryTerms,
636 categoryMap: categoryMap
637 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToggleControl, {
638 label: (0,external_wp_i18n_namespaceObject._x)('Synced', 'pattern (singular)'),
639 help: (0,external_wp_i18n_namespaceObject.__)('Sync this pattern across multiple locations.'),
640 checked: syncType === PATTERN_SYNC_TYPES.full,
641 onChange: () => {
642 setSyncType(syncType === PATTERN_SYNC_TYPES.full ? PATTERN_SYNC_TYPES.unsynced : PATTERN_SYNC_TYPES.full);
643 }
644 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
645 justify: "right",
646 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
647 __next40pxDefaultSize: true,
648 variant: "tertiary",
649 onClick: () => {
650 onClose();
651 setTitle('');
652 },
653 children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
654 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
655 __next40pxDefaultSize: true,
656 variant: "primary",
657 type: "submit",
658 "aria-disabled": !title || isSaving,
659 isBusy: isSaving,
660 children: confirmLabel
661 })]
662 })]
663 })
664 });
665 }
666
667 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/duplicate-pattern-modal.js
668 /**
669 * WordPress dependencies
670 */
671
672
673
674
675
676 /**
677 * Internal dependencies
678 */
679
680
681
682 function getTermLabels(pattern, categories) {
683 // Theme patterns rely on core pattern categories.
684 if (pattern.type !== PATTERN_TYPES.user) {
685 return categories.core?.filter(category => pattern.categories.includes(category.name)).map(category => category.label);
686 }
687 return categories.user?.filter(category => pattern.wp_pattern_category.includes(category.id)).map(category => category.label);
688 }
689 function useDuplicatePatternProps({
690 pattern,
691 onSuccess
692 }) {
693 const {
694 createSuccessNotice
695 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
696 const categories = (0,external_wp_data_namespaceObject.useSelect)(select => {
697 const {
698 getUserPatternCategories,
699 getBlockPatternCategories
700 } = select(external_wp_coreData_namespaceObject.store);
701 return {
702 core: getBlockPatternCategories(),
703 user: getUserPatternCategories()
704 };
705 });
706 if (!pattern) {
707 return null;
708 }
709 return {
710 content: pattern.content,
711 defaultCategories: getTermLabels(pattern, categories),
712 defaultSyncType: pattern.type !== PATTERN_TYPES.user // Theme patterns are unsynced by default.
713 ? PATTERN_SYNC_TYPES.unsynced : pattern.wp_pattern_sync_status || PATTERN_SYNC_TYPES.full,
714 defaultTitle: (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %s: Existing pattern title */
715 (0,external_wp_i18n_namespaceObject.__)('%s (Copy)'), typeof pattern.title === 'string' ? pattern.title : pattern.title.raw),
716 onSuccess: ({
717 pattern: newPattern
718 }) => {
719 createSuccessNotice((0,external_wp_i18n_namespaceObject.sprintf)(
720 // translators: %s: The new pattern's title e.g. 'Call to action (copy)'.
721 (0,external_wp_i18n_namespaceObject.__)('"%s" duplicated.'), newPattern.title.raw), {
722 type: 'snackbar',
723 id: 'patterns-create'
724 });
725 onSuccess?.({
726 pattern: newPattern
727 });
728 }
729 };
730 }
731 function DuplicatePatternModal({
732 pattern,
733 onClose,
734 onSuccess
735 }) {
736 const duplicatedProps = useDuplicatePatternProps({
737 pattern,
738 onSuccess
739 });
740 if (!pattern) {
741 return null;
742 }
743 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CreatePatternModal, {
744 modalTitle: (0,external_wp_i18n_namespaceObject.__)('Duplicate pattern'),
745 confirmLabel: (0,external_wp_i18n_namespaceObject.__)('Duplicate'),
746 onClose: onClose,
747 onError: onClose,
748 ...duplicatedProps
749 });
750 }
751
752 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/rename-pattern-modal.js
753 /**
754 * WordPress dependencies
755 */
756
757
758
759
760
761
762
763
764
765 function RenamePatternModal({
766 onClose,
767 onError,
768 onSuccess,
769 pattern,
770 ...props
771 }) {
772 const originalName = (0,external_wp_htmlEntities_namespaceObject.decodeEntities)(pattern.title);
773 const [name, setName] = (0,external_wp_element_namespaceObject.useState)(originalName);
774 const [isSaving, setIsSaving] = (0,external_wp_element_namespaceObject.useState)(false);
775 const {
776 editEntityRecord,
777 __experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits
778 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_coreData_namespaceObject.store);
779 const {
780 createSuccessNotice,
781 createErrorNotice
782 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
783 const onRename = async event => {
784 event.preventDefault();
785 if (!name || name === pattern.title || isSaving) {
786 return;
787 }
788 try {
789 await editEntityRecord('postType', pattern.type, pattern.id, {
790 title: name
791 });
792 setIsSaving(true);
793 setName('');
794 onClose?.();
795 const savedRecord = await saveSpecifiedEntityEdits('postType', pattern.type, pattern.id, ['title'], {
796 throwOnError: true
797 });
798 onSuccess?.(savedRecord);
799 createSuccessNotice((0,external_wp_i18n_namespaceObject.__)('Pattern renamed'), {
800 type: 'snackbar',
801 id: 'pattern-update'
802 });
803 } catch (error) {
804 onError?.();
805 const errorMessage = error.message && error.code !== 'unknown_error' ? error.message : (0,external_wp_i18n_namespaceObject.__)('An error occurred while renaming the pattern.');
806 createErrorNotice(errorMessage, {
807 type: 'snackbar',
808 id: 'pattern-update'
809 });
810 } finally {
811 setIsSaving(false);
812 setName('');
813 }
814 };
815 const onRequestClose = () => {
816 onClose?.();
817 setName('');
818 };
819 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
820 title: (0,external_wp_i18n_namespaceObject.__)('Rename'),
821 ...props,
822 onRequestClose: onClose,
823 focusOnMount: "firstContentElement",
824 size: "small",
825 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
826 onSubmit: onRename,
827 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
828 spacing: "5",
829 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
830 __nextHasNoMarginBottom: true,
831 __next40pxDefaultSize: true,
832 label: (0,external_wp_i18n_namespaceObject.__)('Name'),
833 value: name,
834 onChange: setName,
835 required: true
836 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
837 justify: "right",
838 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
839 __next40pxDefaultSize: true,
840 variant: "tertiary",
841 onClick: onRequestClose,
842 children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
843 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
844 __next40pxDefaultSize: true,
845 variant: "primary",
846 type: "submit",
847 children: (0,external_wp_i18n_namespaceObject.__)('Save')
848 })]
849 })]
850 })
851 })
852 });
853 }
854
855 ;// CONCATENATED MODULE: external ["wp","primitives"]
856 const external_wp_primitives_namespaceObject = window["wp"]["primitives"];
857 ;// CONCATENATED MODULE: ./packages/icons/build-module/library/symbol.js
858 /**
859 * WordPress dependencies
860 */
861
862
863 const symbol = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, {
864 xmlns: "http://www.w3.org/2000/svg",
865 viewBox: "0 0 24 24",
866 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, {
867 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"
868 })
869 });
870 /* harmony default export */ const library_symbol = (symbol);
871
872 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/pattern-convert-button.js
873 /**
874 * WordPress dependencies
875 */
876
877
878
879
880
881
882
883
884
885 /**
886 * Internal dependencies
887 */
888
889
890
891
892
893 /**
894 * Menu control to convert block(s) to a pattern block.
895 *
896 * @param {Object} props Component props.
897 * @param {string[]} props.clientIds Client ids of selected blocks.
898 * @param {string} props.rootClientId ID of the currently selected top-level block.
899 * @param {()=>void} props.closeBlockSettingsMenu Callback to close the block settings menu dropdown.
900 * @return {import('react').ComponentType} The menu control or null.
901 */
902
903
904
905 function PatternConvertButton({
906 clientIds,
907 rootClientId,
908 closeBlockSettingsMenu
909 }) {
910 const {
911 createSuccessNotice
912 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
913 const {
914 replaceBlocks
915 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_blockEditor_namespaceObject.store);
916 // Ignore reason: false positive of the lint rule.
917 // eslint-disable-next-line @wordpress/no-unused-vars-before-return
918 const {
919 setEditingPattern
920 } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
921 const [isModalOpen, setIsModalOpen] = (0,external_wp_element_namespaceObject.useState)(false);
922 const canConvert = (0,external_wp_data_namespaceObject.useSelect)(select => {
923 var _getBlocksByClientId;
924 const {
925 canUser
926 } = select(external_wp_coreData_namespaceObject.store);
927 const {
928 getBlocksByClientId,
929 canInsertBlockType,
930 getBlockRootClientId
931 } = select(external_wp_blockEditor_namespaceObject.store);
932 const rootId = rootClientId || (clientIds.length > 0 ? getBlockRootClientId(clientIds[0]) : undefined);
933 const blocks = (_getBlocksByClientId = getBlocksByClientId(clientIds)) !== null && _getBlocksByClientId !== void 0 ? _getBlocksByClientId : [];
934 const isReusable = blocks.length === 1 && blocks[0] && (0,external_wp_blocks_namespaceObject.isReusableBlock)(blocks[0]) && !!select(external_wp_coreData_namespaceObject.store).getEntityRecord('postType', 'wp_block', blocks[0].attributes.ref);
935 const _canConvert =
936 // Hide when this is already a synced pattern.
937 !isReusable &&
938 // Hide when patterns are disabled.
939 canInsertBlockType('core/block', rootId) && blocks.every(block =>
940 // Guard against the case where a regular block has *just* been converted.
941 !!block &&
942 // Hide on invalid blocks.
943 block.isValid &&
944 // Hide when block doesn't support being made into a pattern.
945 (0,external_wp_blocks_namespaceObject.hasBlockSupport)(block.name, 'reusable', true)) &&
946 // Hide when current doesn't have permission to do that.
947 // Blocks refers to the wp_block post type, this checks the ability to create a post of that type.
948 !!canUser('create', {
949 kind: 'postType',
950 name: 'wp_block'
951 });
952 return _canConvert;
953 }, [clientIds, rootClientId]);
954 const {
955 getBlocksByClientId
956 } = (0,external_wp_data_namespaceObject.useSelect)(external_wp_blockEditor_namespaceObject.store);
957 const getContent = (0,external_wp_element_namespaceObject.useCallback)(() => (0,external_wp_blocks_namespaceObject.serialize)(getBlocksByClientId(clientIds)), [getBlocksByClientId, clientIds]);
958 if (!canConvert) {
959 return null;
960 }
961 const handleSuccess = ({
962 pattern
963 }) => {
964 if (pattern.wp_pattern_sync_status !== PATTERN_SYNC_TYPES.unsynced) {
965 const newBlock = (0,external_wp_blocks_namespaceObject.createBlock)('core/block', {
966 ref: pattern.id
967 });
968 replaceBlocks(clientIds, newBlock);
969 setEditingPattern(newBlock.clientId, true);
970 closeBlockSettingsMenu();
971 }
972 createSuccessNotice(pattern.wp_pattern_sync_status === PATTERN_SYNC_TYPES.unsynced ? (0,external_wp_i18n_namespaceObject.sprintf)(
973 // translators: %s: the name the user has given to the pattern.
974 (0,external_wp_i18n_namespaceObject.__)('Unsynced pattern created: %s'), pattern.title.raw) : (0,external_wp_i18n_namespaceObject.sprintf)(
975 // translators: %s: the name the user has given to the pattern.
976 (0,external_wp_i18n_namespaceObject.__)('Synced pattern created: %s'), pattern.title.raw), {
977 type: 'snackbar',
978 id: 'convert-to-pattern-success'
979 });
980 setIsModalOpen(false);
981 };
982 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
983 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, {
984 icon: library_symbol,
985 onClick: () => setIsModalOpen(true),
986 "aria-expanded": isModalOpen,
987 "aria-haspopup": "dialog",
988 children: (0,external_wp_i18n_namespaceObject.__)('Create pattern')
989 }), isModalOpen && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(CreatePatternModal, {
990 content: getContent,
991 onSuccess: pattern => {
992 handleSuccess(pattern);
993 },
994 onError: () => {
995 setIsModalOpen(false);
996 },
997 onClose: () => {
998 setIsModalOpen(false);
999 }
1000 })]
1001 });
1002 }
1003
1004 ;// CONCATENATED MODULE: external ["wp","url"]
1005 const external_wp_url_namespaceObject = window["wp"]["url"];
1006 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/patterns-manage-button.js
1007 /**
1008 * WordPress dependencies
1009 */
1010
1011
1012
1013
1014
1015
1016
1017
1018 /**
1019 * Internal dependencies
1020 */
1021
1022
1023
1024
1025
1026 function PatternsManageButton({
1027 clientId
1028 }) {
1029 const {
1030 canRemove,
1031 isVisible,
1032 managePatternsUrl
1033 } = (0,external_wp_data_namespaceObject.useSelect)(select => {
1034 const {
1035 getBlock,
1036 canRemoveBlock,
1037 getBlockCount
1038 } = select(external_wp_blockEditor_namespaceObject.store);
1039 const {
1040 canUser
1041 } = select(external_wp_coreData_namespaceObject.store);
1042 const reusableBlock = getBlock(clientId);
1043 return {
1044 canRemove: canRemoveBlock(clientId),
1045 isVisible: !!reusableBlock && (0,external_wp_blocks_namespaceObject.isReusableBlock)(reusableBlock) && !!canUser('update', {
1046 kind: 'postType',
1047 name: 'wp_block',
1048 id: reusableBlock.attributes.ref
1049 }),
1050 innerBlockCount: getBlockCount(clientId),
1051 // The site editor and templates both check whether the user
1052 // has edit_theme_options capabilities. We can leverage that here
1053 // and omit the manage patterns link if the user can't access it.
1054 managePatternsUrl: canUser('create', {
1055 kind: 'postType',
1056 name: 'wp_template'
1057 }) ? (0,external_wp_url_namespaceObject.addQueryArgs)('site-editor.php', {
1058 path: '/patterns'
1059 }) : (0,external_wp_url_namespaceObject.addQueryArgs)('edit.php', {
1060 post_type: 'wp_block'
1061 })
1062 };
1063 }, [clientId]);
1064
1065 // Ignore reason: false positive of the lint rule.
1066 // eslint-disable-next-line @wordpress/no-unused-vars-before-return
1067 const {
1068 convertSyncedPatternToStatic
1069 } = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
1070 if (!isVisible) {
1071 return null;
1072 }
1073 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
1074 children: [canRemove && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, {
1075 onClick: () => convertSyncedPatternToStatic(clientId),
1076 children: (0,external_wp_i18n_namespaceObject.__)('Detach')
1077 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.MenuItem, {
1078 href: managePatternsUrl,
1079 children: (0,external_wp_i18n_namespaceObject.__)('Manage patterns')
1080 })]
1081 });
1082 }
1083 /* harmony default export */ const patterns_manage_button = (PatternsManageButton);
1084
1085 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/index.js
1086 /**
1087 * WordPress dependencies
1088 */
1089
1090
1091 /**
1092 * Internal dependencies
1093 */
1094
1095
1096
1097
1098
1099 function PatternsMenuItems({
1100 rootClientId
1101 }) {
1102 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.BlockSettingsMenuControls, {
1103 children: ({
1104 selectedClientIds,
1105 onClose
1106 }) => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
1107 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternConvertButton, {
1108 clientIds: selectedClientIds,
1109 rootClientId: rootClientId,
1110 closeBlockSettingsMenu: onClose
1111 }), selectedClientIds.length === 1 && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(patterns_manage_button, {
1112 clientId: selectedClientIds[0]
1113 })]
1114 })
1115 });
1116 }
1117
1118 ;// CONCATENATED MODULE: external ["wp","a11y"]
1119 const external_wp_a11y_namespaceObject = window["wp"]["a11y"];
1120 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/rename-pattern-category-modal.js
1121 /**
1122 * WordPress dependencies
1123 */
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 /**
1134 * Internal dependencies
1135 */
1136
1137
1138
1139 function RenamePatternCategoryModal({
1140 category,
1141 existingCategories,
1142 onClose,
1143 onError,
1144 onSuccess,
1145 ...props
1146 }) {
1147 const id = (0,external_wp_element_namespaceObject.useId)();
1148 const textControlRef = (0,external_wp_element_namespaceObject.useRef)();
1149 const [name, setName] = (0,external_wp_element_namespaceObject.useState)((0,external_wp_htmlEntities_namespaceObject.decodeEntities)(category.name));
1150 const [isSaving, setIsSaving] = (0,external_wp_element_namespaceObject.useState)(false);
1151 const [validationMessage, setValidationMessage] = (0,external_wp_element_namespaceObject.useState)(false);
1152 const validationMessageId = validationMessage ? `patterns-rename-pattern-category-modal__validation-message-${id}` : undefined;
1153 const {
1154 saveEntityRecord,
1155 invalidateResolution
1156 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_coreData_namespaceObject.store);
1157 const {
1158 createErrorNotice,
1159 createSuccessNotice
1160 } = (0,external_wp_data_namespaceObject.useDispatch)(external_wp_notices_namespaceObject.store);
1161 const onChange = newName => {
1162 if (validationMessage) {
1163 setValidationMessage(undefined);
1164 }
1165 setName(newName);
1166 };
1167 const onSave = async event => {
1168 event.preventDefault();
1169 if (isSaving) {
1170 return;
1171 }
1172 if (!name || name === category.name) {
1173 const message = (0,external_wp_i18n_namespaceObject.__)('Please enter a new name for this category.');
1174 (0,external_wp_a11y_namespaceObject.speak)(message, 'assertive');
1175 setValidationMessage(message);
1176 textControlRef.current?.focus();
1177 return;
1178 }
1179
1180 // Check existing categories to avoid creating duplicates.
1181 if (existingCategories.patternCategories.find(existingCategory => {
1182 // Compare the id so that the we don't disallow the user changing the case of their current category
1183 // (i.e. renaming 'test' to 'Test').
1184 return existingCategory.id !== category.id && existingCategory.label.toLowerCase() === name.toLowerCase();
1185 })) {
1186 const message = (0,external_wp_i18n_namespaceObject.__)('This category already exists. Please use a different name.');
1187 (0,external_wp_a11y_namespaceObject.speak)(message, 'assertive');
1188 setValidationMessage(message);
1189 textControlRef.current?.focus();
1190 return;
1191 }
1192 try {
1193 setIsSaving(true);
1194
1195 // User pattern category properties may differ as they can be
1196 // normalized for use alongside template part areas, core pattern
1197 // categories etc. As a result we won't just destructure the passed
1198 // category object.
1199 const savedRecord = await saveEntityRecord('taxonomy', CATEGORY_SLUG, {
1200 id: category.id,
1201 slug: category.slug,
1202 name
1203 });
1204 invalidateResolution('getUserPatternCategories');
1205 onSuccess?.(savedRecord);
1206 onClose();
1207 createSuccessNotice((0,external_wp_i18n_namespaceObject.__)('Pattern category renamed.'), {
1208 type: 'snackbar',
1209 id: 'pattern-category-update'
1210 });
1211 } catch (error) {
1212 onError?.();
1213 createErrorNotice(error.message, {
1214 type: 'snackbar',
1215 id: 'pattern-category-update'
1216 });
1217 } finally {
1218 setIsSaving(false);
1219 setName('');
1220 }
1221 };
1222 const onRequestClose = () => {
1223 onClose();
1224 setName('');
1225 };
1226 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
1227 title: (0,external_wp_i18n_namespaceObject.__)('Rename'),
1228 onRequestClose: onRequestClose,
1229 ...props,
1230 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
1231 onSubmit: onSave,
1232 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
1233 spacing: "5",
1234 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
1235 spacing: "2",
1236 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
1237 ref: textControlRef,
1238 __nextHasNoMarginBottom: true,
1239 __next40pxDefaultSize: true,
1240 label: (0,external_wp_i18n_namespaceObject.__)('Name'),
1241 value: name,
1242 onChange: onChange,
1243 "aria-describedby": validationMessageId,
1244 required: true
1245 }), validationMessage && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("span", {
1246 className: "patterns-rename-pattern-category-modal__validation-message",
1247 id: validationMessageId,
1248 children: validationMessage
1249 })]
1250 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
1251 justify: "right",
1252 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1253 __next40pxDefaultSize: true,
1254 variant: "tertiary",
1255 onClick: onRequestClose,
1256 children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
1257 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1258 __next40pxDefaultSize: true,
1259 variant: "primary",
1260 type: "submit",
1261 "aria-disabled": !name || name === category.name || isSaving,
1262 isBusy: isSaving,
1263 children: (0,external_wp_i18n_namespaceObject.__)('Save')
1264 })]
1265 })]
1266 })
1267 })
1268 });
1269 }
1270
1271 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/allow-overrides-modal.js
1272 /**
1273 * WordPress dependencies
1274 */
1275
1276
1277
1278
1279
1280
1281 function AllowOverridesModal({
1282 placeholder,
1283 initialName = '',
1284 onClose,
1285 onSave
1286 }) {
1287 const [editedBlockName, setEditedBlockName] = (0,external_wp_element_namespaceObject.useState)(initialName);
1288 const descriptionId = (0,external_wp_element_namespaceObject.useId)();
1289 const isNameValid = !!editedBlockName.trim();
1290 const handleSubmit = () => {
1291 if (editedBlockName !== initialName) {
1292 const message = (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %s: new name/label for the block */
1293 (0,external_wp_i18n_namespaceObject.__)('Block name changed to: "%s".'), editedBlockName);
1294
1295 // Must be assertive to immediately announce change.
1296 (0,external_wp_a11y_namespaceObject.speak)(message, 'assertive');
1297 }
1298 onSave(editedBlockName);
1299
1300 // Immediate close avoids ability to hit save multiple times.
1301 onClose();
1302 };
1303 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
1304 title: (0,external_wp_i18n_namespaceObject.__)('Enable overrides'),
1305 onRequestClose: onClose,
1306 focusOnMount: "firstContentElement",
1307 aria: {
1308 describedby: descriptionId
1309 },
1310 size: "small",
1311 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
1312 onSubmit: event => {
1313 event.preventDefault();
1314 if (!isNameValid) {
1315 return;
1316 }
1317 handleSubmit();
1318 },
1319 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
1320 spacing: "6",
1321 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, {
1322 id: descriptionId,
1323 children: (0,external_wp_i18n_namespaceObject.__)('Overrides are changes you make to a block within a synced pattern instance. Use overrides to customize a synced pattern instance to suit its new context. Name this block to specify an override.')
1324 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.TextControl, {
1325 __nextHasNoMarginBottom: true,
1326 __next40pxDefaultSize: true,
1327 value: editedBlockName,
1328 label: (0,external_wp_i18n_namespaceObject.__)('Name'),
1329 help: (0,external_wp_i18n_namespaceObject.__)('For example, if you are creating a recipe pattern, you use "Recipe Title", "Recipe Description", etc.'),
1330 placeholder: placeholder,
1331 onChange: setEditedBlockName
1332 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
1333 justify: "right",
1334 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1335 __next40pxDefaultSize: true,
1336 variant: "tertiary",
1337 onClick: onClose,
1338 children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
1339 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1340 __next40pxDefaultSize: true,
1341 "aria-disabled": !isNameValid,
1342 variant: "primary",
1343 type: "submit",
1344 children: (0,external_wp_i18n_namespaceObject.__)('Enable')
1345 })]
1346 })]
1347 })
1348 })
1349 });
1350 }
1351 function DisallowOverridesModal({
1352 onClose,
1353 onSave
1354 }) {
1355 const descriptionId = (0,external_wp_element_namespaceObject.useId)();
1356 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Modal, {
1357 title: (0,external_wp_i18n_namespaceObject.__)('Disable overrides'),
1358 onRequestClose: onClose,
1359 aria: {
1360 describedby: descriptionId
1361 },
1362 size: "small",
1363 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("form", {
1364 onSubmit: event => {
1365 event.preventDefault();
1366 onSave();
1367 onClose();
1368 },
1369 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalVStack, {
1370 spacing: "6",
1371 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, {
1372 id: descriptionId,
1373 children: (0,external_wp_i18n_namespaceObject.__)('Are you sure you want to disable overrides? Disabling overrides will revert all applied overrides for this block throughout instances of this pattern.')
1374 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_wp_components_namespaceObject.__experimentalHStack, {
1375 justify: "right",
1376 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1377 __next40pxDefaultSize: true,
1378 variant: "tertiary",
1379 onClick: onClose,
1380 children: (0,external_wp_i18n_namespaceObject.__)('Cancel')
1381 }), /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1382 __next40pxDefaultSize: true,
1383 variant: "primary",
1384 type: "submit",
1385 children: (0,external_wp_i18n_namespaceObject.__)('Disable')
1386 })]
1387 })]
1388 })
1389 })
1390 });
1391 }
1392
1393 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/pattern-overrides-controls.js
1394 /**
1395 * WordPress dependencies
1396 */
1397
1398
1399
1400
1401
1402 /**
1403 * Internal dependencies
1404 */
1405
1406
1407
1408
1409
1410 function removeBindings(bindings) {
1411 let updatedBindings = {
1412 ...bindings
1413 };
1414 delete updatedBindings.__default;
1415 if (!Object.keys(updatedBindings).length) {
1416 updatedBindings = undefined;
1417 }
1418 return updatedBindings;
1419 }
1420 function addBindings(bindings) {
1421 return {
1422 ...bindings,
1423 __default: {
1424 source: PATTERN_OVERRIDES_BINDING_SOURCE
1425 }
1426 };
1427 }
1428 function PatternOverridesControls({
1429 attributes,
1430 setAttributes,
1431 name: blockName
1432 }) {
1433 const controlId = (0,external_wp_element_namespaceObject.useId)();
1434 const [showAllowOverridesModal, setShowAllowOverridesModal] = (0,external_wp_element_namespaceObject.useState)(false);
1435 const [showDisallowOverridesModal, setShowDisallowOverridesModal] = (0,external_wp_element_namespaceObject.useState)(false);
1436 const hasName = !!attributes.metadata?.name;
1437 const defaultBindings = attributes.metadata?.bindings?.__default;
1438 const hasOverrides = hasName && defaultBindings?.source === PATTERN_OVERRIDES_BINDING_SOURCE;
1439 const isConnectedToOtherSources = defaultBindings?.source && defaultBindings.source !== PATTERN_OVERRIDES_BINDING_SOURCE;
1440 function updateBindings(isChecked, customName) {
1441 const prevBindings = attributes?.metadata?.bindings;
1442 const updatedBindings = isChecked ? addBindings(prevBindings) : removeBindings(prevBindings);
1443 const updatedMetadata = {
1444 ...attributes.metadata,
1445 bindings: updatedBindings
1446 };
1447 if (customName) {
1448 updatedMetadata.name = customName;
1449 }
1450 setAttributes({
1451 metadata: updatedMetadata
1452 });
1453 }
1454
1455 // Avoid overwriting other (e.g. meta) bindings.
1456 if (isConnectedToOtherSources) {
1457 return null;
1458 }
1459 const hasUnsupportedImageAttributes = blockName === 'core/image' && (!!attributes.caption?.length || !!attributes.href?.length);
1460 const helpText = !hasOverrides && hasUnsupportedImageAttributes ? (0,external_wp_i18n_namespaceObject.__)(`Overrides currently don't support image captions or links. Remove the caption or link first before enabling overrides.`) : (0,external_wp_i18n_namespaceObject.__)('Allow changes to this block throughout instances of this pattern.');
1461 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(external_ReactJSXRuntime_namespaceObject.Fragment, {
1462 children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.InspectorControls, {
1463 group: "advanced",
1464 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.BaseControl, {
1465 id: controlId,
1466 label: (0,external_wp_i18n_namespaceObject.__)('Overrides'),
1467 help: helpText,
1468 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.Button, {
1469 __next40pxDefaultSize: true,
1470 className: "pattern-overrides-control__allow-overrides-button",
1471 variant: "secondary",
1472 "aria-haspopup": "dialog",
1473 onClick: () => {
1474 if (hasOverrides) {
1475 setShowDisallowOverridesModal(true);
1476 } else {
1477 setShowAllowOverridesModal(true);
1478 }
1479 },
1480 disabled: !hasOverrides && hasUnsupportedImageAttributes,
1481 accessibleWhenDisabled: true,
1482 children: hasOverrides ? (0,external_wp_i18n_namespaceObject.__)('Disable overrides') : (0,external_wp_i18n_namespaceObject.__)('Enable overrides')
1483 })
1484 })
1485 }), showAllowOverridesModal && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(AllowOverridesModal, {
1486 initialName: attributes.metadata?.name,
1487 onClose: () => setShowAllowOverridesModal(false),
1488 onSave: newName => {
1489 updateBindings(true, newName);
1490 }
1491 }), showDisallowOverridesModal && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(DisallowOverridesModal, {
1492 onClose: () => setShowDisallowOverridesModal(false),
1493 onSave: () => updateBindings(false)
1494 })]
1495 });
1496 }
1497 /* harmony default export */ const pattern_overrides_controls = (PatternOverridesControls);
1498
1499 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/reset-overrides-control.js
1500 /**
1501 * WordPress dependencies
1502 */
1503
1504
1505
1506
1507
1508 const CONTENT = 'content';
1509 function ResetOverridesControl(props) {
1510 const name = props.attributes.metadata?.name;
1511 const registry = (0,external_wp_data_namespaceObject.useRegistry)();
1512 const isOverriden = (0,external_wp_data_namespaceObject.useSelect)(select => {
1513 if (!name) {
1514 return;
1515 }
1516 const {
1517 getBlockAttributes,
1518 getBlockParentsByBlockName
1519 } = select(external_wp_blockEditor_namespaceObject.store);
1520 const [patternClientId] = getBlockParentsByBlockName(props.clientId, 'core/block', true);
1521 if (!patternClientId) {
1522 return;
1523 }
1524 const overrides = getBlockAttributes(patternClientId)[CONTENT];
1525 if (!overrides) {
1526 return;
1527 }
1528 return overrides.hasOwnProperty(name);
1529 }, [props.clientId, name]);
1530 function onClick() {
1531 const {
1532 getBlockAttributes,
1533 getBlockParentsByBlockName
1534 } = registry.select(external_wp_blockEditor_namespaceObject.store);
1535 const [patternClientId] = getBlockParentsByBlockName(props.clientId, 'core/block', true);
1536 if (!patternClientId) {
1537 return;
1538 }
1539 const overrides = getBlockAttributes(patternClientId)[CONTENT];
1540 if (!overrides.hasOwnProperty(name)) {
1541 return;
1542 }
1543 const {
1544 updateBlockAttributes,
1545 __unstableMarkLastChangeAsPersistent
1546 } = registry.dispatch(external_wp_blockEditor_namespaceObject.store);
1547 __unstableMarkLastChangeAsPersistent();
1548 let newOverrides = {
1549 ...overrides
1550 };
1551 delete newOverrides[name];
1552 if (!Object.keys(newOverrides).length) {
1553 newOverrides = undefined;
1554 }
1555 updateBlockAttributes(patternClientId, {
1556 [CONTENT]: newOverrides
1557 });
1558 }
1559 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.__unstableBlockToolbarLastItem, {
1560 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToolbarGroup, {
1561 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToolbarButton, {
1562 onClick: onClick,
1563 disabled: !isOverriden,
1564 children: (0,external_wp_i18n_namespaceObject.__)('Reset')
1565 })
1566 })
1567 });
1568 }
1569
1570 ;// CONCATENATED MODULE: ./packages/icons/build-module/library/copy.js
1571 /**
1572 * WordPress dependencies
1573 */
1574
1575
1576 const copy = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.SVG, {
1577 xmlns: "http://www.w3.org/2000/svg",
1578 viewBox: "0 0 24 24",
1579 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_primitives_namespaceObject.Path, {
1580 fillRule: "evenodd",
1581 clipRule: "evenodd",
1582 d: "M5 4.5h11a.5.5 0 0 1 .5.5v11a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5ZM3 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5Zm17 3v10.75c0 .69-.56 1.25-1.25 1.25H6v1.5h12.75a2.75 2.75 0 0 0 2.75-2.75V8H20Z"
1583 })
1584 });
1585 /* harmony default export */ const library_copy = (copy);
1586
1587 ;// CONCATENATED MODULE: ./packages/patterns/build-module/components/pattern-overrides-block-controls.js
1588 /**
1589 * WordPress dependencies
1590 */
1591
1592
1593
1594
1595
1596
1597
1598
1599 /**
1600 * Internal dependencies
1601 */
1602
1603
1604
1605
1606 const {
1607 useBlockDisplayTitle
1608 } = unlock(external_wp_blockEditor_namespaceObject.privateApis);
1609 function PatternOverridesToolbarIndicator({
1610 clientIds
1611 }) {
1612 const isSingleBlockSelected = clientIds.length === 1;
1613 const {
1614 icon,
1615 firstBlockName
1616 } = (0,external_wp_data_namespaceObject.useSelect)(select => {
1617 const {
1618 getBlockAttributes,
1619 getBlockNamesByClientId
1620 } = select(external_wp_blockEditor_namespaceObject.store);
1621 const {
1622 getBlockType,
1623 getActiveBlockVariation
1624 } = select(external_wp_blocks_namespaceObject.store);
1625 const blockTypeNames = getBlockNamesByClientId(clientIds);
1626 const _firstBlockTypeName = blockTypeNames[0];
1627 const firstBlockType = getBlockType(_firstBlockTypeName);
1628 let _icon;
1629 if (isSingleBlockSelected) {
1630 const match = getActiveBlockVariation(_firstBlockTypeName, getBlockAttributes(clientIds[0]));
1631 // Take into account active block variations.
1632 _icon = match?.icon || firstBlockType.icon;
1633 } else {
1634 const isSelectionOfSameType = new Set(blockTypeNames).size === 1;
1635 // When selection consists of blocks of multiple types, display an
1636 // appropriate icon to communicate the non-uniformity.
1637 _icon = isSelectionOfSameType ? firstBlockType.icon : library_copy;
1638 }
1639 return {
1640 icon: _icon,
1641 firstBlockName: getBlockAttributes(clientIds[0]).metadata.name
1642 };
1643 }, [clientIds, isSingleBlockSelected]);
1644 const firstBlockTitle = useBlockDisplayTitle({
1645 clientId: clientIds[0],
1646 maximumLength: 35
1647 });
1648 const blockDescription = isSingleBlockSelected ? (0,external_wp_i18n_namespaceObject.sprintf)( /* translators: %1s: The block type's name; %2s: The block's user-provided name (the same as the override name). */
1649 (0,external_wp_i18n_namespaceObject.__)('This %1$s is editable using the "%2$s" override.'), firstBlockTitle.toLowerCase(), firstBlockName) : (0,external_wp_i18n_namespaceObject.__)('These blocks are editable using overrides.');
1650 const descriptionId = (0,external_wp_element_namespaceObject.useId)();
1651 return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.ToolbarItem, {
1652 children: toggleProps => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.DropdownMenu, {
1653 className: "patterns-pattern-overrides-toolbar-indicator",
1654 label: firstBlockTitle,
1655 popoverProps: {
1656 placement: 'bottom-start',
1657 className: 'patterns-pattern-overrides-toolbar-indicator__popover'
1658 },
1659 icon: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_ReactJSXRuntime_namespaceObject.Fragment, {
1660 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.BlockIcon, {
1661 icon: icon,
1662 className: "patterns-pattern-overrides-toolbar-indicator-icon",
1663 showColors: true
1664 })
1665 }),
1666 toggleProps: {
1667 description: blockDescription,
1668 ...toggleProps
1669 },
1670 menuProps: {
1671 orientation: 'both',
1672 'aria-describedby': descriptionId
1673 },
1674 children: () => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_components_namespaceObject.__experimentalText, {
1675 id: descriptionId,
1676 children: blockDescription
1677 })
1678 })
1679 });
1680 }
1681 function PatternOverridesBlockControls() {
1682 const {
1683 clientIds,
1684 hasPatternOverrides,
1685 hasParentPattern
1686 } = (0,external_wp_data_namespaceObject.useSelect)(select => {
1687 const {
1688 getBlockAttributes,
1689 getSelectedBlockClientIds,
1690 getBlockParentsByBlockName
1691 } = select(external_wp_blockEditor_namespaceObject.store);
1692 const selectedClientIds = getSelectedBlockClientIds();
1693 const _hasPatternOverrides = selectedClientIds.every(clientId => {
1694 var _getBlockAttributes$m;
1695 return Object.values((_getBlockAttributes$m = getBlockAttributes(clientId)?.metadata?.bindings) !== null && _getBlockAttributes$m !== void 0 ? _getBlockAttributes$m : {}).some(binding => binding?.source === PATTERN_OVERRIDES_BINDING_SOURCE);
1696 });
1697 const _hasParentPattern = selectedClientIds.every(clientId => getBlockParentsByBlockName(clientId, 'core/block', true).length > 0);
1698 return {
1699 clientIds: selectedClientIds,
1700 hasPatternOverrides: _hasPatternOverrides,
1701 hasParentPattern: _hasParentPattern
1702 };
1703 }, []);
1704 return hasPatternOverrides && hasParentPattern ? /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_blockEditor_namespaceObject.BlockControls, {
1705 group: "parent",
1706 children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(PatternOverridesToolbarIndicator, {
1707 clientIds: clientIds
1708 })
1709 }) : null;
1710 }
1711
1712 ;// CONCATENATED MODULE: ./packages/patterns/build-module/private-apis.js
1713 /**
1714 * Internal dependencies
1715 */
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729 const privateApis = {};
1730 lock(privateApis, {
1731 OverridesPanel: OverridesPanel,
1732 CreatePatternModal: CreatePatternModal,
1733 CreatePatternModalContents: CreatePatternModalContents,
1734 DuplicatePatternModal: DuplicatePatternModal,
1735 isOverridableBlock: isOverridableBlock,
1736 hasOverridableBlocks: hasOverridableBlocks,
1737 useDuplicatePatternProps: useDuplicatePatternProps,
1738 RenamePatternModal: RenamePatternModal,
1739 PatternsMenuItems: PatternsMenuItems,
1740 RenamePatternCategoryModal: RenamePatternCategoryModal,
1741 PatternOverridesControls: pattern_overrides_controls,
1742 ResetOverridesControl: ResetOverridesControl,
1743 PatternOverridesBlockControls: PatternOverridesBlockControls,
1744 useAddPatternCategory: useAddPatternCategory,
1745 PATTERN_TYPES: PATTERN_TYPES,
1746 PATTERN_DEFAULT_CATEGORY: PATTERN_DEFAULT_CATEGORY,
1747 PATTERN_USER_CATEGORY: PATTERN_USER_CATEGORY,
1748 EXCLUDED_PATTERN_SOURCES: EXCLUDED_PATTERN_SOURCES,
1749 PATTERN_SYNC_TYPES: PATTERN_SYNC_TYPES,
1750 PARTIAL_SYNCING_SUPPORTED_BLOCKS: PARTIAL_SYNCING_SUPPORTED_BLOCKS
1751 });
1752
1753 ;// CONCATENATED MODULE: ./packages/patterns/build-module/index.js
1754 /**
1755 * Internal dependencies
1756 */
1757
1758
1759
1760 (window.wp = window.wp || {}).patterns = __webpack_exports__;
1761 /******/ })()
1762 ;