@wordpress/block-library 9.46.0 → 9.48.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 (176) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/button/edit.cjs +7 -4
  3. package/build/button/edit.cjs.map +3 -3
  4. package/build/columns/edit.cjs +4 -10
  5. package/build/columns/edit.cjs.map +2 -2
  6. package/build/cover/edit/inspector-controls.cjs +20 -6
  7. package/build/cover/edit/inspector-controls.cjs.map +2 -2
  8. package/build/freeform/migration-notice.cjs +1 -1
  9. package/build/freeform/migration-notice.cjs.map +1 -1
  10. package/build/home-link/block.json +7 -0
  11. package/build/home-link/edit.cjs +167 -24
  12. package/build/home-link/edit.cjs.map +3 -3
  13. package/build/html/edit.cjs +2 -4
  14. package/build/html/edit.cjs.map +2 -2
  15. package/build/html/modal.cjs +0 -4
  16. package/build/html/modal.cjs.map +2 -2
  17. package/build/image/block.json +4 -0
  18. package/build/image/deprecated.cjs +202 -4
  19. package/build/image/deprecated.cjs.map +3 -3
  20. package/build/image/image.cjs +94 -30
  21. package/build/image/image.cjs.map +2 -2
  22. package/build/image/index.cjs +23 -4
  23. package/build/image/index.cjs.map +2 -2
  24. package/build/image/save.cjs +25 -10
  25. package/build/image/save.cjs.map +2 -2
  26. package/build/image/transforms.cjs +15 -3
  27. package/build/image/transforms.cjs.map +2 -2
  28. package/build/image/use-open-image-media-editor-modal.cjs +37 -14
  29. package/build/image/use-open-image-media-editor-modal.cjs.map +2 -2
  30. package/build/list-item/hooks/use-enter.cjs +8 -4
  31. package/build/list-item/hooks/use-enter.cjs.map +3 -3
  32. package/build/list-item/hooks/use-space.cjs +8 -4
  33. package/build/list-item/hooks/use-space.cjs.map +3 -3
  34. package/build/navigation-link/edit.cjs +2 -1
  35. package/build/navigation-link/edit.cjs.map +2 -2
  36. package/build/navigation-link/shared/use-handle-link-change.cjs +19 -3
  37. package/build/navigation-link/shared/use-handle-link-change.cjs.map +3 -3
  38. package/build/navigation-submenu/edit.cjs +8 -22
  39. package/build/navigation-submenu/edit.cjs.map +2 -2
  40. package/build/paragraph/use-enter.cjs +8 -4
  41. package/build/paragraph/use-enter.cjs.map +3 -3
  42. package/build/post-date/edit.cjs +9 -1
  43. package/build/post-date/edit.cjs.map +2 -2
  44. package/build/post-featured-image/edit.cjs +6 -5
  45. package/build/post-featured-image/edit.cjs.map +2 -2
  46. package/build/site-logo/edit.cjs +5 -2
  47. package/build/site-logo/edit.cjs.map +2 -2
  48. package/build/social-link/edit.cjs.map +3 -3
  49. package/build/tab-list/edit.cjs +2 -0
  50. package/build/tab-list/edit.cjs.map +2 -2
  51. package/build/tab-panels/edit.cjs +5 -1
  52. package/build/tab-panels/edit.cjs.map +2 -2
  53. package/build/table/edit.cjs +1 -0
  54. package/build/table/edit.cjs.map +2 -2
  55. package/build/tabs/edit.cjs +1 -36
  56. package/build/tabs/edit.cjs.map +2 -2
  57. package/build-module/button/edit.mjs +12 -5
  58. package/build-module/button/edit.mjs.map +2 -2
  59. package/build-module/columns/edit.mjs +4 -10
  60. package/build-module/columns/edit.mjs.map +2 -2
  61. package/build-module/cover/edit/inspector-controls.mjs +20 -7
  62. package/build-module/cover/edit/inspector-controls.mjs.map +2 -2
  63. package/build-module/freeform/migration-notice.mjs +1 -1
  64. package/build-module/freeform/migration-notice.mjs.map +1 -1
  65. package/build-module/home-link/block.json +7 -0
  66. package/build-module/home-link/edit.mjs +181 -26
  67. package/build-module/home-link/edit.mjs.map +2 -2
  68. package/build-module/html/edit.mjs +2 -4
  69. package/build-module/html/edit.mjs.map +2 -2
  70. package/build-module/html/modal.mjs +0 -4
  71. package/build-module/html/modal.mjs.map +2 -2
  72. package/build-module/image/block.json +4 -0
  73. package/build-module/image/deprecated.mjs +204 -5
  74. package/build-module/image/deprecated.mjs.map +2 -2
  75. package/build-module/image/image.mjs +96 -30
  76. package/build-module/image/image.mjs.map +2 -2
  77. package/build-module/image/index.mjs +23 -4
  78. package/build-module/image/index.mjs.map +2 -2
  79. package/build-module/image/save.mjs +25 -10
  80. package/build-module/image/save.mjs.map +2 -2
  81. package/build-module/image/transforms.mjs +15 -3
  82. package/build-module/image/transforms.mjs.map +2 -2
  83. package/build-module/image/use-open-image-media-editor-modal.mjs +37 -14
  84. package/build-module/image/use-open-image-media-editor-modal.mjs.map +2 -2
  85. package/build-module/list-item/hooks/use-enter.mjs +12 -5
  86. package/build-module/list-item/hooks/use-enter.mjs.map +2 -2
  87. package/build-module/list-item/hooks/use-space.mjs +12 -5
  88. package/build-module/list-item/hooks/use-space.mjs.map +2 -2
  89. package/build-module/navigation-link/edit.mjs +2 -1
  90. package/build-module/navigation-link/edit.mjs.map +2 -2
  91. package/build-module/navigation-link/shared/use-handle-link-change.mjs +19 -3
  92. package/build-module/navigation-link/shared/use-handle-link-change.mjs.map +2 -2
  93. package/build-module/navigation-submenu/edit.mjs +9 -23
  94. package/build-module/navigation-submenu/edit.mjs.map +2 -2
  95. package/build-module/paragraph/use-enter.mjs +12 -5
  96. package/build-module/paragraph/use-enter.mjs.map +2 -2
  97. package/build-module/post-date/edit.mjs +9 -1
  98. package/build-module/post-date/edit.mjs.map +2 -2
  99. package/build-module/post-featured-image/edit.mjs +6 -5
  100. package/build-module/post-featured-image/edit.mjs.map +2 -2
  101. package/build-module/site-logo/edit.mjs +6 -2
  102. package/build-module/site-logo/edit.mjs.map +2 -2
  103. package/build-module/social-link/edit.mjs +2 -2
  104. package/build-module/social-link/edit.mjs.map +2 -2
  105. package/build-module/tab-list/edit.mjs +2 -0
  106. package/build-module/tab-list/edit.mjs.map +2 -2
  107. package/build-module/tab-panels/edit.mjs +5 -1
  108. package/build-module/tab-panels/edit.mjs.map +2 -2
  109. package/build-module/table/edit.mjs +1 -0
  110. package/build-module/table/edit.mjs.map +2 -2
  111. package/build-module/tabs/edit.mjs +2 -37
  112. package/build-module/tabs/edit.mjs.map +2 -2
  113. package/build-style/breadcrumbs/style-rtl.css +1 -1
  114. package/build-style/breadcrumbs/style.css +1 -1
  115. package/build-style/editor-rtl.css +0 -11
  116. package/build-style/editor.css +0 -11
  117. package/build-style/gallery/editor-rtl.css +0 -11
  118. package/build-style/gallery/editor.css +0 -11
  119. package/build-style/style-rtl.css +1 -1
  120. package/build-style/style.css +1 -1
  121. package/package.json +40 -40
  122. package/src/block/edit-title.native.js +3 -3
  123. package/src/block/edit.native.js +2 -2
  124. package/src/breadcrumbs/style.scss +1 -1
  125. package/src/button/edit.js +14 -5
  126. package/src/columns/edit.js +3 -9
  127. package/src/cover/controls.native.js +2 -2
  128. package/src/cover/edit/inspector-controls.js +69 -52
  129. package/src/cover/edit.native.js +6 -4
  130. package/src/cover/focal-point-settings-button.native.js +2 -2
  131. package/src/cover/test/edit.js +70 -31
  132. package/src/embed/embed-no-preview.native.js +7 -3
  133. package/src/embed/embed-placeholder.native.js +2 -2
  134. package/src/file/edit.native.js +2 -2
  135. package/src/freeform/migration-notice.js +1 -1
  136. package/src/gallery/editor.scss +0 -14
  137. package/src/home-link/block.json +7 -0
  138. package/src/home-link/edit.js +185 -22
  139. package/src/home-link/index.php +14 -2
  140. package/src/html/edit.js +14 -12
  141. package/src/html/modal.js +0 -5
  142. package/src/image/block.json +4 -0
  143. package/src/image/deprecated.js +236 -4
  144. package/src/image/edit.native.js +2 -2
  145. package/src/image/image.js +166 -76
  146. package/src/image/index.js +20 -1
  147. package/src/image/index.php +1 -1
  148. package/src/image/save.js +39 -12
  149. package/src/image/test/use-open-image-media-editor-modal.js +101 -0
  150. package/src/image/transforms.js +21 -5
  151. package/src/image/use-open-image-media-editor-modal.js +41 -17
  152. package/src/latest-posts/edit.native.js +2 -2
  153. package/src/list-item/hooks/use-enter.js +15 -5
  154. package/src/list-item/hooks/use-space.js +15 -5
  155. package/src/list-item/list-style-type.native.js +2 -2
  156. package/src/media-text/media-container.native.js +7 -3
  157. package/src/missing/edit.native.js +4 -4
  158. package/src/missing/test/edit.native.js +3 -3
  159. package/src/navigation/test/use-navigation-menu.js +8 -2
  160. package/src/navigation-link/edit.js +1 -0
  161. package/src/navigation-link/shared/test/use-handle-link-change.test.js +212 -0
  162. package/src/navigation-link/shared/use-handle-link-change.js +36 -9
  163. package/src/navigation-submenu/edit.js +11 -28
  164. package/src/navigation-submenu/index.php +13 -0
  165. package/src/paragraph/use-enter.js +19 -5
  166. package/src/post-date/edit.js +7 -3
  167. package/src/post-featured-image/edit.js +15 -11
  168. package/src/search/edit.native.js +2 -2
  169. package/src/search/test/edit.native.js +2 -2
  170. package/src/site-logo/edit.js +7 -1
  171. package/src/social-link/edit.js +2 -2
  172. package/src/tab-list/edit.js +3 -0
  173. package/src/tab-panels/edit.js +10 -1
  174. package/src/table/edit.js +1 -0
  175. package/src/tabs/edit.js +14 -42
  176. package/src/video/edit.native.js +3 -3
@@ -11,8 +11,14 @@ import {
11
11
  useBlockProps,
12
12
  __experimentalGetElementClassName,
13
13
  __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
14
+ __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
14
15
  } from '@wordpress/block-editor';
15
16
 
17
+ /**
18
+ * Internal dependencies
19
+ */
20
+ import { mediaPosition } from './utils';
21
+
16
22
  /**
17
23
  * Deprecation for adding the `wp-image-${id}` class to the image block for
18
24
  * responsive images.
@@ -854,11 +860,12 @@ const v7 = {
854
860
  },
855
861
  },
856
862
  },
857
- migrate( { width, height, ...attributes } ) {
863
+ migrate( attributes ) {
864
+ const { width, height } = attributes;
858
865
  return {
859
866
  ...attributes,
860
- width: `${ width }px`,
861
- height: `${ height }px`,
867
+ width: typeof width === 'number' ? `${ width }px` : width,
868
+ height: typeof height === 'number' ? `${ height }px` : height,
862
869
  };
863
870
  },
864
871
  save( { attributes } ) {
@@ -1166,4 +1173,229 @@ const v8 = {
1166
1173
  },
1167
1174
  };
1168
1175
 
1169
- export default [ v8, v7, v6, v5, v4, v3, v2, v1 ];
1176
+ /**
1177
+ * Deprecation for adding height: auto when only one dimension is explicitly
1178
+ * set, to prevent theme CSS from squishing images.
1179
+ *
1180
+ * @see https://github.com/WordPress/gutenberg/pull/70575
1181
+ */
1182
+ const v9 = {
1183
+ attributes: {
1184
+ blob: {
1185
+ type: 'string',
1186
+ role: 'local',
1187
+ },
1188
+ url: {
1189
+ type: 'string',
1190
+ source: 'attribute',
1191
+ selector: 'img',
1192
+ attribute: 'src',
1193
+ role: 'content',
1194
+ },
1195
+ alt: {
1196
+ type: 'string',
1197
+ source: 'attribute',
1198
+ selector: 'img',
1199
+ attribute: 'alt',
1200
+ default: '',
1201
+ role: 'content',
1202
+ },
1203
+ caption: {
1204
+ type: 'rich-text',
1205
+ source: 'rich-text',
1206
+ selector: 'figcaption',
1207
+ role: 'content',
1208
+ },
1209
+ lightbox: {
1210
+ type: 'object',
1211
+ enabled: {
1212
+ type: 'boolean',
1213
+ },
1214
+ },
1215
+ title: {
1216
+ type: 'string',
1217
+ source: 'attribute',
1218
+ selector: 'img',
1219
+ attribute: 'title',
1220
+ role: 'content',
1221
+ },
1222
+ href: {
1223
+ type: 'string',
1224
+ source: 'attribute',
1225
+ selector: 'figure > a',
1226
+ attribute: 'href',
1227
+ role: 'content',
1228
+ },
1229
+ rel: {
1230
+ type: 'string',
1231
+ source: 'attribute',
1232
+ selector: 'figure > a',
1233
+ attribute: 'rel',
1234
+ },
1235
+ linkClass: {
1236
+ type: 'string',
1237
+ source: 'attribute',
1238
+ selector: 'figure > a',
1239
+ attribute: 'class',
1240
+ },
1241
+ id: {
1242
+ type: 'number',
1243
+ role: 'content',
1244
+ },
1245
+ width: {
1246
+ type: 'string',
1247
+ },
1248
+ height: {
1249
+ type: 'string',
1250
+ },
1251
+ aspectRatio: {
1252
+ type: 'string',
1253
+ },
1254
+ scale: {
1255
+ type: 'string',
1256
+ },
1257
+ focalPoint: {
1258
+ type: 'object',
1259
+ },
1260
+ sizeSlug: {
1261
+ type: 'string',
1262
+ },
1263
+ linkDestination: {
1264
+ type: 'string',
1265
+ },
1266
+ linkTarget: {
1267
+ type: 'string',
1268
+ source: 'attribute',
1269
+ selector: 'figure > a',
1270
+ attribute: 'target',
1271
+ },
1272
+ },
1273
+ supports: {
1274
+ interactivity: true,
1275
+ align: [ 'left', 'center', 'right', 'wide', 'full' ],
1276
+ anchor: true,
1277
+ color: {
1278
+ text: false,
1279
+ background: false,
1280
+ },
1281
+ filter: {
1282
+ duotone: true,
1283
+ },
1284
+ spacing: {
1285
+ margin: true,
1286
+ },
1287
+ __experimentalBorder: {
1288
+ color: true,
1289
+ radius: true,
1290
+ width: true,
1291
+ __experimentalSkipSerialization: true,
1292
+ __experimentalDefaultControls: {
1293
+ color: true,
1294
+ radius: true,
1295
+ width: true,
1296
+ },
1297
+ },
1298
+ shadow: {
1299
+ __experimentalSkipSerialization: true,
1300
+ },
1301
+ },
1302
+ save( { attributes } ) {
1303
+ const {
1304
+ url,
1305
+ alt,
1306
+ caption,
1307
+ align,
1308
+ href,
1309
+ rel,
1310
+ linkClass,
1311
+ width,
1312
+ height,
1313
+ aspectRatio,
1314
+ scale,
1315
+ focalPoint,
1316
+ id,
1317
+ linkTarget,
1318
+ sizeSlug,
1319
+ title,
1320
+ metadata: { bindings = {} } = {},
1321
+ } = attributes;
1322
+
1323
+ const newRel = ! rel ? undefined : rel;
1324
+ const borderProps = getBorderClassesAndStyles( attributes );
1325
+ const shadowProps = getShadowClassesAndStyles( attributes );
1326
+
1327
+ const classes = clsx( {
1328
+ alignnone: 'none' === align,
1329
+ [ `size-${ sizeSlug }` ]: sizeSlug,
1330
+ 'is-resized': width || height,
1331
+ 'has-custom-border':
1332
+ !! borderProps.className ||
1333
+ ( borderProps.style &&
1334
+ Object.keys( borderProps.style ).length > 0 ),
1335
+ } );
1336
+
1337
+ const imageClasses = clsx( borderProps.className, {
1338
+ [ `wp-image-${ id }` ]: !! id,
1339
+ } );
1340
+
1341
+ const image = (
1342
+ <img
1343
+ src={ url }
1344
+ alt={ alt }
1345
+ className={ imageClasses || undefined }
1346
+ style={ {
1347
+ ...borderProps.style,
1348
+ ...shadowProps.style,
1349
+ aspectRatio,
1350
+ objectFit: scale,
1351
+ objectPosition:
1352
+ focalPoint && scale
1353
+ ? mediaPosition( focalPoint )
1354
+ : undefined,
1355
+ width,
1356
+ height,
1357
+ } }
1358
+ title={ title }
1359
+ />
1360
+ );
1361
+
1362
+ const displayCaption =
1363
+ ! RichText.isEmpty( caption ) ||
1364
+ bindings.caption ||
1365
+ bindings?.__default?.source === 'core/pattern-overrides';
1366
+
1367
+ const figure = (
1368
+ <>
1369
+ { href ? (
1370
+ <a
1371
+ className={ linkClass }
1372
+ href={ href }
1373
+ target={ linkTarget }
1374
+ rel={ newRel }
1375
+ >
1376
+ { image }
1377
+ </a>
1378
+ ) : (
1379
+ image
1380
+ ) }
1381
+ { displayCaption && (
1382
+ <RichText.Content
1383
+ className={ __experimentalGetElementClassName(
1384
+ 'caption'
1385
+ ) }
1386
+ tagName="figcaption"
1387
+ value={ caption }
1388
+ />
1389
+ ) }
1390
+ </>
1391
+ );
1392
+
1393
+ return (
1394
+ <figure { ...useBlockProps.save( { className: classes } ) }>
1395
+ { figure }
1396
+ </figure>
1397
+ );
1398
+ },
1399
+ };
1400
+
1401
+ export default [ v9, v8, v7, v6, v5, v4, v3, v2, v1 ];
@@ -22,7 +22,7 @@ import {
22
22
  setFeaturedImage,
23
23
  } from '@wordpress/react-native-bridge';
24
24
  import {
25
- Icon,
25
+ Icon as WCIcon,
26
26
  PanelBody,
27
27
  ToolbarButton,
28
28
  ToolbarGroup,
@@ -514,7 +514,7 @@ export class ImageEdit extends Component {
514
514
 
515
515
  getPlaceholderIcon() {
516
516
  return (
517
- <Icon
517
+ <WCIcon
518
518
  icon={ placeholderIcon }
519
519
  { ...this.props.getStylesFromColorScheme(
520
520
  styles.iconPlaceholder,
@@ -9,6 +9,7 @@ import {
9
9
  Spinner,
10
10
  TextareaControl,
11
11
  TextControl,
12
+ CheckboxControl,
12
13
  ToolbarButton,
13
14
  ToolbarGroup,
14
15
  __experimentalToolsPanel as ToolsPanel,
@@ -44,6 +45,7 @@ import {
44
45
  useCallback,
45
46
  useEffect,
46
47
  useMemo,
48
+ useRef,
47
49
  useState,
48
50
  } from '@wordpress/element';
49
51
  import { __, _x, sprintf, isRTL } from '@wordpress/i18n';
@@ -295,6 +297,7 @@ export default function Image( {
295
297
  sizeSlug,
296
298
  lightbox,
297
299
  metadata,
300
+ isDecorative,
298
301
  } = attributes;
299
302
  const [ imageElement, setImageElement ] = useState();
300
303
  const [ resizeDelta, setResizeDelta ] = useState( null );
@@ -379,9 +382,15 @@ export default function Image( {
379
382
  [ clientId ]
380
383
  );
381
384
  const { getBlock, getSettings } = useSelect( blockEditorStore );
385
+ const cropButtonRef = useRef();
386
+ const handleMediaEditorModalClose = useCallback(
387
+ () => cropButtonRef.current?.focus(),
388
+ []
389
+ );
382
390
  const openImageMediaEditorModal = useOpenImageMediaEditorModal( {
383
391
  attributes,
384
392
  setAttributes,
393
+ onClose: handleMediaEditorModalClose,
385
394
  } );
386
395
 
387
396
  const {
@@ -513,6 +522,7 @@ export default function Image( {
513
522
  if ( enable && ! lightboxSetting?.enabled ) {
514
523
  setAttributes( {
515
524
  lightbox: { enabled: true },
525
+ isDecorative: false,
516
526
  } );
517
527
  } else if ( ! enable && lightboxSetting?.enabled ) {
518
528
  setAttributes( {
@@ -551,6 +561,20 @@ export default function Image( {
551
561
  setAttributes( { alt: newAlt } );
552
562
  }
553
563
 
564
+ function updateIsDecorative( value ) {
565
+ setAttributes( {
566
+ isDecorative: value || undefined,
567
+ ...( value && {
568
+ alt: '',
569
+ caption: undefined,
570
+ href: undefined,
571
+ linkDestination: undefined,
572
+ linkTarget: undefined,
573
+ rel: undefined,
574
+ } ),
575
+ } );
576
+ }
577
+
554
578
  const imperativeFocalPointPreview = ( value ) => {
555
579
  if ( imageElement ) {
556
580
  imageElement.style.setProperty(
@@ -718,11 +742,14 @@ export default function Image( {
718
742
  lockTitleControls = false,
719
743
  lockTitleControlsMessage,
720
744
  hideCaptionControls = false,
745
+ hasSelectedStyleState = false,
721
746
  } = useSelect(
722
747
  ( select ) => {
723
748
  if ( ! isSingleSelected ) {
724
749
  return {};
725
750
  }
751
+ const { hasSelectedStyleState: hasSelectedBlockStyleState } =
752
+ unlock( select( blockEditorStore ) );
726
753
  const {
727
754
  url: urlBinding,
728
755
  alt: altBinding,
@@ -740,6 +767,7 @@ export default function Image( {
740
767
  titleBinding?.source
741
768
  );
742
769
  return {
770
+ hasSelectedStyleState: hasSelectedBlockStyleState( clientId ),
743
771
  lockUrlControls:
744
772
  !! urlBinding &&
745
773
  ! urlBindingSource?.canUserEditValue?.( {
@@ -784,6 +812,7 @@ export default function Image( {
784
812
  },
785
813
  [
786
814
  arePatternOverridesEnabled,
815
+ clientId,
787
816
  context,
788
817
  isSingleSelected,
789
818
  metadata?.bindings,
@@ -794,7 +823,8 @@ export default function Image( {
794
823
  isSingleSelected &&
795
824
  ! isEditingImage &&
796
825
  ! lockHrefControls &&
797
- ! lockUrlControls;
826
+ ! lockUrlControls &&
827
+ ! isDecorative;
798
828
 
799
829
  const showCoverControls =
800
830
  isSingleSelected && canInsertCover && ! isContentOnlyMode;
@@ -845,6 +875,7 @@ export default function Image( {
845
875
  ) }
846
876
  { allowCrop && (
847
877
  <ToolbarButton
878
+ ref={ cropButtonRef }
848
879
  onClick={
849
880
  openImageMediaEditorModal
850
881
  ? openImageMediaEditorModal
@@ -896,7 +927,10 @@ export default function Image( {
896
927
  <InspectorControls group="content">
897
928
  <ToolsPanel
898
929
  label={ __( 'Media' ) }
899
- resetAll={ () => onSelectImage( undefined ) }
930
+ resetAll={ () => {
931
+ onSelectImage( undefined );
932
+ setAttributes( { isDecorative: false } );
933
+ } }
900
934
  dropdownMenuProps={ dropdownMenuProps }
901
935
  >
902
936
  { ! lockUrlControls && (
@@ -926,24 +960,24 @@ export default function Image( {
926
960
  />
927
961
  </ToolsPanelItem>
928
962
  ) }
929
- <ToolsPanelItem
930
- label={ __( 'Alternative text' ) }
931
- isShownByDefault
932
- hasValue={ () => !! alt }
933
- onDeselect={ () =>
934
- setAttributes( { alt: undefined } )
935
- }
936
- >
937
- <TextareaControl
963
+ { ! isDecorative && (
964
+ <ToolsPanelItem
938
965
  label={ __( 'Alternative text' ) }
939
- value={ alt || '' }
940
- onChange={ updateAlt }
941
- readOnly={ lockAltControls }
942
- help={
943
- lockAltControls ? (
944
- <>{ lockAltControlsMessage }</>
945
- ) : (
946
- <>
966
+ isShownByDefault
967
+ hasValue={ () => !! alt }
968
+ onDeselect={ () =>
969
+ setAttributes( { alt: undefined } )
970
+ }
971
+ >
972
+ <TextareaControl
973
+ label={ __( 'Alternative text' ) }
974
+ value={ alt || '' }
975
+ onChange={ updateAlt }
976
+ readOnly={ lockAltControls }
977
+ help={
978
+ lockAltControls ? (
979
+ <>{ lockAltControlsMessage }</>
980
+ ) : (
947
981
  <ExternalLink
948
982
  href={
949
983
  // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations.
@@ -956,57 +990,75 @@ export default function Image( {
956
990
  'Describe the purpose of the image.'
957
991
  ) }
958
992
  </ExternalLink>
959
- <br />
960
- { __(
961
- 'Leave empty if decorative.'
962
- ) }
963
- </>
964
- )
993
+ )
994
+ }
995
+ />
996
+ </ToolsPanelItem>
997
+ ) }
998
+
999
+ { ! lockAltControls && ! lightboxChecked && (
1000
+ <ToolsPanelItem
1001
+ label={ __( 'Mark as decorative' ) }
1002
+ isShownByDefault
1003
+ hasValue={ () => !! isDecorative }
1004
+ onDeselect={ () =>
1005
+ setAttributes( { isDecorative: false } )
965
1006
  }
966
- />
967
- </ToolsPanelItem>
1007
+ >
1008
+ <CheckboxControl
1009
+ label={ __( 'Mark as decorative' ) }
1010
+ checked={ !! isDecorative }
1011
+ onChange={ updateIsDecorative }
1012
+ help={ __(
1013
+ 'Hidden from assistive technologies.'
1014
+ ) }
1015
+ />
1016
+ </ToolsPanelItem>
1017
+ ) }
968
1018
  </ToolsPanel>
969
1019
  </InspectorControls>
970
1020
  ) }
971
- <InspectorControls
972
- group="dimensions"
973
- resetAllFilter={ ( attrs ) => ( {
974
- ...attrs,
975
- aspectRatio: undefined,
976
- width: undefined,
977
- height: undefined,
978
- scale: undefined,
979
- focalPoint: undefined,
980
- } ) }
981
- >
982
- { dimensionsControl }
983
- { url && scale && (
984
- <ToolsPanelItem
985
- label={ __( 'Focal point' ) }
986
- isShownByDefault
987
- hasValue={ () => !! focalPoint }
988
- onDeselect={ () =>
989
- setAttributes( {
990
- focalPoint: undefined,
991
- } )
992
- }
993
- panelId={ clientId }
994
- >
995
- <FocalPointPicker
1021
+ { ! hasSelectedStyleState && (
1022
+ <InspectorControls
1023
+ group="dimensions"
1024
+ resetAllFilter={ ( attrs ) => ( {
1025
+ ...attrs,
1026
+ aspectRatio: undefined,
1027
+ width: undefined,
1028
+ height: undefined,
1029
+ scale: undefined,
1030
+ focalPoint: undefined,
1031
+ } ) }
1032
+ >
1033
+ { dimensionsControl }
1034
+ { url && scale && (
1035
+ <ToolsPanelItem
996
1036
  label={ __( 'Focal point' ) }
997
- url={ url }
998
- value={ focalPoint }
999
- onDragStart={ imperativeFocalPointPreview }
1000
- onDrag={ imperativeFocalPointPreview }
1001
- onChange={ ( newFocalPoint ) =>
1037
+ isShownByDefault
1038
+ hasValue={ () => !! focalPoint }
1039
+ onDeselect={ () =>
1002
1040
  setAttributes( {
1003
- focalPoint: newFocalPoint,
1041
+ focalPoint: undefined,
1004
1042
  } )
1005
1043
  }
1006
- />
1007
- </ToolsPanelItem>
1008
- ) }
1009
- </InspectorControls>
1044
+ panelId={ clientId }
1045
+ >
1046
+ <FocalPointPicker
1047
+ label={ __( 'Focal point' ) }
1048
+ url={ url }
1049
+ value={ focalPoint }
1050
+ onDragStart={ imperativeFocalPointPreview }
1051
+ onDrag={ imperativeFocalPointPreview }
1052
+ onChange={ ( newFocalPoint ) =>
1053
+ setAttributes( {
1054
+ focalPoint: newFocalPoint,
1055
+ } )
1056
+ }
1057
+ />
1058
+ </ToolsPanelItem>
1059
+ ) }
1060
+ </InspectorControls>
1061
+ ) }
1010
1062
  { !! imageSizeOptions.length && (
1011
1063
  <InspectorControls>
1012
1064
  <ToolsPanel
@@ -1054,7 +1106,17 @@ export default function Image( {
1054
1106
  const filename = getFilename( url );
1055
1107
  let defaultedAlt;
1056
1108
 
1057
- if ( alt ) {
1109
+ if ( isDecorative ) {
1110
+ defaultedAlt = filename
1111
+ ? sprintf(
1112
+ /* translators: %s: file name */
1113
+ __(
1114
+ 'This image has been marked as decorative; its file name is %s'
1115
+ ),
1116
+ filename
1117
+ )
1118
+ : __( 'This image has been marked as decorative.' );
1119
+ } else if ( alt ) {
1058
1120
  defaultedAlt = alt;
1059
1121
  } else if ( filename ) {
1060
1122
  defaultedAlt = sprintf(
@@ -1102,7 +1164,33 @@ export default function Image( {
1102
1164
  height:
1103
1165
  pixelSize.height + resizeDelta.height,
1104
1166
  }
1105
- : { width, height } ),
1167
+ : ( () => {
1168
+ const style = {};
1169
+ if ( width === 'auto' ) {
1170
+ style.width = 'auto';
1171
+ } else if (
1172
+ width !== undefined &&
1173
+ width !== null
1174
+ ) {
1175
+ style.width =
1176
+ typeof width === 'number'
1177
+ ? `${ width }px`
1178
+ : width;
1179
+ }
1180
+ if (
1181
+ height === 'auto' ||
1182
+ height === undefined ||
1183
+ height === null
1184
+ ) {
1185
+ style.height = 'auto';
1186
+ } else {
1187
+ style.height =
1188
+ typeof height === 'number'
1189
+ ? `${ height }px`
1190
+ : height;
1191
+ }
1192
+ return style;
1193
+ } )() ),
1106
1194
  objectFit: scale,
1107
1195
  objectPosition:
1108
1196
  focalPoint && scale
@@ -1309,18 +1397,20 @@ export default function Image( {
1309
1397
  { img }
1310
1398
  { resizableBox }
1311
1399
 
1312
- <Caption
1313
- attributes={ attributes }
1314
- setAttributes={ setAttributes }
1315
- isSelected={ isSingleSelected }
1316
- insertBlocksAfter={ insertBlocksAfter }
1317
- label={ __( 'Image caption text' ) }
1318
- showToolbarButton={
1319
- isSingleSelected &&
1320
- ( hasNonContentControls || isContentOnlyMode ) &&
1321
- ! hideCaptionControls
1322
- }
1323
- />
1400
+ { ! isDecorative && (
1401
+ <Caption
1402
+ attributes={ attributes }
1403
+ setAttributes={ setAttributes }
1404
+ isSelected={ isSingleSelected }
1405
+ insertBlocksAfter={ insertBlocksAfter }
1406
+ label={ __( 'Image caption text' ) }
1407
+ showToolbarButton={
1408
+ isSingleSelected &&
1409
+ ( hasNonContentControls || isContentOnlyMode ) &&
1410
+ ! hideCaptionControls
1411
+ }
1412
+ />
1413
+ ) }
1324
1414
  </>
1325
1415
  );
1326
1416
  }
@@ -108,21 +108,40 @@ if ( window.__experimentalContentOnlyInspectorFields ) {
108
108
  rel: value.rel,
109
109
  linkTarget: value.linkTarget,
110
110
  } ),
111
+ isVisible: ( item ) => ! item.isDecorative,
111
112
  },
112
113
  {
113
114
  id: 'caption',
114
115
  label: __( 'Caption' ),
115
116
  type: 'text',
116
117
  Edit: 'rich-text', // TODO: replace with custom component
118
+ isVisible: ( item ) => ! item.isDecorative,
117
119
  },
118
120
  {
119
121
  id: 'alt',
120
122
  label: __( 'Alt text' ),
121
123
  type: 'text',
124
+ isVisible: ( item ) => ! item.isDecorative,
125
+ },
126
+ {
127
+ id: 'isDecorative',
128
+ label: __( 'Mark as decorative' ),
129
+ type: 'boolean',
130
+ setValue: ( { value } ) => ( {
131
+ isDecorative: value || undefined,
132
+ ...( value && {
133
+ alt: '',
134
+ caption: undefined,
135
+ href: undefined,
136
+ linkDestination: undefined,
137
+ linkTarget: undefined,
138
+ rel: undefined,
139
+ } ),
140
+ } ),
122
141
  },
123
142
  ];
124
143
  settings[ formKey ] = {
125
- fields: [ 'image', 'link', 'caption', 'alt' ],
144
+ fields: [ 'image', 'link', 'caption', 'alt', 'isDecorative' ],
126
145
  };
127
146
  }
128
147
 
@@ -250,7 +250,7 @@ function block_core_image_render_lightbox( $block_content, $block, $block_instan
250
250
  'galleryId' => $block_instance->context['galleryId'] ?? null,
251
251
  'customAriaLabel' => $custom_aria_label ?? null,
252
252
  'navigationButtonType' => $block_instance->context['navigationButtonType'] ?? 'icon',
253
- 'triggerButtonAriaLabel' => null,
253
+ 'triggerButtonAriaLabel' => __( 'Enlarge' ),
254
254
  ),
255
255
  ),
256
256
  )