@wordpress/block-library 9.30.1-next.a730c9c8c.0 → 9.31.1-next.233ccab9b.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 (232) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/accordion/edit.js +6 -5
  3. package/build/accordion/edit.js.map +1 -1
  4. package/build/accordion/index.js +39 -4
  5. package/build/accordion/index.js.map +1 -1
  6. package/build/accordion/save.js +2 -19
  7. package/build/accordion/save.js.map +1 -1
  8. package/build/accordion/view.js +50 -16
  9. package/build/accordion/view.js.map +1 -1
  10. package/build/accordion-content/index.js +17 -3
  11. package/build/accordion-content/index.js.map +1 -1
  12. package/build/accordion-content/save.js +5 -7
  13. package/build/accordion-content/save.js.map +1 -1
  14. package/build/accordion-header/edit.js +13 -47
  15. package/build/accordion-header/edit.js.map +1 -1
  16. package/build/accordion-header/index.js +6 -11
  17. package/build/accordion-header/index.js.map +1 -1
  18. package/build/accordion-header/save.js +11 -44
  19. package/build/accordion-header/save.js.map +1 -1
  20. package/build/accordion-panel/edit.js +2 -1
  21. package/build/accordion-panel/edit.js.map +1 -1
  22. package/build/accordion-panel/index.js +3 -3
  23. package/build/accordion-panel/index.js.map +1 -1
  24. package/build/accordion-panel/save.js +3 -1
  25. package/build/accordion-panel/save.js.map +1 -1
  26. package/build/avatar/hooks.js +7 -17
  27. package/build/avatar/hooks.js.map +1 -1
  28. package/build/group/variations.js +3 -4
  29. package/build/group/variations.js.map +1 -1
  30. package/build/navigation/edit/leaf-more-menu.js +6 -1
  31. package/build/navigation/edit/leaf-more-menu.js.map +1 -1
  32. package/build/navigation/index.js +2 -1
  33. package/build/navigation/index.js.map +1 -1
  34. package/build/navigation-link/index.js +2 -1
  35. package/build/navigation-link/index.js.map +1 -1
  36. package/build/navigation-submenu/edit.js +2 -4
  37. package/build/navigation-submenu/edit.js.map +1 -1
  38. package/build/navigation-submenu/index.js +2 -1
  39. package/build/navigation-submenu/index.js.map +1 -1
  40. package/build/page-list/index.js +2 -1
  41. package/build/page-list/index.js.map +1 -1
  42. package/build/post-author/edit.js +7 -6
  43. package/build/post-author/edit.js.map +1 -1
  44. package/build/post-date/edit.js +16 -3
  45. package/build/post-date/edit.js.map +1 -1
  46. package/build/post-time-to-read/edit.js +111 -11
  47. package/build/post-time-to-read/edit.js.map +1 -1
  48. package/build/post-time-to-read/index.js +17 -1
  49. package/build/post-time-to-read/index.js.map +1 -1
  50. package/build/table-of-contents/index.js +1 -0
  51. package/build/table-of-contents/index.js.map +1 -1
  52. package/build/term-description/edit.js +18 -2
  53. package/build/term-description/edit.js.map +1 -1
  54. package/build/term-description/index.js +1 -0
  55. package/build/term-description/index.js.map +1 -1
  56. package/build/term-description/use-term-description.js +85 -0
  57. package/build/term-description/use-term-description.js.map +1 -0
  58. package/build/term-template/edit.js +11 -7
  59. package/build/term-template/edit.js.map +1 -1
  60. package/build/term-template/index.js +1 -1
  61. package/build/terms-query/index.js +8 -2
  62. package/build/terms-query/index.js.map +1 -1
  63. package/build/terms-query/inspector-controls/advanced-controls.js +51 -0
  64. package/build/terms-query/inspector-controls/advanced-controls.js.map +1 -0
  65. package/build/terms-query/inspector-controls/display-options.js +87 -0
  66. package/build/terms-query/inspector-controls/display-options.js.map +1 -0
  67. package/build/terms-query/inspector-controls/empty-terms-control.js +38 -0
  68. package/build/terms-query/inspector-controls/empty-terms-control.js.map +1 -0
  69. package/build/terms-query/inspector-controls/hierarchy-control.js +40 -0
  70. package/build/terms-query/inspector-controls/hierarchy-control.js.map +1 -0
  71. package/build/terms-query/inspector-controls/index.js +127 -0
  72. package/build/terms-query/inspector-controls/index.js.map +1 -0
  73. package/build/terms-query/inspector-controls/max-terms-control.js +50 -0
  74. package/build/terms-query/inspector-controls/max-terms-control.js.map +1 -0
  75. package/build/terms-query/inspector-controls/ordering-controls.js +57 -0
  76. package/build/terms-query/inspector-controls/ordering-controls.js.map +1 -0
  77. package/build/terms-query/inspector-controls/taxonomy-control.js +52 -0
  78. package/build/terms-query/inspector-controls/taxonomy-control.js.map +1 -0
  79. package/build/utils/hooks.js +15 -0
  80. package/build/utils/hooks.js.map +1 -1
  81. package/build-module/accordion/edit.js +6 -5
  82. package/build-module/accordion/edit.js.map +1 -1
  83. package/build-module/accordion/index.js +40 -4
  84. package/build-module/accordion/index.js.map +1 -1
  85. package/build-module/accordion/save.js +2 -17
  86. package/build-module/accordion/save.js.map +1 -1
  87. package/build-module/accordion/view.js +51 -17
  88. package/build-module/accordion/view.js.map +1 -1
  89. package/build-module/accordion-content/index.js +17 -3
  90. package/build-module/accordion-content/index.js.map +1 -1
  91. package/build-module/accordion-content/save.js +5 -7
  92. package/build-module/accordion-content/save.js.map +1 -1
  93. package/build-module/accordion-header/edit.js +14 -45
  94. package/build-module/accordion-header/edit.js.map +1 -1
  95. package/build-module/accordion-header/index.js +6 -11
  96. package/build-module/accordion-header/index.js.map +1 -1
  97. package/build-module/accordion-header/save.js +12 -42
  98. package/build-module/accordion-header/save.js.map +1 -1
  99. package/build-module/accordion-panel/edit.js +2 -1
  100. package/build-module/accordion-panel/edit.js.map +1 -1
  101. package/build-module/accordion-panel/index.js +3 -3
  102. package/build-module/accordion-panel/index.js.map +1 -1
  103. package/build-module/accordion-panel/save.js +3 -1
  104. package/build-module/accordion-panel/save.js.map +1 -1
  105. package/build-module/avatar/hooks.js +5 -15
  106. package/build-module/avatar/hooks.js.map +1 -1
  107. package/build-module/group/variations.js +3 -4
  108. package/build-module/group/variations.js.map +1 -1
  109. package/build-module/navigation/edit/leaf-more-menu.js +6 -1
  110. package/build-module/navigation/edit/leaf-more-menu.js.map +1 -1
  111. package/build-module/navigation/index.js +2 -1
  112. package/build-module/navigation/index.js.map +1 -1
  113. package/build-module/navigation-link/index.js +2 -1
  114. package/build-module/navigation-link/index.js.map +1 -1
  115. package/build-module/navigation-submenu/edit.js +1 -3
  116. package/build-module/navigation-submenu/edit.js.map +1 -1
  117. package/build-module/navigation-submenu/index.js +2 -1
  118. package/build-module/navigation-submenu/index.js.map +1 -1
  119. package/build-module/page-list/index.js +2 -1
  120. package/build-module/page-list/index.js.map +1 -1
  121. package/build-module/post-author/edit.js +8 -7
  122. package/build-module/post-author/edit.js.map +1 -1
  123. package/build-module/post-date/edit.js +17 -4
  124. package/build-module/post-date/edit.js.map +1 -1
  125. package/build-module/post-time-to-read/edit.js +112 -14
  126. package/build-module/post-time-to-read/edit.js.map +1 -1
  127. package/build-module/post-time-to-read/index.js +17 -1
  128. package/build-module/post-time-to-read/index.js.map +1 -1
  129. package/build-module/table-of-contents/index.js +1 -0
  130. package/build-module/table-of-contents/index.js.map +1 -1
  131. package/build-module/term-description/edit.js +18 -2
  132. package/build-module/term-description/edit.js.map +1 -1
  133. package/build-module/term-description/index.js +1 -0
  134. package/build-module/term-description/index.js.map +1 -1
  135. package/build-module/term-description/use-term-description.js +79 -0
  136. package/build-module/term-description/use-term-description.js.map +1 -0
  137. package/build-module/term-template/edit.js +11 -7
  138. package/build-module/term-template/edit.js.map +1 -1
  139. package/build-module/term-template/index.js +1 -1
  140. package/build-module/terms-query/index.js +8 -2
  141. package/build-module/terms-query/index.js.map +1 -1
  142. package/build-module/terms-query/inspector-controls/advanced-controls.js +44 -0
  143. package/build-module/terms-query/inspector-controls/advanced-controls.js.map +1 -0
  144. package/build-module/terms-query/inspector-controls/display-options.js +80 -0
  145. package/build-module/terms-query/inspector-controls/display-options.js.map +1 -0
  146. package/build-module/terms-query/inspector-controls/empty-terms-control.js +31 -0
  147. package/build-module/terms-query/inspector-controls/empty-terms-control.js.map +1 -0
  148. package/build-module/terms-query/inspector-controls/hierarchy-control.js +33 -0
  149. package/build-module/terms-query/inspector-controls/hierarchy-control.js.map +1 -0
  150. package/build-module/terms-query/inspector-controls/index.js +119 -0
  151. package/build-module/terms-query/inspector-controls/index.js.map +1 -0
  152. package/build-module/terms-query/inspector-controls/max-terms-control.js +43 -0
  153. package/build-module/terms-query/inspector-controls/max-terms-control.js.map +1 -0
  154. package/build-module/terms-query/inspector-controls/ordering-controls.js +50 -0
  155. package/build-module/terms-query/inspector-controls/ordering-controls.js.map +1 -0
  156. package/build-module/terms-query/inspector-controls/taxonomy-control.js +45 -0
  157. package/build-module/terms-query/inspector-controls/taxonomy-control.js.map +1 -0
  158. package/build-module/utils/hooks.js +14 -0
  159. package/build-module/utils/hooks.js.map +1 -1
  160. package/build-style/accordion-content/style-rtl.css +155 -0
  161. package/build-style/accordion-content/style.css +155 -0
  162. package/build-style/{accordion → accordion-header}/style-rtl.css +12 -51
  163. package/build-style/{accordion → accordion-header}/style.css +12 -51
  164. package/build-style/accordion-panel/style-rtl.css +140 -0
  165. package/build-style/accordion-panel/style.css +140 -0
  166. package/build-style/style-rtl.css +25 -38
  167. package/build-style/style.css +25 -38
  168. package/package.json +35 -35
  169. package/src/accordion/block.json +16 -3
  170. package/src/accordion/edit.js +39 -34
  171. package/src/accordion/index.js +35 -1
  172. package/src/accordion/index.php +3 -19
  173. package/src/accordion/save.js +2 -16
  174. package/src/accordion/view.js +64 -15
  175. package/src/accordion-content/block.json +17 -3
  176. package/src/accordion-content/index.php +3 -2
  177. package/src/accordion-content/save.js +4 -10
  178. package/src/accordion-content/style.scss +21 -0
  179. package/src/accordion-header/block.json +6 -11
  180. package/src/accordion-header/edit.js +17 -61
  181. package/src/accordion-header/save.js +24 -54
  182. package/src/accordion-header/style.scss +39 -0
  183. package/src/accordion-panel/block.json +3 -3
  184. package/src/accordion-panel/edit.js +1 -0
  185. package/src/accordion-panel/save.js +3 -1
  186. package/src/accordion-panel/style.scss +8 -0
  187. package/src/avatar/hooks.js +5 -10
  188. package/src/comments/index.php +2 -2
  189. package/src/group/variations.js +3 -14
  190. package/src/navigation/block.json +2 -1
  191. package/src/navigation/edit/leaf-more-menu.js +9 -1
  192. package/src/navigation/index.php +2 -2
  193. package/src/navigation-link/block.json +2 -1
  194. package/src/navigation-submenu/block.json +2 -1
  195. package/src/navigation-submenu/edit.js +1 -4
  196. package/src/page-list/block.json +2 -1
  197. package/src/post-author/edit.js +16 -7
  198. package/src/post-date/edit.js +16 -16
  199. package/src/post-time-to-read/block.json +17 -1
  200. package/src/post-time-to-read/edit.js +167 -20
  201. package/src/post-time-to-read/index.php +47 -15
  202. package/src/social-link/index.php +2 -2
  203. package/src/style.scss +3 -1
  204. package/src/table-of-contents/block.json +1 -0
  205. package/src/table-of-contents/index.php +44 -0
  206. package/src/term-description/block.json +1 -0
  207. package/src/term-description/edit.js +18 -3
  208. package/src/term-description/use-term-description.js +109 -0
  209. package/src/term-template/block.json +1 -1
  210. package/src/term-template/edit.js +11 -6
  211. package/src/term-template/index.php +13 -7
  212. package/src/terms-query/block.json +8 -2
  213. package/src/terms-query/inspector-controls/advanced-controls.js +37 -0
  214. package/src/terms-query/inspector-controls/display-options.js +87 -0
  215. package/src/terms-query/inspector-controls/empty-terms-control.js +30 -0
  216. package/src/terms-query/inspector-controls/hierarchy-control.js +30 -0
  217. package/src/terms-query/inspector-controls/index.js +137 -0
  218. package/src/terms-query/inspector-controls/max-terms-control.js +44 -0
  219. package/src/terms-query/inspector-controls/ordering-controls.js +55 -0
  220. package/src/terms-query/inspector-controls/taxonomy-control.js +41 -0
  221. package/src/utils/hooks.js +9 -0
  222. package/build/accordion-content/icons.js +0 -30
  223. package/build/accordion-content/icons.js.map +0 -1
  224. package/build/terms-query/inspector-controls.js +0 -231
  225. package/build/terms-query/inspector-controls.js.map +0 -1
  226. package/build-module/accordion-content/icons.js +0 -22
  227. package/build-module/accordion-content/icons.js.map +0 -1
  228. package/build-module/terms-query/inspector-controls.js +0 -224
  229. package/build-module/terms-query/inspector-controls.js.map +0 -1
  230. package/src/accordion/style.scss +0 -82
  231. package/src/accordion-content/icons.js +0 -23
  232. package/src/terms-query/inspector-controls.js +0 -239
@@ -1,11 +1,15 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { store as blockEditorStore } from '@wordpress/block-editor';
5
4
  import { store as coreStore, useEntityProp } from '@wordpress/core-data';
6
5
  import { __, sprintf } from '@wordpress/i18n';
7
6
  import { useSelect } from '@wordpress/data';
8
7
 
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { useDefaultAvatar } from '../utils/hooks';
12
+
9
13
  function getAvatarSizes( sizes ) {
10
14
  const minSize = sizes ? sizes[ 0 ] : 24;
11
15
  const maxSize = sizes ? sizes[ sizes.length - 1 ] : 96;
@@ -16,15 +20,6 @@ function getAvatarSizes( sizes ) {
16
20
  };
17
21
  }
18
22
 
19
- function useDefaultAvatar() {
20
- const { avatarURL: defaultAvatarUrl } = useSelect( ( select ) => {
21
- const { getSettings } = select( blockEditorStore );
22
- const { __experimentalDiscussionSettings } = getSettings();
23
- return __experimentalDiscussionSettings;
24
- } );
25
- return defaultAvatarUrl;
26
- }
27
-
28
23
  export function useCommentAvatar( { commentId } ) {
29
24
  const [ avatars ] = useEntityProp(
30
25
  'root',
@@ -28,11 +28,11 @@
28
28
  function render_block_core_comments( $attributes, $content, $block ) {
29
29
  global $post;
30
30
 
31
- $post_id = $block->context['postId'];
32
- if ( ! isset( $post_id ) ) {
31
+ if ( ! isset( $block->context['postId'] ) ) {
33
32
  return '';
34
33
  }
35
34
 
35
+ $post_id = $block->context['postId'];
36
36
  // Return early if there are no comments and comments are closed.
37
37
  if ( ! comments_open( $post_id ) && (int) get_comments_number( $post_id ) === 0 ) {
38
38
  return '';
@@ -53,11 +53,6 @@ const variations = [
53
53
  attributes: { layout: { type: 'constrained' } },
54
54
  isDefault: true,
55
55
  scope: [ 'block', 'inserter', 'transform' ],
56
- isActive: ( blockAttributes ) =>
57
- ! blockAttributes.layout ||
58
- ! blockAttributes.layout?.type ||
59
- blockAttributes.layout?.type === 'default' ||
60
- blockAttributes.layout?.type === 'constrained',
61
56
  icon: group,
62
57
  },
63
58
  {
@@ -66,10 +61,7 @@ const variations = [
66
61
  description: __( 'Arrange blocks horizontally.' ),
67
62
  attributes: { layout: { type: 'flex', flexWrap: 'nowrap' } },
68
63
  scope: [ 'block', 'inserter', 'transform' ],
69
- isActive: ( blockAttributes ) =>
70
- blockAttributes.layout?.type === 'flex' &&
71
- ( ! blockAttributes.layout?.orientation ||
72
- blockAttributes.layout?.orientation === 'horizontal' ),
64
+ isActive: [ 'layout.type' ],
73
65
  icon: row,
74
66
  example,
75
67
  },
@@ -79,9 +71,7 @@ const variations = [
79
71
  description: __( 'Arrange blocks vertically.' ),
80
72
  attributes: { layout: { type: 'flex', orientation: 'vertical' } },
81
73
  scope: [ 'block', 'inserter', 'transform' ],
82
- isActive: ( blockAttributes ) =>
83
- blockAttributes.layout?.type === 'flex' &&
84
- blockAttributes.layout?.orientation === 'vertical',
74
+ isActive: [ 'layout.type', 'layout.orientation' ],
85
75
  icon: stack,
86
76
  example,
87
77
  },
@@ -91,8 +81,7 @@ const variations = [
91
81
  description: __( 'Arrange blocks in a grid.' ),
92
82
  attributes: { layout: { type: 'grid' } },
93
83
  scope: [ 'block', 'inserter', 'transform' ],
94
- isActive: ( blockAttributes ) =>
95
- blockAttributes.layout?.type === 'grid',
84
+ isActive: [ 'layout.type' ],
96
85
  icon: grid,
97
86
  example,
98
87
  },
@@ -138,7 +138,8 @@
138
138
  }
139
139
  },
140
140
  "interactivity": true,
141
- "renaming": false
141
+ "renaming": false,
142
+ "contentRole": true
142
143
  },
143
144
  "editorStyle": "wp-block-navigation-editor",
144
145
  "style": "wp-block-navigation"
@@ -13,6 +13,11 @@ import { useDispatch, useSelect } from '@wordpress/data';
13
13
  import { __, sprintf } from '@wordpress/i18n';
14
14
  import { BlockTitle, store as blockEditorStore } from '@wordpress/block-editor';
15
15
 
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { DEFAULT_BLOCK } from '../constants';
20
+
16
21
  const POPOVER_PROPS = {
17
22
  className: 'block-editor-block-settings-menu__popover',
18
23
  placement: 'bottom-start',
@@ -43,7 +48,10 @@ function AddSubmenuItem( {
43
48
  disabled={ isDisabled }
44
49
  onClick={ () => {
45
50
  const updateSelectionOnInsert = false;
46
- const newLink = createBlock( 'core/navigation-link' );
51
+ const newLink = createBlock(
52
+ DEFAULT_BLOCK.name,
53
+ DEFAULT_BLOCK.attributes
54
+ );
47
55
 
48
56
  if ( block.name === 'core/navigation-submenu' ) {
49
57
  insertBlock(
@@ -478,10 +478,10 @@ class WP_Navigation_Block_Renderer {
478
478
  );
479
479
 
480
480
  $should_display_icon_label = isset( $attributes['hasIcon'] ) && true === $attributes['hasIcon'];
481
- $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><rect x="4" y="7.5" width="16" height="1.5" /><rect x="4" y="15" width="16" height="1.5" /></svg>';
481
+ $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M4 7.5h16v1.5H4z"></path><path d="M4 15h16v1.5H4z"></path></svg>';
482
482
  if ( isset( $attributes['icon'] ) ) {
483
483
  if ( 'menu' === $attributes['icon'] ) {
484
- $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 5v1.5h14V5H5zm0 7.8h14v-1.5H5v1.5zM5 19h14v-1.5H5V19z" /></svg>';
484
+ $toggle_button_icon = '<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 5v1.5h14V5H5z"></path><path d="M5 12.8h14v-1.5H5v1.5z"></path><path d="M5 19h14v-1.5H5V19z"></path></svg>';
485
485
  }
486
486
  }
487
487
  $toggle_button_content = $should_display_icon_label ? $toggle_button_icon : __( 'Menu' );
@@ -14,7 +14,8 @@
14
14
  "textdomain": "default",
15
15
  "attributes": {
16
16
  "label": {
17
- "type": "string"
17
+ "type": "string",
18
+ "role": "content"
18
19
  },
19
20
  "type": {
20
21
  "type": "string"
@@ -9,7 +9,8 @@
9
9
  "textdomain": "default",
10
10
  "attributes": {
11
11
  "label": {
12
- "type": "string"
12
+ "type": "string",
13
+ "role": "content"
13
14
  },
14
15
  "type": {
15
16
  "type": "string"
@@ -46,6 +46,7 @@ import {
46
46
  getNavigationChildBlockProps,
47
47
  } from '../navigation/edit/utils';
48
48
  import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
49
+ import { DEFAULT_BLOCK } from '../navigation/constants';
49
50
 
50
51
  const ALLOWED_BLOCKS = [
51
52
  'core/navigation-link',
@@ -53,10 +54,6 @@ const ALLOWED_BLOCKS = [
53
54
  'core/page-list',
54
55
  ];
55
56
 
56
- const DEFAULT_BLOCK = {
57
- name: 'core/navigation-link',
58
- };
59
-
60
57
  /**
61
58
  * A React hook to determine if it's dragging within the target element.
62
59
  *
@@ -76,7 +76,8 @@
76
76
  "padding": false,
77
77
  "margin": false
78
78
  }
79
- }
79
+ },
80
+ "contentRole": true
80
81
  },
81
82
  "editorStyle": "wp-block-page-list-editor",
82
83
  "style": "wp-block-page-list"
@@ -21,16 +21,19 @@ import {
21
21
  __experimentalToolsPanelItem as ToolsPanelItem,
22
22
  } from '@wordpress/components';
23
23
  import { debounce } from '@wordpress/compose';
24
+ import { store as coreStore } from '@wordpress/core-data';
25
+ import { useDispatch, useSelect } from '@wordpress/data';
24
26
  import { useMemo, useState } from '@wordpress/element';
25
- import { useSelect, useDispatch } from '@wordpress/data';
26
- import { __, sprintf } from '@wordpress/i18n';
27
27
  import { decodeEntities } from '@wordpress/html-entities';
28
- import { store as coreStore } from '@wordpress/core-data';
28
+ import { __, sprintf } from '@wordpress/i18n';
29
29
 
30
30
  /**
31
31
  * Internal dependencies
32
32
  */
33
- import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
33
+ import {
34
+ useDefaultAvatar,
35
+ useToolsPanelDropdownMenuProps,
36
+ } from '../utils/hooks';
34
37
 
35
38
  const AUTHORS_QUERY = {
36
39
  who: 'authors',
@@ -115,6 +118,7 @@ function PostAuthorEdit( {
115
118
  } ) {
116
119
  const isDescendentOfQueryLoop = Number.isFinite( queryId );
117
120
  const dropdownMenuProps = useToolsPanelDropdownMenuProps();
121
+ const defaultAvatar = useDefaultAvatar();
118
122
 
119
123
  const { authorDetails, canAssignAuthor, supportsAuthor } = useSelect(
120
124
  ( select ) => {
@@ -323,12 +327,17 @@ function PostAuthorEdit( {
323
327
  </BlockControls>
324
328
 
325
329
  <div { ...blockProps }>
326
- { showAvatar && authorDetails?.avatar_urls && (
330
+ { showAvatar && (
327
331
  <div className="wp-block-post-author__avatar">
328
332
  <img
329
333
  width={ avatarSize }
330
- src={ authorDetails.avatar_urls[ avatarSize ] }
331
- alt={ authorDetails.name }
334
+ src={
335
+ authorDetails?.avatar_urls?.[ avatarSize ] ||
336
+ defaultAvatar
337
+ }
338
+ alt={
339
+ authorDetails?.name || __( 'Default Avatar' )
340
+ }
332
341
  />
333
342
  </div>
334
343
  ) }
@@ -6,7 +6,7 @@ import clsx from 'clsx';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { useEntityProp, store as coreStore } from '@wordpress/core-data';
9
+ import { store as coreStore } from '@wordpress/core-data';
10
10
  import { useEffect, useMemo, useState } from '@wordpress/element';
11
11
  import {
12
12
  dateI18n,
@@ -81,22 +81,22 @@ export default function PostDateEdit( {
81
81
 
82
82
  const isDescendentOfQueryLoop = Number.isFinite( queryId );
83
83
  const dateSettings = getDateSettings();
84
- const [ siteFormat = dateSettings.formats.date ] = useEntityProp(
85
- 'root',
86
- 'site',
87
- 'date_format'
88
- );
89
- const [ siteTimeFormat = dateSettings.formats.time ] = useEntityProp(
90
- 'root',
91
- 'site',
92
- 'time_format'
93
- );
94
84
 
95
- const postType = useSelect(
96
- ( select ) =>
97
- postTypeSlug
98
- ? select( coreStore ).getPostType( postTypeSlug )
99
- : null,
85
+ const {
86
+ postType,
87
+ siteFormat = dateSettings.formats.date,
88
+ siteTimeFormat = dateSettings.formats.time,
89
+ } = useSelect(
90
+ ( select ) => {
91
+ const { getPostType, getEntityRecord } = select( coreStore );
92
+ const siteSettings = getEntityRecord( 'root', 'site' );
93
+
94
+ return {
95
+ siteFormat: siteSettings?.date_format,
96
+ siteTimeFormat: siteSettings?.time_format,
97
+ postType: postTypeSlug ? getPostType( postTypeSlug ) : null,
98
+ };
99
+ },
100
100
  [ postTypeSlug ]
101
101
  );
102
102
 
@@ -5,12 +5,28 @@
5
5
  "name": "core/post-time-to-read",
6
6
  "title": "Time to Read",
7
7
  "category": "theme",
8
- "description": "Show minutes required to finish reading the post.",
8
+ "description": "Show minutes required to finish reading the post. Can also show a word count.",
9
9
  "textdomain": "default",
10
10
  "usesContext": [ "postId", "postType" ],
11
11
  "attributes": {
12
12
  "textAlign": {
13
13
  "type": "string"
14
+ },
15
+ "displayAsRange": {
16
+ "type": "boolean",
17
+ "default": true
18
+ },
19
+ "showTimeToRead": {
20
+ "type": "boolean",
21
+ "default": true
22
+ },
23
+ "showWordCount": {
24
+ "type": "boolean",
25
+ "default": false
26
+ },
27
+ "averageReadingSpeed": {
28
+ "type": "number",
29
+ "default": 189
14
30
  }
15
31
  },
16
32
  "supports": {
@@ -6,27 +6,39 @@ import clsx from 'clsx';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { _x, _n, sprintf } from '@wordpress/i18n';
9
+ import { __, _x, _n, sprintf } from '@wordpress/i18n';
10
10
  import { useMemo } from '@wordpress/element';
11
11
  import {
12
12
  AlignmentControl,
13
13
  BlockControls,
14
+ InspectorControls,
14
15
  useBlockProps,
15
16
  } from '@wordpress/block-editor';
17
+ import {
18
+ ToggleControl,
19
+ __experimentalToolsPanel as ToolsPanel,
20
+ __experimentalToolsPanelItem as ToolsPanelItem,
21
+ } from '@wordpress/components';
16
22
  import { __unstableSerializeAndClean } from '@wordpress/blocks';
17
23
  import { useEntityProp, useEntityBlockEditor } from '@wordpress/core-data';
18
24
  import { count as wordCount } from '@wordpress/wordcount';
19
25
 
20
26
  /**
21
- * Average reading rate - based on average taken from
22
- * https://irisreading.com/average-reading-speed-in-various-languages/
23
- * (Characters/minute used for Chinese rather than words).
27
+ * Internal dependencies
24
28
  */
25
- const AVERAGE_READING_RATE = 189;
29
+ import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
26
30
 
27
31
  function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
28
- const { textAlign } = attributes;
32
+ const {
33
+ textAlign,
34
+ displayAsRange,
35
+ showTimeToRead,
36
+ showWordCount,
37
+ averageReadingSpeed,
38
+ } = attributes;
39
+
29
40
  const { postId, postType } = context;
41
+ const dropdownMenuProps = useToolsPanelDropdownMenuProps();
30
42
 
31
43
  const [ contentStructure ] = useEntityProp(
32
44
  'postType',
@@ -39,7 +51,7 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
39
51
  id: postId,
40
52
  } );
41
53
 
42
- const minutesToReadString = useMemo( () => {
54
+ const displayString = useMemo( () => {
43
55
  // Replicates the logic found in getEditedPostContent().
44
56
  let content;
45
57
  if ( contentStructure instanceof Function ) {
@@ -63,19 +75,74 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
63
75
  'Word count type. Do not translate!'
64
76
  );
65
77
 
66
- const minutesToRead = Math.max(
67
- 1,
68
- Math.round(
69
- wordCount( content || '', wordCountType ) / AVERAGE_READING_RATE
70
- )
71
- );
78
+ const totalWords = wordCount( content || '', wordCountType );
72
79
 
73
- return sprintf(
74
- /* translators: %s: the number of minutes to read the post. */
75
- _n( '%s minute', '%s minutes', minutesToRead ),
76
- minutesToRead
77
- );
78
- }, [ contentStructure, blocks ] );
80
+ const parts = [];
81
+
82
+ // Add "time to read" part, if enabled.
83
+ if ( showTimeToRead ) {
84
+ let timeString;
85
+ if ( displayAsRange ) {
86
+ let maxMinutes = Math.max(
87
+ 1,
88
+ Math.round( ( totalWords / averageReadingSpeed ) * 1.2 )
89
+ );
90
+ const minMinutes = Math.max(
91
+ 1,
92
+ Math.round( ( totalWords / averageReadingSpeed ) * 0.8 )
93
+ );
94
+
95
+ if ( minMinutes === maxMinutes ) {
96
+ maxMinutes = maxMinutes + 1;
97
+ }
98
+ // translators: %1$s: minimum minutes, %2$s: maximum minutes to read the post.
99
+ const rangeLabel = _x(
100
+ '%1$s–%2$s minutes',
101
+ 'Range of minutes to read'
102
+ );
103
+ timeString = sprintf( rangeLabel, minMinutes, maxMinutes );
104
+ } else {
105
+ const minutesToRead = Math.max(
106
+ 1,
107
+ Math.round( totalWords / averageReadingSpeed )
108
+ );
109
+
110
+ timeString = sprintf(
111
+ /* translators: %s: the number of minutes to read the post. */
112
+ _n( '%s minute', '%s minutes', minutesToRead ),
113
+ minutesToRead
114
+ );
115
+ }
116
+ parts.push( timeString );
117
+ }
118
+
119
+ // Add "word count" part, if enabled.
120
+ if ( showWordCount ) {
121
+ const wordCountString = sprintf(
122
+ /* translators: %s: the number of words in the post. */
123
+ _n( '%s word', '%s words', totalWords ),
124
+ totalWords.toLocaleString()
125
+ );
126
+ parts.push( wordCountString );
127
+ }
128
+
129
+ if ( parts.length === 1 ) {
130
+ return parts[ 0 ];
131
+ }
132
+ return parts.map( ( part, index ) => (
133
+ <span key={ index }>
134
+ { part }
135
+ { index < parts.length - 1 && <br /> }
136
+ </span>
137
+ ) );
138
+ }, [
139
+ contentStructure,
140
+ blocks,
141
+ displayAsRange,
142
+ showTimeToRead,
143
+ showWordCount,
144
+ averageReadingSpeed,
145
+ ] );
79
146
 
80
147
  const blockProps = useBlockProps( {
81
148
  className: clsx( {
@@ -93,7 +160,87 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
93
160
  } }
94
161
  />
95
162
  </BlockControls>
96
- <div { ...blockProps }>{ minutesToReadString }</div>
163
+ <InspectorControls>
164
+ <ToolsPanel
165
+ label={ __( 'Settings' ) }
166
+ resetAll={ () => {
167
+ setAttributes( {
168
+ displayAsRange: true,
169
+ showTimeToRead: true,
170
+ showWordCount: false,
171
+ } );
172
+ } }
173
+ dropdownMenuProps={ dropdownMenuProps }
174
+ >
175
+ <ToolsPanelItem
176
+ label={ __( 'Show time to read' ) }
177
+ hasValue={ () => ! showTimeToRead }
178
+ onDeselect={ () => {
179
+ setAttributes( {
180
+ showTimeToRead: true,
181
+ } );
182
+ } }
183
+ >
184
+ <ToggleControl
185
+ __nextHasNoMarginBottom
186
+ label={ __( 'Show time to read' ) }
187
+ checked={ !! showTimeToRead }
188
+ onChange={ () =>
189
+ setAttributes( {
190
+ showTimeToRead: ! showTimeToRead,
191
+ } )
192
+ }
193
+ />
194
+ </ToolsPanelItem>
195
+ { showTimeToRead && (
196
+ <ToolsPanelItem
197
+ isShownByDefault
198
+ label={ _x(
199
+ 'Display as range',
200
+ 'Turns reading time range display on or off'
201
+ ) }
202
+ hasValue={ () => ! displayAsRange }
203
+ onDeselect={ () => {
204
+ setAttributes( {
205
+ displayAsRange: true,
206
+ } );
207
+ } }
208
+ >
209
+ <ToggleControl
210
+ __nextHasNoMarginBottom
211
+ label={ __( 'Display as range' ) }
212
+ checked={ !! displayAsRange }
213
+ onChange={ () =>
214
+ setAttributes( {
215
+ displayAsRange: ! displayAsRange,
216
+ } )
217
+ }
218
+ />
219
+ </ToolsPanelItem>
220
+ ) }
221
+ <ToolsPanelItem
222
+ label={ __( 'Show word count' ) }
223
+ hasValue={ () => !! showWordCount }
224
+ onDeselect={ () => {
225
+ setAttributes( {
226
+ showWordCount: false,
227
+ } );
228
+ } }
229
+ >
230
+ <ToggleControl
231
+ __nextHasNoMarginBottom
232
+ label={ __( 'Show word count' ) }
233
+ checked={ !! showWordCount }
234
+ onChange={ () =>
235
+ setAttributes( {
236
+ showWordCount: ! showWordCount,
237
+ } )
238
+ }
239
+ />
240
+ </ToolsPanelItem>
241
+ </ToolsPanel>
242
+ </InspectorControls>
243
+ <div { ...blockProps }>{ displayString }</div>
97
244
  </>
98
245
  );
99
246
  }
@@ -18,24 +18,54 @@ function render_block_core_post_time_to_read( $attributes, $content, $block ) {
18
18
  return '';
19
19
  }
20
20
 
21
- $content = get_the_content();
21
+ $content = get_the_content();
22
+ $average_reading_rate = isset( $attributes['averageReadingSpeed'] ) ? $attributes['averageReadingSpeed'] : 189;
23
+ $show_time_to_read = isset( $attributes['showTimeToRead'] ) ? $attributes['showTimeToRead'] : true;
24
+ $show_word_count = isset( $attributes['showWordCount'] ) ? $attributes['showWordCount'] : false;
25
+ $word_count_type = wp_get_word_count_type();
26
+ $total_words = wp_word_count( $content, $word_count_type );
22
27
 
23
- /*
24
- * Average reading rate - based on average taken from
25
- * https://irisreading.com/average-reading-speed-in-various-languages/
26
- * (Characters/minute used for Chinese rather than words).
27
- */
28
- $average_reading_rate = 189;
28
+ $parts = array();
29
29
 
30
- $word_count_type = wp_get_word_count_type();
30
+ // Add "time to read" part, if enabled.
31
+ if ( $show_time_to_read ) {
32
+ if ( ! empty( $attributes['displayAsRange'] ) ) {
33
+ // Calculate faster reading rate with 20% speed = lower minutes,
34
+ // and slower reading rate with 20% speed = higher minutes.
35
+ $min_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 0.8 ) );
36
+ $max_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 1.2 ) );
37
+ if ( $min_minutes === $max_minutes ) {
38
+ $max_minutes = $min_minutes + 1;
39
+ }
40
+ /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */
41
+ $time_string = sprintf(
42
+ /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */
43
+ _x( '%1$s–%2$s minutes', 'Range of minutes to read' ),
44
+ $min_minutes,
45
+ $max_minutes
46
+ );
47
+ } else {
48
+ $minutes_to_read = max( 1, (int) round( $total_words / $average_reading_rate ) );
49
+ $time_string = sprintf(
50
+ /* translators: %s: the number of minutes to read the post. */
51
+ _n( '%s minute', '%s minutes', $minutes_to_read ),
52
+ $minutes_to_read
53
+ );
54
+ }
55
+ $parts[] = $time_string;
56
+ }
31
57
 
32
- $minutes_to_read = max( 1, (int) round( wp_word_count( $content, $word_count_type ) / $average_reading_rate ) );
58
+ // Add "word count" part, if enabled.
59
+ if ( $show_word_count ) {
60
+ $word_count_string = sprintf(
61
+ /* translators: %s: the number of words in the post. */
62
+ _n( '%s word', '%s words', $total_words ),
63
+ number_format_i18n( $total_words )
64
+ );
65
+ $parts[] = $word_count_string;
66
+ }
33
67
 
34
- $minutes_to_read_string = sprintf(
35
- /* translators: %s: the number of minutes to read the post. */
36
- _n( '%s minute', '%s minutes', $minutes_to_read ),
37
- $minutes_to_read
38
- );
68
+ $display_string = implode( '<br>', $parts );
39
69
 
40
70
  $align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}";
41
71
 
@@ -44,10 +74,11 @@ function render_block_core_post_time_to_read( $attributes, $content, $block ) {
44
74
  return sprintf(
45
75
  '<div %1$s>%2$s</div>',
46
76
  $wrapper_attributes,
47
- $minutes_to_read_string
77
+ $display_string
48
78
  );
49
79
  }
50
80
 
81
+
51
82
  /**
52
83
  * Registers the `core/post-time-to-read` block on the server.
53
84
  */
@@ -59,4 +90,5 @@ function register_block_core_post_time_to_read() {
59
90
  )
60
91
  );
61
92
  }
93
+
62
94
  add_action( 'init', 'register_block_core_post_time_to_read' );
@@ -374,11 +374,11 @@ function block_core_social_link_get_color_styles( $context ) {
374
374
  $styles = array();
375
375
 
376
376
  if ( array_key_exists( 'iconColorValue', $context ) ) {
377
- $styles[] = 'color: ' . $context['iconColorValue'] . '; ';
377
+ $styles[] = 'color:' . $context['iconColorValue'] . ';';
378
378
  }
379
379
 
380
380
  if ( array_key_exists( 'iconBackgroundColorValue', $context ) ) {
381
- $styles[] = 'background-color: ' . $context['iconBackgroundColorValue'] . '; ';
381
+ $styles[] = 'background-color:' . $context['iconBackgroundColorValue'] . ';';
382
382
  }
383
383
 
384
384
  return implode( '', $styles );
package/src/style.scss CHANGED
@@ -1,4 +1,6 @@
1
- @import "./accordion/style.scss";
1
+ @import "./accordion-content/style.scss";
2
+ @import "./accordion-header/style.scss";
3
+ @import "./accordion-panel/style.scss";
2
4
  @import "./archives/style.scss";
3
5
  @import "./avatar/style.scss";
4
6
  @import "./audio/style.scss";
@@ -29,6 +29,7 @@
29
29
  }
30
30
  },
31
31
  "supports": {
32
+ "ariaLabel": true,
32
33
  "html": false,
33
34
  "color": {
34
35
  "text": true,