@wordpress/block-library 9.0.1 → 9.1.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 (63) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/comment-date/edit.js +1 -1
  3. package/build/comment-date/edit.js.map +1 -1
  4. package/build/list-item/edit.native.js +1 -15
  5. package/build/list-item/edit.native.js.map +1 -1
  6. package/build/missing/edit.native.js +29 -4
  7. package/build/missing/edit.native.js.map +1 -1
  8. package/build/post-content/index.js +13 -1
  9. package/build/post-content/index.js.map +1 -1
  10. package/build/post-date/edit.js +1 -1
  11. package/build/post-date/edit.js.map +1 -1
  12. package/build/pullquote/index.js +13 -0
  13. package/build/pullquote/index.js.map +1 -1
  14. package/build/query/edit/inspector-controls/create-new-post-link.js +10 -10
  15. package/build/query/edit/inspector-controls/create-new-post-link.js.map +1 -1
  16. package/build/query/edit/inspector-controls/index.js +2 -2
  17. package/build/query/edit/inspector-controls/index.js.map +1 -1
  18. package/build/quote/index.js +13 -0
  19. package/build/quote/index.js.map +1 -1
  20. package/build/verse/index.js +13 -0
  21. package/build/verse/index.js.map +1 -1
  22. package/build-module/comment-date/edit.js +2 -2
  23. package/build-module/comment-date/edit.js.map +1 -1
  24. package/build-module/list-item/edit.native.js +2 -16
  25. package/build-module/list-item/edit.native.js.map +1 -1
  26. package/build-module/missing/edit.native.js +30 -5
  27. package/build-module/missing/edit.native.js.map +1 -1
  28. package/build-module/post-content/index.js +13 -1
  29. package/build-module/post-content/index.js.map +1 -1
  30. package/build-module/post-date/edit.js +2 -2
  31. package/build-module/post-date/edit.js.map +1 -1
  32. package/build-module/pullquote/index.js +13 -0
  33. package/build-module/pullquote/index.js.map +1 -1
  34. package/build-module/query/edit/inspector-controls/create-new-post-link.js +10 -10
  35. package/build-module/query/edit/inspector-controls/create-new-post-link.js.map +1 -1
  36. package/build-module/query/edit/inspector-controls/index.js +2 -2
  37. package/build-module/query/edit/inspector-controls/index.js.map +1 -1
  38. package/build-module/quote/index.js +13 -0
  39. package/build-module/quote/index.js.map +1 -1
  40. package/build-module/verse/index.js +13 -0
  41. package/build-module/verse/index.js.map +1 -1
  42. package/build-style/editor-rtl.css +0 -11
  43. package/build-style/editor.css +0 -11
  44. package/build-style/navigation/editor-rtl.css +0 -11
  45. package/build-style/navigation/editor.css +0 -11
  46. package/package.json +35 -35
  47. package/src/buttons/test/edit.native.js +48 -8
  48. package/src/comment-date/edit.js +8 -2
  49. package/src/comment-date/index.php +7 -5
  50. package/src/list-item/edit.native.js +2 -22
  51. package/src/missing/edit.native.js +44 -12
  52. package/src/missing/test/__snapshots__/edit.native.js.snap +75 -59
  53. package/src/navigation/editor.scss +0 -12
  54. package/src/post-content/block.json +13 -1
  55. package/src/post-date/edit.js +8 -2
  56. package/src/post-date/index.php +14 -3
  57. package/src/pullquote/block.json +13 -0
  58. package/src/query/edit/inspector-controls/create-new-post-link.js +12 -8
  59. package/src/query/edit/inspector-controls/index.js +5 -3
  60. package/src/quote/block.json +13 -0
  61. package/src/site-logo/index.php +6 -0
  62. package/src/social-links/test/edit.native.js +41 -5
  63. package/src/verse/block.json +13 -0
@@ -10,6 +10,7 @@ import {
10
10
  initializeEditor,
11
11
  triggerBlockListLayout,
12
12
  typeInRichText,
13
+ screen,
13
14
  openBlockSettings,
14
15
  waitFor,
15
16
  } from 'test/helpers';
@@ -92,7 +93,7 @@ describe( 'Buttons block', () => {
92
93
  } );
93
94
 
94
95
  it( 'adds another button using the inline appender', async () => {
95
- const screen = await initializeEditor( {
96
+ await initializeEditor( {
96
97
  initialHtml: BUTTONS_HTML,
97
98
  } );
98
99
 
@@ -143,7 +144,7 @@ describe( 'Buttons block', () => {
143
144
  } );
144
145
 
145
146
  it( 'adds another button using the inserter', async () => {
146
- const screen = await initializeEditor( {
147
+ await initializeEditor( {
147
148
  initialHtml: BUTTONS_HTML,
148
149
  } );
149
150
 
@@ -202,9 +203,48 @@ describe( 'Buttons block', () => {
202
203
  expect( getEditorHtml() ).toMatchSnapshot();
203
204
  } );
204
205
 
206
+ it( 'shows only the button block when using the inserter', async () => {
207
+ await initializeEditor();
208
+
209
+ // Add block
210
+ await addBlock( screen, 'Buttons' );
211
+
212
+ // Get block
213
+ const buttonsBlock = await getBlock( screen, 'Buttons' );
214
+ fireEvent.press( buttonsBlock );
215
+ await triggerBlockListLayout( buttonsBlock );
216
+
217
+ // Get inner button block
218
+ const buttonBlock = await getBlock( screen, 'Button' );
219
+ fireEvent.press( buttonBlock );
220
+
221
+ // Open the block inserter
222
+ fireEvent.press( screen.getByLabelText( 'Add block' ) );
223
+
224
+ const inserterList = screen.getByTestId( 'InserterUI-Blocks' );
225
+ // onScroll event used to force the FlatList to render all items
226
+ fireEvent.scroll( inserterList, {
227
+ nativeEvent: {
228
+ contentOffset: { y: 0, x: 0 },
229
+ contentSize: { width: 100, height: 100 },
230
+ layoutMeasurement: { width: 100, height: 100 },
231
+ },
232
+ } );
233
+
234
+ // Check the Button block is in the list
235
+ const buttonInserterBlock =
236
+ await within( inserterList ).findByText( 'Button' );
237
+ expect( buttonInserterBlock ).toBeVisible();
238
+
239
+ // Check the Paragraph core block is not in the list
240
+ expect(
241
+ within( inserterList ).queryByLabelText( 'Paragraph block' )
242
+ ).toBeNull();
243
+ } );
244
+
205
245
  describe( 'removing button along with buttons block', () => {
206
246
  it( 'removes the button and buttons block when deleting the block using the block delete action', async () => {
207
- const screen = await initializeEditor( {
247
+ await initializeEditor( {
208
248
  initialHtml: BUTTONS_HTML,
209
249
  } );
210
250
 
@@ -250,7 +290,7 @@ describe( 'Buttons block', () => {
250
290
  'Justify items right',
251
291
  ].forEach( ( justificationOption ) =>
252
292
  it( `sets ${ justificationOption } option`, async () => {
253
- const screen = await initializeEditor( {
293
+ await initializeEditor( {
254
294
  initialHtml: BUTTONS_HTML,
255
295
  } );
256
296
 
@@ -276,7 +316,7 @@ describe( 'Buttons block', () => {
276
316
  describe( 'color customization', () => {
277
317
  it( 'sets a text color', async () => {
278
318
  // Arrange
279
- const screen = await initializeEditor();
319
+ await initializeEditor();
280
320
  await addBlock( screen, 'Buttons' );
281
321
 
282
322
  // Act
@@ -317,7 +357,7 @@ describe( 'Buttons block', () => {
317
357
 
318
358
  it( 'sets a background color', async () => {
319
359
  // Arrange
320
- const screen = await initializeEditor();
360
+ await initializeEditor();
321
361
  await addBlock( screen, 'Buttons' );
322
362
 
323
363
  // Act
@@ -354,7 +394,7 @@ describe( 'Buttons block', () => {
354
394
 
355
395
  it( 'sets a gradient background color', async () => {
356
396
  // Arrange
357
- const screen = await initializeEditor();
397
+ await initializeEditor();
358
398
  await addBlock( screen, 'Buttons' );
359
399
 
360
400
  // Act
@@ -396,7 +436,7 @@ describe( 'Buttons block', () => {
396
436
 
397
437
  it( 'sets a custom gradient background color', async () => {
398
438
  // Arrange
399
- const screen = await initializeEditor();
439
+ await initializeEditor();
400
440
  await addBlock( screen, 'Buttons' );
401
441
 
402
442
  // Act
@@ -2,7 +2,11 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { useEntityProp } from '@wordpress/core-data';
5
- import { dateI18n, getSettings as getDateSettings } from '@wordpress/date';
5
+ import {
6
+ dateI18n,
7
+ humanTimeDiff,
8
+ getSettings as getDateSettings,
9
+ } from '@wordpress/date';
6
10
  import {
7
11
  InspectorControls,
8
12
  useBlockProps,
@@ -64,7 +68,9 @@ export default function Edit( {
64
68
  let commentDate =
65
69
  date instanceof Date ? (
66
70
  <time dateTime={ dateI18n( 'c', date ) }>
67
- { dateI18n( format || siteFormat, date ) }
71
+ { format === 'human-diff'
72
+ ? humanTimeDiff( date )
73
+ : dateI18n( format || siteFormat, date ) }
68
74
  </time>
69
75
  ) : (
70
76
  <time>{ date }</time>
@@ -28,11 +28,13 @@ function render_block_core_comment_date( $attributes, $content, $block ) {
28
28
  $classes = ( isset( $attributes['style']['elements']['link']['color']['text'] ) ) ? 'has-link-color' : '';
29
29
 
30
30
  $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) );
31
- $formatted_date = get_comment_date(
32
- isset( $attributes['format'] ) ? $attributes['format'] : '',
33
- $comment
34
- );
35
- $link = get_comment_link( $comment );
31
+ if ( isset( $attributes['format'] ) && 'human-diff' === $attributes['format'] ) {
32
+ // translators: %s: human-readable time difference.
33
+ $formatted_date = sprintf( __( '%s ago', 'gutenberg' ), human_time_diff( get_comment_date( 'U', $comment ) ) );
34
+ } else {
35
+ $formatted_date = get_comment_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $comment );
36
+ }
37
+ $link = get_comment_link( $comment );
36
38
 
37
39
  if ( ! empty( $attributes['isLink'] ) ) {
38
40
  $formatted_date = sprintf( '<a href="%1s">%2s</a>', esc_url( $link ), $formatted_date );
@@ -21,8 +21,7 @@ import { useState, useCallback, useRef } from '@wordpress/element';
21
21
  /**
22
22
  * Internal dependencies
23
23
  */
24
- import { useSplit, useMerge, useEnter } from './hooks';
25
- import { convertToListItems } from './utils';
24
+ import { useMerge, useEnter } from './hooks';
26
25
  import { IndentUI } from './edit.js';
27
26
  import styles from './style.scss';
28
27
  import ListStyleType from './list-style-type';
@@ -32,7 +31,6 @@ const OPACITY = '9e';
32
31
  export default function ListItemEdit( {
33
32
  attributes,
34
33
  setAttributes,
35
- onReplace,
36
34
  clientId,
37
35
  style,
38
36
  mergeBlocks,
@@ -118,24 +116,7 @@ export default function ListItemEdit( {
118
116
 
119
117
  const preventDefault = useRef( false );
120
118
  const { onEnter } = useEnter( { content, clientId }, preventDefault );
121
- const onSplit = useSplit( clientId );
122
119
  const onMerge = useMerge( clientId, mergeBlocks );
123
- const onSplitList = useCallback(
124
- ( value ) => {
125
- if ( ! preventDefault.current ) {
126
- return onSplit( value );
127
- }
128
- },
129
- [ clientId, onSplit ]
130
- );
131
- const onReplaceList = useCallback(
132
- ( blocks, ...args ) => {
133
- if ( ! preventDefault.current ) {
134
- onReplace( convertToListItems( blocks ), ...args );
135
- }
136
- },
137
- [ clientId, onReplace, convertToListItems ]
138
- );
139
120
  const onLayout = useCallback( ( { nativeEvent } ) => {
140
121
  setContentWidth( ( prevState ) => {
141
122
  const { width } = nativeEvent.layout;
@@ -166,6 +147,7 @@ export default function ListItemEdit( {
166
147
  onLayout={ onLayout }
167
148
  >
168
149
  <RichText
150
+ __unstableUseSplitSelection
169
151
  identifier="content"
170
152
  tagName="p"
171
153
  onChange={ ( nextContent ) =>
@@ -176,9 +158,7 @@ export default function ListItemEdit( {
176
158
  placeholderTextColor={
177
159
  defaultPlaceholderTextColorWithOpacity
178
160
  }
179
- onSplit={ onSplitList }
180
161
  onMerge={ onMerge }
181
- onReplace={ onReplaceList }
182
162
  onEnter={ onEnter }
183
163
  style={ styleWithPlaceholderOpacity }
184
164
  deleteEnter
@@ -1,12 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import {
5
- View,
6
- Text,
7
- TouchableWithoutFeedback,
8
- TouchableOpacity,
9
- } from 'react-native';
4
+ import { View, Text, TouchableOpacity } from 'react-native';
10
5
 
11
6
  /**
12
7
  * WordPress dependencies
@@ -25,6 +20,7 @@ import {
25
20
  store as blockEditorStore,
26
21
  } from '@wordpress/block-editor';
27
22
  import { store as noticesStore } from '@wordpress/notices';
23
+ import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge';
28
24
 
29
25
  /**
30
26
  * Internal dependencies
@@ -48,11 +44,40 @@ export class UnsupportedBlockEdit extends Component {
48
44
  }
49
45
 
50
46
  toggleSheet() {
47
+ const { attributes, block, clientId } = this.props;
48
+ const { originalName } = attributes;
49
+ const title = this.getTitle();
50
+ const blockContent = serialize( block ? [ block ] : [] );
51
+
52
+ if ( this.canEditUnsupportedBlock() ) {
53
+ requestUnsupportedBlockFallback(
54
+ blockContent,
55
+ clientId,
56
+ originalName,
57
+ title
58
+ );
59
+ return;
60
+ }
61
+
51
62
  this.setState( {
52
63
  showHelp: ! this.state.showHelp,
53
64
  } );
54
65
  }
55
66
 
67
+ canEditUnsupportedBlock() {
68
+ const {
69
+ canEnableUnsupportedBlockEditor,
70
+ isEditableInUnsupportedBlockEditor,
71
+ isUnsupportedBlockEditorSupported,
72
+ } = this.props;
73
+
74
+ return (
75
+ ! canEnableUnsupportedBlockEditor &&
76
+ isUnsupportedBlockEditorSupported &&
77
+ isEditableInUnsupportedBlockEditor
78
+ );
79
+ }
80
+
56
81
  closeSheet() {
57
82
  this.setState( {
58
83
  showHelp: false,
@@ -171,7 +196,8 @@ export class UnsupportedBlockEdit extends Component {
171
196
 
172
197
  render() {
173
198
  const { originalName } = this.props.attributes;
174
- const { getStylesFromColorScheme, preferredColorScheme } = this.props;
199
+ const { isSelected, getStylesFromColorScheme, preferredColorScheme } =
200
+ this.props;
175
201
  const blockType = coreBlocks[ originalName ];
176
202
 
177
203
  const title = this.getTitle();
@@ -186,7 +212,11 @@ export class UnsupportedBlockEdit extends Component {
186
212
  );
187
213
 
188
214
  const subtitle = (
189
- <Text style={ subTitleStyle }>{ __( 'Unsupported' ) }</Text>
215
+ <Text style={ subTitleStyle }>
216
+ { this.canEditUnsupportedBlock()
217
+ ? __( 'Tap to edit' )
218
+ : __( 'Unsupported' ) }
219
+ </Text>
190
220
  );
191
221
 
192
222
  const icon = blockType
@@ -198,8 +228,9 @@ export class UnsupportedBlockEdit extends Component {
198
228
  );
199
229
  const iconClassName = 'unsupported-icon' + '-' + preferredColorScheme;
200
230
  return (
201
- <TouchableWithoutFeedback
202
- disabled={ ! this.props.isSelected }
231
+ <TouchableOpacity
232
+ disabled={ ! isSelected }
233
+ activeOpacity={ 0.5 }
203
234
  accessibilityLabel={ __( 'Help button' ) }
204
235
  accessibilityRole="button"
205
236
  accessibilityHint={ __( 'Tap here to show help' ) }
@@ -211,7 +242,8 @@ export class UnsupportedBlockEdit extends Component {
211
242
  styles.unsupportedBlockDark
212
243
  ) }
213
244
  >
214
- { this.renderHelpIcon() }
245
+ { ! this.canEditUnsupportedBlock() &&
246
+ this.renderHelpIcon() }
215
247
  <View style={ styles.unsupportedBlockHeader }>
216
248
  <Icon
217
249
  className={ iconClassName }
@@ -223,7 +255,7 @@ export class UnsupportedBlockEdit extends Component {
223
255
  { subtitle }
224
256
  { this.renderSheet( title, originalName ) }
225
257
  </View>
226
- </TouchableWithoutFeedback>
258
+ </TouchableOpacity>
227
259
  );
228
260
  }
229
261
  }
@@ -14,7 +14,16 @@ exports[`Missing block renders without crashing 1`] = `
14
14
  "selected": undefined,
15
15
  }
16
16
  }
17
+ accessibilityValue={
18
+ {
19
+ "max": undefined,
20
+ "min": undefined,
21
+ "now": undefined,
22
+ "text": undefined,
23
+ }
24
+ }
17
25
  accessible={true}
26
+ collapsable={false}
18
27
  focusable={true}
19
28
  onClick={[Function]}
20
29
  onResponderGrant={[Function]}
@@ -23,72 +32,79 @@ exports[`Missing block renders without crashing 1`] = `
23
32
  onResponderTerminate={[Function]}
24
33
  onResponderTerminationRequest={[Function]}
25
34
  onStartShouldSetResponder={[Function]}
35
+ style={
36
+ {
37
+ "opacity": 1,
38
+ }
39
+ }
26
40
  >
27
- <View
28
- accessibilityHint="Tap here to show help"
29
- accessibilityLabel="Help button"
30
- accessibilityRole="button"
31
- accessibilityState={
32
- {
33
- "busy": undefined,
34
- "checked": undefined,
35
- "disabled": undefined,
36
- "expanded": undefined,
37
- "selected": undefined,
41
+ <View>
42
+ <View
43
+ accessibilityHint="Tap here to show help"
44
+ accessibilityLabel="Help button"
45
+ accessibilityRole="button"
46
+ accessibilityState={
47
+ {
48
+ "busy": undefined,
49
+ "checked": undefined,
50
+ "disabled": undefined,
51
+ "expanded": undefined,
52
+ "selected": undefined,
53
+ }
38
54
  }
39
- }
40
- accessibilityValue={
41
- {
42
- "max": undefined,
43
- "min": undefined,
44
- "now": undefined,
45
- "text": undefined,
55
+ accessibilityValue={
56
+ {
57
+ "max": undefined,
58
+ "min": undefined,
59
+ "now": undefined,
60
+ "text": undefined,
61
+ }
46
62
  }
47
- }
48
- accessible={true}
49
- collapsable={false}
50
- focusable={true}
51
- onClick={[Function]}
52
- onResponderGrant={[Function]}
53
- onResponderMove={[Function]}
54
- onResponderRelease={[Function]}
55
- onResponderTerminate={[Function]}
56
- onResponderTerminationRequest={[Function]}
57
- onStartShouldSetResponder={[Function]}
58
- style={
59
- {
60
- "opacity": 1,
63
+ accessible={true}
64
+ collapsable={false}
65
+ focusable={true}
66
+ onClick={[Function]}
67
+ onResponderGrant={[Function]}
68
+ onResponderMove={[Function]}
69
+ onResponderRelease={[Function]}
70
+ onResponderTerminate={[Function]}
71
+ onResponderTerminationRequest={[Function]}
72
+ onStartShouldSetResponder={[Function]}
73
+ style={
74
+ {
75
+ "opacity": 1,
76
+ }
61
77
  }
62
- }
63
- >
64
- <Svg
65
- height={24}
66
- label="Help icon"
67
- style={{}}
68
- viewBox="0 0 24 24"
69
- width={24}
70
- xmlns="http://www.w3.org/2000/svg"
71
- >
72
- Path
73
- </Svg>
74
- </View>
75
- <View>
76
- <Svg
77
- fill="white"
78
- height={24}
79
- style={{}}
80
- viewBox="0 0 24 24"
81
- width={24}
82
- xmlns="http://www.w3.org/2000/svg"
83
78
  >
84
- Path
85
- </Svg>
79
+ <Svg
80
+ height={24}
81
+ label="Help icon"
82
+ style={{}}
83
+ viewBox="0 0 24 24"
84
+ width={24}
85
+ xmlns="http://www.w3.org/2000/svg"
86
+ >
87
+ Path
88
+ </Svg>
89
+ </View>
90
+ <View>
91
+ <Svg
92
+ fill="white"
93
+ height={24}
94
+ style={{}}
95
+ viewBox="0 0 24 24"
96
+ width={24}
97
+ xmlns="http://www.w3.org/2000/svg"
98
+ >
99
+ Path
100
+ </Svg>
101
+ <Text>
102
+ missing/block/title
103
+ </Text>
104
+ </View>
86
105
  <Text>
87
- missing/block/title
106
+ Unsupported
88
107
  </Text>
89
108
  </View>
90
- <Text>
91
- Unsupported
92
- </Text>
93
109
  </View>
94
110
  `;
@@ -457,12 +457,6 @@ $color-control-label-height: 20px;
457
457
  }
458
458
  }
459
459
 
460
- .has-fixed-toolbar .wp-block-navigation__responsive-container.is-menu-open {
461
- @include break-medium() {
462
- top: $admin-bar-height + $header-height + $block-toolbar-height + $border-width;
463
- }
464
- }
465
-
466
460
  .is-mobile-preview .wp-block-navigation__responsive-container.is-menu-open,
467
461
  .is-tablet-preview .wp-block-navigation__responsive-container.is-menu-open {
468
462
  top: $admin-bar-height + $header-height + $block-toolbar-height + $border-width;
@@ -479,12 +473,6 @@ $color-control-label-height: 20px;
479
473
  }
480
474
  }
481
475
 
482
- .has-fixed-toolbar .wp-block-navigation__responsive-container.is-menu-open {
483
- @include break-medium() {
484
- top: $header-height + $block-toolbar-height + $border-width;
485
- }
486
- }
487
-
488
476
  .is-mobile-preview .wp-block-navigation__responsive-container.is-menu-open,
489
477
  .is-tablet-preview .wp-block-navigation__responsive-container.is-menu-open {
490
478
  top: $header-height + $block-toolbar-height + $border-width;
@@ -11,11 +11,23 @@
11
11
  "align": [ "wide", "full" ],
12
12
  "html": false,
13
13
  "layout": true,
14
+ "background": {
15
+ "backgroundImage": true,
16
+ "backgroundSize": true,
17
+ "__experimentalDefaultControls": {
18
+ "backgroundImage": true
19
+ }
20
+ },
14
21
  "dimensions": {
15
22
  "minHeight": true
16
23
  },
17
24
  "spacing": {
18
- "blockGap": true
25
+ "blockGap": true,
26
+ "padding": true,
27
+ "__experimentalDefaultControls": {
28
+ "margin": false,
29
+ "padding": false
30
+ }
19
31
  },
20
32
  "color": {
21
33
  "gradients": true,
@@ -8,7 +8,11 @@ import clsx from 'clsx';
8
8
  */
9
9
  import { useEntityProp, store as coreStore } from '@wordpress/core-data';
10
10
  import { useMemo, useState } from '@wordpress/element';
11
- import { dateI18n, getSettings as getDateSettings } from '@wordpress/date';
11
+ import {
12
+ dateI18n,
13
+ humanTimeDiff,
14
+ getSettings as getDateSettings,
15
+ } from '@wordpress/date';
12
16
  import {
13
17
  AlignmentControl,
14
18
  BlockControls,
@@ -82,7 +86,9 @@ export default function PostDateEdit( {
82
86
 
83
87
  let postDate = date ? (
84
88
  <time dateTime={ dateI18n( 'c', date ) } ref={ setPopoverAnchor }>
85
- { dateI18n( format || siteFormat, date ) }
89
+ { format === 'human-diff'
90
+ ? humanTimeDiff( date )
91
+ : dateI18n( format || siteFormat, date ) }
86
92
  </time>
87
93
  ) : (
88
94
  dateLabel
@@ -20,8 +20,14 @@ function render_block_core_post_date( $attributes, $content, $block ) {
20
20
  return '';
21
21
  }
22
22
 
23
- $post_ID = $block->context['postId'];
24
- $formatted_date = get_the_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $post_ID );
23
+ $post_ID = $block->context['postId'];
24
+
25
+ if ( isset( $attributes['format'] ) && 'human-diff' === $attributes['format'] ) {
26
+ // translators: %s: human-readable time difference.
27
+ $formatted_date = sprintf( __( '%s ago', 'gutenberg' ), human_time_diff( get_post_timestamp( $post_ID ) ) );
28
+ } else {
29
+ $formatted_date = get_the_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $post_ID );
30
+ }
25
31
  $unformatted_date = esc_attr( get_the_date( 'c', $post_ID ) );
26
32
  $classes = array();
27
33
 
@@ -38,7 +44,12 @@ function render_block_core_post_date( $attributes, $content, $block ) {
38
44
  */
39
45
  if ( isset( $attributes['displayType'] ) && 'modified' === $attributes['displayType'] ) {
40
46
  if ( get_the_modified_date( 'Ymdhi', $post_ID ) > get_the_date( 'Ymdhi', $post_ID ) ) {
41
- $formatted_date = get_the_modified_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $post_ID );
47
+ if ( 'human-diff' === $attributes['format'] ) {
48
+ // translators: %s: human-readable time difference.
49
+ $formatted_date = sprintf( __( '%s ago', 'gutenberg' ), human_time_diff( get_post_timestamp( $post_ID, 'modified' ) ) );
50
+ } else {
51
+ $formatted_date = get_the_modified_date( empty( $attributes['format'] ) ? '' : $attributes['format'], $post_ID );
52
+ }
42
53
  $unformatted_date = esc_attr( get_the_modified_date( 'c', $post_ID ) );
43
54
  $classes[] = 'wp-block-post-date__modified-date';
44
55
  } else {
@@ -26,6 +26,13 @@
26
26
  "supports": {
27
27
  "anchor": true,
28
28
  "align": [ "left", "right", "wide", "full" ],
29
+ "background": {
30
+ "backgroundImage": true,
31
+ "backgroundSize": true,
32
+ "__experimentalDefaultControls": {
33
+ "backgroundImage": true
34
+ }
35
+ },
29
36
  "color": {
30
37
  "gradients": true,
31
38
  "background": true,
@@ -35,6 +42,12 @@
35
42
  "text": true
36
43
  }
37
44
  },
45
+ "dimensions": {
46
+ "minHeight": true,
47
+ "__experimentalDefaultControls": {
48
+ "minHeight": false
49
+ }
50
+ },
38
51
  "spacing": {
39
52
  "margin": true,
40
53
  "padding": true
@@ -1,23 +1,27 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { __ } from '@wordpress/i18n';
5
4
  import { createInterpolateElement } from '@wordpress/element';
6
5
  import { addQueryArgs } from '@wordpress/url';
6
+ import { store as coreStore } from '@wordpress/core-data';
7
+ import { useSelect } from '@wordpress/data';
7
8
 
8
- const CreateNewPostLink = ( {
9
- attributes: { query: { postType } = {} } = {},
10
- } ) => {
11
- if ( ! postType ) {
12
- return null;
13
- }
9
+ const CreateNewPostLink = ( { postType } ) => {
14
10
  const newPostUrl = addQueryArgs( 'post-new.php', {
15
11
  post_type: postType,
16
12
  } );
13
+
14
+ const addNewItemLabel = useSelect(
15
+ ( select ) => {
16
+ const { getPostType } = select( coreStore );
17
+ return getPostType( postType )?.labels?.add_new_item;
18
+ },
19
+ [ postType ]
20
+ );
17
21
  return (
18
22
  <div className="wp-block-query__create-new-link">
19
23
  { createInterpolateElement(
20
- __( '<a>Add new post</a>' ),
24
+ '<a>' + addNewItemLabel + '</a>',
21
25
  // eslint-disable-next-line jsx-a11y/anchor-has-content
22
26
  { a: <a href={ newPostUrl } /> }
23
27
  ) }
@@ -131,9 +131,11 @@ export default function QueryInspectorControls( props ) {
131
131
 
132
132
  return (
133
133
  <>
134
- <BlockInfo>
135
- <CreateNewPostLink { ...props } />
136
- </BlockInfo>
134
+ { !! postType && (
135
+ <BlockInfo>
136
+ <CreateNewPostLink postType={ postType } />
137
+ </BlockInfo>
138
+ ) }
137
139
  { showSettingsPanel && (
138
140
  <PanelBody title={ __( 'Settings' ) }>
139
141
  { showInheritControl && (