@wordpress/reusable-blocks 3.0.1 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ Install the module
10
10
  npm install @wordpress/reusable-blocks --save
11
11
  ```
12
12
 
13
- _This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as IE browsers then using [core-js](https://github.com/zloirock/core-js) will add polyfills for these methods._
13
+ _This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._
14
14
 
15
15
  ## How it works
16
16
 
@@ -3,15 +3,23 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.__experimentalConvertBlockToStatic = __experimentalConvertBlockToStatic;
7
- exports.__experimentalConvertBlocksToReusable = __experimentalConvertBlocksToReusable;
8
- exports.__experimentalDeleteReusableBlock = __experimentalDeleteReusableBlock;
9
6
  exports.__experimentalSetEditingReusableBlock = __experimentalSetEditingReusableBlock;
7
+ exports.__experimentalDeleteReusableBlock = exports.__experimentalConvertBlocksToReusable = exports.__experimentalConvertBlockToStatic = void 0;
8
+
9
+ var _lodash = require("lodash");
10
10
 
11
- var _controls = require("./controls");
11
+ var _blockEditor = require("@wordpress/block-editor");
12
+
13
+ var _blocks = require("@wordpress/blocks");
14
+
15
+ var _i18n = require("@wordpress/i18n");
12
16
 
13
17
  /**
14
- * Internal dependencies
18
+ * External dependencies
19
+ */
20
+
21
+ /**
22
+ * WordPress dependencies
15
23
  */
16
24
 
17
25
  /**
@@ -19,9 +27,14 @@ var _controls = require("./controls");
19
27
  *
20
28
  * @param {string} clientId The client ID of the block to attach.
21
29
  */
22
- function* __experimentalConvertBlockToStatic(clientId) {
23
- yield (0, _controls.convertBlockToStatic)(clientId);
24
- }
30
+ const __experimentalConvertBlockToStatic = clientId => ({
31
+ registry
32
+ }) => {
33
+ const oldBlock = registry.select(_blockEditor.store).getBlock(clientId);
34
+ const reusableBlock = registry.select('core').getEditedEntityRecord('postType', 'wp_block', oldBlock.attributes.ref);
35
+ const newBlocks = (0, _blocks.parse)((0, _lodash.isFunction)(reusableBlock.content) ? reusableBlock.content(reusableBlock) : reusableBlock.content);
36
+ registry.dispatch(_blockEditor.store).replaceBlocks(oldBlock.clientId, newBlocks);
37
+ };
25
38
  /**
26
39
  * Returns a generator converting one or more static blocks into a reusable block.
27
40
  *
@@ -30,9 +43,25 @@ function* __experimentalConvertBlockToStatic(clientId) {
30
43
  */
31
44
 
32
45
 
33
- function* __experimentalConvertBlocksToReusable(clientIds, title) {
34
- yield (0, _controls.convertBlocksToReusable)(clientIds, title);
35
- }
46
+ exports.__experimentalConvertBlockToStatic = __experimentalConvertBlockToStatic;
47
+
48
+ const __experimentalConvertBlocksToReusable = (clientIds, title) => async ({
49
+ registry,
50
+ dispatch
51
+ }) => {
52
+ const reusableBlock = {
53
+ title: title || (0, _i18n.__)('Untitled Reusable block'),
54
+ content: (0, _blocks.serialize)(registry.select(_blockEditor.store).getBlocksByClientId(clientIds)),
55
+ status: 'publish'
56
+ };
57
+ const updatedRecord = await registry.dispatch('core').saveEntityRecord('postType', 'wp_block', reusableBlock);
58
+ const newBlock = (0, _blocks.createBlock)('core/block', {
59
+ ref: updatedRecord.id
60
+ });
61
+ registry.dispatch(_blockEditor.store).replaceBlocks(clientIds, newBlock);
62
+
63
+ dispatch.__experimentalSetEditingReusableBlock(newBlock.clientId, true);
64
+ };
36
65
  /**
37
66
  * Returns a generator deleting a reusable block.
38
67
  *
@@ -40,9 +69,28 @@ function* __experimentalConvertBlocksToReusable(clientIds, title) {
40
69
  */
41
70
 
42
71
 
43
- function* __experimentalDeleteReusableBlock(id) {
44
- yield (0, _controls.deleteReusableBlock)(id);
45
- }
72
+ exports.__experimentalConvertBlocksToReusable = __experimentalConvertBlocksToReusable;
73
+
74
+ const __experimentalDeleteReusableBlock = id => async ({
75
+ registry
76
+ }) => {
77
+ const reusableBlock = registry.select('core').getEditedEntityRecord('postType', 'wp_block', id); // Don't allow a reusable block with a temporary ID to be deleted
78
+
79
+ if (!reusableBlock) {
80
+ return;
81
+ } // Remove any other blocks that reference this reusable block
82
+
83
+
84
+ const allBlocks = registry.select(_blockEditor.store).getBlocks();
85
+ const associatedBlocks = allBlocks.filter(block => (0, _blocks.isReusableBlock)(block) && block.attributes.ref === id);
86
+ const associatedBlockClientIds = associatedBlocks.map(block => block.clientId); // Remove the parsed block.
87
+
88
+ if (associatedBlockClientIds.length) {
89
+ registry.dispatch(_blockEditor.store).removeBlocks(associatedBlockClientIds);
90
+ }
91
+
92
+ await registry.dispatch('core').deleteEntityRecord('postType', 'wp_block', id);
93
+ };
46
94
  /**
47
95
  * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.
48
96
  *
@@ -52,6 +100,8 @@ function* __experimentalDeleteReusableBlock(id) {
52
100
  */
53
101
 
54
102
 
103
+ exports.__experimentalDeleteReusableBlock = __experimentalDeleteReusableBlock;
104
+
55
105
  function __experimentalSetEditingReusableBlock(clientId, isEditing) {
56
106
  return {
57
107
  type: 'SET_EDITING_REUSABLE_BLOCK',
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/reusable-blocks/src/store/actions.js"],"names":["__experimentalConvertBlockToStatic","clientId","__experimentalConvertBlocksToReusable","clientIds","title","__experimentalDeleteReusableBlock","id","__experimentalSetEditingReusableBlock","isEditing","type"],"mappings":";;;;;;;;;;AAGA;;AAHA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACO,UAAUA,kCAAV,CAA8CC,QAA9C,EAAyD;AAC/D,QAAM,oCAAsBA,QAAtB,CAAN;AACA;AAED;AACA;AACA;AACA;AACA;AACA;;;AACO,UAAUC,qCAAV,CAAiDC,SAAjD,EAA4DC,KAA5D,EAAoE;AAC1E,QAAM,uCAAyBD,SAAzB,EAAoCC,KAApC,CAAN;AACA;AAED;AACA;AACA;AACA;AACA;;;AACO,UAAUC,iCAAV,CAA6CC,EAA7C,EAAkD;AACxD,QAAM,mCAAqBA,EAArB,CAAN;AACA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASC,qCAAT,CAAgDN,QAAhD,EAA0DO,SAA1D,EAAsE;AAC5E,SAAO;AACNC,IAAAA,IAAI,EAAE,4BADA;AAENR,IAAAA,QAFM;AAGNO,IAAAA;AAHM,GAAP;AAKA","sourcesContent":["/**\n * Internal dependencies\n */\nimport {\n\tconvertBlockToStatic,\n\tconvertBlocksToReusable,\n\tdeleteReusableBlock,\n} from './controls';\n\n/**\n * Returns a generator converting a reusable block into a static block.\n *\n * @param {string} clientId The client ID of the block to attach.\n */\nexport function* __experimentalConvertBlockToStatic( clientId ) {\n\tyield convertBlockToStatic( clientId );\n}\n\n/**\n * Returns a generator converting one or more static blocks into a reusable block.\n *\n * @param {string[]} clientIds The client IDs of the block to detach.\n * @param {string} title Reusable block title.\n */\nexport function* __experimentalConvertBlocksToReusable( clientIds, title ) {\n\tyield convertBlocksToReusable( clientIds, title );\n}\n\n/**\n * Returns a generator deleting a reusable block.\n *\n * @param {string} id The ID of the reusable block to delete.\n */\nexport function* __experimentalDeleteReusableBlock( id ) {\n\tyield deleteReusableBlock( id );\n}\n\n/**\n * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.\n *\n * @param {string} clientId The clientID of the reusable block to target.\n * @param {boolean} isEditing Whether the block should be in editing state.\n * @return {Object} Action descriptor.\n */\nexport function __experimentalSetEditingReusableBlock( clientId, isEditing ) {\n\treturn {\n\t\ttype: 'SET_EDITING_REUSABLE_BLOCK',\n\t\tclientId,\n\t\tisEditing,\n\t};\n}\n"]}
1
+ {"version":3,"sources":["@wordpress/reusable-blocks/src/store/actions.js"],"names":["__experimentalConvertBlockToStatic","clientId","registry","oldBlock","select","blockEditorStore","getBlock","reusableBlock","getEditedEntityRecord","attributes","ref","newBlocks","content","dispatch","replaceBlocks","__experimentalConvertBlocksToReusable","clientIds","title","getBlocksByClientId","status","updatedRecord","saveEntityRecord","newBlock","id","__experimentalSetEditingReusableBlock","__experimentalDeleteReusableBlock","allBlocks","getBlocks","associatedBlocks","filter","block","associatedBlockClientIds","map","length","removeBlocks","deleteEntityRecord","isEditing","type"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isFunction } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { store as blockEditorStore } from '@wordpress/block-editor';\nimport {\n\tcreateBlock,\n\tisReusableBlock,\n\tparse,\n\tserialize,\n} from '@wordpress/blocks';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Returns a generator converting a reusable block into a static block.\n *\n * @param {string} clientId The client ID of the block to attach.\n */\nexport const __experimentalConvertBlockToStatic = ( clientId ) => ( {\n\tregistry,\n} ) => {\n\tconst oldBlock = registry.select( blockEditorStore ).getBlock( clientId );\n\tconst reusableBlock = registry\n\t\t.select( 'core' )\n\t\t.getEditedEntityRecord(\n\t\t\t'postType',\n\t\t\t'wp_block',\n\t\t\toldBlock.attributes.ref\n\t\t);\n\n\tconst newBlocks = parse(\n\t\tisFunction( reusableBlock.content )\n\t\t\t? reusableBlock.content( reusableBlock )\n\t\t\t: reusableBlock.content\n\t);\n\tregistry\n\t\t.dispatch( blockEditorStore )\n\t\t.replaceBlocks( oldBlock.clientId, newBlocks );\n};\n\n/**\n * Returns a generator converting one or more static blocks into a reusable block.\n *\n * @param {string[]} clientIds The client IDs of the block to detach.\n * @param {string} title Reusable block title.\n */\nexport const __experimentalConvertBlocksToReusable = (\n\tclientIds,\n\ttitle\n) => async ( { registry, dispatch } ) => {\n\tconst reusableBlock = {\n\t\ttitle: title || __( 'Untitled Reusable block' ),\n\t\tcontent: serialize(\n\t\t\tregistry.select( blockEditorStore ).getBlocksByClientId( clientIds )\n\t\t),\n\t\tstatus: 'publish',\n\t};\n\n\tconst updatedRecord = await registry\n\t\t.dispatch( 'core' )\n\t\t.saveEntityRecord( 'postType', 'wp_block', reusableBlock );\n\n\tconst newBlock = createBlock( 'core/block', {\n\t\tref: updatedRecord.id,\n\t} );\n\tregistry.dispatch( blockEditorStore ).replaceBlocks( clientIds, newBlock );\n\tdispatch.__experimentalSetEditingReusableBlock( newBlock.clientId, true );\n};\n\n/**\n * Returns a generator deleting a reusable block.\n *\n * @param {string} id The ID of the reusable block to delete.\n */\nexport const __experimentalDeleteReusableBlock = ( id ) => async ( {\n\tregistry,\n} ) => {\n\tconst reusableBlock = registry\n\t\t.select( 'core' )\n\t\t.getEditedEntityRecord( 'postType', 'wp_block', id );\n\n\t// Don't allow a reusable block with a temporary ID to be deleted\n\tif ( ! reusableBlock ) {\n\t\treturn;\n\t}\n\n\t// Remove any other blocks that reference this reusable block\n\tconst allBlocks = registry.select( blockEditorStore ).getBlocks();\n\tconst associatedBlocks = allBlocks.filter(\n\t\t( block ) => isReusableBlock( block ) && block.attributes.ref === id\n\t);\n\tconst associatedBlockClientIds = associatedBlocks.map(\n\t\t( block ) => block.clientId\n\t);\n\n\t// Remove the parsed block.\n\tif ( associatedBlockClientIds.length ) {\n\t\tregistry\n\t\t\t.dispatch( blockEditorStore )\n\t\t\t.removeBlocks( associatedBlockClientIds );\n\t}\n\n\tawait registry\n\t\t.dispatch( 'core' )\n\t\t.deleteEntityRecord( 'postType', 'wp_block', id );\n};\n\n/**\n * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.\n *\n * @param {string} clientId The clientID of the reusable block to target.\n * @param {boolean} isEditing Whether the block should be in editing state.\n * @return {Object} Action descriptor.\n */\nexport function __experimentalSetEditingReusableBlock( clientId, isEditing ) {\n\treturn {\n\t\ttype: 'SET_EDITING_REUSABLE_BLOCK',\n\t\tclientId,\n\t\tisEditing,\n\t};\n}\n"]}
@@ -13,8 +13,6 @@ var _data = require("@wordpress/data");
13
13
 
14
14
  var actions = _interopRequireWildcard(require("./actions"));
15
15
 
16
- var _controls = _interopRequireDefault(require("./controls"));
17
-
18
16
  var _reducer = _interopRequireDefault(require("./reducer"));
19
17
 
20
18
  var selectors = _interopRequireWildcard(require("./selectors"));
@@ -37,9 +35,9 @@ const STORE_NAME = 'core/reusable-blocks';
37
35
 
38
36
  const store = (0, _data.createReduxStore)(STORE_NAME, {
39
37
  actions,
40
- controls: _controls.default,
41
38
  reducer: _reducer.default,
42
- selectors
39
+ selectors,
40
+ __experimentalUseThunks: true
43
41
  });
44
42
  exports.store = store;
45
43
  (0, _data.register)(store);
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/reusable-blocks/src/store/index.js"],"names":["STORE_NAME","store","actions","controls","reducer","selectors"],"mappings":";;;;;;;;;;;AAGA;;AAKA;;AACA;;AACA;;AACA;;AAXA;AACA;AACA;;AAGA;AACA;AACA;AAMA,MAAMA,UAAU,GAAG,sBAAnB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACO,MAAMC,KAAK,GAAG,4BAAkBD,UAAlB,EAA8B;AAClDE,EAAAA,OADkD;AAElDC,EAAAA,QAAQ,EAARA,iBAFkD;AAGlDC,EAAAA,OAAO,EAAPA,gBAHkD;AAIlDC,EAAAA;AAJkD,CAA9B,CAAd;;AAOP,oBAAUJ,KAAV","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport * as actions from './actions';\nimport controls from './controls';\nimport reducer from './reducer';\nimport * as selectors from './selectors';\n\nconst STORE_NAME = 'core/reusable-blocks';\n\n/**\n * Store definition for the reusable blocks namespace.\n *\n * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore\n *\n * @type {Object}\n */\nexport const store = createReduxStore( STORE_NAME, {\n\tactions,\n\tcontrols,\n\treducer,\n\tselectors,\n} );\n\nregister( store );\n"]}
1
+ {"version":3,"sources":["@wordpress/reusable-blocks/src/store/index.js"],"names":["STORE_NAME","store","actions","reducer","selectors","__experimentalUseThunks"],"mappings":";;;;;;;;;;;AAGA;;AAKA;;AACA;;AACA;;AAVA;AACA;AACA;;AAGA;AACA;AACA;AAKA,MAAMA,UAAU,GAAG,sBAAnB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACO,MAAMC,KAAK,GAAG,4BAAkBD,UAAlB,EAA8B;AAClDE,EAAAA,OADkD;AAElDC,EAAAA,OAAO,EAAPA,gBAFkD;AAGlDC,EAAAA,SAHkD;AAIlDC,EAAAA,uBAAuB,EAAE;AAJyB,CAA9B,CAAd;;AAOP,oBAAUJ,KAAV","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport * as actions from './actions';\nimport reducer from './reducer';\nimport * as selectors from './selectors';\n\nconst STORE_NAME = 'core/reusable-blocks';\n\n/**\n * Store definition for the reusable blocks namespace.\n *\n * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore\n *\n * @type {Object}\n */\nexport const store = createReduxStore( STORE_NAME, {\n\tactions,\n\treducer,\n\tselectors,\n\t__experimentalUseThunks: true,\n} );\n\nregister( store );\n"]}
@@ -1,16 +1,28 @@
1
1
  /**
2
- * Internal dependencies
2
+ * External dependencies
3
3
  */
4
- import { convertBlockToStatic, convertBlocksToReusable, deleteReusableBlock } from './controls';
4
+ import { isFunction } from 'lodash';
5
+ /**
6
+ * WordPress dependencies
7
+ */
8
+
9
+ import { store as blockEditorStore } from '@wordpress/block-editor';
10
+ import { createBlock, isReusableBlock, parse, serialize } from '@wordpress/blocks';
11
+ import { __ } from '@wordpress/i18n';
5
12
  /**
6
13
  * Returns a generator converting a reusable block into a static block.
7
14
  *
8
15
  * @param {string} clientId The client ID of the block to attach.
9
16
  */
10
17
 
11
- export function* __experimentalConvertBlockToStatic(clientId) {
12
- yield convertBlockToStatic(clientId);
13
- }
18
+ export const __experimentalConvertBlockToStatic = clientId => ({
19
+ registry
20
+ }) => {
21
+ const oldBlock = registry.select(blockEditorStore).getBlock(clientId);
22
+ const reusableBlock = registry.select('core').getEditedEntityRecord('postType', 'wp_block', oldBlock.attributes.ref);
23
+ const newBlocks = parse(isFunction(reusableBlock.content) ? reusableBlock.content(reusableBlock) : reusableBlock.content);
24
+ registry.dispatch(blockEditorStore).replaceBlocks(oldBlock.clientId, newBlocks);
25
+ };
14
26
  /**
15
27
  * Returns a generator converting one or more static blocks into a reusable block.
16
28
  *
@@ -18,18 +30,49 @@ export function* __experimentalConvertBlockToStatic(clientId) {
18
30
  * @param {string} title Reusable block title.
19
31
  */
20
32
 
21
- export function* __experimentalConvertBlocksToReusable(clientIds, title) {
22
- yield convertBlocksToReusable(clientIds, title);
23
- }
33
+ export const __experimentalConvertBlocksToReusable = (clientIds, title) => async ({
34
+ registry,
35
+ dispatch
36
+ }) => {
37
+ const reusableBlock = {
38
+ title: title || __('Untitled Reusable block'),
39
+ content: serialize(registry.select(blockEditorStore).getBlocksByClientId(clientIds)),
40
+ status: 'publish'
41
+ };
42
+ const updatedRecord = await registry.dispatch('core').saveEntityRecord('postType', 'wp_block', reusableBlock);
43
+ const newBlock = createBlock('core/block', {
44
+ ref: updatedRecord.id
45
+ });
46
+ registry.dispatch(blockEditorStore).replaceBlocks(clientIds, newBlock);
47
+
48
+ dispatch.__experimentalSetEditingReusableBlock(newBlock.clientId, true);
49
+ };
24
50
  /**
25
51
  * Returns a generator deleting a reusable block.
26
52
  *
27
53
  * @param {string} id The ID of the reusable block to delete.
28
54
  */
29
55
 
30
- export function* __experimentalDeleteReusableBlock(id) {
31
- yield deleteReusableBlock(id);
32
- }
56
+ export const __experimentalDeleteReusableBlock = id => async ({
57
+ registry
58
+ }) => {
59
+ const reusableBlock = registry.select('core').getEditedEntityRecord('postType', 'wp_block', id); // Don't allow a reusable block with a temporary ID to be deleted
60
+
61
+ if (!reusableBlock) {
62
+ return;
63
+ } // Remove any other blocks that reference this reusable block
64
+
65
+
66
+ const allBlocks = registry.select(blockEditorStore).getBlocks();
67
+ const associatedBlocks = allBlocks.filter(block => isReusableBlock(block) && block.attributes.ref === id);
68
+ const associatedBlockClientIds = associatedBlocks.map(block => block.clientId); // Remove the parsed block.
69
+
70
+ if (associatedBlockClientIds.length) {
71
+ registry.dispatch(blockEditorStore).removeBlocks(associatedBlockClientIds);
72
+ }
73
+
74
+ await registry.dispatch('core').deleteEntityRecord('postType', 'wp_block', id);
75
+ };
33
76
  /**
34
77
  * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.
35
78
  *
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/reusable-blocks/src/store/actions.js"],"names":["convertBlockToStatic","convertBlocksToReusable","deleteReusableBlock","__experimentalConvertBlockToStatic","clientId","__experimentalConvertBlocksToReusable","clientIds","title","__experimentalDeleteReusableBlock","id","__experimentalSetEditingReusableBlock","isEditing","type"],"mappings":"AAAA;AACA;AACA;AACA,SACCA,oBADD,EAECC,uBAFD,EAGCC,mBAHD,QAIO,YAJP;AAMA;AACA;AACA;AACA;AACA;;AACA,OAAO,UAAUC,kCAAV,CAA8CC,QAA9C,EAAyD;AAC/D,QAAMJ,oBAAoB,CAAEI,QAAF,CAA1B;AACA;AAED;AACA;AACA;AACA;AACA;AACA;;AACA,OAAO,UAAUC,qCAAV,CAAiDC,SAAjD,EAA4DC,KAA5D,EAAoE;AAC1E,QAAMN,uBAAuB,CAAEK,SAAF,EAAaC,KAAb,CAA7B;AACA;AAED;AACA;AACA;AACA;AACA;;AACA,OAAO,UAAUC,iCAAV,CAA6CC,EAA7C,EAAkD;AACxD,QAAMP,mBAAmB,CAAEO,EAAF,CAAzB;AACA;AAED;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,OAAO,SAASC,qCAAT,CAAgDN,QAAhD,EAA0DO,SAA1D,EAAsE;AAC5E,SAAO;AACNC,IAAAA,IAAI,EAAE,4BADA;AAENR,IAAAA,QAFM;AAGNO,IAAAA;AAHM,GAAP;AAKA","sourcesContent":["/**\n * Internal dependencies\n */\nimport {\n\tconvertBlockToStatic,\n\tconvertBlocksToReusable,\n\tdeleteReusableBlock,\n} from './controls';\n\n/**\n * Returns a generator converting a reusable block into a static block.\n *\n * @param {string} clientId The client ID of the block to attach.\n */\nexport function* __experimentalConvertBlockToStatic( clientId ) {\n\tyield convertBlockToStatic( clientId );\n}\n\n/**\n * Returns a generator converting one or more static blocks into a reusable block.\n *\n * @param {string[]} clientIds The client IDs of the block to detach.\n * @param {string} title Reusable block title.\n */\nexport function* __experimentalConvertBlocksToReusable( clientIds, title ) {\n\tyield convertBlocksToReusable( clientIds, title );\n}\n\n/**\n * Returns a generator deleting a reusable block.\n *\n * @param {string} id The ID of the reusable block to delete.\n */\nexport function* __experimentalDeleteReusableBlock( id ) {\n\tyield deleteReusableBlock( id );\n}\n\n/**\n * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.\n *\n * @param {string} clientId The clientID of the reusable block to target.\n * @param {boolean} isEditing Whether the block should be in editing state.\n * @return {Object} Action descriptor.\n */\nexport function __experimentalSetEditingReusableBlock( clientId, isEditing ) {\n\treturn {\n\t\ttype: 'SET_EDITING_REUSABLE_BLOCK',\n\t\tclientId,\n\t\tisEditing,\n\t};\n}\n"]}
1
+ {"version":3,"sources":["@wordpress/reusable-blocks/src/store/actions.js"],"names":["isFunction","store","blockEditorStore","createBlock","isReusableBlock","parse","serialize","__","__experimentalConvertBlockToStatic","clientId","registry","oldBlock","select","getBlock","reusableBlock","getEditedEntityRecord","attributes","ref","newBlocks","content","dispatch","replaceBlocks","__experimentalConvertBlocksToReusable","clientIds","title","getBlocksByClientId","status","updatedRecord","saveEntityRecord","newBlock","id","__experimentalSetEditingReusableBlock","__experimentalDeleteReusableBlock","allBlocks","getBlocks","associatedBlocks","filter","block","associatedBlockClientIds","map","length","removeBlocks","deleteEntityRecord","isEditing","type"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isFunction } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { store as blockEditorStore } from '@wordpress/block-editor';\nimport {\n\tcreateBlock,\n\tisReusableBlock,\n\tparse,\n\tserialize,\n} from '@wordpress/blocks';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Returns a generator converting a reusable block into a static block.\n *\n * @param {string} clientId The client ID of the block to attach.\n */\nexport const __experimentalConvertBlockToStatic = ( clientId ) => ( {\n\tregistry,\n} ) => {\n\tconst oldBlock = registry.select( blockEditorStore ).getBlock( clientId );\n\tconst reusableBlock = registry\n\t\t.select( 'core' )\n\t\t.getEditedEntityRecord(\n\t\t\t'postType',\n\t\t\t'wp_block',\n\t\t\toldBlock.attributes.ref\n\t\t);\n\n\tconst newBlocks = parse(\n\t\tisFunction( reusableBlock.content )\n\t\t\t? reusableBlock.content( reusableBlock )\n\t\t\t: reusableBlock.content\n\t);\n\tregistry\n\t\t.dispatch( blockEditorStore )\n\t\t.replaceBlocks( oldBlock.clientId, newBlocks );\n};\n\n/**\n * Returns a generator converting one or more static blocks into a reusable block.\n *\n * @param {string[]} clientIds The client IDs of the block to detach.\n * @param {string} title Reusable block title.\n */\nexport const __experimentalConvertBlocksToReusable = (\n\tclientIds,\n\ttitle\n) => async ( { registry, dispatch } ) => {\n\tconst reusableBlock = {\n\t\ttitle: title || __( 'Untitled Reusable block' ),\n\t\tcontent: serialize(\n\t\t\tregistry.select( blockEditorStore ).getBlocksByClientId( clientIds )\n\t\t),\n\t\tstatus: 'publish',\n\t};\n\n\tconst updatedRecord = await registry\n\t\t.dispatch( 'core' )\n\t\t.saveEntityRecord( 'postType', 'wp_block', reusableBlock );\n\n\tconst newBlock = createBlock( 'core/block', {\n\t\tref: updatedRecord.id,\n\t} );\n\tregistry.dispatch( blockEditorStore ).replaceBlocks( clientIds, newBlock );\n\tdispatch.__experimentalSetEditingReusableBlock( newBlock.clientId, true );\n};\n\n/**\n * Returns a generator deleting a reusable block.\n *\n * @param {string} id The ID of the reusable block to delete.\n */\nexport const __experimentalDeleteReusableBlock = ( id ) => async ( {\n\tregistry,\n} ) => {\n\tconst reusableBlock = registry\n\t\t.select( 'core' )\n\t\t.getEditedEntityRecord( 'postType', 'wp_block', id );\n\n\t// Don't allow a reusable block with a temporary ID to be deleted\n\tif ( ! reusableBlock ) {\n\t\treturn;\n\t}\n\n\t// Remove any other blocks that reference this reusable block\n\tconst allBlocks = registry.select( blockEditorStore ).getBlocks();\n\tconst associatedBlocks = allBlocks.filter(\n\t\t( block ) => isReusableBlock( block ) && block.attributes.ref === id\n\t);\n\tconst associatedBlockClientIds = associatedBlocks.map(\n\t\t( block ) => block.clientId\n\t);\n\n\t// Remove the parsed block.\n\tif ( associatedBlockClientIds.length ) {\n\t\tregistry\n\t\t\t.dispatch( blockEditorStore )\n\t\t\t.removeBlocks( associatedBlockClientIds );\n\t}\n\n\tawait registry\n\t\t.dispatch( 'core' )\n\t\t.deleteEntityRecord( 'postType', 'wp_block', id );\n};\n\n/**\n * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.\n *\n * @param {string} clientId The clientID of the reusable block to target.\n * @param {boolean} isEditing Whether the block should be in editing state.\n * @return {Object} Action descriptor.\n */\nexport function __experimentalSetEditingReusableBlock( clientId, isEditing ) {\n\treturn {\n\t\ttype: 'SET_EDITING_REUSABLE_BLOCK',\n\t\tclientId,\n\t\tisEditing,\n\t};\n}\n"]}
@@ -7,7 +7,6 @@ import { createReduxStore, register } from '@wordpress/data';
7
7
  */
8
8
 
9
9
  import * as actions from './actions';
10
- import controls from './controls';
11
10
  import reducer from './reducer';
12
11
  import * as selectors from './selectors';
13
12
  const STORE_NAME = 'core/reusable-blocks';
@@ -21,9 +20,9 @@ const STORE_NAME = 'core/reusable-blocks';
21
20
 
22
21
  export const store = createReduxStore(STORE_NAME, {
23
22
  actions,
24
- controls,
25
23
  reducer,
26
- selectors
24
+ selectors,
25
+ __experimentalUseThunks: true
27
26
  });
28
27
  register(store);
29
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/reusable-blocks/src/store/index.js"],"names":["createReduxStore","register","actions","controls","reducer","selectors","STORE_NAME","store"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,gBAAT,EAA2BC,QAA3B,QAA2C,iBAA3C;AAEA;AACA;AACA;;AACA,OAAO,KAAKC,OAAZ,MAAyB,WAAzB;AACA,OAAOC,QAAP,MAAqB,YAArB;AACA,OAAOC,OAAP,MAAoB,WAApB;AACA,OAAO,KAAKC,SAAZ,MAA2B,aAA3B;AAEA,MAAMC,UAAU,GAAG,sBAAnB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,OAAO,MAAMC,KAAK,GAAGP,gBAAgB,CAAEM,UAAF,EAAc;AAClDJ,EAAAA,OADkD;AAElDC,EAAAA,QAFkD;AAGlDC,EAAAA,OAHkD;AAIlDC,EAAAA;AAJkD,CAAd,CAA9B;AAOPJ,QAAQ,CAAEM,KAAF,CAAR","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport * as actions from './actions';\nimport controls from './controls';\nimport reducer from './reducer';\nimport * as selectors from './selectors';\n\nconst STORE_NAME = 'core/reusable-blocks';\n\n/**\n * Store definition for the reusable blocks namespace.\n *\n * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore\n *\n * @type {Object}\n */\nexport const store = createReduxStore( STORE_NAME, {\n\tactions,\n\tcontrols,\n\treducer,\n\tselectors,\n} );\n\nregister( store );\n"]}
1
+ {"version":3,"sources":["@wordpress/reusable-blocks/src/store/index.js"],"names":["createReduxStore","register","actions","reducer","selectors","STORE_NAME","store","__experimentalUseThunks"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,gBAAT,EAA2BC,QAA3B,QAA2C,iBAA3C;AAEA;AACA;AACA;;AACA,OAAO,KAAKC,OAAZ,MAAyB,WAAzB;AACA,OAAOC,OAAP,MAAoB,WAApB;AACA,OAAO,KAAKC,SAAZ,MAA2B,aAA3B;AAEA,MAAMC,UAAU,GAAG,sBAAnB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,OAAO,MAAMC,KAAK,GAAGN,gBAAgB,CAAEK,UAAF,EAAc;AAClDH,EAAAA,OADkD;AAElDC,EAAAA,OAFkD;AAGlDC,EAAAA,SAHkD;AAIlDG,EAAAA,uBAAuB,EAAE;AAJyB,CAAd,CAA9B;AAOPN,QAAQ,CAAEK,KAAF,CAAR","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createReduxStore, register } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport * as actions from './actions';\nimport reducer from './reducer';\nimport * as selectors from './selectors';\n\nconst STORE_NAME = 'core/reusable-blocks';\n\n/**\n * Store definition for the reusable blocks namespace.\n *\n * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore\n *\n * @type {Object}\n */\nexport const store = createReduxStore( STORE_NAME, {\n\tactions,\n\treducer,\n\tselectors,\n\t__experimentalUseThunks: true,\n} );\n\nregister( store );\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/reusable-blocks",
3
- "version": "3.0.1",
3
+ "version": "3.0.5",
4
4
  "description": "Reusable blocks utilities.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -28,21 +28,21 @@
28
28
  "{src,build,build-module}/{index.js,store/index.js}"
29
29
  ],
30
30
  "dependencies": {
31
- "@wordpress/block-editor": "^7.0.1",
32
- "@wordpress/blocks": "^11.0.1",
33
- "@wordpress/components": "^16.0.0",
34
- "@wordpress/compose": "^5.0.1",
35
- "@wordpress/core-data": "^4.0.1",
36
- "@wordpress/data": "^6.0.1",
37
- "@wordpress/element": "^4.0.0",
38
- "@wordpress/i18n": "^4.2.1",
39
- "@wordpress/icons": "^5.0.1",
40
- "@wordpress/notices": "^3.2.2",
41
- "@wordpress/url": "^3.2.1",
31
+ "@wordpress/block-editor": "^8.0.0",
32
+ "@wordpress/blocks": "^11.1.3",
33
+ "@wordpress/components": "^19.0.1",
34
+ "@wordpress/compose": "^5.0.5",
35
+ "@wordpress/core-data": "^4.0.5",
36
+ "@wordpress/data": "^6.1.3",
37
+ "@wordpress/element": "^4.0.3",
38
+ "@wordpress/i18n": "^4.2.3",
39
+ "@wordpress/icons": "^6.1.0",
40
+ "@wordpress/notices": "^3.2.6",
41
+ "@wordpress/url": "^3.3.0",
42
42
  "lodash": "^4.17.21"
43
43
  },
44
44
  "publishConfig": {
45
45
  "access": "public"
46
46
  },
47
- "gitHead": "8b67fbd424bc67f81c2d825877f0fae726d6363a"
47
+ "gitHead": "393c2b5533837fd637e998d23f0124c081a10df0"
48
48
  }
@@ -1,20 +1,46 @@
1
1
  /**
2
- * Internal dependencies
2
+ * External dependencies
3
3
  */
4
+ import { isFunction } from 'lodash';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { store as blockEditorStore } from '@wordpress/block-editor';
4
10
  import {
5
- convertBlockToStatic,
6
- convertBlocksToReusable,
7
- deleteReusableBlock,
8
- } from './controls';
11
+ createBlock,
12
+ isReusableBlock,
13
+ parse,
14
+ serialize,
15
+ } from '@wordpress/blocks';
16
+ import { __ } from '@wordpress/i18n';
9
17
 
10
18
  /**
11
19
  * Returns a generator converting a reusable block into a static block.
12
20
  *
13
21
  * @param {string} clientId The client ID of the block to attach.
14
22
  */
15
- export function* __experimentalConvertBlockToStatic( clientId ) {
16
- yield convertBlockToStatic( clientId );
17
- }
23
+ export const __experimentalConvertBlockToStatic = ( clientId ) => ( {
24
+ registry,
25
+ } ) => {
26
+ const oldBlock = registry.select( blockEditorStore ).getBlock( clientId );
27
+ const reusableBlock = registry
28
+ .select( 'core' )
29
+ .getEditedEntityRecord(
30
+ 'postType',
31
+ 'wp_block',
32
+ oldBlock.attributes.ref
33
+ );
34
+
35
+ const newBlocks = parse(
36
+ isFunction( reusableBlock.content )
37
+ ? reusableBlock.content( reusableBlock )
38
+ : reusableBlock.content
39
+ );
40
+ registry
41
+ .dispatch( blockEditorStore )
42
+ .replaceBlocks( oldBlock.clientId, newBlocks );
43
+ };
18
44
 
19
45
  /**
20
46
  * Returns a generator converting one or more static blocks into a reusable block.
@@ -22,18 +48,66 @@ export function* __experimentalConvertBlockToStatic( clientId ) {
22
48
  * @param {string[]} clientIds The client IDs of the block to detach.
23
49
  * @param {string} title Reusable block title.
24
50
  */
25
- export function* __experimentalConvertBlocksToReusable( clientIds, title ) {
26
- yield convertBlocksToReusable( clientIds, title );
27
- }
51
+ export const __experimentalConvertBlocksToReusable = (
52
+ clientIds,
53
+ title
54
+ ) => async ( { registry, dispatch } ) => {
55
+ const reusableBlock = {
56
+ title: title || __( 'Untitled Reusable block' ),
57
+ content: serialize(
58
+ registry.select( blockEditorStore ).getBlocksByClientId( clientIds )
59
+ ),
60
+ status: 'publish',
61
+ };
62
+
63
+ const updatedRecord = await registry
64
+ .dispatch( 'core' )
65
+ .saveEntityRecord( 'postType', 'wp_block', reusableBlock );
66
+
67
+ const newBlock = createBlock( 'core/block', {
68
+ ref: updatedRecord.id,
69
+ } );
70
+ registry.dispatch( blockEditorStore ).replaceBlocks( clientIds, newBlock );
71
+ dispatch.__experimentalSetEditingReusableBlock( newBlock.clientId, true );
72
+ };
28
73
 
29
74
  /**
30
75
  * Returns a generator deleting a reusable block.
31
76
  *
32
77
  * @param {string} id The ID of the reusable block to delete.
33
78
  */
34
- export function* __experimentalDeleteReusableBlock( id ) {
35
- yield deleteReusableBlock( id );
36
- }
79
+ export const __experimentalDeleteReusableBlock = ( id ) => async ( {
80
+ registry,
81
+ } ) => {
82
+ const reusableBlock = registry
83
+ .select( 'core' )
84
+ .getEditedEntityRecord( 'postType', 'wp_block', id );
85
+
86
+ // Don't allow a reusable block with a temporary ID to be deleted
87
+ if ( ! reusableBlock ) {
88
+ return;
89
+ }
90
+
91
+ // Remove any other blocks that reference this reusable block
92
+ const allBlocks = registry.select( blockEditorStore ).getBlocks();
93
+ const associatedBlocks = allBlocks.filter(
94
+ ( block ) => isReusableBlock( block ) && block.attributes.ref === id
95
+ );
96
+ const associatedBlockClientIds = associatedBlocks.map(
97
+ ( block ) => block.clientId
98
+ );
99
+
100
+ // Remove the parsed block.
101
+ if ( associatedBlockClientIds.length ) {
102
+ registry
103
+ .dispatch( blockEditorStore )
104
+ .removeBlocks( associatedBlockClientIds );
105
+ }
106
+
107
+ await registry
108
+ .dispatch( 'core' )
109
+ .deleteEntityRecord( 'postType', 'wp_block', id );
110
+ };
37
111
 
38
112
  /**
39
113
  * Returns an action descriptor for SET_EDITING_REUSABLE_BLOCK action.
@@ -7,7 +7,6 @@ import { createReduxStore, register } from '@wordpress/data';
7
7
  * Internal dependencies
8
8
  */
9
9
  import * as actions from './actions';
10
- import controls from './controls';
11
10
  import reducer from './reducer';
12
11
  import * as selectors from './selectors';
13
12
 
@@ -22,9 +21,9 @@ const STORE_NAME = 'core/reusable-blocks';
22
21
  */
23
22
  export const store = createReduxStore( STORE_NAME, {
24
23
  actions,
25
- controls,
26
24
  reducer,
27
25
  selectors,
26
+ __experimentalUseThunks: true,
28
27
  } );
29
28
 
30
29
  register( store );
@@ -0,0 +1,50 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Actions __experimentalConvertBlockToStatic should convert a static reusable into a static block 1`] = `
4
+ Array [
5
+ Object {
6
+ "attributes": Object {
7
+ "name": "Big Bird",
8
+ },
9
+ "innerBlocks": Array [
10
+ Object {
11
+ "attributes": Object {
12
+ "name": "Oscar the Grouch",
13
+ },
14
+ "innerBlocks": Array [],
15
+ "isValid": true,
16
+ "name": "core/test-block",
17
+ "originalContent": "",
18
+ "validationIssues": Array [],
19
+ },
20
+ Object {
21
+ "attributes": Object {
22
+ "name": "Cookie Monster",
23
+ },
24
+ "innerBlocks": Array [],
25
+ "isValid": true,
26
+ "name": "core/test-block",
27
+ "originalContent": "",
28
+ "validationIssues": Array [],
29
+ },
30
+ ],
31
+ "isValid": true,
32
+ "name": "core/test-block",
33
+ "originalContent": "",
34
+ "validationIssues": Array [],
35
+ },
36
+ ]
37
+ `;
38
+
39
+ exports[`Actions __experimentalConvertBlocksToReusable should convert a static block into a reusable block 1`] = `
40
+ Array [
41
+ Object {
42
+ "attributes": Object {
43
+ "ref": "new-id",
44
+ },
45
+ "innerBlocks": Array [],
46
+ "isValid": true,
47
+ "name": "core/block",
48
+ },
49
+ ]
50
+ `;