PluginProbe
Gutenberg / 23.5.3
Gutenberg v23.5.3
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 / scripts / reusable-blocks / index.js

index.js in Gutenberg 23.5.3, at build/scripts/reusable-blocks/index.js

505 lines 20.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 var wp;
2 (wp ||= {}).reusableBlocks = (() => {
3 var __create = Object.create;
4 var __defProp = Object.defineProperty;
5 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6 var __getOwnPropNames = Object.getOwnPropertyNames;
7 var __getProtoOf = Object.getPrototypeOf;
8 var __hasOwnProp = Object.prototype.hasOwnProperty;
9 var __commonJS = (cb, mod) => function __require() {
10 return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11 };
12 var __export = (target, all) => {
13 for (var name in all)
14 __defProp(target, name, { get: all[name], enumerable: true });
15 };
16 var __copyProps = (to, from, except, desc) => {
17 if (from && typeof from === "object" || typeof from === "function") {
18 for (let key of __getOwnPropNames(from))
19 if (!__hasOwnProp.call(to, key) && key !== except)
20 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21 }
22 return to;
23 };
24 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25 // If the importer is in node compatibility mode or this is not an ESM
26 // file that has been converted to a CommonJS file using a Babel-
27 // compatible transform (i.e. "__esModule" has not been set), then set
28 // "default" to the CommonJS "module.exports" for node compatibility.
29 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30 mod
31 ));
32 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
34 // package-external:@wordpress/data
35 var require_data = __commonJS({
36 "package-external:@wordpress/data"(exports, module) {
37 module.exports = window.wp.data;
38 }
39 });
40
41 // package-external:@wordpress/block-editor
42 var require_block_editor = __commonJS({
43 "package-external:@wordpress/block-editor"(exports, module) {
44 module.exports = window.wp.blockEditor;
45 }
46 });
47
48 // package-external:@wordpress/blocks
49 var require_blocks = __commonJS({
50 "package-external:@wordpress/blocks"(exports, module) {
51 module.exports = window.wp.blocks;
52 }
53 });
54
55 // package-external:@wordpress/i18n
56 var require_i18n = __commonJS({
57 "package-external:@wordpress/i18n"(exports, module) {
58 module.exports = window.wp.i18n;
59 }
60 });
61
62 // package-external:@wordpress/element
63 var require_element = __commonJS({
64 "package-external:@wordpress/element"(exports, module) {
65 module.exports = window.wp.element;
66 }
67 });
68
69 // package-external:@wordpress/components
70 var require_components = __commonJS({
71 "package-external:@wordpress/components"(exports, module) {
72 module.exports = window.wp.components;
73 }
74 });
75
76 // package-external:@wordpress/primitives
77 var require_primitives = __commonJS({
78 "package-external:@wordpress/primitives"(exports, module) {
79 module.exports = window.wp.primitives;
80 }
81 });
82
83 // vendor-external:react/jsx-runtime
84 var require_jsx_runtime = __commonJS({
85 "vendor-external:react/jsx-runtime"(exports, module) {
86 module.exports = window.ReactJSXRuntime;
87 }
88 });
89
90 // package-external:@wordpress/notices
91 var require_notices = __commonJS({
92 "package-external:@wordpress/notices"(exports, module) {
93 module.exports = window.wp.notices;
94 }
95 });
96
97 // package-external:@wordpress/core-data
98 var require_core_data = __commonJS({
99 "package-external:@wordpress/core-data"(exports, module) {
100 module.exports = window.wp.coreData;
101 }
102 });
103
104 // package-external:@wordpress/url
105 var require_url = __commonJS({
106 "package-external:@wordpress/url"(exports, module) {
107 module.exports = window.wp.url;
108 }
109 });
110
111 // packages/reusable-blocks/build-module/index.mjs
112 var index_exports = {};
113 __export(index_exports, {
114 ReusableBlocksMenuItems: () => ReusableBlocksMenuItems,
115 store: () => store
116 });
117
118 // packages/reusable-blocks/build-module/store/index.mjs
119 var import_data2 = __toESM(require_data(), 1);
120
121 // packages/reusable-blocks/build-module/store/actions.mjs
122 var actions_exports = {};
123 __export(actions_exports, {
124 __experimentalConvertBlockToStatic: () => __experimentalConvertBlockToStatic,
125 __experimentalConvertBlocksToReusable: () => __experimentalConvertBlocksToReusable,
126 __experimentalDeleteReusableBlock: () => __experimentalDeleteReusableBlock,
127 __experimentalSetEditingReusableBlock: () => __experimentalSetEditingReusableBlock
128 });
129 var import_block_editor = __toESM(require_block_editor(), 1);
130 var import_blocks = __toESM(require_blocks(), 1);
131 var import_i18n = __toESM(require_i18n(), 1);
132 var __experimentalConvertBlockToStatic = (clientId) => ({ registry }) => {
133 const oldBlock = registry.select(import_block_editor.store).getBlock(clientId);
134 const reusableBlock = registry.select("core").getEditedEntityRecord(
135 "postType",
136 "wp_block",
137 oldBlock.attributes.ref
138 );
139 const newBlocks = (0, import_blocks.parse)(
140 typeof reusableBlock.content === "function" ? reusableBlock.content(reusableBlock) : reusableBlock.content
141 );
142 registry.dispatch(import_block_editor.store).replaceBlocks(oldBlock.clientId, newBlocks);
143 };
144 var __experimentalConvertBlocksToReusable = (clientIds, title, syncType) => async ({ registry, dispatch }) => {
145 const meta = syncType === "unsynced" ? {
146 wp_pattern_sync_status: syncType
147 } : void 0;
148 const reusableBlock = {
149 title: title || (0, import_i18n.__)("Untitled pattern block"),
150 content: (0, import_blocks.serialize)(
151 registry.select(import_block_editor.store).getBlocksByClientId(clientIds)
152 ),
153 status: "publish",
154 meta
155 };
156 const updatedRecord = await registry.dispatch("core").saveEntityRecord("postType", "wp_block", reusableBlock);
157 if (syncType === "unsynced") {
158 return;
159 }
160 const newBlock = (0, import_blocks.createBlock)("core/block", {
161 ref: updatedRecord.id
162 });
163 registry.dispatch(import_block_editor.store).replaceBlocks(clientIds, newBlock);
164 dispatch.__experimentalSetEditingReusableBlock(
165 newBlock.clientId,
166 true
167 );
168 };
169 var __experimentalDeleteReusableBlock = (id) => async ({ registry }) => {
170 const reusableBlock = registry.select("core").getEditedEntityRecord("postType", "wp_block", id);
171 if (!reusableBlock) {
172 return;
173 }
174 const allBlocks = registry.select(import_block_editor.store).getBlocks();
175 const associatedBlocks = allBlocks.filter(
176 (block) => (0, import_blocks.isReusableBlock)(block) && block.attributes.ref === id
177 );
178 const associatedBlockClientIds = associatedBlocks.map(
179 (block) => block.clientId
180 );
181 if (associatedBlockClientIds.length) {
182 registry.dispatch(import_block_editor.store).removeBlocks(associatedBlockClientIds);
183 }
184 await registry.dispatch("core").deleteEntityRecord("postType", "wp_block", id);
185 };
186 function __experimentalSetEditingReusableBlock(clientId, isEditing) {
187 return {
188 type: "SET_EDITING_REUSABLE_BLOCK",
189 clientId,
190 isEditing
191 };
192 }
193
194 // packages/reusable-blocks/build-module/store/reducer.mjs
195 var import_data = __toESM(require_data(), 1);
196 function isEditingReusableBlock(state = {}, action) {
197 if (action?.type === "SET_EDITING_REUSABLE_BLOCK") {
198 return {
199 ...state,
200 [action.clientId]: action.isEditing
201 };
202 }
203 return state;
204 }
205 var reducer_default = (0, import_data.combineReducers)({
206 isEditingReusableBlock
207 });
208
209 // packages/reusable-blocks/build-module/store/selectors.mjs
210 var selectors_exports = {};
211 __export(selectors_exports, {
212 __experimentalIsEditingReusableBlock: () => __experimentalIsEditingReusableBlock
213 });
214 function __experimentalIsEditingReusableBlock(state, clientId) {
215 return state.isEditingReusableBlock[clientId];
216 }
217
218 // packages/reusable-blocks/build-module/store/index.mjs
219 var STORE_NAME = "core/reusable-blocks";
220 var store = (0, import_data2.createReduxStore)(STORE_NAME, {
221 actions: actions_exports,
222 reducer: reducer_default,
223 selectors: selectors_exports
224 });
225 (0, import_data2.register)(store);
226
227 // packages/reusable-blocks/build-module/components/reusable-blocks-menu-items/index.mjs
228 var import_block_editor4 = __toESM(require_block_editor(), 1);
229
230 // packages/reusable-blocks/build-module/components/reusable-blocks-menu-items/reusable-block-convert-button.mjs
231 var import_blocks2 = __toESM(require_blocks(), 1);
232 var import_block_editor2 = __toESM(require_block_editor(), 1);
233 var import_element = __toESM(require_element(), 1);
234 var import_components = __toESM(require_components(), 1);
235
236 // packages/icons/build-module/library/symbol.mjs
237 var import_primitives = __toESM(require_primitives(), 1);
238 var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
239 var symbol_default = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_primitives.SVG, { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_primitives.Path, { d: "M21.3 10.8l-5.6-5.6c-.7-.7-1.8-.7-2.5 0l-5.6 5.6c-.7.7-.7 1.8 0 2.5l5.6 5.6c.3.3.8.5 1.2.5s.9-.2 1.2-.5l5.6-5.6c.8-.7.8-1.9.1-2.5zm-1 1.4l-5.6 5.6c-.1.1-.3.1-.4 0l-5.6-5.6c-.1-.1-.1-.3 0-.4l5.6-5.6s.1-.1.2-.1.1 0 .2.1l5.6 5.6c.1.1.1.3 0 .4zm-16.6-.4L10 5.5l-1-1-6.3 6.3c-.7.7-.7 1.8 0 2.5L9 19.5l1.1-1.1-6.3-6.3c-.2 0-.2-.2-.1-.3z" }) });
240
241 // packages/reusable-blocks/build-module/components/reusable-blocks-menu-items/reusable-block-convert-button.mjs
242 var import_data3 = __toESM(require_data(), 1);
243 var import_i18n2 = __toESM(require_i18n(), 1);
244 var import_notices = __toESM(require_notices(), 1);
245 var import_core_data = __toESM(require_core_data(), 1);
246 var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
247 function ReusableBlockConvertButton({
248 clientIds,
249 rootClientId,
250 onClose
251 }) {
252 const [syncType, setSyncType] = (0, import_element.useState)(void 0);
253 const [isModalOpen, setIsModalOpen] = (0, import_element.useState)(false);
254 const [title, setTitle] = (0, import_element.useState)("");
255 const canConvert = (0, import_data3.useSelect)(
256 (select) => {
257 const { canUser } = select(import_core_data.store);
258 const {
259 getBlocksByClientId,
260 canInsertBlockType,
261 getBlockRootClientId
262 } = select(import_block_editor2.store);
263 const rootId = rootClientId || (clientIds.length > 0 ? getBlockRootClientId(clientIds[0]) : void 0);
264 const blocks = getBlocksByClientId(clientIds) ?? [];
265 const isReusable = blocks.length === 1 && blocks[0] && (0, import_blocks2.isReusableBlock)(blocks[0]) && !!select(import_core_data.store).getEntityRecord(
266 "postType",
267 "wp_block",
268 blocks[0].attributes.ref
269 );
270 const _canConvert = (
271 // Hide when this is already a reusable block.
272 !isReusable && // Hide when reusable blocks are disabled.
273 canInsertBlockType("core/block", rootId) && blocks.every(
274 (block) => (
275 // Guard against the case where a regular block has *just* been converted.
276 !!block && // Hide on invalid blocks.
277 block.isValid && // Hide when block doesn't support being made reusable.
278 (0, import_blocks2.hasBlockSupport)(block.name, "reusable", true)
279 )
280 ) && // Hide when current doesn't have permission to do that.
281 // Blocks refers to the wp_block post type, this checks the ability to create a post of that type.
282 !!canUser("create", {
283 kind: "postType",
284 name: "wp_block"
285 })
286 );
287 return _canConvert;
288 },
289 [clientIds, rootClientId]
290 );
291 const { __experimentalConvertBlocksToReusable: convertBlocksToReusable } = (0, import_data3.useDispatch)(store);
292 const { createSuccessNotice, createErrorNotice } = (0, import_data3.useDispatch)(import_notices.store);
293 const onConvert = (0, import_element.useCallback)(
294 async function(reusableBlockTitle) {
295 try {
296 await convertBlocksToReusable(
297 clientIds,
298 reusableBlockTitle,
299 syncType
300 );
301 createSuccessNotice(
302 !syncType ? (0, import_i18n2.sprintf)(
303 // translators: %s: the name the user has given to the pattern.
304 (0, import_i18n2.__)("Synced pattern created: %s"),
305 reusableBlockTitle
306 ) : (0, import_i18n2.sprintf)(
307 // translators: %s: the name the user has given to the pattern.
308 (0, import_i18n2.__)("Unsynced pattern created: %s"),
309 reusableBlockTitle
310 ),
311 {
312 type: "snackbar",
313 id: "convert-to-reusable-block-success"
314 }
315 );
316 } catch (error) {
317 createErrorNotice(error.message, {
318 type: "snackbar",
319 id: "convert-to-reusable-block-error"
320 });
321 }
322 },
323 [
324 convertBlocksToReusable,
325 clientIds,
326 syncType,
327 createSuccessNotice,
328 createErrorNotice
329 ]
330 );
331 if (!canConvert) {
332 return null;
333 }
334 return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
335 /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_components.MenuItem, { icon: symbol_default, onClick: () => setIsModalOpen(true), children: (0, import_i18n2.__)("Create pattern") }),
336 isModalOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
337 import_components.Modal,
338 {
339 title: (0, import_i18n2.__)("Create pattern"),
340 onRequestClose: () => {
341 setIsModalOpen(false);
342 setTitle("");
343 },
344 overlayClassName: "reusable-blocks-menu-items__convert-modal",
345 children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
346 "form",
347 {
348 onSubmit: (event) => {
349 event.preventDefault();
350 onConvert(title);
351 setIsModalOpen(false);
352 setTitle("");
353 onClose();
354 },
355 children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_components.__experimentalVStack, { spacing: "5", children: [
356 /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
357 import_components.TextControl,
358 {
359 label: (0, import_i18n2.__)("Name"),
360 value: title,
361 onChange: setTitle,
362 placeholder: (0, import_i18n2.__)("My pattern")
363 }
364 ),
365 /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
366 import_components.ToggleControl,
367 {
368 label: (0, import_i18n2._x)("Synced", "pattern (singular)"),
369 help: (0, import_i18n2.__)(
370 "Sync this pattern across multiple locations."
371 ),
372 checked: !syncType,
373 onChange: () => {
374 setSyncType(
375 !syncType ? "unsynced" : void 0
376 );
377 }
378 }
379 ),
380 /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_components.__experimentalHStack, { justify: "right", children: [
381 /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
382 import_components.Button,
383 {
384 __next40pxDefaultSize: true,
385 variant: "tertiary",
386 onClick: () => {
387 setIsModalOpen(false);
388 setTitle("");
389 },
390 children: (0, import_i18n2.__)("Cancel")
391 }
392 ),
393 /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
394 import_components.Button,
395 {
396 __next40pxDefaultSize: true,
397 variant: "primary",
398 type: "submit",
399 children: (0, import_i18n2.__)("Create")
400 }
401 )
402 ] })
403 ] })
404 }
405 )
406 }
407 )
408 ] });
409 }
410
411 // packages/reusable-blocks/build-module/components/reusable-blocks-menu-items/reusable-blocks-manage-button.mjs
412 var import_components2 = __toESM(require_components(), 1);
413 var import_i18n3 = __toESM(require_i18n(), 1);
414 var import_blocks3 = __toESM(require_blocks(), 1);
415 var import_data4 = __toESM(require_data(), 1);
416 var import_element2 = __toESM(require_element(), 1);
417 var import_block_editor3 = __toESM(require_block_editor(), 1);
418 var import_url = __toESM(require_url(), 1);
419 var import_core_data2 = __toESM(require_core_data(), 1);
420 var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
421 function ReusableBlocksManageButton({ clientId }) {
422 const [showConfirmDialog, setShowConfirmDialog] = (0, import_element2.useState)(false);
423 const { canRemove, isVisible, managePatternsUrl } = (0, import_data4.useSelect)(
424 (select) => {
425 const { getBlock, canRemoveBlock } = select(import_block_editor3.store);
426 const { canUser } = select(import_core_data2.store);
427 const reusableBlock = getBlock(clientId);
428 return {
429 canRemove: canRemoveBlock(clientId),
430 isVisible: !!reusableBlock && (0, import_blocks3.isReusableBlock)(reusableBlock) && !!canUser("update", {
431 kind: "postType",
432 name: "wp_block",
433 id: reusableBlock.attributes.ref
434 }),
435 // The site editor and templates both check whether the user
436 // has edit_theme_options capabilities. We can leverage that here
437 // and omit the manage patterns link if the user can't access it.
438 managePatternsUrl: canUser("create", {
439 kind: "postType",
440 name: "wp_template"
441 }) ? (0, import_url.addQueryArgs)("site-editor.php", {
442 p: "/pattern"
443 }) : (0, import_url.addQueryArgs)("edit.php", {
444 post_type: "wp_block"
445 })
446 };
447 },
448 [clientId]
449 );
450 const { __experimentalConvertBlockToStatic: convertBlockToStatic } = (0, import_data4.useDispatch)(store);
451 if (!isVisible) {
452 return null;
453 }
454 const handleDetach = () => {
455 convertBlockToStatic(clientId);
456 setShowConfirmDialog(false);
457 };
458 return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
459 /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_components2.MenuItem, { href: managePatternsUrl, children: (0, import_i18n3.__)("Manage patterns") }),
460 canRemove && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
461 /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_components2.MenuItem, { onClick: () => setShowConfirmDialog(true), children: (0, import_i18n3.__)("Disconnect pattern") }),
462 /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
463 import_components2.__experimentalConfirmDialog,
464 {
465 isOpen: showConfirmDialog,
466 onConfirm: handleDetach,
467 onCancel: () => setShowConfirmDialog(false),
468 confirmButtonText: (0, import_i18n3.__)("Disconnect"),
469 size: "medium",
470 title: (0, import_i18n3.__)("Disconnect pattern?"),
471 __experimentalHideHeader: false,
472 children: (0, import_i18n3.__)(
473 "Blocks will be separated from the original pattern and will be fully editable. Future changes to the pattern will not apply here."
474 )
475 }
476 )
477 ] })
478 ] });
479 }
480 var reusable_blocks_manage_button_default = ReusableBlocksManageButton;
481
482 // packages/reusable-blocks/build-module/components/reusable-blocks-menu-items/index.mjs
483 var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
484 function ReusableBlocksMenuItems({ rootClientId }) {
485 return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_block_editor4.BlockSettingsMenuControls, { children: ({ onClose, selectedClientIds }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
486 /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
487 ReusableBlockConvertButton,
488 {
489 clientIds: selectedClientIds,
490 rootClientId,
491 onClose
492 }
493 ),
494 selectedClientIds.length === 1 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
495 reusable_blocks_manage_button_default,
496 {
497 clientId: selectedClientIds[0]
498 }
499 )
500 ] }) });
501 }
502 return __toCommonJS(index_exports);
503 })();
504 //# sourceMappingURL=index.js.map
505