@wordpress/editor 11.0.1 → 12.0.2

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 (241) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +1 -1
  3. package/build/components/autosave-monitor/index.js +5 -0
  4. package/build/components/autosave-monitor/index.js.map +1 -1
  5. package/build/components/character-count/index.js +1 -1
  6. package/build/components/character-count/index.js.map +1 -1
  7. package/build/components/editor-help/add-blocks.native.js +6 -5
  8. package/build/components/editor-help/add-blocks.native.js.map +1 -1
  9. package/build/components/editor-help/customize-blocks.native.js +7 -6
  10. package/build/components/editor-help/customize-blocks.native.js.map +1 -1
  11. package/build/components/editor-help/help-detail-navigation-screen.native.js +29 -15
  12. package/build/components/editor-help/help-detail-navigation-screen.native.js.map +1 -1
  13. package/build/components/editor-help/help-get-support-button.native.js +46 -0
  14. package/build/components/editor-help/help-get-support-button.native.js.map +1 -0
  15. package/build/components/editor-help/help-topic-row.native.js +3 -2
  16. package/build/components/editor-help/help-topic-row.native.js.map +1 -1
  17. package/build/components/editor-help/index.native.js +87 -26
  18. package/build/components/editor-help/index.native.js.map +1 -1
  19. package/build/components/editor-help/intro-to-blocks.native.js +19 -9
  20. package/build/components/editor-help/intro-to-blocks.native.js.map +1 -1
  21. package/build/components/editor-help/move-blocks.native.js +6 -5
  22. package/build/components/editor-help/move-blocks.native.js.map +1 -1
  23. package/build/components/editor-help/remove-blocks.native.js +6 -5
  24. package/build/components/editor-help/remove-blocks.native.js.map +1 -1
  25. package/build/components/editor-help/view-sections.native.js +23 -5
  26. package/build/components/editor-help/view-sections.native.js.map +1 -1
  27. package/build/components/entities-saved-states/entity-type-list.js +22 -13
  28. package/build/components/entities-saved-states/entity-type-list.js.map +1 -1
  29. package/build/components/entities-saved-states/index.js +23 -4
  30. package/build/components/entities-saved-states/index.js.map +1 -1
  31. package/build/components/global-keyboard-shortcuts/save-shortcut.js +12 -14
  32. package/build/components/global-keyboard-shortcuts/save-shortcut.js.map +1 -1
  33. package/build/components/global-keyboard-shortcuts/visual-editor-shortcuts.js +0 -4
  34. package/build/components/global-keyboard-shortcuts/visual-editor-shortcuts.js.map +1 -1
  35. package/build/components/index.js +9 -0
  36. package/build/components/index.js.map +1 -1
  37. package/build/components/local-autosave-monitor/index.js +1 -2
  38. package/build/components/local-autosave-monitor/index.js.map +1 -1
  39. package/build/components/post-format/index.js +3 -1
  40. package/build/components/post-format/index.js.map +1 -1
  41. package/build/components/post-locked-modal/index.js +1 -1
  42. package/build/components/post-locked-modal/index.js.map +1 -1
  43. package/build/components/post-saved-state/index.js +37 -46
  44. package/build/components/post-saved-state/index.js.map +1 -1
  45. package/build/components/post-taxonomies/flat-term-selector.js +154 -211
  46. package/build/components/post-taxonomies/flat-term-selector.js.map +1 -1
  47. package/build/components/post-title/index.js +53 -25
  48. package/build/components/post-title/index.js.map +1 -1
  49. package/build/components/provider/index.native.js +18 -7
  50. package/build/components/provider/index.native.js.map +1 -1
  51. package/build/components/provider/use-block-editor-settings.js +32 -5
  52. package/build/components/provider/use-block-editor-settings.js.map +1 -1
  53. package/build/components/word-count/index.js +1 -1
  54. package/build/components/word-count/index.js.map +1 -1
  55. package/build/store/actions.js +13 -38
  56. package/build/store/actions.js.map +1 -1
  57. package/build/store/defaults.js +7 -2
  58. package/build/store/defaults.js.map +1 -1
  59. package/build/store/selectors.js +4 -93
  60. package/build/store/selectors.js.map +1 -1
  61. package/build/store/utils/notice-builder.js +15 -18
  62. package/build/store/utils/notice-builder.js.map +1 -1
  63. package/build/{store/utils → utils}/get-template-part-icon.js +1 -1
  64. package/build/utils/get-template-part-icon.js.map +1 -0
  65. package/build/utils/index.js +8 -0
  66. package/build/utils/index.js.map +1 -1
  67. package/build-module/components/autosave-monitor/index.js +5 -0
  68. package/build-module/components/autosave-monitor/index.js.map +1 -1
  69. package/build-module/components/character-count/index.js +1 -1
  70. package/build-module/components/character-count/index.js.map +1 -1
  71. package/build-module/components/editor-help/add-blocks.native.js +7 -6
  72. package/build-module/components/editor-help/add-blocks.native.js.map +1 -1
  73. package/build-module/components/editor-help/customize-blocks.native.js +8 -7
  74. package/build-module/components/editor-help/customize-blocks.native.js.map +1 -1
  75. package/build-module/components/editor-help/help-detail-navigation-screen.native.js +31 -18
  76. package/build-module/components/editor-help/help-detail-navigation-screen.native.js.map +1 -1
  77. package/build-module/components/editor-help/help-get-support-button.native.js +34 -0
  78. package/build-module/components/editor-help/help-get-support-button.native.js.map +1 -0
  79. package/build-module/components/editor-help/help-topic-row.native.js +3 -2
  80. package/build-module/components/editor-help/help-topic-row.native.js.map +1 -1
  81. package/build-module/components/editor-help/index.native.js +81 -28
  82. package/build-module/components/editor-help/index.native.js.map +1 -1
  83. package/build-module/components/editor-help/intro-to-blocks.native.js +19 -10
  84. package/build-module/components/editor-help/intro-to-blocks.native.js.map +1 -1
  85. package/build-module/components/editor-help/move-blocks.native.js +7 -6
  86. package/build-module/components/editor-help/move-blocks.native.js.map +1 -1
  87. package/build-module/components/editor-help/remove-blocks.native.js +7 -6
  88. package/build-module/components/editor-help/remove-blocks.native.js.map +1 -1
  89. package/build-module/components/editor-help/view-sections.native.js +22 -5
  90. package/build-module/components/editor-help/view-sections.native.js.map +1 -1
  91. package/build-module/components/entities-saved-states/entity-type-list.js +24 -13
  92. package/build-module/components/entities-saved-states/entity-type-list.js.map +1 -1
  93. package/build-module/components/entities-saved-states/index.js +23 -4
  94. package/build-module/components/entities-saved-states/index.js.map +1 -1
  95. package/build-module/components/global-keyboard-shortcuts/save-shortcut.js +12 -14
  96. package/build-module/components/global-keyboard-shortcuts/save-shortcut.js.map +1 -1
  97. package/build-module/components/global-keyboard-shortcuts/visual-editor-shortcuts.js +0 -4
  98. package/build-module/components/global-keyboard-shortcuts/visual-editor-shortcuts.js.map +1 -1
  99. package/build-module/components/index.js +1 -0
  100. package/build-module/components/index.js.map +1 -1
  101. package/build-module/components/local-autosave-monitor/index.js +1 -2
  102. package/build-module/components/local-autosave-monitor/index.js.map +1 -1
  103. package/build-module/components/post-format/index.js +4 -2
  104. package/build-module/components/post-format/index.js.map +1 -1
  105. package/build-module/components/post-locked-modal/index.js +1 -1
  106. package/build-module/components/post-locked-modal/index.js.map +1 -1
  107. package/build-module/components/post-saved-state/index.js +38 -46
  108. package/build-module/components/post-saved-state/index.js.map +1 -1
  109. package/build-module/components/post-taxonomies/flat-term-selector.js +156 -214
  110. package/build-module/components/post-taxonomies/flat-term-selector.js.map +1 -1
  111. package/build-module/components/post-title/index.js +53 -22
  112. package/build-module/components/post-title/index.js.map +1 -1
  113. package/build-module/components/provider/index.native.js +18 -7
  114. package/build-module/components/provider/index.native.js.map +1 -1
  115. package/build-module/components/provider/use-block-editor-settings.js +31 -5
  116. package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
  117. package/build-module/components/word-count/index.js +1 -1
  118. package/build-module/components/word-count/index.js.map +1 -1
  119. package/build-module/store/actions.js +13 -36
  120. package/build-module/store/actions.js.map +1 -1
  121. package/build-module/store/defaults.js +7 -2
  122. package/build-module/store/defaults.js.map +1 -1
  123. package/build-module/store/selectors.js +3 -85
  124. package/build-module/store/selectors.js.map +1 -1
  125. package/build-module/store/utils/notice-builder.js +15 -18
  126. package/build-module/store/utils/notice-builder.js.map +1 -1
  127. package/build-module/{store/utils → utils}/get-template-part-icon.js +2 -2
  128. package/build-module/utils/get-template-part-icon.js.map +1 -0
  129. package/build-module/utils/index.js +1 -0
  130. package/build-module/utils/index.js.map +1 -1
  131. package/build-style/style-rtl.css +9 -60
  132. package/build-style/style.css +9 -60
  133. package/package.json +28 -28
  134. package/src/components/autosave-monitor/index.js +5 -0
  135. package/src/components/autosave-monitor/test/index.js +10 -4
  136. package/src/components/character-count/index.js +3 -2
  137. package/src/components/editor-help/add-blocks.native.js +17 -12
  138. package/src/components/editor-help/customize-blocks.native.js +16 -13
  139. package/src/components/editor-help/help-detail-navigation-screen.native.js +45 -15
  140. package/src/components/editor-help/help-get-support-button.native.js +38 -0
  141. package/src/components/editor-help/help-topic-row.native.js +2 -2
  142. package/src/components/editor-help/images/add-dark.png +0 -0
  143. package/src/components/editor-help/images/add-dark@2x.png +0 -0
  144. package/src/components/editor-help/images/add-dark@3x.png +0 -0
  145. package/src/components/editor-help/images/add-light.png +0 -0
  146. package/src/components/editor-help/images/add-light@2x.png +0 -0
  147. package/src/components/editor-help/images/add-light@3x.png +0 -0
  148. package/src/components/editor-help/images/block-layout-collage.png +0 -0
  149. package/src/components/editor-help/images/block-layout-collage@2x.png +0 -0
  150. package/src/components/editor-help/images/block-layout-collage@3x.png +0 -0
  151. package/src/components/editor-help/images/build-layouts-dark.png +0 -0
  152. package/src/components/editor-help/images/build-layouts-dark@2x.png +0 -0
  153. package/src/components/editor-help/images/build-layouts-dark@3x.png +0 -0
  154. package/src/components/editor-help/images/build-layouts-light.png +0 -0
  155. package/src/components/editor-help/images/build-layouts-light@2x.png +0 -0
  156. package/src/components/editor-help/images/build-layouts-light@3x.png +0 -0
  157. package/src/components/editor-help/images/edit-media-dark.png +0 -0
  158. package/src/components/editor-help/images/edit-media-dark@2x.png +0 -0
  159. package/src/components/editor-help/images/edit-media-dark@3x.png +0 -0
  160. package/src/components/editor-help/images/edit-media-light.png +0 -0
  161. package/src/components/editor-help/images/edit-media-light@2x.png +0 -0
  162. package/src/components/editor-help/images/edit-media-light@3x.png +0 -0
  163. package/src/components/editor-help/images/embed-media-dark.png +0 -0
  164. package/src/components/editor-help/images/embed-media-dark@2x.png +0 -0
  165. package/src/components/editor-help/images/embed-media-dark@3x.png +0 -0
  166. package/src/components/editor-help/images/embed-media-light.png +0 -0
  167. package/src/components/editor-help/images/embed-media-light@2x.png +0 -0
  168. package/src/components/editor-help/images/embed-media-light@3x.png +0 -0
  169. package/src/components/editor-help/images/move-dark.png +0 -0
  170. package/src/components/editor-help/images/move-dark@2x.png +0 -0
  171. package/src/components/editor-help/images/move-dark@3x.png +0 -0
  172. package/src/components/editor-help/images/move-light.png +0 -0
  173. package/src/components/editor-help/images/move-light@2x.png +0 -0
  174. package/src/components/editor-help/images/move-light@3x.png +0 -0
  175. package/src/components/editor-help/images/options-dark.png +0 -0
  176. package/src/components/editor-help/images/options-dark@2x.png +0 -0
  177. package/src/components/editor-help/images/options-dark@3x.png +0 -0
  178. package/src/components/editor-help/images/options-light.png +0 -0
  179. package/src/components/editor-help/images/options-light@2x.png +0 -0
  180. package/src/components/editor-help/images/options-light@3x.png +0 -0
  181. package/src/components/editor-help/images/rich-text-dark.png +0 -0
  182. package/src/components/editor-help/images/rich-text-dark@2x.png +0 -0
  183. package/src/components/editor-help/images/rich-text-dark@3x.png +0 -0
  184. package/src/components/editor-help/images/rich-text-light.png +0 -0
  185. package/src/components/editor-help/images/rich-text-light@2x.png +0 -0
  186. package/src/components/editor-help/images/rich-text-light@3x.png +0 -0
  187. package/src/components/editor-help/images/settings-dark.png +0 -0
  188. package/src/components/editor-help/images/settings-dark@2x.png +0 -0
  189. package/src/components/editor-help/images/settings-dark@3x.png +0 -0
  190. package/src/components/editor-help/images/settings-light.png +0 -0
  191. package/src/components/editor-help/images/settings-light@2x.png +0 -0
  192. package/src/components/editor-help/images/settings-light@3x.png +0 -0
  193. package/src/components/editor-help/index.native.js +147 -43
  194. package/src/components/editor-help/intro-to-blocks.native.js +63 -43
  195. package/src/components/editor-help/move-blocks.native.js +12 -7
  196. package/src/components/editor-help/remove-blocks.native.js +11 -8
  197. package/src/components/editor-help/style.android.scss +6 -0
  198. package/src/components/editor-help/style.ios.scss +6 -0
  199. package/src/components/editor-help/style.scss +49 -32
  200. package/src/components/editor-help/test/index.native.js +80 -0
  201. package/src/components/editor-help/view-sections.native.js +47 -4
  202. package/src/components/entities-saved-states/entity-type-list.js +29 -10
  203. package/src/components/entities-saved-states/index.js +38 -8
  204. package/src/components/global-keyboard-shortcuts/save-shortcut.js +34 -42
  205. package/src/components/global-keyboard-shortcuts/visual-editor-shortcuts.js +8 -16
  206. package/src/components/index.js +1 -0
  207. package/src/components/local-autosave-monitor/index.js +1 -3
  208. package/src/components/post-format/index.js +6 -2
  209. package/src/components/post-format/style.scss +1 -0
  210. package/src/components/post-locked-modal/index.js +1 -1
  211. package/src/components/post-saved-state/index.js +41 -55
  212. package/src/components/post-saved-state/style.scss +10 -1
  213. package/src/components/post-saved-state/test/__snapshots__/index.js.snap +20 -0
  214. package/src/components/post-saved-state/test/index.js +2 -2
  215. package/src/components/post-taxonomies/flat-term-selector.js +220 -254
  216. package/src/components/post-title/index.js +47 -30
  217. package/src/components/post-title/style.scss +1 -70
  218. package/src/components/provider/index.native.js +17 -5
  219. package/src/components/provider/use-block-editor-settings.js +25 -2
  220. package/src/components/word-count/index.js +3 -2
  221. package/src/store/actions.js +13 -41
  222. package/src/store/defaults.js +7 -2
  223. package/src/store/selectors.js +2 -112
  224. package/src/store/test/actions.js +4 -2
  225. package/src/store/utils/notice-builder.js +17 -19
  226. package/src/store/utils/test/notice-builder.js +1 -1
  227. package/src/{store/utils → utils}/get-template-part-icon.js +2 -2
  228. package/src/utils/index.js +1 -0
  229. package/build/store/utils/get-template-part-icon.js.map +0 -1
  230. package/build-module/store/utils/get-template-part-icon.js.map +0 -1
  231. package/src/components/editor-help/images/add-blocks.png +0 -0
  232. package/src/components/editor-help/images/customize-blocks.png +0 -0
  233. package/src/components/editor-help/images/cut-copy-duplicate-blocks.png +0 -0
  234. package/src/components/editor-help/images/edit-or-replace-media.png +0 -0
  235. package/src/components/editor-help/images/intro-blocks-1.png +0 -0
  236. package/src/components/editor-help/images/intro-blocks-2.png +0 -0
  237. package/src/components/editor-help/images/intro-blocks-3.png +0 -0
  238. package/src/components/editor-help/images/intro-blocks-4.png +0 -0
  239. package/src/components/editor-help/images/move-blocks.png +0 -0
  240. package/src/components/editor-help/images/remove-blocks.png +0 -0
  241. package/src/components/editor-help/images/what-is-a-block.png +0 -0
@@ -3,19 +3,20 @@ import { createElement, Fragment } from "@wordpress/element";
3
3
  /**
4
4
  * External dependencies
5
5
  */
6
- import { debounce, escape as escapeString, find, get, invoke, isEmpty, uniqBy } from 'lodash';
6
+ import { escape as escapeString, find, get, uniqBy } from 'lodash';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
10
 
11
11
  import { __, _x, sprintf } from '@wordpress/i18n';
12
- import { Component } from '@wordpress/element';
13
- import { FormTokenField, withFilters, withSpokenMessages } from '@wordpress/components';
14
- import { withSelect, withDispatch } from '@wordpress/data';
12
+ import { useEffect, useMemo, useState } from '@wordpress/element';
13
+ import { FormTokenField, withFilters } from '@wordpress/components';
14
+ import { useSelect, useDispatch } from '@wordpress/data';
15
15
  import { store as coreStore } from '@wordpress/core-data';
16
- import { compose } from '@wordpress/compose';
16
+ import { useDebounce } from '@wordpress/compose';
17
17
  import apiFetch from '@wordpress/api-fetch';
18
18
  import { addQueryArgs } from '@wordpress/url';
19
+ import { speak } from '@wordpress/a11y';
19
20
  /**
20
21
  * Internal dependencies
21
22
  */
@@ -23,6 +24,14 @@ import { addQueryArgs } from '@wordpress/url';
23
24
  import { store as editorStore } from '../../store';
24
25
  import { unescapeString, unescapeTerm, unescapeTerms } from '../../utils/terms';
25
26
  import MostUsedTerms from './most-used-terms';
27
+ /**
28
+ * Shared reference to an empty array for cases where it is important to avoid
29
+ * returning a new array reference on every invocation.
30
+ *
31
+ * @type {Array<any>}
32
+ */
33
+
34
+ const EMPTY_ARRAY = [];
26
35
  /**
27
36
  * Module constants
28
37
  */
@@ -32,254 +41,187 @@ const DEFAULT_QUERY = {
32
41
  per_page: MAX_TERMS_SUGGESTIONS,
33
42
  orderby: 'count',
34
43
  order: 'desc',
35
- _fields: 'id,name,count'
44
+ _fields: 'id,name',
45
+ context: 'view'
36
46
  };
37
47
 
38
48
  const isSameTermName = (termA, termB) => unescapeString(termA).toLowerCase() === unescapeString(termB).toLowerCase();
39
49
 
40
50
  const termNamesToIds = (names, terms) => {
41
51
  return names.map(termName => find(terms, term => isSameTermName(term.name, termName)).id);
42
- };
52
+ }; // Tries to create a term or fetch it if it already exists.
43
53
 
44
- class FlatTermSelector extends Component {
45
- constructor() {
46
- super(...arguments);
47
- this.onChange = this.onChange.bind(this);
48
- this.searchTerms = debounce(this.searchTerms.bind(this), 500);
49
- this.findOrCreateTerm = this.findOrCreateTerm.bind(this);
50
- this.appendTerm = this.appendTerm.bind(this);
51
- this.state = {
52
- loading: !isEmpty(this.props.terms),
53
- availableTerms: [],
54
- selectedTerms: []
55
- };
56
- }
57
-
58
- componentDidMount() {
59
- if (!isEmpty(this.props.terms)) {
60
- this.initRequest = this.fetchTerms({
61
- include: this.props.terms.join(','),
62
- per_page: -1
63
- });
64
- this.initRequest.then(() => {
65
- this.setState({
66
- loading: false
67
- });
68
- }, xhr => {
69
- if (xhr.statusText === 'abort') {
70
- return;
71
- }
72
54
 
73
- this.setState({
74
- loading: false
75
- });
55
+ function findOrCreateTerm(termName, restBase) {
56
+ const escapedTermName = escapeString(termName);
57
+ return apiFetch({
58
+ path: `/wp/v2/${restBase}`,
59
+ method: 'POST',
60
+ data: {
61
+ name: escapedTermName
62
+ }
63
+ }).catch(error => {
64
+ const errorCode = error.code;
65
+
66
+ if (errorCode === 'term_exists') {
67
+ // If the terms exist, fetch it instead of creating a new one.
68
+ const addRequest = apiFetch({
69
+ path: addQueryArgs(`/wp/v2/${restBase}`, { ...DEFAULT_QUERY,
70
+ search: escapedTermName
71
+ })
72
+ }).then(unescapeTerms);
73
+ return addRequest.then(searchResult => {
74
+ return find(searchResult, result => isSameTermName(result.name, termName));
76
75
  });
77
76
  }
78
- }
79
-
80
- componentWillUnmount() {
81
- invoke(this.initRequest, ['abort']);
82
- invoke(this.searchRequest, ['abort']);
83
- }
84
77
 
85
- componentDidUpdate(prevProps) {
86
- if (prevProps.terms !== this.props.terms) {
87
- this.updateSelectedTerms(this.props.terms);
88
- }
89
- }
78
+ return Promise.reject(error);
79
+ }).then(unescapeTerm);
80
+ }
90
81
 
91
- fetchTerms(params = {}) {
82
+ function FlatTermSelector({
83
+ slug
84
+ }) {
85
+ const [values, setValues] = useState([]);
86
+ const [search, setSearch] = useState('');
87
+ const debouncedSearch = useDebounce(setSearch, 500);
88
+ const {
89
+ terms,
90
+ termIds,
91
+ taxonomy,
92
+ hasAssignAction,
93
+ hasCreateAction,
94
+ hasResolvedTerms
95
+ } = useSelect(select => {
92
96
  const {
93
- taxonomy
94
- } = this.props;
95
- const query = { ...DEFAULT_QUERY,
96
- ...params
97
- };
98
- const request = apiFetch({
99
- path: addQueryArgs(`/wp/v2/${taxonomy.rest_base}`, query)
100
- });
101
- request.then(unescapeTerms).then(terms => {
102
- this.setState(state => ({
103
- availableTerms: state.availableTerms.concat(terms.filter(term => !find(state.availableTerms, availableTerm => availableTerm.id === term.id)))
104
- }));
105
- this.updateSelectedTerms(this.props.terms);
106
- });
107
- return request;
108
- }
109
-
110
- updateSelectedTerms(terms = []) {
111
- const selectedTerms = terms.reduce((accumulator, termId) => {
112
- const termObject = find(this.state.availableTerms, term => term.id === termId);
97
+ getCurrentPost,
98
+ getEditedPostAttribute
99
+ } = select(editorStore);
100
+ const {
101
+ getEntityRecords,
102
+ getTaxonomy,
103
+ hasFinishedResolution
104
+ } = select(coreStore);
105
+ const post = getCurrentPost();
113
106
 
114
- if (termObject) {
115
- accumulator.push(termObject.name);
116
- }
107
+ const _taxonomy = getTaxonomy(slug);
117
108
 
118
- return accumulator;
119
- }, []);
120
- this.setState({
121
- selectedTerms
122
- });
123
- }
109
+ const _termIds = _taxonomy ? getEditedPostAttribute(_taxonomy.rest_base) : EMPTY_ARRAY;
124
110
 
125
- findOrCreateTerm(termName) {
111
+ const query = { ...DEFAULT_QUERY,
112
+ include: _termIds.join(','),
113
+ per_page: -1
114
+ };
115
+ return {
116
+ hasCreateAction: _taxonomy ? get(post, ['_links', 'wp:action-create-' + _taxonomy.rest_base], false) : false,
117
+ hasAssignAction: _taxonomy ? get(post, ['_links', 'wp:action-assign-' + _taxonomy.rest_base], false) : false,
118
+ taxonomy: _taxonomy,
119
+ termIds: _termIds,
120
+ terms: _termIds.length ? getEntityRecords('taxonomy', slug, query) : EMPTY_ARRAY,
121
+ hasResolvedTerms: hasFinishedResolution('getEntityRecords', ['taxonomy', slug, query])
122
+ };
123
+ }, [slug]);
124
+ const {
125
+ searchResults
126
+ } = useSelect(select => {
126
127
  const {
127
- taxonomy
128
- } = this.props;
129
- const termNameEscaped = escapeString(termName); // Tries to create a term or fetch it if it already exists.
130
-
131
- return apiFetch({
132
- path: `/wp/v2/${taxonomy.rest_base}`,
133
- method: 'POST',
134
- data: {
135
- name: termNameEscaped
136
- }
137
- }).catch(error => {
138
- const errorCode = error.code;
128
+ getEntityRecords
129
+ } = select(coreStore);
130
+ return {
131
+ searchResults: !!search ? getEntityRecords('taxonomy', slug, { ...DEFAULT_QUERY,
132
+ search
133
+ }) : EMPTY_ARRAY
134
+ };
135
+ }, [search]); // Update terms state only after the selectors are resolved.
136
+ // We're using this to avoid terms temporarily disappearing on slow networks
137
+ // while core data makes REST API requests.
138
+
139
+ useEffect(() => {
140
+ if (hasResolvedTerms) {
141
+ const newValues = terms.map(term => unescapeString(term.name));
142
+ setValues(newValues);
143
+ }
144
+ }, [terms, hasResolvedTerms]);
145
+ const suggestions = useMemo(() => {
146
+ return (searchResults !== null && searchResults !== void 0 ? searchResults : []).map(term => unescapeString(term.name));
147
+ }, [searchResults]);
148
+ const {
149
+ editPost
150
+ } = useDispatch(editorStore);
139
151
 
140
- if (errorCode === 'term_exists') {
141
- // If the terms exist, fetch it instead of creating a new one.
142
- this.addRequest = apiFetch({
143
- path: addQueryArgs(`/wp/v2/${taxonomy.rest_base}`, { ...DEFAULT_QUERY,
144
- search: termNameEscaped
145
- })
146
- }).then(unescapeTerms);
147
- return this.addRequest.then(searchResult => {
148
- return find(searchResult, result => isSameTermName(result.name, termName));
149
- });
150
- }
152
+ if (!hasAssignAction) {
153
+ return null;
154
+ }
151
155
 
152
- return Promise.reject(error);
153
- }).then(unescapeTerm);
156
+ function onUpdateTerms(newTermIds) {
157
+ editPost({
158
+ [taxonomy.rest_base]: newTermIds
159
+ });
154
160
  }
155
161
 
156
- onChange(termNames) {
162
+ function onChange(termNames) {
163
+ const availableTerms = [...terms, ...(searchResults !== null && searchResults !== void 0 ? searchResults : [])];
157
164
  const uniqueTerms = uniqBy(termNames, term => term.toLowerCase());
158
- this.setState({
159
- selectedTerms: uniqueTerms
160
- });
161
- const newTermNames = uniqueTerms.filter(termName => !find(this.state.availableTerms, term => isSameTermName(term.name, termName)));
165
+ const newTermNames = uniqueTerms.filter(termName => !find(availableTerms, term => isSameTermName(term.name, termName))); // Optimistically update term values.
166
+ // The selector will always re-fetch terms later.
167
+
168
+ setValues(uniqueTerms);
162
169
 
163
170
  if (newTermNames.length === 0) {
164
- return this.props.onUpdateTerms(termNamesToIds(uniqueTerms, this.state.availableTerms), this.props.taxonomy.rest_base);
171
+ return onUpdateTerms(termNamesToIds(uniqueTerms, availableTerms));
165
172
  }
166
173
 
167
- Promise.all(newTermNames.map(this.findOrCreateTerm)).then(newTerms => {
168
- const newAvailableTerms = this.state.availableTerms.concat(newTerms);
169
- this.setState({
170
- availableTerms: newAvailableTerms
171
- });
172
- return this.props.onUpdateTerms(termNamesToIds(uniqueTerms, newAvailableTerms), this.props.taxonomy.rest_base);
173
- });
174
- }
175
-
176
- searchTerms(search = '') {
177
- invoke(this.searchRequest, ['abort']);
178
-
179
- if (search.length >= 3) {
180
- this.searchRequest = this.fetchTerms({
181
- search
182
- });
174
+ if (!hasCreateAction) {
175
+ return;
183
176
  }
184
- }
185
177
 
186
- appendTerm(newTerm) {
187
- const {
188
- onUpdateTerms,
189
- taxonomy,
190
- terms = [],
191
- slug,
192
- speak
193
- } = this.props;
178
+ Promise.all(newTermNames.map(termName => findOrCreateTerm(termName, taxonomy.rest_base))).then(newTerms => {
179
+ const newAvailableTerms = availableTerms.concat(newTerms);
180
+ return onUpdateTerms(termNamesToIds(uniqueTerms, newAvailableTerms));
181
+ });
182
+ }
194
183
 
195
- if (terms.includes(newTerm.id)) {
184
+ function appendTerm(newTerm) {
185
+ if (termIds.includes(newTerm.id)) {
196
186
  return;
197
187
  }
198
188
 
199
- const newTerms = [...terms, newTerm.id];
189
+ const newTermIds = [...termIds, newTerm.id];
200
190
  const termAddedMessage = sprintf(
201
191
  /* translators: %s: term name. */
202
192
  _x('%s added', 'term'), get(taxonomy, ['labels', 'singular_name'], slug === 'post_tag' ? __('Tag') : __('Term')));
203
193
  speak(termAddedMessage, 'assertive');
204
- this.setState({
205
- availableTerms: [...this.state.availableTerms, newTerm]
206
- });
207
- onUpdateTerms(newTerms, taxonomy.rest_base);
194
+ onUpdateTerms(newTermIds);
208
195
  }
209
196
 
210
- render() {
211
- const {
212
- slug,
213
- taxonomy,
214
- hasAssignAction
215
- } = this.props;
216
-
217
- if (!hasAssignAction) {
218
- return null;
197
+ const newTermLabel = get(taxonomy, ['labels', 'add_new_item'], slug === 'post_tag' ? __('Add new tag') : __('Add new Term'));
198
+ const singularName = get(taxonomy, ['labels', 'singular_name'], slug === 'post_tag' ? __('Tag') : __('Term'));
199
+ const termAddedLabel = sprintf(
200
+ /* translators: %s: term name. */
201
+ _x('%s added', 'term'), singularName);
202
+ const termRemovedLabel = sprintf(
203
+ /* translators: %s: term name. */
204
+ _x('%s removed', 'term'), singularName);
205
+ const removeTermLabel = sprintf(
206
+ /* translators: %s: term name. */
207
+ _x('Remove %s', 'term'), singularName);
208
+ return createElement(Fragment, null, createElement(FormTokenField, {
209
+ value: values,
210
+ suggestions: suggestions,
211
+ onChange: onChange,
212
+ onInputChange: debouncedSearch,
213
+ maxSuggestions: MAX_TERMS_SUGGESTIONS,
214
+ label: newTermLabel,
215
+ messages: {
216
+ added: termAddedLabel,
217
+ removed: termRemovedLabel,
218
+ remove: removeTermLabel
219
219
  }
220
-
221
- const {
222
- loading,
223
- availableTerms,
224
- selectedTerms
225
- } = this.state;
226
- const termNames = availableTerms.map(term => term.name);
227
- const newTermLabel = get(taxonomy, ['labels', 'add_new_item'], slug === 'post_tag' ? __('Add new tag') : __('Add new Term'));
228
- const singularName = get(taxonomy, ['labels', 'singular_name'], slug === 'post_tag' ? __('Tag') : __('Term'));
229
- const termAddedLabel = sprintf(
230
- /* translators: %s: term name. */
231
- _x('%s added', 'term'), singularName);
232
- const termRemovedLabel = sprintf(
233
- /* translators: %s: term name. */
234
- _x('%s removed', 'term'), singularName);
235
- const removeTermLabel = sprintf(
236
- /* translators: %s: term name. */
237
- _x('Remove %s', 'term'), singularName);
238
- return createElement(Fragment, null, createElement(FormTokenField, {
239
- value: selectedTerms,
240
- suggestions: termNames,
241
- onChange: this.onChange,
242
- onInputChange: this.searchTerms,
243
- maxSuggestions: MAX_TERMS_SUGGESTIONS,
244
- disabled: loading,
245
- label: newTermLabel,
246
- messages: {
247
- added: termAddedLabel,
248
- removed: termRemovedLabel,
249
- remove: removeTermLabel
250
- }
251
- }), createElement(MostUsedTerms, {
252
- taxonomy: taxonomy,
253
- onSelect: this.appendTerm
254
- }));
255
- }
256
-
220
+ }), createElement(MostUsedTerms, {
221
+ taxonomy: taxonomy,
222
+ onSelect: appendTerm
223
+ }));
257
224
  }
258
225
 
259
- export default compose(withSelect((select, {
260
- slug
261
- }) => {
262
- const {
263
- getCurrentPost
264
- } = select(editorStore);
265
- const {
266
- getTaxonomy
267
- } = select(coreStore);
268
- const taxonomy = getTaxonomy(slug);
269
- return {
270
- hasCreateAction: taxonomy ? get(getCurrentPost(), ['_links', 'wp:action-create-' + taxonomy.rest_base], false) : false,
271
- hasAssignAction: taxonomy ? get(getCurrentPost(), ['_links', 'wp:action-assign-' + taxonomy.rest_base], false) : false,
272
- terms: taxonomy ? select(editorStore).getEditedPostAttribute(taxonomy.rest_base) : [],
273
- taxonomy
274
- };
275
- }), withDispatch(dispatch => {
276
- return {
277
- onUpdateTerms(terms, restBase) {
278
- dispatch(editorStore).editPost({
279
- [restBase]: terms
280
- });
281
- }
282
-
283
- };
284
- }), withSpokenMessages, withFilters('editor.PostTaxonomyType'))(FlatTermSelector);
226
+ export default withFilters('editor.PostTaxonomyType')(FlatTermSelector);
285
227
  //# sourceMappingURL=flat-term-selector.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/editor/src/components/post-taxonomies/flat-term-selector.js"],"names":["debounce","escape","escapeString","find","get","invoke","isEmpty","uniqBy","__","_x","sprintf","Component","FormTokenField","withFilters","withSpokenMessages","withSelect","withDispatch","store","coreStore","compose","apiFetch","addQueryArgs","editorStore","unescapeString","unescapeTerm","unescapeTerms","MostUsedTerms","MAX_TERMS_SUGGESTIONS","DEFAULT_QUERY","per_page","orderby","order","_fields","isSameTermName","termA","termB","toLowerCase","termNamesToIds","names","terms","map","termName","term","name","id","FlatTermSelector","constructor","arguments","onChange","bind","searchTerms","findOrCreateTerm","appendTerm","state","loading","props","availableTerms","selectedTerms","componentDidMount","initRequest","fetchTerms","include","join","then","setState","xhr","statusText","componentWillUnmount","searchRequest","componentDidUpdate","prevProps","updateSelectedTerms","params","taxonomy","query","request","path","rest_base","concat","filter","availableTerm","reduce","accumulator","termId","termObject","push","termNameEscaped","method","data","catch","error","errorCode","code","addRequest","search","searchResult","result","Promise","reject","termNames","uniqueTerms","newTermNames","length","onUpdateTerms","all","newTerms","newAvailableTerms","newTerm","slug","speak","includes","termAddedMessage","render","hasAssignAction","newTermLabel","singularName","termAddedLabel","termRemovedLabel","removeTermLabel","added","removed","remove","select","getCurrentPost","getTaxonomy","hasCreateAction","getEditedPostAttribute","dispatch","restBase","editPost"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport {\n\tdebounce,\n\tescape as escapeString,\n\tfind,\n\tget,\n\tinvoke,\n\tisEmpty,\n\tuniqBy,\n} from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport { Component } from '@wordpress/element';\nimport {\n\tFormTokenField,\n\twithFilters,\n\twithSpokenMessages,\n} from '@wordpress/components';\nimport { withSelect, withDispatch } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport { compose } from '@wordpress/compose';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\n\n/**\n * Internal dependencies\n */\nimport { store as editorStore } from '../../store';\nimport { unescapeString, unescapeTerm, unescapeTerms } from '../../utils/terms';\nimport MostUsedTerms from './most-used-terms';\n\n/**\n * Module constants\n */\nconst MAX_TERMS_SUGGESTIONS = 20;\nconst DEFAULT_QUERY = {\n\tper_page: MAX_TERMS_SUGGESTIONS,\n\torderby: 'count',\n\torder: 'desc',\n\t_fields: 'id,name,count',\n};\n\nconst isSameTermName = ( termA, termB ) =>\n\tunescapeString( termA ).toLowerCase() ===\n\tunescapeString( termB ).toLowerCase();\n\nconst termNamesToIds = ( names, terms ) => {\n\treturn names.map(\n\t\t( termName ) =>\n\t\t\tfind( terms, ( term ) => isSameTermName( term.name, termName ) ).id\n\t);\n};\n\nclass FlatTermSelector extends Component {\n\tconstructor() {\n\t\tsuper( ...arguments );\n\t\tthis.onChange = this.onChange.bind( this );\n\t\tthis.searchTerms = debounce( this.searchTerms.bind( this ), 500 );\n\t\tthis.findOrCreateTerm = this.findOrCreateTerm.bind( this );\n\t\tthis.appendTerm = this.appendTerm.bind( this );\n\t\tthis.state = {\n\t\t\tloading: ! isEmpty( this.props.terms ),\n\t\t\tavailableTerms: [],\n\t\t\tselectedTerms: [],\n\t\t};\n\t}\n\n\tcomponentDidMount() {\n\t\tif ( ! isEmpty( this.props.terms ) ) {\n\t\t\tthis.initRequest = this.fetchTerms( {\n\t\t\t\tinclude: this.props.terms.join( ',' ),\n\t\t\t\tper_page: -1,\n\t\t\t} );\n\t\t\tthis.initRequest.then(\n\t\t\t\t() => {\n\t\t\t\t\tthis.setState( { loading: false } );\n\t\t\t\t},\n\t\t\t\t( xhr ) => {\n\t\t\t\t\tif ( xhr.statusText === 'abort' ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.setState( {\n\t\t\t\t\t\tloading: false,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\tcomponentWillUnmount() {\n\t\tinvoke( this.initRequest, [ 'abort' ] );\n\t\tinvoke( this.searchRequest, [ 'abort' ] );\n\t}\n\n\tcomponentDidUpdate( prevProps ) {\n\t\tif ( prevProps.terms !== this.props.terms ) {\n\t\t\tthis.updateSelectedTerms( this.props.terms );\n\t\t}\n\t}\n\n\tfetchTerms( params = {} ) {\n\t\tconst { taxonomy } = this.props;\n\t\tconst query = { ...DEFAULT_QUERY, ...params };\n\t\tconst request = apiFetch( {\n\t\t\tpath: addQueryArgs( `/wp/v2/${ taxonomy.rest_base }`, query ),\n\t\t} );\n\t\trequest.then( unescapeTerms ).then( ( terms ) => {\n\t\t\tthis.setState( ( state ) => ( {\n\t\t\t\tavailableTerms: state.availableTerms.concat(\n\t\t\t\t\tterms.filter(\n\t\t\t\t\t\t( term ) =>\n\t\t\t\t\t\t\t! find(\n\t\t\t\t\t\t\t\tstate.availableTerms,\n\t\t\t\t\t\t\t\t( availableTerm ) =>\n\t\t\t\t\t\t\t\t\tavailableTerm.id === term.id\n\t\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t),\n\t\t\t} ) );\n\t\t\tthis.updateSelectedTerms( this.props.terms );\n\t\t} );\n\n\t\treturn request;\n\t}\n\n\tupdateSelectedTerms( terms = [] ) {\n\t\tconst selectedTerms = terms.reduce( ( accumulator, termId ) => {\n\t\t\tconst termObject = find(\n\t\t\t\tthis.state.availableTerms,\n\t\t\t\t( term ) => term.id === termId\n\t\t\t);\n\t\t\tif ( termObject ) {\n\t\t\t\taccumulator.push( termObject.name );\n\t\t\t}\n\n\t\t\treturn accumulator;\n\t\t}, [] );\n\t\tthis.setState( {\n\t\t\tselectedTerms,\n\t\t} );\n\t}\n\n\tfindOrCreateTerm( termName ) {\n\t\tconst { taxonomy } = this.props;\n\t\tconst termNameEscaped = escapeString( termName );\n\t\t// Tries to create a term or fetch it if it already exists.\n\t\treturn apiFetch( {\n\t\t\tpath: `/wp/v2/${ taxonomy.rest_base }`,\n\t\t\tmethod: 'POST',\n\t\t\tdata: { name: termNameEscaped },\n\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tconst errorCode = error.code;\n\t\t\t\tif ( errorCode === 'term_exists' ) {\n\t\t\t\t\t// If the terms exist, fetch it instead of creating a new one.\n\t\t\t\t\tthis.addRequest = apiFetch( {\n\t\t\t\t\t\tpath: addQueryArgs( `/wp/v2/${ taxonomy.rest_base }`, {\n\t\t\t\t\t\t\t...DEFAULT_QUERY,\n\t\t\t\t\t\t\tsearch: termNameEscaped,\n\t\t\t\t\t\t} ),\n\t\t\t\t\t} ).then( unescapeTerms );\n\t\t\t\t\treturn this.addRequest.then( ( searchResult ) => {\n\t\t\t\t\t\treturn find( searchResult, ( result ) =>\n\t\t\t\t\t\t\tisSameTermName( result.name, termName )\n\t\t\t\t\t\t);\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\treturn Promise.reject( error );\n\t\t\t} )\n\t\t\t.then( unescapeTerm );\n\t}\n\n\tonChange( termNames ) {\n\t\tconst uniqueTerms = uniqBy( termNames, ( term ) => term.toLowerCase() );\n\t\tthis.setState( { selectedTerms: uniqueTerms } );\n\t\tconst newTermNames = uniqueTerms.filter(\n\t\t\t( termName ) =>\n\t\t\t\t! find( this.state.availableTerms, ( term ) =>\n\t\t\t\t\tisSameTermName( term.name, termName )\n\t\t\t\t)\n\t\t);\n\n\t\tif ( newTermNames.length === 0 ) {\n\t\t\treturn this.props.onUpdateTerms(\n\t\t\t\ttermNamesToIds( uniqueTerms, this.state.availableTerms ),\n\t\t\t\tthis.props.taxonomy.rest_base\n\t\t\t);\n\t\t}\n\t\tPromise.all( newTermNames.map( this.findOrCreateTerm ) ).then(\n\t\t\t( newTerms ) => {\n\t\t\t\tconst newAvailableTerms = this.state.availableTerms.concat(\n\t\t\t\t\tnewTerms\n\t\t\t\t);\n\t\t\t\tthis.setState( { availableTerms: newAvailableTerms } );\n\t\t\t\treturn this.props.onUpdateTerms(\n\t\t\t\t\ttermNamesToIds( uniqueTerms, newAvailableTerms ),\n\t\t\t\t\tthis.props.taxonomy.rest_base\n\t\t\t\t);\n\t\t\t}\n\t\t);\n\t}\n\n\tsearchTerms( search = '' ) {\n\t\tinvoke( this.searchRequest, [ 'abort' ] );\n\t\tif ( search.length >= 3 ) {\n\t\t\tthis.searchRequest = this.fetchTerms( { search } );\n\t\t}\n\t}\n\n\tappendTerm( newTerm ) {\n\t\tconst { onUpdateTerms, taxonomy, terms = [], slug, speak } = this.props;\n\n\t\tif ( terms.includes( newTerm.id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newTerms = [ ...terms, newTerm.id ];\n\n\t\tconst termAddedMessage = sprintf(\n\t\t\t/* translators: %s: term name. */\n\t\t\t_x( '%s added', 'term' ),\n\t\t\tget(\n\t\t\t\ttaxonomy,\n\t\t\t\t[ 'labels', 'singular_name' ],\n\t\t\t\tslug === 'post_tag' ? __( 'Tag' ) : __( 'Term' )\n\t\t\t)\n\t\t);\n\n\t\tspeak( termAddedMessage, 'assertive' );\n\n\t\tthis.setState( {\n\t\t\tavailableTerms: [ ...this.state.availableTerms, newTerm ],\n\t\t} );\n\n\t\tonUpdateTerms( newTerms, taxonomy.rest_base );\n\t}\n\n\trender() {\n\t\tconst { slug, taxonomy, hasAssignAction } = this.props;\n\n\t\tif ( ! hasAssignAction ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst { loading, availableTerms, selectedTerms } = this.state;\n\t\tconst termNames = availableTerms.map( ( term ) => term.name );\n\t\tconst newTermLabel = get(\n\t\t\ttaxonomy,\n\t\t\t[ 'labels', 'add_new_item' ],\n\t\t\tslug === 'post_tag' ? __( 'Add new tag' ) : __( 'Add new Term' )\n\t\t);\n\t\tconst singularName = get(\n\t\t\ttaxonomy,\n\t\t\t[ 'labels', 'singular_name' ],\n\t\t\tslug === 'post_tag' ? __( 'Tag' ) : __( 'Term' )\n\t\t);\n\t\tconst termAddedLabel = sprintf(\n\t\t\t/* translators: %s: term name. */\n\t\t\t_x( '%s added', 'term' ),\n\t\t\tsingularName\n\t\t);\n\t\tconst termRemovedLabel = sprintf(\n\t\t\t/* translators: %s: term name. */\n\t\t\t_x( '%s removed', 'term' ),\n\t\t\tsingularName\n\t\t);\n\t\tconst removeTermLabel = sprintf(\n\t\t\t/* translators: %s: term name. */\n\t\t\t_x( 'Remove %s', 'term' ),\n\t\t\tsingularName\n\t\t);\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<FormTokenField\n\t\t\t\t\tvalue={ selectedTerms }\n\t\t\t\t\tsuggestions={ termNames }\n\t\t\t\t\tonChange={ this.onChange }\n\t\t\t\t\tonInputChange={ this.searchTerms }\n\t\t\t\t\tmaxSuggestions={ MAX_TERMS_SUGGESTIONS }\n\t\t\t\t\tdisabled={ loading }\n\t\t\t\t\tlabel={ newTermLabel }\n\t\t\t\t\tmessages={ {\n\t\t\t\t\t\tadded: termAddedLabel,\n\t\t\t\t\t\tremoved: termRemovedLabel,\n\t\t\t\t\t\tremove: removeTermLabel,\n\t\t\t\t\t} }\n\t\t\t\t/>\n\t\t\t\t<MostUsedTerms\n\t\t\t\t\ttaxonomy={ taxonomy }\n\t\t\t\t\tonSelect={ this.appendTerm }\n\t\t\t\t/>\n\t\t\t</>\n\t\t);\n\t}\n}\n\nexport default compose(\n\twithSelect( ( select, { slug } ) => {\n\t\tconst { getCurrentPost } = select( editorStore );\n\t\tconst { getTaxonomy } = select( coreStore );\n\t\tconst taxonomy = getTaxonomy( slug );\n\t\treturn {\n\t\t\thasCreateAction: taxonomy\n\t\t\t\t? get(\n\t\t\t\t\t\tgetCurrentPost(),\n\t\t\t\t\t\t[ '_links', 'wp:action-create-' + taxonomy.rest_base ],\n\t\t\t\t\t\tfalse\n\t\t\t\t )\n\t\t\t\t: false,\n\t\t\thasAssignAction: taxonomy\n\t\t\t\t? get(\n\t\t\t\t\t\tgetCurrentPost(),\n\t\t\t\t\t\t[ '_links', 'wp:action-assign-' + taxonomy.rest_base ],\n\t\t\t\t\t\tfalse\n\t\t\t\t )\n\t\t\t\t: false,\n\t\t\tterms: taxonomy\n\t\t\t\t? select( editorStore ).getEditedPostAttribute(\n\t\t\t\t\t\ttaxonomy.rest_base\n\t\t\t\t )\n\t\t\t\t: [],\n\t\t\ttaxonomy,\n\t\t};\n\t} ),\n\twithDispatch( ( dispatch ) => {\n\t\treturn {\n\t\t\tonUpdateTerms( terms, restBase ) {\n\t\t\t\tdispatch( editorStore ).editPost( { [ restBase ]: terms } );\n\t\t\t},\n\t\t};\n\t} ),\n\twithSpokenMessages,\n\twithFilters( 'editor.PostTaxonomyType' )\n)( FlatTermSelector );\n"]}
1
+ {"version":3,"sources":["@wordpress/editor/src/components/post-taxonomies/flat-term-selector.js"],"names":["escape","escapeString","find","get","uniqBy","__","_x","sprintf","useEffect","useMemo","useState","FormTokenField","withFilters","useSelect","useDispatch","store","coreStore","useDebounce","apiFetch","addQueryArgs","speak","editorStore","unescapeString","unescapeTerm","unescapeTerms","MostUsedTerms","EMPTY_ARRAY","MAX_TERMS_SUGGESTIONS","DEFAULT_QUERY","per_page","orderby","order","_fields","context","isSameTermName","termA","termB","toLowerCase","termNamesToIds","names","terms","map","termName","term","name","id","findOrCreateTerm","restBase","escapedTermName","path","method","data","catch","error","errorCode","code","addRequest","search","then","searchResult","result","Promise","reject","FlatTermSelector","slug","values","setValues","setSearch","debouncedSearch","termIds","taxonomy","hasAssignAction","hasCreateAction","hasResolvedTerms","select","getCurrentPost","getEditedPostAttribute","getEntityRecords","getTaxonomy","hasFinishedResolution","post","_taxonomy","_termIds","rest_base","query","include","join","length","searchResults","newValues","suggestions","editPost","onUpdateTerms","newTermIds","onChange","termNames","availableTerms","uniqueTerms","newTermNames","filter","all","newTerms","newAvailableTerms","concat","appendTerm","newTerm","includes","termAddedMessage","newTermLabel","singularName","termAddedLabel","termRemovedLabel","removeTermLabel","added","removed","remove"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { escape as escapeString, find, get, uniqBy } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport { useEffect, useMemo, useState } from '@wordpress/element';\nimport { FormTokenField, withFilters } from '@wordpress/components';\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport { useDebounce } from '@wordpress/compose';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport { store as editorStore } from '../../store';\nimport { unescapeString, unescapeTerm, unescapeTerms } from '../../utils/terms';\nimport MostUsedTerms from './most-used-terms';\n\n/**\n * Shared reference to an empty array for cases where it is important to avoid\n * returning a new array reference on every invocation.\n *\n * @type {Array<any>}\n */\nconst EMPTY_ARRAY = [];\n\n/**\n * Module constants\n */\nconst MAX_TERMS_SUGGESTIONS = 20;\nconst DEFAULT_QUERY = {\n\tper_page: MAX_TERMS_SUGGESTIONS,\n\torderby: 'count',\n\torder: 'desc',\n\t_fields: 'id,name',\n\tcontext: 'view',\n};\n\nconst isSameTermName = ( termA, termB ) =>\n\tunescapeString( termA ).toLowerCase() ===\n\tunescapeString( termB ).toLowerCase();\n\nconst termNamesToIds = ( names, terms ) => {\n\treturn names.map(\n\t\t( termName ) =>\n\t\t\tfind( terms, ( term ) => isSameTermName( term.name, termName ) ).id\n\t);\n};\n\n// Tries to create a term or fetch it if it already exists.\nfunction findOrCreateTerm( termName, restBase ) {\n\tconst escapedTermName = escapeString( termName );\n\n\treturn apiFetch( {\n\t\tpath: `/wp/v2/${ restBase }`,\n\t\tmethod: 'POST',\n\t\tdata: { name: escapedTermName },\n\t} )\n\t\t.catch( ( error ) => {\n\t\t\tconst errorCode = error.code;\n\t\t\tif ( errorCode === 'term_exists' ) {\n\t\t\t\t// If the terms exist, fetch it instead of creating a new one.\n\t\t\t\tconst addRequest = apiFetch( {\n\t\t\t\t\tpath: addQueryArgs( `/wp/v2/${ restBase }`, {\n\t\t\t\t\t\t...DEFAULT_QUERY,\n\t\t\t\t\t\tsearch: escapedTermName,\n\t\t\t\t\t} ),\n\t\t\t\t} ).then( unescapeTerms );\n\n\t\t\t\treturn addRequest.then( ( searchResult ) => {\n\t\t\t\t\treturn find( searchResult, ( result ) =>\n\t\t\t\t\t\tisSameTermName( result.name, termName )\n\t\t\t\t\t);\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn Promise.reject( error );\n\t\t} )\n\t\t.then( unescapeTerm );\n}\n\nfunction FlatTermSelector( { slug } ) {\n\tconst [ values, setValues ] = useState( [] );\n\tconst [ search, setSearch ] = useState( '' );\n\tconst debouncedSearch = useDebounce( setSearch, 500 );\n\n\tconst {\n\t\tterms,\n\t\ttermIds,\n\t\ttaxonomy,\n\t\thasAssignAction,\n\t\thasCreateAction,\n\t\thasResolvedTerms,\n\t} = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getCurrentPost, getEditedPostAttribute } = select(\n\t\t\t\teditorStore\n\t\t\t);\n\t\t\tconst {\n\t\t\t\tgetEntityRecords,\n\t\t\t\tgetTaxonomy,\n\t\t\t\thasFinishedResolution,\n\t\t\t} = select( coreStore );\n\t\t\tconst post = getCurrentPost();\n\t\t\tconst _taxonomy = getTaxonomy( slug );\n\t\t\tconst _termIds = _taxonomy\n\t\t\t\t? getEditedPostAttribute( _taxonomy.rest_base )\n\t\t\t\t: EMPTY_ARRAY;\n\n\t\t\tconst query = {\n\t\t\t\t...DEFAULT_QUERY,\n\t\t\t\tinclude: _termIds.join( ',' ),\n\t\t\t\tper_page: -1,\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\thasCreateAction: _taxonomy\n\t\t\t\t\t? get(\n\t\t\t\t\t\t\tpost,\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'_links',\n\t\t\t\t\t\t\t\t'wp:action-create-' + _taxonomy.rest_base,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tfalse\n\t\t\t\t\t )\n\t\t\t\t\t: false,\n\t\t\t\thasAssignAction: _taxonomy\n\t\t\t\t\t? get(\n\t\t\t\t\t\t\tpost,\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'_links',\n\t\t\t\t\t\t\t\t'wp:action-assign-' + _taxonomy.rest_base,\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tfalse\n\t\t\t\t\t )\n\t\t\t\t\t: false,\n\t\t\t\ttaxonomy: _taxonomy,\n\t\t\t\ttermIds: _termIds,\n\t\t\t\tterms: _termIds.length\n\t\t\t\t\t? getEntityRecords( 'taxonomy', slug, query )\n\t\t\t\t\t: EMPTY_ARRAY,\n\t\t\t\thasResolvedTerms: hasFinishedResolution( 'getEntityRecords', [\n\t\t\t\t\t'taxonomy',\n\t\t\t\t\tslug,\n\t\t\t\t\tquery,\n\t\t\t\t] ),\n\t\t\t};\n\t\t},\n\t\t[ slug ]\n\t);\n\n\tconst { searchResults } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getEntityRecords } = select( coreStore );\n\n\t\t\treturn {\n\t\t\t\tsearchResults: !! search\n\t\t\t\t\t? getEntityRecords( 'taxonomy', slug, {\n\t\t\t\t\t\t\t...DEFAULT_QUERY,\n\t\t\t\t\t\t\tsearch,\n\t\t\t\t\t } )\n\t\t\t\t\t: EMPTY_ARRAY,\n\t\t\t};\n\t\t},\n\t\t[ search ]\n\t);\n\n\t// Update terms state only after the selectors are resolved.\n\t// We're using this to avoid terms temporarily disappearing on slow networks\n\t// while core data makes REST API requests.\n\tuseEffect( () => {\n\t\tif ( hasResolvedTerms ) {\n\t\t\tconst newValues = terms.map( ( term ) =>\n\t\t\t\tunescapeString( term.name )\n\t\t\t);\n\n\t\t\tsetValues( newValues );\n\t\t}\n\t}, [ terms, hasResolvedTerms ] );\n\n\tconst suggestions = useMemo( () => {\n\t\treturn ( searchResults ?? [] ).map( ( term ) =>\n\t\t\tunescapeString( term.name )\n\t\t);\n\t}, [ searchResults ] );\n\n\tconst { editPost } = useDispatch( editorStore );\n\n\tif ( ! hasAssignAction ) {\n\t\treturn null;\n\t}\n\n\tfunction onUpdateTerms( newTermIds ) {\n\t\teditPost( { [ taxonomy.rest_base ]: newTermIds } );\n\t}\n\n\tfunction onChange( termNames ) {\n\t\tconst availableTerms = [ ...terms, ...( searchResults ?? [] ) ];\n\t\tconst uniqueTerms = uniqBy( termNames, ( term ) => term.toLowerCase() );\n\t\tconst newTermNames = uniqueTerms.filter(\n\t\t\t( termName ) =>\n\t\t\t\t! find( availableTerms, ( term ) =>\n\t\t\t\t\tisSameTermName( term.name, termName )\n\t\t\t\t)\n\t\t);\n\n\t\t// Optimistically update term values.\n\t\t// The selector will always re-fetch terms later.\n\t\tsetValues( uniqueTerms );\n\n\t\tif ( newTermNames.length === 0 ) {\n\t\t\treturn onUpdateTerms(\n\t\t\t\ttermNamesToIds( uniqueTerms, availableTerms )\n\t\t\t);\n\t\t}\n\n\t\tif ( ! hasCreateAction ) {\n\t\t\treturn;\n\t\t}\n\n\t\tPromise.all(\n\t\t\tnewTermNames.map( ( termName ) =>\n\t\t\t\tfindOrCreateTerm( termName, taxonomy.rest_base )\n\t\t\t)\n\t\t).then( ( newTerms ) => {\n\t\t\tconst newAvailableTerms = availableTerms.concat( newTerms );\n\t\t\treturn onUpdateTerms(\n\t\t\t\ttermNamesToIds( uniqueTerms, newAvailableTerms )\n\t\t\t);\n\t\t} );\n\t}\n\n\tfunction appendTerm( newTerm ) {\n\t\tif ( termIds.includes( newTerm.id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newTermIds = [ ...termIds, newTerm.id ];\n\t\tconst termAddedMessage = sprintf(\n\t\t\t/* translators: %s: term name. */\n\t\t\t_x( '%s added', 'term' ),\n\t\t\tget(\n\t\t\t\ttaxonomy,\n\t\t\t\t[ 'labels', 'singular_name' ],\n\t\t\t\tslug === 'post_tag' ? __( 'Tag' ) : __( 'Term' )\n\t\t\t)\n\t\t);\n\n\t\tspeak( termAddedMessage, 'assertive' );\n\t\tonUpdateTerms( newTermIds );\n\t}\n\n\tconst newTermLabel = get(\n\t\ttaxonomy,\n\t\t[ 'labels', 'add_new_item' ],\n\t\tslug === 'post_tag' ? __( 'Add new tag' ) : __( 'Add new Term' )\n\t);\n\tconst singularName = get(\n\t\ttaxonomy,\n\t\t[ 'labels', 'singular_name' ],\n\t\tslug === 'post_tag' ? __( 'Tag' ) : __( 'Term' )\n\t);\n\tconst termAddedLabel = sprintf(\n\t\t/* translators: %s: term name. */\n\t\t_x( '%s added', 'term' ),\n\t\tsingularName\n\t);\n\tconst termRemovedLabel = sprintf(\n\t\t/* translators: %s: term name. */\n\t\t_x( '%s removed', 'term' ),\n\t\tsingularName\n\t);\n\tconst removeTermLabel = sprintf(\n\t\t/* translators: %s: term name. */\n\t\t_x( 'Remove %s', 'term' ),\n\t\tsingularName\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t<FormTokenField\n\t\t\t\tvalue={ values }\n\t\t\t\tsuggestions={ suggestions }\n\t\t\t\tonChange={ onChange }\n\t\t\t\tonInputChange={ debouncedSearch }\n\t\t\t\tmaxSuggestions={ MAX_TERMS_SUGGESTIONS }\n\t\t\t\tlabel={ newTermLabel }\n\t\t\t\tmessages={ {\n\t\t\t\t\tadded: termAddedLabel,\n\t\t\t\t\tremoved: termRemovedLabel,\n\t\t\t\t\tremove: removeTermLabel,\n\t\t\t\t} }\n\t\t\t/>\n\t\t\t<MostUsedTerms taxonomy={ taxonomy } onSelect={ appendTerm } />\n\t\t</>\n\t);\n}\n\nexport default withFilters( 'editor.PostTaxonomyType' )( FlatTermSelector );\n"]}
@@ -3,7 +3,6 @@ import { createElement } from "@wordpress/element";
3
3
  /**
4
4
  * External dependencies
5
5
  */
6
- import TextareaAutosize from 'react-autosize-textarea';
7
6
  import classnames from 'classnames';
8
7
  /**
9
8
  * WordPress dependencies
@@ -14,10 +13,10 @@ import { useEffect, useRef, useState } from '@wordpress/element';
14
13
  import { decodeEntities } from '@wordpress/html-entities';
15
14
  import { ENTER } from '@wordpress/keycodes';
16
15
  import { useSelect, useDispatch } from '@wordpress/data';
17
- import { VisuallyHidden } from '@wordpress/components';
18
- import { useInstanceId } from '@wordpress/compose';
19
16
  import { pasteHandler } from '@wordpress/blocks';
20
17
  import { store as blockEditorStore } from '@wordpress/block-editor';
18
+ import { __unstableUseRichText as useRichText } from '@wordpress/rich-text';
19
+ import { useMergeRefs } from '@wordpress/compose';
21
20
  /**
22
21
  * Internal dependencies
23
22
  */
@@ -30,7 +29,6 @@ import { store as editorStore } from '../../store';
30
29
 
31
30
  const REGEXP_NEWLINES = /[\r\n]+/g;
32
31
  export default function PostTitle() {
33
- const instanceId = useInstanceId(PostTitle);
34
32
  const ref = useRef();
35
33
  const [isSelected, setIsSelected] = useState(false);
36
34
  const {
@@ -67,7 +65,7 @@ export default function PostTitle() {
67
65
  isFocusMode: focusMode,
68
66
  hasFixedToolbar: _hasFixedToolbar
69
67
  };
70
- });
68
+ }, []);
71
69
  useEffect(() => {
72
70
  if (!ref.current) {
73
71
  return;
@@ -103,6 +101,8 @@ export default function PostTitle() {
103
101
  });
104
102
  }
105
103
 
104
+ const [selection, setSelection] = useState({});
105
+
106
106
  function onSelect() {
107
107
  setIsSelected(true);
108
108
  clearSelectedBlock();
@@ -110,10 +110,11 @@ export default function PostTitle() {
110
110
 
111
111
  function onUnselect() {
112
112
  setIsSelected(false);
113
+ setSelection({});
113
114
  }
114
115
 
115
- function onChange(event) {
116
- onUpdate(event.target.value.replace(REGEXP_NEWLINES, ' '));
116
+ function onChange(value) {
117
+ onUpdate(value.replace(REGEXP_NEWLINES, ' '));
117
118
  }
118
119
 
119
120
  function onKeyDown(event) {
@@ -167,31 +168,61 @@ export default function PostTitle() {
167
168
  // This same block is used in both the visual and the code editor.
168
169
 
169
170
 
170
- const className = classnames('wp-block editor-post-title editor-post-title__block', {
171
+ const className = classnames('wp-block wp-block-post-title block-editor-block-list__block editor-post-title editor-post-title__input rich-text', {
171
172
  'is-selected': isSelected,
172
173
  'is-focus-mode': isFocusMode,
173
174
  'has-fixed-toolbar': hasFixedToolbar
174
175
  });
175
- const decodedPlaceholder = decodeEntities(placeholder);
176
+
177
+ const decodedPlaceholder = decodeEntities(placeholder) || __('Add title');
178
+
179
+ const {
180
+ ref: richTextRef
181
+ } = useRichText({
182
+ value: title,
183
+ onChange,
184
+ placeholder: decodedPlaceholder,
185
+ selectionStart: selection.start,
186
+ selectionEnd: selection.end,
187
+
188
+ onSelectionChange(newStart, newEnd) {
189
+ setSelection(sel => {
190
+ const {
191
+ start,
192
+ end
193
+ } = sel;
194
+
195
+ if (start === newStart && end === newEnd) {
196
+ return sel;
197
+ }
198
+
199
+ return {
200
+ start: newStart,
201
+ end: newEnd
202
+ };
203
+ });
204
+ },
205
+
206
+ __unstableDisableFormats: true,
207
+ preserveWhiteSpace: true
208
+ });
209
+ /* eslint-disable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
210
+
176
211
  return createElement(PostTypeSupportCheck, {
177
212
  supportKeys: "title"
178
- }, createElement("div", {
179
- className: className
180
- }, createElement(VisuallyHidden, {
181
- as: "label",
182
- htmlFor: `post-title-${instanceId}`
183
- }, decodedPlaceholder || __('Add title')), createElement(TextareaAutosize, {
184
- ref: ref,
185
- id: `post-title-${instanceId}`,
186
- className: "editor-post-title__input",
187
- value: title,
188
- onChange: onChange,
189
- placeholder: decodedPlaceholder || __('Add title'),
213
+ }, createElement("h1", {
214
+ ref: useMergeRefs([richTextRef, ref]),
215
+ contentEditable: true,
216
+ className: className,
217
+ "aria-label": decodedPlaceholder,
218
+ role: "textbox",
219
+ "aria-multiline": "true",
190
220
  onFocus: onSelect,
191
221
  onBlur: onUnselect,
192
222
  onKeyDown: onKeyDown,
193
223
  onKeyPress: onUnselect,
194
224
  onPaste: onPaste
195
- })));
225
+ }));
226
+ /* eslint-enable jsx-a11y/heading-has-content, jsx-a11y/no-noninteractive-element-to-interactive-role */
196
227
  }
197
228
  //# sourceMappingURL=index.js.map