PluginProbe
Gutenberg / 20.0.1
Gutenberg v20.0.1
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 7.4.0 All 402 releases
gutenberg / build / patterns / index.js

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

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