@wordpress/block-library 6.0.16 → 6.0.19

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 (92) hide show
  1. package/build/columns/index.js +1 -2
  2. package/build/columns/index.js.map +1 -1
  3. package/build/gallery/deprecated.js +1 -5
  4. package/build/gallery/deprecated.js.map +1 -1
  5. package/build/navigation/index.js +1 -5
  6. package/build/navigation/index.js.map +1 -1
  7. package/build/post-author/edit.js +1 -1
  8. package/build/post-author/edit.js.map +1 -1
  9. package/build/post-content/edit.js +1 -1
  10. package/build/post-content/edit.js.map +1 -1
  11. package/build/post-date/edit.js +1 -1
  12. package/build/post-date/edit.js.map +1 -1
  13. package/build/post-excerpt/edit.js +1 -1
  14. package/build/post-excerpt/edit.js.map +1 -1
  15. package/build/post-featured-image/edit.js +1 -1
  16. package/build/post-featured-image/edit.js.map +1 -1
  17. package/build/post-title/edit.js +1 -1
  18. package/build/post-title/edit.js.map +1 -1
  19. package/build/site-logo/edit.js +110 -12
  20. package/build/site-logo/edit.js.map +1 -1
  21. package/build/site-logo/index.js +5 -1
  22. package/build/site-logo/index.js.map +1 -1
  23. package/build/template-part/index.js +25 -1
  24. package/build/template-part/index.js.map +1 -1
  25. package/build-module/columns/index.js +1 -2
  26. package/build-module/columns/index.js.map +1 -1
  27. package/build-module/gallery/deprecated.js +2 -6
  28. package/build-module/gallery/deprecated.js.map +1 -1
  29. package/build-module/navigation/index.js +1 -5
  30. package/build-module/navigation/index.js.map +1 -1
  31. package/build-module/post-author/edit.js +1 -1
  32. package/build-module/post-author/edit.js.map +1 -1
  33. package/build-module/post-content/edit.js +1 -1
  34. package/build-module/post-content/edit.js.map +1 -1
  35. package/build-module/post-date/edit.js +1 -1
  36. package/build-module/post-date/edit.js.map +1 -1
  37. package/build-module/post-excerpt/edit.js +1 -1
  38. package/build-module/post-excerpt/edit.js.map +1 -1
  39. package/build-module/post-featured-image/edit.js +1 -1
  40. package/build-module/post-featured-image/edit.js.map +1 -1
  41. package/build-module/post-title/edit.js +1 -1
  42. package/build-module/post-title/edit.js.map +1 -1
  43. package/build-module/site-logo/edit.js +111 -13
  44. package/build-module/site-logo/edit.js.map +1 -1
  45. package/build-module/site-logo/index.js +5 -1
  46. package/build-module/site-logo/index.js.map +1 -1
  47. package/build-module/template-part/index.js +25 -1
  48. package/build-module/template-part/index.js.map +1 -1
  49. package/build-style/common-rtl.css +2 -2
  50. package/build-style/common.css +2 -2
  51. package/build-style/editor-rtl.css +20 -10
  52. package/build-style/editor.css +20 -10
  53. package/build-style/navigation/editor-rtl.css +13 -6
  54. package/build-style/navigation/editor.css +13 -6
  55. package/build-style/navigation/style-rtl.css +1 -0
  56. package/build-style/navigation/style.css +1 -0
  57. package/build-style/page-list/style-rtl.css +4 -4
  58. package/build-style/page-list/style.css +4 -4
  59. package/build-style/post-comments/style-rtl.css +0 -1
  60. package/build-style/post-comments/style.css +0 -1
  61. package/build-style/post-template/style-rtl.css +2 -29
  62. package/build-style/post-template/style.css +2 -29
  63. package/build-style/style-rtl.css +9 -36
  64. package/build-style/style.css +9 -36
  65. package/package.json +8 -8
  66. package/src/columns/block.json +1 -2
  67. package/src/common.scss +2 -2
  68. package/src/editor.scss +7 -4
  69. package/src/gallery/deprecated.js +2 -5
  70. package/src/navigation/block.json +1 -11
  71. package/src/navigation/editor.scss +18 -8
  72. package/src/navigation/style.scss +1 -0
  73. package/src/navigation-submenu/index.php +2 -2
  74. package/src/page-list/index.php +1 -1
  75. package/src/page-list/style.scss +4 -4
  76. package/src/post-author/edit.js +1 -1
  77. package/src/post-comments/style.scss +0 -1
  78. package/src/post-content/edit.js +1 -1
  79. package/src/post-content/index.php +11 -1
  80. package/src/post-date/edit.js +1 -1
  81. package/src/post-excerpt/edit.js +1 -1
  82. package/src/post-excerpt/index.php +1 -1
  83. package/src/post-featured-image/edit.js +1 -1
  84. package/src/post-template/style.scss +2 -13
  85. package/src/post-title/edit.js +1 -1
  86. package/src/post-title/index.php +1 -1
  87. package/src/query-pagination-next/index.php +3 -2
  88. package/src/search/index.php +9 -9
  89. package/src/site-logo/block.json +5 -1
  90. package/src/site-logo/edit.js +127 -9
  91. package/src/site-logo/index.php +17 -0
  92. package/src/template-part/index.js +28 -0
@@ -8,7 +8,12 @@ import { includes, pick } from 'lodash';
8
8
  * WordPress dependencies
9
9
  */
10
10
  import { isBlobURL } from '@wordpress/blob';
11
- import { useEffect, useState, useRef } from '@wordpress/element';
11
+ import {
12
+ createInterpolateElement,
13
+ useEffect,
14
+ useState,
15
+ useRef,
16
+ } from '@wordpress/element';
12
17
  import { __, isRTL } from '@wordpress/i18n';
13
18
  import {
14
19
  MenuItem,
@@ -53,7 +58,7 @@ const ACCEPT_MEDIA_STRING = 'image/*';
53
58
 
54
59
  const SiteLogo = ( {
55
60
  alt,
56
- attributes: { align, width, height, isLink, linkTarget },
61
+ attributes: { align, width, height, isLink, linkTarget, shouldSyncIcon },
57
62
  containerRef,
58
63
  isSelected,
59
64
  setAttributes,
@@ -61,6 +66,9 @@ const SiteLogo = ( {
61
66
  logoUrl,
62
67
  siteUrl,
63
68
  logoId,
69
+ iconId,
70
+ setIcon,
71
+ canUserEdit,
64
72
  } ) => {
65
73
  const clientWidth = useClientWidth( containerRef, [ align ] );
66
74
  const isLargeViewport = useViewportMatch( 'medium' );
@@ -84,6 +92,15 @@ const SiteLogo = ( {
84
92
  };
85
93
  }, [] );
86
94
 
95
+ useEffect( () => {
96
+ // Turn the `Use as site icon` toggle off if it is on but the logo and icon have
97
+ // fallen out of sync. This can happen if the toggle is saved in the `on` position,
98
+ // but changes are later made to the site icon in the Customizer.
99
+ if ( shouldSyncIcon && logoId !== iconId ) {
100
+ setAttributes( { shouldSyncIcon: false } );
101
+ }
102
+ }, [] );
103
+
87
104
  useEffect( () => {
88
105
  if ( ! isSelected ) {
89
106
  setIsEditingImage( false );
@@ -149,9 +166,10 @@ const SiteLogo = ( {
149
166
  const currentWidth = width || defaultWidth;
150
167
  const ratio = naturalWidth / naturalHeight;
151
168
  const currentHeight = currentWidth / ratio;
152
- const minWidth = naturalWidth < naturalHeight ? MIN_SIZE : MIN_SIZE * ratio;
169
+ const minWidth =
170
+ naturalWidth < naturalHeight ? MIN_SIZE : Math.ceil( MIN_SIZE * ratio );
153
171
  const minHeight =
154
- naturalHeight < naturalWidth ? MIN_SIZE : MIN_SIZE / ratio;
172
+ naturalHeight < naturalWidth ? MIN_SIZE : Math.ceil( MIN_SIZE / ratio );
155
173
 
156
174
  // With the current implementation of ResizableBox, an image needs an
157
175
  // explicit pixel value for the max-width. In absence of being able to
@@ -250,6 +268,25 @@ const SiteLogo = ( {
250
268
  </ResizableBox>
251
269
  );
252
270
 
271
+ const syncSiteIconHelpText = createInterpolateElement(
272
+ __(
273
+ 'Site Icons are what you see in browser tabs, bookmark bars, and within the WordPress mobile apps. To use a custom icon that is different from your site logo, use the <a>Site Icon settings</a>.'
274
+ ),
275
+ {
276
+ a: (
277
+ // eslint-disable-next-line jsx-a11y/anchor-has-content
278
+ <a
279
+ href={
280
+ siteUrl +
281
+ '/wp-admin/customize.php?autofocus[section]=title_tagline'
282
+ }
283
+ target="_blank"
284
+ rel="noopener noreferrer"
285
+ />
286
+ ),
287
+ }
288
+ );
289
+
253
290
  return (
254
291
  <>
255
292
  <InspectorControls>
@@ -286,6 +323,19 @@ const SiteLogo = ( {
286
323
  />
287
324
  </>
288
325
  ) }
326
+ { canUserEdit && (
327
+ <>
328
+ <ToggleControl
329
+ label={ __( 'Use as site icon' ) }
330
+ onChange={ ( value ) => {
331
+ setAttributes( { shouldSyncIcon: value } );
332
+ setIcon( value ? logoId : undefined );
333
+ } }
334
+ checked={ !! shouldSyncIcon }
335
+ help={ syncSiteIconHelpText }
336
+ />
337
+ </>
338
+ ) }
289
339
  </PanelBody>
290
340
  </InspectorControls>
291
341
  <BlockControls group="block">
@@ -308,7 +358,7 @@ export default function LogoEdit( {
308
358
  setAttributes,
309
359
  isSelected,
310
360
  } ) {
311
- const { width } = attributes;
361
+ const { className: styleClass, width, shouldSyncIcon } = attributes;
312
362
  const [ logoUrl, setLogoUrl ] = useState();
313
363
  const ref = useRef();
314
364
 
@@ -316,6 +366,7 @@ export default function LogoEdit( {
316
366
  siteLogoId,
317
367
  canUserEdit,
318
368
  url,
369
+ siteIconId,
319
370
  mediaItemData,
320
371
  isRequestingMediaItem,
321
372
  } = useSelect( ( select ) => {
@@ -328,6 +379,7 @@ export default function LogoEdit( {
328
379
  const _readOnlyLogo = siteData?.site_logo;
329
380
  const _canUserEdit = canUser( 'update', 'settings' );
330
381
  const _siteLogoId = _canUserEdit ? _siteLogo : _readOnlyLogo;
382
+ const _siteIconId = siteSettings?.site_icon;
331
383
  const mediaItem =
332
384
  _siteLogoId &&
333
385
  select( coreStore ).getMedia( _siteLogoId, {
@@ -339,6 +391,7 @@ export default function LogoEdit( {
339
391
  _siteLogoId,
340
392
  { context: 'view' },
341
393
  ] );
394
+
342
395
  return {
343
396
  siteLogoId: _siteLogoId,
344
397
  canUserEdit: _canUserEdit,
@@ -349,14 +402,59 @@ export default function LogoEdit( {
349
402
  alt: mediaItem.alt_text,
350
403
  },
351
404
  isRequestingMediaItem: _isRequestingMediaItem,
405
+ siteIconId: _siteIconId,
352
406
  };
353
407
  }, [] );
354
408
 
409
+ const { getGlobalBlockCount } = useSelect( blockEditorStore );
355
410
  const { editEntityRecord } = useDispatch( coreStore );
356
- const setLogo = ( newValue ) =>
411
+
412
+ useEffect( () => {
413
+ // Cleanup function to discard unsaved changes to the icon and logo when
414
+ // the block is removed.
415
+ return () => {
416
+ // Do nothing if the block is being rendered in the styles preview or the
417
+ // block inserter.
418
+ if (
419
+ styleClass?.includes(
420
+ 'block-editor-block-types-list__site-logo-example'
421
+ ) ||
422
+ styleClass?.includes(
423
+ 'block-editor-block-styles__block-preview-container'
424
+ )
425
+ ) {
426
+ return;
427
+ }
428
+
429
+ const logoBlockCount = getGlobalBlockCount( 'core/site-logo' );
430
+
431
+ // Only discard unsaved changes if we are removing the last Site Logo block
432
+ // on the page.
433
+ if ( logoBlockCount === 0 ) {
434
+ editEntityRecord( 'root', 'site', undefined, {
435
+ site_logo: undefined,
436
+ site_icon: undefined,
437
+ } );
438
+ }
439
+ };
440
+ }, [] );
441
+
442
+ const setLogo = ( newValue, shouldForceSync = false ) => {
443
+ // `shouldForceSync` is used to force syncing when the attribute
444
+ // may not have updated yet.
445
+ if ( shouldSyncIcon || shouldForceSync ) {
446
+ setIcon( newValue );
447
+ }
448
+
357
449
  editEntityRecord( 'root', 'site', undefined, {
358
450
  site_logo: newValue,
359
451
  } );
452
+ };
453
+
454
+ const setIcon = ( newValue ) =>
455
+ editEntityRecord( 'root', 'site', undefined, {
456
+ site_icon: newValue,
457
+ } );
360
458
 
361
459
  let alt = null;
362
460
  if ( mediaItemData ) {
@@ -365,7 +463,24 @@ export default function LogoEdit( {
365
463
  setLogoUrl( mediaItemData.url );
366
464
  }
367
465
  }
368
- const onSelectLogo = ( media ) => {
466
+
467
+ const onInitialSelectLogo = ( media ) => {
468
+ // Initialize the syncSiteIcon toggle. If we currently have no Site logo and no
469
+ // site icon, automatically sync the logo to the icon.
470
+ if ( shouldSyncIcon === undefined ) {
471
+ const shouldForceSync = ! siteIconId;
472
+ setAttributes( { shouldSyncIcon: shouldForceSync } );
473
+
474
+ // Because we cannot rely on the `shouldSyncIcon` attribute to have updated by
475
+ // the time `setLogo` is called, pass an argument to force the syncing.
476
+ onSelectLogo( media, shouldForceSync );
477
+ return;
478
+ }
479
+
480
+ onSelectLogo( media );
481
+ };
482
+
483
+ const onSelectLogo = ( media, shouldForceSync = false ) => {
369
484
  if ( ! media ) {
370
485
  return;
371
486
  }
@@ -377,7 +492,7 @@ export default function LogoEdit( {
377
492
  return;
378
493
  }
379
494
 
380
- setLogo( media.id );
495
+ setLogo( media.id, shouldForceSync );
381
496
  };
382
497
 
383
498
  const onRemoveLogo = () => {
@@ -423,6 +538,9 @@ export default function LogoEdit( {
423
538
  setLogo={ setLogo }
424
539
  logoId={ mediaItemData?.id || siteLogoId }
425
540
  siteUrl={ url }
541
+ setIcon={ setIcon }
542
+ iconId={ siteIconId }
543
+ canUserEdit={ canUserEdit }
426
544
  />
427
545
  );
428
546
  }
@@ -481,7 +599,7 @@ export default function LogoEdit( {
481
599
  ) }
482
600
  { ! logoUrl && canUserEdit && (
483
601
  <MediaPlaceholder
484
- onSelect={ onSelectLogo }
602
+ onSelect={ onInitialSelectLogo }
485
603
  accept={ ACCEPT_MEDIA_STRING }
486
604
  allowedTypes={ ALLOWED_MEDIA_TYPES }
487
605
  onError={ onUploadError }
@@ -76,6 +76,23 @@ function register_block_core_site_logo_setting() {
76
76
 
77
77
  add_action( 'rest_api_init', 'register_block_core_site_logo_setting', 10 );
78
78
 
79
+ /**
80
+ * Register a core site setting for a site icon
81
+ */
82
+ function register_block_core_site_icon_setting() {
83
+ register_setting(
84
+ 'general',
85
+ 'site_icon',
86
+ array(
87
+ 'show_in_rest' => true,
88
+ 'type' => 'integer',
89
+ 'description' => __( 'Site icon.' ),
90
+ )
91
+ );
92
+ }
93
+
94
+ add_action( 'rest_api_init', 'register_block_core_site_icon_setting', 10 );
95
+
79
96
  /**
80
97
  * Registers the `core/site-logo` block on the server.
81
98
  */
@@ -50,3 +50,31 @@ addFilter(
50
50
  'core/template-part',
51
51
  enhanceTemplatePartVariations
52
52
  );
53
+
54
+ // Prevent adding template parts inside post templates.
55
+ const DISALLOWED_PARENTS = [ 'core/post-template', 'core/post-content' ];
56
+ addFilter(
57
+ 'blockEditor.__unstableCanInsertBlockType',
58
+ 'removeTemplatePartsFromPostTemplates',
59
+ (
60
+ can,
61
+ blockType,
62
+ rootClientId,
63
+ { getBlock, getBlockParentsByBlockName }
64
+ ) => {
65
+ if ( blockType.name !== 'core/template-part' ) {
66
+ return can;
67
+ }
68
+
69
+ for ( const disallowedParentType of DISALLOWED_PARENTS ) {
70
+ const hasDisallowedParent =
71
+ getBlock( rootClientId )?.name === disallowedParentType ||
72
+ getBlockParentsByBlockName( rootClientId, disallowedParentType )
73
+ .length;
74
+ if ( hasDisallowedParent ) {
75
+ return false;
76
+ }
77
+ }
78
+ return true;
79
+ }
80
+ );