@wordpress/block-library 9.30.1-next.a730c9c8c.0 → 9.31.1-next.f56bd8138.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 (180) 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 +40 -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 +15 -2
  11. package/build/accordion-content/index.js.map +1 -1
  12. package/build/accordion-header/edit.js +15 -39
  13. package/build/accordion-header/edit.js.map +1 -1
  14. package/build/accordion-header/index.js +6 -6
  15. package/build/accordion-header/index.js.map +1 -1
  16. package/build/accordion-header/save.js +15 -37
  17. package/build/accordion-header/save.js.map +1 -1
  18. package/build/accordion-panel/index.js +1 -2
  19. package/build/accordion-panel/index.js.map +1 -1
  20. package/build/avatar/hooks.js +7 -17
  21. package/build/avatar/hooks.js.map +1 -1
  22. package/build/navigation/index.js +2 -1
  23. package/build/navigation/index.js.map +1 -1
  24. package/build/navigation-link/index.js +2 -1
  25. package/build/navigation-link/index.js.map +1 -1
  26. package/build/navigation-submenu/index.js +2 -1
  27. package/build/navigation-submenu/index.js.map +1 -1
  28. package/build/page-list/index.js +2 -1
  29. package/build/page-list/index.js.map +1 -1
  30. package/build/post-author/edit.js +7 -6
  31. package/build/post-author/edit.js.map +1 -1
  32. package/build/post-time-to-read/edit.js +50 -7
  33. package/build/post-time-to-read/edit.js.map +1 -1
  34. package/build/post-time-to-read/index.js +8 -0
  35. package/build/post-time-to-read/index.js.map +1 -1
  36. package/build/term-description/edit.js +18 -2
  37. package/build/term-description/edit.js.map +1 -1
  38. package/build/term-description/index.js +1 -0
  39. package/build/term-description/index.js.map +1 -1
  40. package/build/term-description/use-term-description.js +85 -0
  41. package/build/term-description/use-term-description.js.map +1 -0
  42. package/build/term-template/edit.js +11 -7
  43. package/build/term-template/edit.js.map +1 -1
  44. package/build/term-template/index.js +1 -1
  45. package/build/terms-query/index.js +8 -2
  46. package/build/terms-query/index.js.map +1 -1
  47. package/build/terms-query/inspector-controls/advanced-controls.js +51 -0
  48. package/build/terms-query/inspector-controls/advanced-controls.js.map +1 -0
  49. package/build/terms-query/inspector-controls/display-options.js +87 -0
  50. package/build/terms-query/inspector-controls/display-options.js.map +1 -0
  51. package/build/terms-query/inspector-controls/empty-terms-control.js +38 -0
  52. package/build/terms-query/inspector-controls/empty-terms-control.js.map +1 -0
  53. package/build/terms-query/inspector-controls/hierarchy-control.js +40 -0
  54. package/build/terms-query/inspector-controls/hierarchy-control.js.map +1 -0
  55. package/build/terms-query/inspector-controls/index.js +127 -0
  56. package/build/terms-query/inspector-controls/index.js.map +1 -0
  57. package/build/terms-query/inspector-controls/max-terms-control.js +50 -0
  58. package/build/terms-query/inspector-controls/max-terms-control.js.map +1 -0
  59. package/build/terms-query/inspector-controls/ordering-controls.js +57 -0
  60. package/build/terms-query/inspector-controls/ordering-controls.js.map +1 -0
  61. package/build/terms-query/inspector-controls/taxonomy-control.js +52 -0
  62. package/build/terms-query/inspector-controls/taxonomy-control.js.map +1 -0
  63. package/build/utils/hooks.js +15 -0
  64. package/build/utils/hooks.js.map +1 -1
  65. package/build-module/accordion/edit.js +6 -5
  66. package/build-module/accordion/edit.js.map +1 -1
  67. package/build-module/accordion/index.js +41 -4
  68. package/build-module/accordion/index.js.map +1 -1
  69. package/build-module/accordion/save.js +2 -17
  70. package/build-module/accordion/save.js.map +1 -1
  71. package/build-module/accordion/view.js +51 -17
  72. package/build-module/accordion/view.js.map +1 -1
  73. package/build-module/accordion-content/index.js +15 -2
  74. package/build-module/accordion-content/index.js.map +1 -1
  75. package/build-module/accordion-header/edit.js +16 -39
  76. package/build-module/accordion-header/edit.js.map +1 -1
  77. package/build-module/accordion-header/index.js +6 -6
  78. package/build-module/accordion-header/index.js.map +1 -1
  79. package/build-module/accordion-header/save.js +16 -37
  80. package/build-module/accordion-header/save.js.map +1 -1
  81. package/build-module/accordion-panel/index.js +1 -2
  82. package/build-module/accordion-panel/index.js.map +1 -1
  83. package/build-module/avatar/hooks.js +5 -15
  84. package/build-module/avatar/hooks.js.map +1 -1
  85. package/build-module/navigation/index.js +2 -1
  86. package/build-module/navigation/index.js.map +1 -1
  87. package/build-module/navigation-link/index.js +2 -1
  88. package/build-module/navigation-link/index.js.map +1 -1
  89. package/build-module/navigation-submenu/index.js +2 -1
  90. package/build-module/navigation-submenu/index.js.map +1 -1
  91. package/build-module/page-list/index.js +2 -1
  92. package/build-module/page-list/index.js.map +1 -1
  93. package/build-module/post-author/edit.js +8 -7
  94. package/build-module/post-author/edit.js.map +1 -1
  95. package/build-module/post-time-to-read/edit.js +50 -9
  96. package/build-module/post-time-to-read/edit.js.map +1 -1
  97. package/build-module/post-time-to-read/index.js +8 -0
  98. package/build-module/post-time-to-read/index.js.map +1 -1
  99. package/build-module/term-description/edit.js +18 -2
  100. package/build-module/term-description/edit.js.map +1 -1
  101. package/build-module/term-description/index.js +1 -0
  102. package/build-module/term-description/index.js.map +1 -1
  103. package/build-module/term-description/use-term-description.js +79 -0
  104. package/build-module/term-description/use-term-description.js.map +1 -0
  105. package/build-module/term-template/edit.js +11 -7
  106. package/build-module/term-template/edit.js.map +1 -1
  107. package/build-module/term-template/index.js +1 -1
  108. package/build-module/terms-query/index.js +8 -2
  109. package/build-module/terms-query/index.js.map +1 -1
  110. package/build-module/terms-query/inspector-controls/advanced-controls.js +44 -0
  111. package/build-module/terms-query/inspector-controls/advanced-controls.js.map +1 -0
  112. package/build-module/terms-query/inspector-controls/display-options.js +80 -0
  113. package/build-module/terms-query/inspector-controls/display-options.js.map +1 -0
  114. package/build-module/terms-query/inspector-controls/empty-terms-control.js +31 -0
  115. package/build-module/terms-query/inspector-controls/empty-terms-control.js.map +1 -0
  116. package/build-module/terms-query/inspector-controls/hierarchy-control.js +33 -0
  117. package/build-module/terms-query/inspector-controls/hierarchy-control.js.map +1 -0
  118. package/build-module/terms-query/inspector-controls/index.js +119 -0
  119. package/build-module/terms-query/inspector-controls/index.js.map +1 -0
  120. package/build-module/terms-query/inspector-controls/max-terms-control.js +43 -0
  121. package/build-module/terms-query/inspector-controls/max-terms-control.js.map +1 -0
  122. package/build-module/terms-query/inspector-controls/ordering-controls.js +50 -0
  123. package/build-module/terms-query/inspector-controls/ordering-controls.js.map +1 -0
  124. package/build-module/terms-query/inspector-controls/taxonomy-control.js +45 -0
  125. package/build-module/terms-query/inspector-controls/taxonomy-control.js.map +1 -0
  126. package/build-module/utils/hooks.js +14 -0
  127. package/build-module/utils/hooks.js.map +1 -1
  128. package/build-style/accordion/style-rtl.css +15 -8
  129. package/build-style/accordion/style.css +15 -8
  130. package/build-style/style-rtl.css +15 -8
  131. package/build-style/style.css +15 -8
  132. package/package.json +35 -35
  133. package/src/accordion/block.json +17 -3
  134. package/src/accordion/edit.js +39 -34
  135. package/src/accordion/index.js +35 -1
  136. package/src/accordion/index.php +3 -19
  137. package/src/accordion/save.js +2 -16
  138. package/src/accordion/style.scss +16 -8
  139. package/src/accordion/view.js +64 -15
  140. package/src/accordion-content/block.json +15 -2
  141. package/src/accordion-content/index.php +2 -1
  142. package/src/accordion-header/block.json +6 -6
  143. package/src/accordion-header/edit.js +19 -56
  144. package/src/accordion-header/save.js +27 -49
  145. package/src/accordion-panel/block.json +1 -2
  146. package/src/avatar/hooks.js +5 -10
  147. package/src/navigation/block.json +2 -1
  148. package/src/navigation-link/block.json +2 -1
  149. package/src/navigation-submenu/block.json +2 -1
  150. package/src/page-list/block.json +2 -1
  151. package/src/post-author/edit.js +16 -7
  152. package/src/post-time-to-read/block.json +8 -0
  153. package/src/post-time-to-read/edit.js +71 -10
  154. package/src/post-time-to-read/index.php +29 -17
  155. package/src/term-description/block.json +1 -0
  156. package/src/term-description/edit.js +18 -3
  157. package/src/term-description/use-term-description.js +109 -0
  158. package/src/term-template/block.json +1 -1
  159. package/src/term-template/edit.js +11 -6
  160. package/src/term-template/index.php +13 -7
  161. package/src/terms-query/block.json +8 -2
  162. package/src/terms-query/inspector-controls/advanced-controls.js +37 -0
  163. package/src/terms-query/inspector-controls/display-options.js +87 -0
  164. package/src/terms-query/inspector-controls/empty-terms-control.js +30 -0
  165. package/src/terms-query/inspector-controls/hierarchy-control.js +30 -0
  166. package/src/terms-query/inspector-controls/index.js +137 -0
  167. package/src/terms-query/inspector-controls/max-terms-control.js +44 -0
  168. package/src/terms-query/inspector-controls/ordering-controls.js +55 -0
  169. package/src/terms-query/inspector-controls/taxonomy-control.js +41 -0
  170. package/src/utils/hooks.js +9 -0
  171. package/build/accordion-content/icons.js +0 -30
  172. package/build/accordion-content/icons.js.map +0 -1
  173. package/build/terms-query/inspector-controls.js +0 -231
  174. package/build/terms-query/inspector-controls.js.map +0 -1
  175. package/build-module/accordion-content/icons.js +0 -22
  176. package/build-module/accordion-content/icons.js.map +0 -1
  177. package/build-module/terms-query/inspector-controls.js +0 -224
  178. package/build-module/terms-query/inspector-controls.js.map +0 -1
  179. package/src/accordion-content/icons.js +0 -23
  180. package/src/terms-query/inspector-controls.js +0 -239
@@ -9,23 +9,12 @@ import { __ } from '@wordpress/i18n';
9
9
  import { useEffect } from '@wordpress/element';
10
10
  import {
11
11
  useBlockProps,
12
- __experimentalUseBorderProps as useBorderProps,
13
- __experimentalUseColorProps as useColorProps,
14
12
  __experimentalGetSpacingClassesAndStyles as useSpacingProps,
15
- __experimentalGetShadowClassesAndStyles as useShadowProps,
16
13
  BlockControls,
17
14
  HeadingLevelDropdown,
18
15
  RichText,
19
16
  } from '@wordpress/block-editor';
20
17
  import { ToolbarGroup } from '@wordpress/components';
21
- /**
22
- * Internal dependencies
23
- */
24
- import { plus } from '../accordion-content/icons';
25
-
26
- const ICONS = {
27
- plus,
28
- };
29
18
 
30
19
  export default function Edit( { attributes, setAttributes, context } ) {
31
20
  const { level, title, textAlign, levelOptions } = attributes;
@@ -45,14 +34,12 @@ export default function Edit( { attributes, setAttributes, context } ) {
45
34
  }
46
35
  }, [ iconPosition, showIcon, setAttributes ] );
47
36
 
48
- const blockProps = useBlockProps();
49
- const borderProps = useBorderProps( attributes );
50
- const colorProps = useColorProps( attributes );
37
+ const blockProps = useBlockProps( {
38
+ className: clsx( 'accordion-content__heading', {
39
+ [ `has-text-align-${ textAlign }` ]: textAlign,
40
+ } ),
41
+ } );
51
42
  const spacingProps = useSpacingProps( attributes );
52
- const shadowProps = useShadowProps( attributes );
53
-
54
- const Icon = ICONS.plus;
55
- const shouldShowIcon = showIcon && Icon;
56
43
 
57
44
  return (
58
45
  <>
@@ -67,38 +54,23 @@ export default function Edit( { attributes, setAttributes, context } ) {
67
54
  />
68
55
  </ToolbarGroup>
69
56
  </BlockControls>
70
- <TagName
71
- { ...blockProps }
72
- className={ clsx(
73
- blockProps.className,
74
- colorProps.className,
75
- borderProps.className,
76
- 'accordion-content__heading',
77
- {
78
- [ `has-custom-font-size` ]: blockProps.style.fontSize,
79
- [ `icon-position-left` ]: iconPosition === 'left',
80
- [ `has-text-align-${ textAlign }` ]: textAlign,
81
- }
82
- ) }
83
- style={ {
84
- ...borderProps.style,
85
- ...colorProps.style,
86
- ...shadowProps.style,
87
- } }
88
- >
57
+ <TagName { ...blockProps }>
89
58
  <button
90
59
  className={ clsx( 'accordion-content__toggle' ) }
91
60
  style={ {
92
61
  ...spacingProps.style,
93
62
  } }
94
63
  >
64
+ { showIcon && iconPosition === 'left' && (
65
+ <span
66
+ className="accordion-content__toggle-icon"
67
+ aria-hidden="true"
68
+ >
69
+ +
70
+ </span>
71
+ ) }
95
72
  <RichText
96
- allowedFormats={ [
97
- 'core/bold',
98
- 'core/italic',
99
- 'core/image',
100
- 'core/strikethrough',
101
- ] }
73
+ withoutInteractiveFormatting
102
74
  disableLineBreaks
103
75
  tagName="span"
104
76
  value={ title }
@@ -107,21 +79,12 @@ export default function Edit( { attributes, setAttributes, context } ) {
107
79
  }
108
80
  placeholder={ __( 'Accordion title' ) }
109
81
  />
110
- { shouldShowIcon && (
82
+ { showIcon && iconPosition === 'right' && (
111
83
  <span
112
- className={ clsx(
113
- `accordion-content__toggle-icon`,
114
- {
115
- 'has-icon-plus': true,
116
- }
117
- ) }
118
- style={ {
119
- // TO-DO: make this configurable
120
- width: `1.2em`,
121
- height: `1.2em`,
122
- } }
84
+ className="accordion-content__toggle-icon"
85
+ aria-hidden="true"
123
86
  >
124
- { Icon && <Icon width="1.2em" height="1.2em" /> }
87
+ +
125
88
  </span>
126
89
  ) }
127
90
  </button>
@@ -7,72 +7,50 @@ import clsx from 'clsx';
7
7
  */
8
8
  import {
9
9
  useBlockProps,
10
- __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
11
- __experimentalGetColorClassesAndStyles as getColorClassesAndStyles,
12
10
  __experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
13
- __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
14
11
  RichText,
15
12
  } from '@wordpress/block-editor';
16
- /**
17
- * Internal dependencies
18
- */
19
- import { plus } from '../accordion-content/icons';
20
-
21
- const ICONS = {
22
- plus,
23
- };
24
13
 
25
14
  export default function save( { attributes } ) {
26
15
  const { level, title, iconPosition, textAlign, showIcon } = attributes;
27
16
  const TagName = 'h' + level;
28
17
 
29
- const blockProps = useBlockProps.save();
30
- const borderProps = getBorderClassesAndStyles( attributes );
31
- const colorProps = getColorClassesAndStyles( attributes );
18
+ const blockProps = useBlockProps.save( {
19
+ className: clsx( 'accordion-content__heading', {
20
+ [ `has-text-align-${ textAlign }` ]: textAlign,
21
+ } ),
22
+ } );
32
23
  const spacingProps = getSpacingClassesAndStyles( attributes );
33
- const shadowProps = getShadowClassesAndStyles( attributes );
34
-
35
- const Icon = ICONS.plus;
36
24
 
37
25
  return (
38
- <TagName
39
- { ...blockProps }
40
- className={ clsx(
41
- blockProps.className,
42
- colorProps.className,
43
- borderProps.className,
44
- 'accordion-content__heading',
45
- {
46
- [ `has-custom-font-size` ]: blockProps?.style?.fontSize,
47
- [ `icon-position-left` ]: iconPosition === 'left',
48
- [ `has-text-align-${ textAlign }` ]: textAlign,
49
- }
50
- ) }
51
- style={ {
52
- ...borderProps.style,
53
- ...colorProps.style,
54
- ...shadowProps.style,
55
- } }
56
- >
26
+ <TagName { ...blockProps }>
57
27
  <button
58
28
  className={ clsx( 'accordion-content__toggle' ) }
59
29
  style={ {
60
30
  ...spacingProps.style,
61
31
  } }
62
32
  >
63
- <RichText.Content tagName="span" value={ title } />
64
- <span
65
- className={ clsx( `accordion-content__toggle-icon`, {
66
- 'has-icon-plus': showIcon,
67
- } ) }
68
- style={ {
69
- // TO-DO: make this configurable
70
- width: `1.2em`,
71
- height: `1.2em`,
72
- } }
73
- >
74
- { showIcon && <Icon width="1.2em" height="1.2em" /> }
75
- </span>
33
+ { showIcon && iconPosition === 'left' && (
34
+ <span
35
+ className="accordion-content__toggle-icon"
36
+ aria-hidden="true"
37
+ >
38
+ +
39
+ </span>
40
+ ) }
41
+ <RichText.Content
42
+ className="accordion-content__toggle-title"
43
+ tagName="span"
44
+ value={ title }
45
+ />
46
+ { showIcon && iconPosition === 'right' && (
47
+ <span
48
+ className="accordion-content__toggle-icon"
49
+ aria-hidden="true"
50
+ >
51
+ +
52
+ </span>
53
+ ) }
76
54
  </button>
77
55
  </TagName>
78
56
  );
@@ -10,12 +10,11 @@
10
10
  "supports": {
11
11
  "color": {
12
12
  "background": true,
13
- "gradient": true
13
+ "gradients": true
14
14
  },
15
15
  "interactivity": true,
16
16
  "spacing": {
17
17
  "padding": true,
18
- "margin": [ "top", "bottom" ],
19
18
  "blockGap": true,
20
19
  "__experimentalDefaultControls": {
21
20
  "padding": true,
@@ -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',
@@ -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"
@@ -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"
@@ -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
  ) }
@@ -11,6 +11,14 @@
11
11
  "attributes": {
12
12
  "textAlign": {
13
13
  "type": "string"
14
+ },
15
+ "displayAsRange": {
16
+ "type": "boolean",
17
+ "default": true
18
+ },
19
+ "averageReadingSpeed": {
20
+ "type": "number",
21
+ "default": 189
14
22
  }
15
23
  },
16
24
  "supports": {
@@ -6,27 +6,32 @@ 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 { textAlign, displayAsRange, averageReadingSpeed } = attributes;
29
33
  const { postId, postType } = context;
34
+ const dropdownMenuProps = useToolsPanelDropdownMenuProps();
30
35
 
31
36
  const [ contentStructure ] = useEntityProp(
32
37
  'postType',
@@ -63,11 +68,31 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
63
68
  'Word count type. Do not translate!'
64
69
  );
65
70
 
71
+ const totalWords = wordCount( content || '', wordCountType );
72
+ if ( displayAsRange ) {
73
+ let maxMinutes = Math.max(
74
+ 1,
75
+ Math.round( ( totalWords / averageReadingSpeed ) * 1.2 )
76
+ );
77
+ const minMinutes = Math.max(
78
+ 1,
79
+ Math.round( ( totalWords / averageReadingSpeed ) * 0.8 )
80
+ );
81
+
82
+ if ( minMinutes === maxMinutes ) {
83
+ maxMinutes = maxMinutes + 1;
84
+ }
85
+ // translators: %1$s: minimum minutes, %2$s: maximum minutes to read the post.
86
+ const rangeLabel = _x(
87
+ '%1$s–%2$s minutes',
88
+ 'Range of minutes to read'
89
+ );
90
+ return sprintf( rangeLabel, minMinutes, maxMinutes );
91
+ }
92
+
66
93
  const minutesToRead = Math.max(
67
94
  1,
68
- Math.round(
69
- wordCount( content || '', wordCountType ) / AVERAGE_READING_RATE
70
- )
95
+ Math.round( totalWords / averageReadingSpeed )
71
96
  );
72
97
 
73
98
  return sprintf(
@@ -75,7 +100,7 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
75
100
  _n( '%s minute', '%s minutes', minutesToRead ),
76
101
  minutesToRead
77
102
  );
78
- }, [ contentStructure, blocks ] );
103
+ }, [ contentStructure, blocks, displayAsRange, averageReadingSpeed ] );
79
104
 
80
105
  const blockProps = useBlockProps( {
81
106
  className: clsx( {
@@ -93,6 +118,42 @@ function PostTimeToReadEdit( { attributes, setAttributes, context } ) {
93
118
  } }
94
119
  />
95
120
  </BlockControls>
121
+ <InspectorControls>
122
+ <ToolsPanel
123
+ label={ __( 'Settings' ) }
124
+ resetAll={ () => {
125
+ setAttributes( {
126
+ displayAsRange: true,
127
+ } );
128
+ } }
129
+ dropdownMenuProps={ dropdownMenuProps }
130
+ >
131
+ <ToolsPanelItem
132
+ isShownByDefault
133
+ label={ _x(
134
+ 'Display as range',
135
+ 'Turns reading time range display on or off'
136
+ ) }
137
+ hasValue={ () => ! displayAsRange }
138
+ onDeselect={ () => {
139
+ setAttributes( {
140
+ displayAsRange: true,
141
+ } );
142
+ } }
143
+ >
144
+ <ToggleControl
145
+ __nextHasNoMarginBottom
146
+ label={ __( 'Display as range' ) }
147
+ checked={ !! displayAsRange }
148
+ onChange={ () =>
149
+ setAttributes( {
150
+ displayAsRange: ! displayAsRange,
151
+ } )
152
+ }
153
+ />
154
+ </ToolsPanelItem>
155
+ </ToolsPanel>
156
+ </InspectorControls>
96
157
  <div { ...blockProps }>{ minutesToReadString }</div>
97
158
  </>
98
159
  );
@@ -18,24 +18,34 @@ 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
+ $word_count_type = wp_get_word_count_type();
24
+ $total_words = wp_word_count( $content, $word_count_type );
22
25
 
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;
29
-
30
- $word_count_type = wp_get_word_count_type();
31
-
32
- $minutes_to_read = max( 1, (int) round( wp_word_count( $content, $word_count_type ) / $average_reading_rate ) );
33
-
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
- );
26
+ if ( ! empty( $attributes['displayAsRange'] ) ) {
27
+ // Calculate faster reading rate with 20% speed = lower minutes,
28
+ // and slower reading rate with 20% speed = higher minutes.
29
+ $min_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 0.8 ) );
30
+ $max_minutes = max( 1, (int) round( $total_words / $average_reading_rate * 1.2 ) );
31
+ if ( $min_minutes === $max_minutes ) {
32
+ $max_minutes = $min_minutes + 1;
33
+ }
34
+ /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */
35
+ $minutes_to_read_string = sprintf(
36
+ /* translators: 1: minimum minutes, 2: maximum minutes to read the post. */
37
+ _x( '%1$s–%2$s minutes', 'Range of minutes to read' ),
38
+ $min_minutes,
39
+ $max_minutes
40
+ );
41
+ } else {
42
+ $minutes_to_read = max( 1, (int) round( $total_words / $average_reading_rate ) );
43
+ $minutes_to_read_string = sprintf(
44
+ /* translators: %s: the number of minutes to read the post. */
45
+ _n( '%s minute', '%s minutes', $minutes_to_read ),
46
+ $minutes_to_read
47
+ );
48
+ }
39
49
 
40
50
  $align_class_name = empty( $attributes['textAlign'] ) ? '' : "has-text-align-{$attributes['textAlign']}";
41
51
 
@@ -48,6 +58,7 @@ function render_block_core_post_time_to_read( $attributes, $content, $block ) {
48
58
  );
49
59
  }
50
60
 
61
+
51
62
  /**
52
63
  * Registers the `core/post-time-to-read` block on the server.
53
64
  */
@@ -59,4 +70,5 @@ function register_block_core_post_time_to_read() {
59
70
  )
60
71
  );
61
72
  }
73
+
62
74
  add_action( 'init', 'register_block_core_post_time_to_read' );
@@ -6,6 +6,7 @@
6
6
  "category": "theme",
7
7
  "description": "Display the description of categories, tags and custom taxonomies when viewing an archive.",
8
8
  "textdomain": "default",
9
+ "usesContext": [ "termId", "taxonomy" ],
9
10
  "attributes": {
10
11
  "textAlign": {
11
12
  "type": "string"
@@ -13,18 +13,27 @@ import {
13
13
  AlignmentControl,
14
14
  } from '@wordpress/block-editor';
15
15
 
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import { useTermDescription } from './use-term-description';
20
+
16
21
  export default function TermDescriptionEdit( {
17
22
  attributes,
18
23
  setAttributes,
19
24
  mergedStyle,
25
+ context: { termId, taxonomy },
20
26
  } ) {
21
27
  const { textAlign } = attributes;
28
+ const { termDescription } = useTermDescription( termId, taxonomy );
29
+
22
30
  const blockProps = useBlockProps( {
23
31
  className: clsx( {
24
32
  [ `has-text-align-${ textAlign }` ]: textAlign,
25
33
  } ),
26
34
  style: mergedStyle,
27
35
  } );
36
+
28
37
  return (
29
38
  <>
30
39
  <BlockControls group="block">
@@ -36,9 +45,15 @@ export default function TermDescriptionEdit( {
36
45
  />
37
46
  </BlockControls>
38
47
  <div { ...blockProps }>
39
- <div className="wp-block-term-description__placeholder">
40
- <span>{ __( 'Term Description' ) }</span>
41
- </div>
48
+ { termDescription ? (
49
+ <div
50
+ dangerouslySetInnerHTML={ { __html: termDescription } }
51
+ />
52
+ ) : (
53
+ <div className="wp-block-term-description__placeholder">
54
+ <span>{ __( 'Term Description' ) }</span>
55
+ </div>
56
+ ) }
42
57
  </div>
43
58
  </>
44
59
  );