@wordpress/edit-site 4.10.0 → 4.11.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 (69) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/add-new-template/add-custom-template-modal.js +22 -42
  3. package/build/components/add-new-template/add-custom-template-modal.js.map +1 -1
  4. package/build/components/add-new-template/new-template.js +17 -20
  5. package/build/components/add-new-template/new-template.js.map +1 -1
  6. package/build/components/add-new-template/utils.js +366 -239
  7. package/build/components/add-new-template/utils.js.map +1 -1
  8. package/build/components/block-editor/index.js +1 -3
  9. package/build/components/block-editor/index.js.map +1 -1
  10. package/build/components/global-styles/dimensions-panel.js +183 -13
  11. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  12. package/build/components/global-styles/hooks.js +1 -1
  13. package/build/components/global-styles/hooks.js.map +1 -1
  14. package/build/components/global-styles/use-global-styles-output.js +95 -17
  15. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  16. package/build/components/global-styles/utils.js +31 -0
  17. package/build/components/global-styles/utils.js.map +1 -1
  18. package/build/components/header/index.js +7 -6
  19. package/build/components/header/index.js.map +1 -1
  20. package/build/hooks/index.js +2 -0
  21. package/build/hooks/index.js.map +1 -1
  22. package/build/hooks/template-part-edit.js +86 -0
  23. package/build/hooks/template-part-edit.js.map +1 -0
  24. package/build-module/components/add-new-template/add-custom-template-modal.js +23 -43
  25. package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -1
  26. package/build-module/components/add-new-template/new-template.js +18 -21
  27. package/build-module/components/add-new-template/new-template.js.map +1 -1
  28. package/build-module/components/add-new-template/utils.js +365 -227
  29. package/build-module/components/add-new-template/utils.js.map +1 -1
  30. package/build-module/components/block-editor/index.js +1 -2
  31. package/build-module/components/block-editor/index.js.map +1 -1
  32. package/build-module/components/global-styles/dimensions-panel.js +183 -14
  33. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  34. package/build-module/components/global-styles/hooks.js +1 -1
  35. package/build-module/components/global-styles/hooks.js.map +1 -1
  36. package/build-module/components/global-styles/use-global-styles-output.js +94 -22
  37. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  38. package/build-module/components/global-styles/utils.js +29 -0
  39. package/build-module/components/global-styles/utils.js.map +1 -1
  40. package/build-module/components/header/index.js +8 -6
  41. package/build-module/components/header/index.js.map +1 -1
  42. package/build-module/hooks/index.js +1 -0
  43. package/build-module/hooks/index.js.map +1 -1
  44. package/build-module/hooks/template-part-edit.js +67 -0
  45. package/build-module/hooks/template-part-edit.js.map +1 -0
  46. package/build-style/style-rtl.css +25 -25
  47. package/build-style/style.css +25 -25
  48. package/package.json +29 -29
  49. package/src/components/add-new-template/add-custom-template-modal.js +27 -45
  50. package/src/components/add-new-template/new-template.js +27 -64
  51. package/src/components/add-new-template/style.scss +20 -8
  52. package/src/components/add-new-template/utils.js +398 -229
  53. package/src/components/block-editor/index.js +0 -2
  54. package/src/components/global-styles/dimensions-panel.js +207 -14
  55. package/src/components/global-styles/hooks.js +2 -0
  56. package/src/components/global-styles/test/use-global-styles-output.js +64 -1
  57. package/src/components/global-styles/use-global-styles-output.js +100 -8
  58. package/src/components/global-styles/utils.js +31 -0
  59. package/src/components/header/index.js +9 -10
  60. package/src/components/header/style.scss +5 -3
  61. package/src/components/sidebar/style.scss +4 -0
  62. package/src/hooks/index.js +1 -0
  63. package/src/hooks/template-part-edit.js +82 -0
  64. package/src/style.scss +0 -1
  65. package/build/components/edit-template-part-menu-button/index.js +0 -90
  66. package/build/components/edit-template-part-menu-button/index.js.map +0 -1
  67. package/build-module/components/edit-template-part-menu-button/index.js +0 -72
  68. package/build-module/components/edit-template-part-menu-button/index.js.map +0 -1
  69. package/src/components/edit-template-part-menu-button/index.js +0 -82
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.useTaxonomyTag = exports.useTaxonomyCategory = exports.useTaxonomies = exports.usePostTypes = exports.usePostTypePage = exports.useExtraTemplates = exports.useExistingTemplates = exports.useDefaultTemplateTypes = exports.mapToIHasNameAndId = exports.entitiesConfig = void 0;
6
+ exports.useTaxonomiesMenuItems = exports.usePostTypeMenuItems = exports.useExistingTemplates = exports.useDefaultTemplateTypes = exports.mapToIHasNameAndId = void 0;
7
7
 
8
8
  var _lodash = require("lodash");
9
9
 
@@ -55,76 +55,8 @@ const mapToIHasNameAndId = (entities, path) => {
55
55
  * @property {number[]} existingEntitiesIds An array of the existing entities ids.
56
56
  */
57
57
 
58
- /**
59
- * @typedef {Object} EntityConfig
60
- * @property {string} entityName The entity's name.
61
- * @property {Function} getOrderBy Getter for an entity's `orderBy` query parameter, given the object
62
- * {search} as argument.
63
- * @property {Function} getIcon Getter function for returning an entity's icon for the menu item.
64
- * @property {Function} getTitle Getter function for returning an entity's title for the menu item.
65
- * @property {Function} getDescription Getter function for returning an entity's description for the menu item.
66
- * @property {string} recordNamePath The path to an entity's properties to use as a `name`. If not provided
67
- * is assumed that `name` property exists.
68
- * @property {string} templatePrefix The template prefix to create new templates and check against existing
69
- * templates. For example custom post types need a `single-` prefix to all
70
- * templates(`single-post-hello`), whereas `pages` don't (`page-hello`).
71
- * @property {string} templateSlug If this property is provided, it is going to be used for the creation of
72
- * new templates and the check against existing templates in the place
73
- * of the actual entity's `slug`. An example is `Tag` templates where the
74
- * the Tag's taxonomy slug is `post_tag`, but template hierarchy is based
75
- * on `tag` alias.
76
- */
77
-
78
58
 
79
59
  exports.mapToIHasNameAndId = mapToIHasNameAndId;
80
- const taxonomyBaseConfig = {
81
- entityName: 'taxonomy',
82
- getOrderBy: _ref => {
83
- let {
84
- search
85
- } = _ref;
86
- return search ? 'name' : 'count';
87
- },
88
- getIcon: () => _icons.blockMeta,
89
- getTitle: labels => (0, _i18n.sprintf)( // translators: %s: Name of the taxonomy e.g: "Cagegory".
90
- (0, _i18n.__)('Single taxonomy: %s'), labels.singular_name),
91
- getDescription: labels => (0, _i18n.sprintf)( // translators: %s: Name of the taxonomy e.g: "Product Categories".
92
- (0, _i18n.__)('Displays a single taxonomy: %s.'), labels.singular_name)
93
- };
94
- const postTypeBaseConfig = {
95
- entityName: 'postType',
96
- getOrderBy: _ref2 => {
97
- let {
98
- search
99
- } = _ref2;
100
- return search ? 'relevance' : 'modified';
101
- },
102
- recordNamePath: 'title.rendered',
103
- // `icon` is the `menu_icon` property of a post type. We
104
- // only handle `dashicons` for now, even if the `menu_icon`
105
- // also supports urls and svg as values.
106
- getIcon: _icon => _icon !== null && _icon !== void 0 && _icon.startsWith('dashicons-') ? _icon.slice(10) : _icons.post,
107
- getTitle: labels => (0, _i18n.sprintf)( // translators: %s: Name of the post type e.g: "Post".
108
- (0, _i18n.__)('Single item: %s'), labels.singular_name),
109
- getDescription: labels => (0, _i18n.sprintf)( // translators: %s: Name of the post type e.g: "Post".
110
- (0, _i18n.__)('Displays a single item: %s.'), labels.singular_name)
111
- };
112
- const entitiesConfig = {
113
- postType: { ...postTypeBaseConfig,
114
- templatePrefix: 'single-'
115
- },
116
- page: { ...postTypeBaseConfig
117
- },
118
- taxonomy: { ...taxonomyBaseConfig,
119
- templatePrefix: 'taxonomy-'
120
- },
121
- category: { ...taxonomyBaseConfig
122
- },
123
- tag: { ...taxonomyBaseConfig,
124
- templateSlug: 'tag'
125
- }
126
- };
127
- exports.entitiesConfig = entitiesConfig;
128
60
 
129
61
  const useExistingTemplates = () => {
130
62
  return (0, _data.useSelect)(select => select(_coreData.store).getEntityRecords('postType', 'wp_template', {
@@ -146,135 +78,369 @@ const usePublicPostTypes = () => {
146
78
  }), []);
147
79
  return (0, _element.useMemo)(() => {
148
80
  const excludedPostTypes = ['attachment'];
149
- return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref3 => {
81
+ return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref => {
150
82
  let {
151
83
  viewable,
152
84
  slug
153
- } = _ref3;
85
+ } = _ref;
154
86
  return viewable && !excludedPostTypes.includes(slug);
155
87
  });
156
88
  }, [postTypes]);
157
- }; // `page` post type is a special case in the template hierarchy,
158
- // so we exclude it from the list of post types and we handle it
159
- // separately.
160
-
161
-
162
- const usePostTypes = () => {
163
- const postTypes = usePublicPostTypes();
164
- return (0, _element.useMemo)(() => {
165
- return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref4 => {
166
- let {
167
- slug
168
- } = _ref4;
169
- return slug !== 'page';
170
- });
171
- }, [postTypes]);
172
89
  };
173
90
 
174
- exports.usePostTypes = usePostTypes;
175
-
176
- const usePostTypePage = () => {
177
- const postTypes = usePublicPostTypes();
178
- return (0, _element.useMemo)(() => {
179
- return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref5 => {
180
- let {
181
- slug
182
- } = _ref5;
183
- return slug === 'page';
184
- });
185
- }, [postTypes]);
186
- };
187
-
188
- exports.usePostTypePage = usePostTypePage;
189
-
190
91
  const usePublicTaxonomies = () => {
191
92
  const taxonomies = (0, _data.useSelect)(select => select(_coreData.store).getTaxonomies({
192
93
  per_page: -1
193
94
  }), []);
194
95
  return (0, _element.useMemo)(() => {
195
- return taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref6 => {
96
+ return taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref2 => {
196
97
  let {
197
98
  visibility
198
- } = _ref6;
99
+ } = _ref2;
199
100
  return visibility === null || visibility === void 0 ? void 0 : visibility.publicly_queryable;
200
101
  });
201
102
  }, [taxonomies]);
202
103
  };
203
- /**
204
- * `category` and `post_tag` are handled specifically in template
205
- * hierarchy so we need to differentiate them and return the rest,
206
- * e.g. `category-$slug` and `taxonomy-$taxonomy-$term`.
207
- */
208
104
 
105
+ const usePostTypeMenuItems = onClickMenuItem => {
106
+ const publicPostTypes = usePublicPostTypes();
107
+ const existingTemplates = useExistingTemplates();
108
+ const defaultTemplateTypes = useDefaultTemplateTypes(); // `page`is a special case in template hierarchy.
209
109
 
210
- const useTaxonomies = () => {
211
- const taxonomies = usePublicTaxonomies();
212
- const specialTaxonomies = ['category', 'post_tag'];
213
- return (0, _element.useMemo)(() => taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref7 => {
110
+ const templatePrefixes = (0, _element.useMemo)(() => publicPostTypes === null || publicPostTypes === void 0 ? void 0 : publicPostTypes.reduce((accumulator, _ref3) => {
214
111
  let {
215
112
  slug
216
- } = _ref7;
217
- return !specialTaxonomies.includes(slug);
218
- }), [taxonomies]);
219
- };
113
+ } = _ref3;
114
+ let suffix = slug;
220
115
 
221
- exports.useTaxonomies = useTaxonomies;
116
+ if (slug !== 'page') {
117
+ suffix = `single-${suffix}`;
118
+ }
119
+
120
+ accumulator[slug] = suffix;
121
+ return accumulator;
122
+ }, {}), [publicPostTypes]); // We need to keep track of naming conflicts. If a conflict
123
+ // occurs, we need to add slug.
124
+
125
+ const postTypeLabels = publicPostTypes === null || publicPostTypes === void 0 ? void 0 : publicPostTypes.reduce((accumulator, _ref4) => {
126
+ let {
127
+ labels
128
+ } = _ref4;
129
+ const singularName = labels.singular_name.toLowerCase();
130
+ accumulator[singularName] = (accumulator[singularName] || 0) + 1;
131
+ return accumulator;
132
+ }, {});
133
+
134
+ const needsUniqueIdentifier = (labels, slug) => {
135
+ const singularName = labels.singular_name.toLowerCase();
136
+ return postTypeLabels[singularName] > 1 && singularName !== slug;
137
+ };
222
138
 
223
- const useTaxonomyCategory = () => {
224
- const taxonomies = usePublicTaxonomies();
225
- return (0, _element.useMemo)(() => taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref8 => {
139
+ const postTypesInfo = useEntitiesInfo('postType', templatePrefixes);
140
+ const existingTemplateSlugs = (existingTemplates || []).map(_ref5 => {
226
141
  let {
227
142
  slug
228
- } = _ref8;
229
- return slug === 'category';
230
- }), [taxonomies]);
143
+ } = _ref5;
144
+ return slug;
145
+ });
146
+ const menuItems = (publicPostTypes || []).reduce((accumulator, postType) => {
147
+ var _postTypesInfo$slug;
148
+
149
+ const {
150
+ slug,
151
+ labels,
152
+ icon
153
+ } = postType; // We need to check if the general template is part of the
154
+ // defaultTemplateTypes. If it is, just use that info and
155
+ // augment it with the specific template functionality.
156
+
157
+ const generalTemplateSlug = templatePrefixes[slug];
158
+ const defaultTemplateType = defaultTemplateTypes === null || defaultTemplateTypes === void 0 ? void 0 : defaultTemplateTypes.find(_ref6 => {
159
+ let {
160
+ slug: _slug
161
+ } = _ref6;
162
+ return _slug === generalTemplateSlug;
163
+ });
164
+ const hasGeneralTemplate = existingTemplateSlugs === null || existingTemplateSlugs === void 0 ? void 0 : existingTemplateSlugs.includes(generalTemplateSlug);
165
+
166
+ const _needsUniqueIdentifier = needsUniqueIdentifier(labels, slug);
167
+
168
+ let menuItemTitle = (0, _i18n.sprintf)( // translators: %s: Name of the post type e.g: "Post".
169
+ (0, _i18n.__)('Single item: %s'), labels.singular_name);
170
+
171
+ if (_needsUniqueIdentifier) {
172
+ menuItemTitle = (0, _i18n.sprintf)( // translators: %1s: Name of the post type e.g: "Post"; %2s: Slug of the post type e.g: "book".
173
+ (0, _i18n.__)('Single item: %1$s (%2$s)'), labels.singular_name, slug);
174
+ }
175
+
176
+ const menuItem = defaultTemplateType ? { ...defaultTemplateType
177
+ } : {
178
+ slug: generalTemplateSlug,
179
+ title: menuItemTitle,
180
+ description: (0, _i18n.sprintf)( // translators: %s: Name of the post type e.g: "Post".
181
+ (0, _i18n.__)('Displays a single item: %s.'), labels.singular_name),
182
+ // `icon` is the `menu_icon` property of a post type. We
183
+ // only handle `dashicons` for now, even if the `menu_icon`
184
+ // also supports urls and svg as values.
185
+ icon: icon !== null && icon !== void 0 && icon.startsWith('dashicons-') ? icon.slice(10) : _icons.post
186
+ };
187
+ const hasEntities = postTypesInfo === null || postTypesInfo === void 0 ? void 0 : (_postTypesInfo$slug = postTypesInfo[slug]) === null || _postTypesInfo$slug === void 0 ? void 0 : _postTypesInfo$slug.hasEntities; // We have a different template creation flow only if they have entities.
188
+
189
+ if (hasEntities) {
190
+ menuItem.onClick = template => {
191
+ onClickMenuItem({
192
+ type: 'postType',
193
+ slug,
194
+ config: {
195
+ recordNamePath: 'title.rendered',
196
+ queryArgs: _ref7 => {
197
+ let {
198
+ search
199
+ } = _ref7;
200
+ return {
201
+ _fields: 'id,title,slug,link',
202
+ orderBy: search ? 'relevance' : 'modified',
203
+ exclude: postTypesInfo[slug].existingEntitiesIds
204
+ };
205
+ },
206
+ getSpecificTemplate: suggestion => {
207
+ let title = (0, _i18n.sprintf)( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a post type and %2$s is the name of the post, e.g. "Page: Hello".
208
+ (0, _i18n.__)('%1$s: %2$s'), labels.singular_name, suggestion.name);
209
+ const description = (0, _i18n.sprintf)( // translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Page: Hello"
210
+ (0, _i18n.__)('Template for %1$s'), title);
211
+
212
+ if (_needsUniqueIdentifier) {
213
+ title = (0, _i18n.sprintf)( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the post type, e.g. "Project: Hello (project_type)"
214
+ (0, _i18n.__)('%1$s %2$s'), title, `(${slug})`);
215
+ }
216
+
217
+ return {
218
+ title,
219
+ description,
220
+ slug: `${templatePrefixes[slug]}-${suggestion.slug}`
221
+ };
222
+ }
223
+ },
224
+ labels,
225
+ hasGeneralTemplate,
226
+ template
227
+ });
228
+ };
229
+ } // We don't need to add the menu item if there are no
230
+ // entities and the general template exists.
231
+
232
+
233
+ if (!hasGeneralTemplate || hasEntities) {
234
+ accumulator.push(menuItem);
235
+ }
236
+
237
+ return accumulator;
238
+ }, []); // Split menu items into two groups: one for the default post types
239
+ // and one for the rest.
240
+
241
+ const postTypesMenuItems = (0, _element.useMemo)(() => menuItems.reduce((accumulator, postType) => {
242
+ const {
243
+ slug
244
+ } = postType;
245
+ let key = 'postTypesMenuItems';
246
+
247
+ if (slug === 'page') {
248
+ key = 'defaultPostTypesMenuItems';
249
+ }
250
+
251
+ accumulator[key].push(postType);
252
+ return accumulator;
253
+ }, {
254
+ defaultPostTypesMenuItems: [],
255
+ postTypesMenuItems: []
256
+ }), [menuItems]);
257
+ return postTypesMenuItems;
231
258
  };
232
259
 
233
- exports.useTaxonomyCategory = useTaxonomyCategory;
260
+ exports.usePostTypeMenuItems = usePostTypeMenuItems;
261
+
262
+ const useTaxonomiesMenuItems = onClickMenuItem => {
263
+ const publicTaxonomies = usePublicTaxonomies();
264
+ const existingTemplates = useExistingTemplates();
265
+ const defaultTemplateTypes = useDefaultTemplateTypes(); // `category` and `post_tag` are special cases in template hierarchy.
234
266
 
235
- const useTaxonomyTag = () => {
236
- const taxonomies = usePublicTaxonomies();
237
- return (0, _element.useMemo)(() => taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref9 => {
267
+ const templatePrefixes = (0, _element.useMemo)(() => publicTaxonomies === null || publicTaxonomies === void 0 ? void 0 : publicTaxonomies.reduce((accumulator, _ref8) => {
238
268
  let {
239
269
  slug
270
+ } = _ref8;
271
+ let suffix = slug;
272
+
273
+ if (!['category', 'post_tag'].includes(slug)) {
274
+ suffix = `taxonomy-${suffix}`;
275
+ }
276
+
277
+ if (slug === 'post_tag') {
278
+ suffix = `tag`;
279
+ }
280
+
281
+ accumulator[slug] = suffix;
282
+ return accumulator;
283
+ }, {}), [publicTaxonomies]); // We need to keep track of naming conflicts. If a conflict
284
+ // occurs, we need to add slug.
285
+
286
+ const taxonomyLabels = publicTaxonomies === null || publicTaxonomies === void 0 ? void 0 : publicTaxonomies.reduce((accumulator, _ref9) => {
287
+ let {
288
+ labels
240
289
  } = _ref9;
241
- return slug === 'post_tag';
242
- }), [taxonomies]);
290
+ const singularName = labels.singular_name.toLowerCase();
291
+ accumulator[singularName] = (accumulator[singularName] || 0) + 1;
292
+ return accumulator;
293
+ }, {});
294
+
295
+ const needsUniqueIdentifier = (labels, slug) => {
296
+ if (['category', 'post_tag'].includes(slug)) {
297
+ return false;
298
+ }
299
+
300
+ const singularName = labels.singular_name.toLowerCase();
301
+ return taxonomyLabels[singularName] > 1 && singularName !== slug;
302
+ };
303
+
304
+ const taxonomiesInfo = useEntitiesInfo('taxonomy', templatePrefixes);
305
+ const existingTemplateSlugs = (existingTemplates || []).map(_ref10 => {
306
+ let {
307
+ slug
308
+ } = _ref10;
309
+ return slug;
310
+ });
311
+ const menuItems = (publicTaxonomies || []).reduce((accumulator, taxonomy) => {
312
+ var _taxonomiesInfo$slug;
313
+
314
+ const {
315
+ slug,
316
+ labels
317
+ } = taxonomy; // We need to check if the general template is part of the
318
+ // defaultTemplateTypes. If it is, just use that info and
319
+ // augment it with the specific template functionality.
320
+
321
+ const generalTemplateSlug = templatePrefixes[slug];
322
+ const defaultTemplateType = defaultTemplateTypes === null || defaultTemplateTypes === void 0 ? void 0 : defaultTemplateTypes.find(_ref11 => {
323
+ let {
324
+ slug: _slug
325
+ } = _ref11;
326
+ return _slug === generalTemplateSlug;
327
+ });
328
+ const hasGeneralTemplate = existingTemplateSlugs === null || existingTemplateSlugs === void 0 ? void 0 : existingTemplateSlugs.includes(generalTemplateSlug);
329
+
330
+ const _needsUniqueIdentifier = needsUniqueIdentifier(labels, slug);
331
+
332
+ let menuItemTitle = labels.singular_name;
333
+
334
+ if (_needsUniqueIdentifier) {
335
+ menuItemTitle = (0, _i18n.sprintf)( // translators: %1s: Name of the taxonomy e.g: "Category"; %2s: Slug of the taxonomy e.g: "product_cat".
336
+ (0, _i18n.__)('%1$s (%2$s)'), labels.singular_name, slug);
337
+ }
338
+
339
+ const menuItem = defaultTemplateType ? { ...defaultTemplateType
340
+ } : {
341
+ slug: generalTemplateSlug,
342
+ title: menuItemTitle,
343
+ description: (0, _i18n.sprintf)( // translators: %s: Name of the taxonomy e.g: "Product Categories".
344
+ (0, _i18n.__)('Displays taxonomy: %s.'), labels.singular_name),
345
+ icon: _icons.blockMeta
346
+ };
347
+ const hasEntities = taxonomiesInfo === null || taxonomiesInfo === void 0 ? void 0 : (_taxonomiesInfo$slug = taxonomiesInfo[slug]) === null || _taxonomiesInfo$slug === void 0 ? void 0 : _taxonomiesInfo$slug.hasEntities; // We have a different template creation flow only if they have entities.
348
+
349
+ if (hasEntities) {
350
+ menuItem.onClick = template => {
351
+ onClickMenuItem({
352
+ type: 'taxonomy',
353
+ slug,
354
+ config: {
355
+ queryArgs: _ref12 => {
356
+ let {
357
+ search
358
+ } = _ref12;
359
+ return {
360
+ _fields: 'id,name,slug,link',
361
+ orderBy: search ? 'name' : 'count',
362
+ exclude: taxonomiesInfo[slug].existingEntitiesIds
363
+ };
364
+ },
365
+ getSpecificTemplate: suggestion => {
366
+ let title = (0, _i18n.sprintf)( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a taxonomy and %2$s is the name of the term, e.g. "Category: shoes".
367
+ (0, _i18n.__)('%1$s: %2$s'), labels.singular_name, suggestion.name);
368
+ const description = (0, _i18n.sprintf)( // translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Category: shoes"
369
+ (0, _i18n.__)('Template for %1$s'), title);
370
+
371
+ if (_needsUniqueIdentifier) {
372
+ title = (0, _i18n.sprintf)( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the taxonomy, e.g. "Category: shoes (product_tag)"
373
+ (0, _i18n.__)('%1$s %2$s'), title, `(${slug})`);
374
+ }
375
+
376
+ return {
377
+ title,
378
+ description,
379
+ slug: `${templatePrefixes[slug]}-${suggestion.slug}`
380
+ };
381
+ }
382
+ },
383
+ labels,
384
+ hasGeneralTemplate,
385
+ template
386
+ });
387
+ };
388
+ } // We don't need to add the menu item if there are no
389
+ // entities and the general template exists.
390
+
391
+
392
+ if (!hasGeneralTemplate || hasEntities) {
393
+ accumulator.push(menuItem);
394
+ }
395
+
396
+ return accumulator;
397
+ }, []); // Split menu items into two groups: one for the default taxonomies
398
+ // and one for the rest.
399
+
400
+ const taxonomiesMenuItems = (0, _element.useMemo)(() => menuItems.reduce((accumulator, taxonomy) => {
401
+ const {
402
+ slug
403
+ } = taxonomy;
404
+ let key = 'taxonomiesMenuItems';
405
+
406
+ if (['category', 'tag'].includes(slug)) {
407
+ key = 'defaultTaxonomiesMenuItems';
408
+ }
409
+
410
+ accumulator[key].push(taxonomy);
411
+ return accumulator;
412
+ }, {
413
+ defaultTaxonomiesMenuItems: [],
414
+ taxonomiesMenuItems: []
415
+ }), [menuItems]);
416
+ return taxonomiesMenuItems;
243
417
  };
244
418
  /**
245
- * Helper hook that returns information about an entity having
246
- * records that we can create a specific template for.
419
+ * Helper hook that filters all the existing templates by the given
420
+ * object with the entity's slug as key and the template prefix as value.
247
421
  *
248
- * For example we can search for `terms` in `taxonomy` entity or
249
- * `posts` in `postType` entity.
422
+ * Example:
423
+ * `existingTemplates` is: [ { slug: tag-apple }, { slug: page-about }, { slug: tag } ]
424
+ * `templatePrefixes` is: { post_tag: 'tag' }
425
+ * It will return: { post_tag: [apple] }
250
426
  *
251
- * First we need to find the existing records with an associated template,
252
- * to query afterwards for any remaing record, by excluding them.
427
+ * Note: We append the `-` to the given template prefix in this function for our checks.
253
428
  *
254
- * @param {string[]} existingTemplates The existing templates.
255
- * @param {Object[]} entities The array of entities we need to get extra information.
256
- * @param {EntityConfig} entityConfig The entity config.
257
- * @return {Record<string,EntitiesInfo>} An object with the `entities.slug` as `keys` and EntitiesInfo as values.
429
+ * @param {Record<string,string>} templatePrefixes An object with the entity's slug as key and the template prefix as value.
430
+ * @return {Record<string,string[]>} An object with the entity's slug as key and an array with the existing template slugs as value.
258
431
  */
259
432
 
260
433
 
261
- exports.useTaxonomyTag = useTaxonomyTag;
262
-
263
- const useEntitiesInfo = (existingTemplates, entities, _ref10) => {
264
- let {
265
- entityName,
266
- templatePrefix,
267
- templateSlug
268
- } = _ref10;
269
- const slugsToExcludePerEntity = (0, _element.useMemo)(() => {
270
- return entities === null || entities === void 0 ? void 0 : entities.reduce((accumulator, entity) => {
271
- let _prefix = `${templateSlug || entity.slug}-`;
272
-
273
- if (templatePrefix) {
274
- _prefix = templatePrefix + _prefix;
275
- }
434
+ exports.useTaxonomiesMenuItems = useTaxonomiesMenuItems;
276
435
 
436
+ const useExistingTemplateSlugs = templatePrefixes => {
437
+ const existingTemplates = useExistingTemplates();
438
+ const existingSlugs = (0, _element.useMemo)(() => {
439
+ return Object.entries(templatePrefixes || {}).reduce((accumulator, _ref13) => {
440
+ let [slug, prefix] = _ref13;
277
441
  const slugsWithTemplates = (existingTemplates || []).reduce((_accumulator, existingTemplate) => {
442
+ const _prefix = `${prefix}-`;
443
+
278
444
  if (existingTemplate.slug.startsWith(_prefix)) {
279
445
  _accumulator.push(existingTemplate.slug.substring(_prefix.length));
280
446
  }
@@ -283,43 +449,70 @@ const useEntitiesInfo = (existingTemplates, entities, _ref10) => {
283
449
  }, []);
284
450
 
285
451
  if (slugsWithTemplates.length) {
286
- accumulator[entity.slug] = slugsWithTemplates;
452
+ accumulator[slug] = slugsWithTemplates;
287
453
  }
288
454
 
289
455
  return accumulator;
290
456
  }, {});
291
- }, [entities, existingTemplates]);
292
- const recordsToExcludePerEntity = (0, _data.useSelect)(select => {
293
- if (!slugsToExcludePerEntity) {
294
- return;
295
- }
457
+ }, [templatePrefixes, existingTemplates]);
458
+ return existingSlugs;
459
+ };
460
+ /**
461
+ * Helper hook that finds the existing records with an associated template,
462
+ * as they need to be excluded from the template suggestions.
463
+ *
464
+ * @param {string} entityName The entity's name.
465
+ * @param {Record<string,string>} templatePrefixes An object with the entity's slug as key and the template prefix as value.
466
+ * @return {Record<string,EntitiesInfo>} An object with the entity's slug as key and the existing records as value.
467
+ */
296
468
 
297
- return Object.entries(slugsToExcludePerEntity).reduce((accumulator, _ref11) => {
298
- let [slug, slugsWithTemplates] = _ref11;
299
- const postsWithTemplates = select(_coreData.store).getEntityRecords(entityName, slug, {
469
+
470
+ const useTemplatesToExclude = (entityName, templatePrefixes) => {
471
+ const slugsToExcludePerEntity = useExistingTemplateSlugs(templatePrefixes);
472
+ const recordsToExcludePerEntity = (0, _data.useSelect)(select => {
473
+ return Object.entries(slugsToExcludePerEntity || {}).reduce((accumulator, _ref14) => {
474
+ let [slug, slugsWithTemplates] = _ref14;
475
+ const entitiesWithTemplates = select(_coreData.store).getEntityRecords(entityName, slug, {
300
476
  _fields: 'id',
301
477
  context: 'view',
302
478
  slug: slugsWithTemplates
303
479
  });
304
480
 
305
- if (postsWithTemplates !== null && postsWithTemplates !== void 0 && postsWithTemplates.length) {
306
- accumulator[slug] = postsWithTemplates;
481
+ if (entitiesWithTemplates !== null && entitiesWithTemplates !== void 0 && entitiesWithTemplates.length) {
482
+ accumulator[slug] = entitiesWithTemplates;
307
483
  }
308
484
 
309
485
  return accumulator;
310
486
  }, {});
311
487
  }, [slugsToExcludePerEntity]);
488
+ return recordsToExcludePerEntity;
489
+ };
490
+ /**
491
+ * Helper hook that returns information about an entity having
492
+ * records that we can create a specific template for.
493
+ *
494
+ * For example we can search for `terms` in `taxonomy` entity or
495
+ * `posts` in `postType` entity.
496
+ *
497
+ * First we need to find the existing records with an associated template,
498
+ * to query afterwards for any remaining record, by excluding them.
499
+ *
500
+ * @param {string} entityName The entity's name.
501
+ * @param {Record<string,string>} templatePrefixes An object with the entity's slug as key and the template prefix as value.
502
+ * @return {Record<string,EntitiesInfo>} An object with the entity's slug as key and the EntitiesInfo as value.
503
+ */
504
+
505
+
506
+ const useEntitiesInfo = (entityName, templatePrefixes) => {
507
+ const recordsToExcludePerEntity = useTemplatesToExclude(entityName, templatePrefixes);
312
508
  const entitiesInfo = (0, _data.useSelect)(select => {
313
- return entities === null || entities === void 0 ? void 0 : entities.reduce((accumulator, _ref12) => {
509
+ return Object.keys(templatePrefixes || {}).reduce((accumulator, slug) => {
314
510
  var _recordsToExcludePerE, _select$getEntityReco;
315
511
 
316
- let {
317
- slug
318
- } = _ref12;
319
- const existingEntitiesIds = (recordsToExcludePerEntity === null || recordsToExcludePerEntity === void 0 ? void 0 : (_recordsToExcludePerE = recordsToExcludePerEntity[slug]) === null || _recordsToExcludePerE === void 0 ? void 0 : _recordsToExcludePerE.map(_ref13 => {
512
+ const existingEntitiesIds = (recordsToExcludePerEntity === null || recordsToExcludePerEntity === void 0 ? void 0 : (_recordsToExcludePerE = recordsToExcludePerEntity[slug]) === null || _recordsToExcludePerE === void 0 ? void 0 : _recordsToExcludePerE.map(_ref15 => {
320
513
  let {
321
514
  id
322
- } = _ref13;
515
+ } = _ref15;
323
516
  return id;
324
517
  })) || [];
325
518
  accumulator[slug] = {
@@ -333,73 +526,7 @@ const useEntitiesInfo = (existingTemplates, entities, _ref10) => {
333
526
  };
334
527
  return accumulator;
335
528
  }, {});
336
- }, [entities, recordsToExcludePerEntity]);
529
+ }, [templatePrefixes, recordsToExcludePerEntity]);
337
530
  return entitiesInfo;
338
531
  };
339
-
340
- const useExtraTemplates = (entities, entityConfig, onClickMenuItem) => {
341
- const existingTemplates = useExistingTemplates();
342
- const defaultTemplateTypes = useDefaultTemplateTypes();
343
- const entitiesInfo = useEntitiesInfo(existingTemplates, entities, entityConfig);
344
- const existingTemplateSlugs = (existingTemplates || []).map(_ref14 => {
345
- let {
346
- slug
347
- } = _ref14;
348
- return slug;
349
- });
350
- const extraTemplates = (entities || []).reduce((accumulator, entity) => {
351
- var _entityConfig$getIcon, _entitiesInfo$slug;
352
-
353
- const {
354
- slug,
355
- labels,
356
- icon
357
- } = entity;
358
- const slugForGeneralTemplate = entityConfig.templateSlug || slug; // We need to check if the general template is part of the
359
- // defaultTemplateTypes. If it is, just use that info and
360
- // augment it with the specific template functionality.
361
-
362
- const defaultTemplateType = defaultTemplateTypes === null || defaultTemplateTypes === void 0 ? void 0 : defaultTemplateTypes.find(_ref15 => {
363
- let {
364
- slug: _slug
365
- } = _ref15;
366
- return _slug === slugForGeneralTemplate;
367
- });
368
- const generalTemplateSlug = (defaultTemplateType === null || defaultTemplateType === void 0 ? void 0 : defaultTemplateType.slug) || `${entityConfig.templatePrefix}${slug}`;
369
- const hasGeneralTemplate = existingTemplateSlugs === null || existingTemplateSlugs === void 0 ? void 0 : existingTemplateSlugs.includes(generalTemplateSlug);
370
- const menuItem = defaultTemplateType ? { ...defaultTemplateType
371
- } : {
372
- slug: generalTemplateSlug,
373
- title: entityConfig.getTitle(labels),
374
- description: entityConfig.getDescription(labels),
375
- icon: (_entityConfig$getIcon = entityConfig.getIcon) === null || _entityConfig$getIcon === void 0 ? void 0 : _entityConfig$getIcon.call(entityConfig, icon)
376
- };
377
- const hasEntities = entitiesInfo === null || entitiesInfo === void 0 ? void 0 : (_entitiesInfo$slug = entitiesInfo[slug]) === null || _entitiesInfo$slug === void 0 ? void 0 : _entitiesInfo$slug.hasEntities; // We have a different template creation flow only if they have entities.
378
-
379
- if (hasEntities) {
380
- menuItem.onClick = template => {
381
- onClickMenuItem({
382
- type: entityConfig.entityName,
383
- slug,
384
- config: entityConfig,
385
- labels,
386
- hasGeneralTemplate,
387
- template,
388
- postsToExclude: entitiesInfo[slug].existingEntitiesIds
389
- });
390
- };
391
- } // We don't need to add the menu item if there are no
392
- // entities and the general template exists.
393
-
394
-
395
- if (!hasGeneralTemplate || hasEntities) {
396
- accumulator.push(menuItem);
397
- }
398
-
399
- return accumulator;
400
- }, []);
401
- return extraTemplates;
402
- };
403
-
404
- exports.useExtraTemplates = useExtraTemplates;
405
532
  //# sourceMappingURL=utils.js.map