@wordpress/patterns 1.2.0 → 1.3.0

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/category-selector.js +105 -0
  3. package/build/components/category-selector.js.map +1 -0
  4. package/build/components/create-pattern-modal.js +26 -19
  5. package/build/components/create-pattern-modal.js.map +1 -1
  6. package/build/components/pattern-convert-button.js +20 -1
  7. package/build/components/pattern-convert-button.js.map +1 -1
  8. package/build/components/patterns-manage-button.js +7 -3
  9. package/build/components/patterns-manage-button.js.map +1 -1
  10. package/build/constants.js +21 -0
  11. package/build/constants.js.map +1 -0
  12. package/build/index.js +11 -1
  13. package/build/index.js.map +1 -1
  14. package/build/private-apis.js +6 -1
  15. package/build/private-apis.js.map +1 -1
  16. package/build/store/actions.js +45 -23
  17. package/build/store/actions.js.map +1 -1
  18. package/build/store/index.js +4 -3
  19. package/build/store/index.js.map +1 -1
  20. package/build/store/selectors.js +2 -2
  21. package/build/store/selectors.js.map +1 -1
  22. package/build-module/components/category-selector.js +99 -0
  23. package/build-module/components/category-selector.js.map +1 -0
  24. package/build-module/components/create-pattern-modal.js +27 -18
  25. package/build-module/components/create-pattern-modal.js.map +1 -1
  26. package/build-module/components/pattern-convert-button.js +22 -3
  27. package/build-module/components/pattern-convert-button.js.map +1 -1
  28. package/build-module/components/patterns-manage-button.js +8 -4
  29. package/build-module/components/patterns-manage-button.js.map +1 -1
  30. package/build-module/constants.js +11 -0
  31. package/build-module/constants.js.map +1 -0
  32. package/build-module/index.js +1 -1
  33. package/build-module/index.js.map +1 -1
  34. package/build-module/private-apis.js +6 -1
  35. package/build-module/private-apis.js.map +1 -1
  36. package/build-module/store/actions.js +41 -20
  37. package/build-module/store/actions.js.map +1 -1
  38. package/build-module/store/index.js +4 -3
  39. package/build-module/store/index.js.map +1 -1
  40. package/build-module/store/selectors.js +1 -1
  41. package/build-module/store/selectors.js.map +1 -1
  42. package/build-style/style-rtl.css +7 -0
  43. package/build-style/style.css +7 -0
  44. package/package.json +16 -14
  45. package/src/components/category-selector.js +118 -0
  46. package/src/components/create-pattern-modal.js +45 -38
  47. package/src/components/pattern-convert-button.js +26 -3
  48. package/src/components/patterns-manage-button.js +10 -4
  49. package/src/components/style.scss +7 -0
  50. package/src/constants.js +16 -0
  51. package/src/index.js +1 -2
  52. package/src/private-apis.js +10 -0
  53. package/src/store/actions.js +55 -27
  54. package/src/store/index.js +3 -2
  55. package/src/store/selectors.js +1 -1
@@ -1,9 +1,14 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { hasBlockSupport, isReusableBlock } from '@wordpress/blocks';
4
+ import {
5
+ hasBlockSupport,
6
+ isReusableBlock,
7
+ createBlock,
8
+ serialize,
9
+ } from '@wordpress/blocks';
5
10
  import { store as blockEditorStore } from '@wordpress/block-editor';
6
- import { useState } from '@wordpress/element';
11
+ import { useState, useCallback } from '@wordpress/element';
7
12
  import { MenuItem } from '@wordpress/components';
8
13
  import { symbol } from '@wordpress/icons';
9
14
  import { useSelect, useDispatch } from '@wordpress/data';
@@ -13,7 +18,9 @@ import { store as noticesStore } from '@wordpress/notices';
13
18
  /**
14
19
  * Internal dependencies
15
20
  */
21
+ import { store as patternsStore } from '../store';
16
22
  import CreatePatternModal from './create-pattern-modal';
23
+ import { unlock } from '../lock-unlock';
17
24
 
18
25
  /**
19
26
  * Menu control to convert block(s) to a pattern block.
@@ -25,6 +32,10 @@ import CreatePatternModal from './create-pattern-modal';
25
32
  */
26
33
  export default function PatternConvertButton( { clientIds, rootClientId } ) {
27
34
  const { createSuccessNotice } = useDispatch( noticesStore );
35
+ const { replaceBlocks } = useDispatch( blockEditorStore );
36
+ // Ignore reason: false positive of the lint rule.
37
+ // eslint-disable-next-line @wordpress/no-unused-vars-before-return
38
+ const { setEditingPattern } = unlock( useDispatch( patternsStore ) );
28
39
  const [ isModalOpen, setIsModalOpen ] = useState( false );
29
40
  const canConvert = useSelect(
30
41
  ( select ) => {
@@ -74,12 +85,24 @@ export default function PatternConvertButton( { clientIds, rootClientId } ) {
74
85
  },
75
86
  [ clientIds, rootClientId ]
76
87
  );
88
+ const { getBlocksByClientId } = useSelect( blockEditorStore );
89
+ const getContent = useCallback(
90
+ () => serialize( getBlocksByClientId( clientIds ) ),
91
+ [ getBlocksByClientId, clientIds ]
92
+ );
77
93
 
78
94
  if ( ! canConvert ) {
79
95
  return null;
80
96
  }
81
97
 
82
98
  const handleSuccess = ( { pattern } ) => {
99
+ const newBlock = createBlock( 'core/block', {
100
+ ref: pattern.id,
101
+ } );
102
+
103
+ replaceBlocks( clientIds, newBlock );
104
+ setEditingPattern( newBlock.clientId, true );
105
+
83
106
  createSuccessNotice(
84
107
  pattern.wp_pattern_sync_status === 'unsynced'
85
108
  ? sprintf(
@@ -111,7 +134,7 @@ export default function PatternConvertButton( { clientIds, rootClientId } ) {
111
134
  </MenuItem>
112
135
  { isModalOpen && (
113
136
  <CreatePatternModal
114
- clientIds={ clientIds }
137
+ content={ getContent }
115
138
  onSuccess={ ( pattern ) => {
116
139
  handleSuccess( pattern );
117
140
  } }
@@ -12,7 +12,8 @@ import { store as coreStore } from '@wordpress/core-data';
12
12
  /**
13
13
  * Internal dependencies
14
14
  */
15
- import { store as editorStore } from '../store';
15
+ import { store as patternsStore } from '../store';
16
+ import { unlock } from '../lock-unlock';
16
17
 
17
18
  function PatternsManageButton( { clientId } ) {
18
19
  const { canRemove, isVisible, innerBlockCount, managePatternsUrl } =
@@ -51,8 +52,11 @@ function PatternsManageButton( { clientId } ) {
51
52
  [ clientId ]
52
53
  );
53
54
 
54
- const { __experimentalConvertSyncedPatternToStatic: convertBlockToStatic } =
55
- useDispatch( editorStore );
55
+ // Ignore reason: false positive of the lint rule.
56
+ // eslint-disable-next-line @wordpress/no-unused-vars-before-return
57
+ const { convertSyncedPatternToStatic } = unlock(
58
+ useDispatch( patternsStore )
59
+ );
56
60
 
57
61
  if ( ! isVisible ) {
58
62
  return null;
@@ -64,7 +68,9 @@ function PatternsManageButton( { clientId } ) {
64
68
  { __( 'Manage patterns' ) }
65
69
  </MenuItem>
66
70
  { canRemove && (
67
- <MenuItem onClick={ () => convertBlockToStatic( clientId ) }>
71
+ <MenuItem
72
+ onClick={ () => convertSyncedPatternToStatic( clientId ) }
73
+ >
68
74
  { innerBlockCount > 1
69
75
  ? __( 'Detach patterns' )
70
76
  : __( 'Detach pattern' ) }
@@ -1,3 +1,10 @@
1
1
  .patterns-menu-items__convert-modal {
2
2
  z-index: z-index(".patterns-menu-items__convert-modal");
3
+ .patterns-menu-items__convert-modal-categories {
4
+ max-width: 300px;
5
+ }
6
+ }
7
+
8
+ .patterns-create-modal__name-input input[type="text"] {
9
+ min-height: 34px;
3
10
  }
@@ -0,0 +1,16 @@
1
+ export const PATTERN_TYPES = {
2
+ theme: 'pattern',
3
+ user: 'wp_block',
4
+ };
5
+
6
+ export const PATTERN_DEFAULT_CATEGORY = 'all-patterns';
7
+ export const PATTERN_CORE_SOURCES = [
8
+ 'core',
9
+ 'pattern-directory/core',
10
+ 'pattern-directory/featured',
11
+ 'pattern-directory/theme',
12
+ ];
13
+ export const PATTERN_SYNC_TYPES = {
14
+ full: 'fully',
15
+ unsynced: 'unsynced',
16
+ };
package/src/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- import './store';
5
-
4
+ export { store } from './store';
6
5
  export * from './private-apis';
@@ -4,9 +4,19 @@
4
4
  import { lock } from './lock-unlock';
5
5
  import CreatePatternModal from './components/create-pattern-modal';
6
6
  import PatternsMenuItems from './components';
7
+ import {
8
+ PATTERN_TYPES,
9
+ PATTERN_DEFAULT_CATEGORY,
10
+ PATTERN_CORE_SOURCES,
11
+ PATTERN_SYNC_TYPES,
12
+ } from './constants';
7
13
 
8
14
  export const privateApis = {};
9
15
  lock( privateApis, {
10
16
  CreatePatternModal,
11
17
  PatternsMenuItems,
18
+ PATTERN_TYPES,
19
+ PATTERN_DEFAULT_CATEGORY,
20
+ PATTERN_CORE_SOURCES,
21
+ PATTERN_SYNC_TYPES,
12
22
  } );
@@ -2,22 +2,28 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
 
5
- import { parse, serialize, createBlock } from '@wordpress/blocks';
5
+ import { parse } from '@wordpress/blocks';
6
6
  import { store as coreStore } from '@wordpress/core-data';
7
7
  import { store as blockEditorStore } from '@wordpress/block-editor';
8
8
 
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import { PATTERN_SYNC_TYPES } from '../constants';
13
+
9
14
  /**
10
15
  * Returns a generator converting one or more static blocks into a pattern, or creating a new empty pattern.
11
16
  *
12
- * @param {string} title Pattern title.
13
- * @param {'full'|'unsynced'} syncType They way block is synced, 'full' or 'unsynced'.
14
- * @param {string[]|undefined} clientIds Optional client IDs of blocks to convert to pattern.
17
+ * @param {string} title Pattern title.
18
+ * @param {'full'|'unsynced'} syncType They way block is synced, 'full' or 'unsynced'.
19
+ * @param {string|undefined} [content] Optional serialized content of blocks to convert to pattern.
20
+ * @param {number[]|undefined} [categories] Ids of any selected categories.
15
21
  */
16
- export const __experimentalCreatePattern =
17
- ( title, syncType, clientIds ) =>
18
- async ( { registry, dispatch } ) => {
22
+ export const createPattern =
23
+ ( title, syncType, content, categories ) =>
24
+ async ( { registry } ) => {
19
25
  const meta =
20
- syncType === 'unsynced'
26
+ syncType === PATTERN_SYNC_TYPES.unsynced
21
27
  ? {
22
28
  wp_pattern_sync_status: syncType,
23
29
  }
@@ -25,33 +31,55 @@ export const __experimentalCreatePattern =
25
31
 
26
32
  const reusableBlock = {
27
33
  title,
28
- content: clientIds
29
- ? serialize(
30
- registry
31
- .select( blockEditorStore )
32
- .getBlocksByClientId( clientIds )
33
- )
34
- : undefined,
34
+ content,
35
35
  status: 'publish',
36
36
  meta,
37
+ wp_pattern_category: categories,
37
38
  };
38
39
 
39
40
  const updatedRecord = await registry
40
41
  .dispatch( coreStore )
41
42
  .saveEntityRecord( 'postType', 'wp_block', reusableBlock );
42
43
 
43
- if ( syncType === 'unsynced' || ! clientIds ) {
44
- return updatedRecord;
44
+ return updatedRecord;
45
+ };
46
+
47
+ /**
48
+ * Create a pattern from a JSON file.
49
+ * @param {File} file The JSON file instance of the pattern.
50
+ * @param {number[]|undefined} [categories] Ids of any selected categories.
51
+ */
52
+ export const createPatternFromFile =
53
+ ( file, categories ) =>
54
+ async ( { dispatch } ) => {
55
+ const fileContent = await file.text();
56
+ /** @type {import('./types').PatternJSON} */
57
+ let parsedContent;
58
+ try {
59
+ parsedContent = JSON.parse( fileContent );
60
+ } catch ( e ) {
61
+ throw new Error( 'Invalid JSON file' );
62
+ }
63
+ if (
64
+ parsedContent.__file !== 'wp_block' ||
65
+ ! parsedContent.title ||
66
+ ! parsedContent.content ||
67
+ typeof parsedContent.title !== 'string' ||
68
+ typeof parsedContent.content !== 'string' ||
69
+ ( parsedContent.syncStatus &&
70
+ typeof parsedContent.syncStatus !== 'string' )
71
+ ) {
72
+ throw new Error( 'Invalid Pattern JSON file' );
45
73
  }
46
74
 
47
- const newBlock = createBlock( 'core/block', {
48
- ref: updatedRecord.id,
49
- } );
50
- registry
51
- .dispatch( blockEditorStore )
52
- .replaceBlocks( clientIds, newBlock );
53
- dispatch.__experimentalSetEditingPattern( newBlock.clientId, true );
54
- return updatedRecord;
75
+ const pattern = await dispatch.createPattern(
76
+ parsedContent.title,
77
+ parsedContent.syncStatus,
78
+ parsedContent.content,
79
+ categories
80
+ );
81
+
82
+ return pattern;
55
83
  };
56
84
 
57
85
  /**
@@ -59,7 +87,7 @@ export const __experimentalCreatePattern =
59
87
  *
60
88
  * @param {string} clientId The client ID of the block to attach.
61
89
  */
62
- export const __experimentalConvertSyncedPatternToStatic =
90
+ export const convertSyncedPatternToStatic =
63
91
  ( clientId ) =>
64
92
  ( { registry } ) => {
65
93
  const oldBlock = registry
@@ -90,7 +118,7 @@ export const __experimentalConvertSyncedPatternToStatic =
90
118
  * @param {boolean} isEditing Whether the block should be in editing state.
91
119
  * @return {Object} Action descriptor.
92
120
  */
93
- export function __experimentalSetEditingPattern( clientId, isEditing ) {
121
+ export function setEditingPattern( clientId, isEditing ) {
94
122
  return {
95
123
  type: 'SET_EDITING_PATTERN',
96
124
  clientId,
@@ -10,6 +10,7 @@ import reducer from './reducer';
10
10
  import * as actions from './actions';
11
11
  import { STORE_NAME } from './constants';
12
12
  import * as selectors from './selectors';
13
+ import { unlock } from '../lock-unlock';
13
14
 
14
15
  /**
15
16
  * Post editor data store configuration.
@@ -20,8 +21,6 @@ import * as selectors from './selectors';
20
21
  */
21
22
  export const storeConfig = {
22
23
  reducer,
23
- selectors,
24
- actions,
25
24
  };
26
25
 
27
26
  /**
@@ -36,3 +35,5 @@ export const store = createReduxStore( STORE_NAME, {
36
35
  } );
37
36
 
38
37
  register( store );
38
+ unlock( store ).registerPrivateActions( actions );
39
+ unlock( store ).registerPrivateSelectors( selectors );
@@ -5,6 +5,6 @@
5
5
  * @param {number} clientId the clientID of the block.
6
6
  * @return {boolean} Whether the pattern is in the editing state.
7
7
  */
8
- export function __experimentalIsEditingPattern( state, clientId ) {
8
+ export function isEditingPattern( state, clientId ) {
9
9
  return state.isEditingPattern[ clientId ];
10
10
  }