@wordpress/block-library 7.18.0 → 7.19.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 (188) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/button/deprecated.js +16 -2
  3. package/build/button/deprecated.js.map +1 -1
  4. package/build/button/edit.js +13 -7
  5. package/build/button/edit.js.map +1 -1
  6. package/build/button/index.js +4 -1
  7. package/build/button/index.js.map +1 -1
  8. package/build/button/save.js +2 -0
  9. package/build/button/save.js.map +1 -1
  10. package/build/columns/transforms.js +5 -0
  11. package/build/columns/transforms.js.map +1 -1
  12. package/build/cover/edit/index.js +3 -1
  13. package/build/cover/edit/index.js.map +1 -1
  14. package/build/gallery/v1/edit.js +4 -2
  15. package/build/gallery/v1/edit.js.map +1 -1
  16. package/build/group/edit.js +98 -45
  17. package/build/group/edit.js.map +1 -1
  18. package/build/group/index.js +3 -0
  19. package/build/group/index.js.map +1 -1
  20. package/build/group/placeholder.js +168 -0
  21. package/build/group/placeholder.js.map +1 -0
  22. package/build/group/variations.js +3 -3
  23. package/build/group/variations.js.map +1 -1
  24. package/build/latest-comments/edit.js +2 -1
  25. package/build/latest-comments/edit.js.map +1 -1
  26. package/build/latest-comments/index.js +5 -1
  27. package/build/latest-comments/index.js.map +1 -1
  28. package/build/latest-posts/deprecated.js +13 -0
  29. package/build/latest-posts/deprecated.js.map +1 -1
  30. package/build/latest-posts/index.js +13 -0
  31. package/build/latest-posts/index.js.map +1 -1
  32. package/build/list-item/edit.js +2 -1
  33. package/build/list-item/edit.js.map +1 -1
  34. package/build/navigation/edit/index.js +82 -92
  35. package/build/navigation/edit/index.js.map +1 -1
  36. package/build/navigation/edit/manage-menus-button.js +36 -0
  37. package/build/navigation/edit/manage-menus-button.js.map +1 -0
  38. package/build/navigation/edit/navigation-menu-selector.js +12 -5
  39. package/build/navigation/edit/navigation-menu-selector.js.map +1 -1
  40. package/build/navigation/edit/responsive-wrapper.js +2 -6
  41. package/build/navigation/edit/responsive-wrapper.js.map +1 -1
  42. package/build/navigation/edit/unsaved-inner-blocks.js +5 -19
  43. package/build/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  44. package/build/navigation-link/edit.js +10 -1
  45. package/build/navigation-link/edit.js.map +1 -1
  46. package/build/post-author/edit.js +35 -20
  47. package/build/post-author/edit.js.map +1 -1
  48. package/build/post-content/index.js +3 -0
  49. package/build/post-content/index.js.map +1 -1
  50. package/build/site-logo/edit.js +1 -1
  51. package/build/site-logo/edit.js.map +1 -1
  52. package/build/template-part/variations.js +5 -0
  53. package/build/template-part/variations.js.map +1 -1
  54. package/build-module/button/deprecated.js +16 -2
  55. package/build-module/button/deprecated.js.map +1 -1
  56. package/build-module/button/edit.js +15 -9
  57. package/build-module/button/edit.js.map +1 -1
  58. package/build-module/button/index.js +4 -1
  59. package/build-module/button/index.js.map +1 -1
  60. package/build-module/button/save.js +2 -0
  61. package/build-module/button/save.js.map +1 -1
  62. package/build-module/columns/transforms.js +5 -0
  63. package/build-module/columns/transforms.js.map +1 -1
  64. package/build-module/cover/edit/index.js +3 -1
  65. package/build-module/cover/edit/index.js.map +1 -1
  66. package/build-module/gallery/v1/edit.js +5 -3
  67. package/build-module/gallery/v1/edit.js.map +1 -1
  68. package/build-module/group/edit.js +94 -45
  69. package/build-module/group/edit.js.map +1 -1
  70. package/build-module/group/index.js +3 -0
  71. package/build-module/group/index.js.map +1 -1
  72. package/build-module/group/placeholder.js +154 -0
  73. package/build-module/group/placeholder.js.map +1 -0
  74. package/build-module/group/variations.js +3 -3
  75. package/build-module/group/variations.js.map +1 -1
  76. package/build-module/latest-comments/edit.js +2 -1
  77. package/build-module/latest-comments/edit.js.map +1 -1
  78. package/build-module/latest-comments/index.js +5 -1
  79. package/build-module/latest-comments/index.js.map +1 -1
  80. package/build-module/latest-posts/deprecated.js +13 -0
  81. package/build-module/latest-posts/deprecated.js.map +1 -1
  82. package/build-module/latest-posts/index.js +13 -0
  83. package/build-module/latest-posts/index.js.map +1 -1
  84. package/build-module/list-item/edit.js +2 -1
  85. package/build-module/list-item/edit.js.map +1 -1
  86. package/build-module/navigation/edit/index.js +84 -94
  87. package/build-module/navigation/edit/index.js.map +1 -1
  88. package/build-module/navigation/edit/manage-menus-button.js +26 -0
  89. package/build-module/navigation/edit/manage-menus-button.js.map +1 -0
  90. package/build-module/navigation/edit/navigation-menu-selector.js +13 -6
  91. package/build-module/navigation/edit/navigation-menu-selector.js.map +1 -1
  92. package/build-module/navigation/edit/responsive-wrapper.js +2 -6
  93. package/build-module/navigation/edit/responsive-wrapper.js.map +1 -1
  94. package/build-module/navigation/edit/unsaved-inner-blocks.js +7 -20
  95. package/build-module/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  96. package/build-module/navigation-link/edit.js +10 -1
  97. package/build-module/navigation-link/edit.js.map +1 -1
  98. package/build-module/post-author/edit.js +35 -21
  99. package/build-module/post-author/edit.js.map +1 -1
  100. package/build-module/post-content/index.js +3 -0
  101. package/build-module/post-content/index.js.map +1 -1
  102. package/build-module/site-logo/edit.js +1 -1
  103. package/build-module/site-logo/edit.js.map +1 -1
  104. package/build-module/template-part/variations.js +5 -0
  105. package/build-module/template-part/variations.js.map +1 -1
  106. package/build-style/editor-rtl.css +76 -1
  107. package/build-style/editor.css +76 -1
  108. package/build-style/group/editor-rtl.css +44 -0
  109. package/build-style/group/editor.css +44 -0
  110. package/build-style/latest-comments/style-rtl.css +1 -0
  111. package/build-style/latest-comments/style.css +1 -0
  112. package/build-style/latest-posts/style-rtl.css +3 -0
  113. package/build-style/latest-posts/style.css +3 -0
  114. package/build-style/navigation/editor-rtl.css +23 -0
  115. package/build-style/navigation/editor.css +23 -0
  116. package/build-style/navigation/style-rtl.css +10 -0
  117. package/build-style/navigation/style.css +10 -0
  118. package/build-style/navigation-link/editor-rtl.css +8 -1
  119. package/build-style/navigation-link/editor.css +8 -1
  120. package/build-style/query/editor-rtl.css +1 -1
  121. package/build-style/query/editor.css +1 -1
  122. package/build-style/query-pagination/style-rtl.css +1 -1
  123. package/build-style/query-pagination/style.css +1 -1
  124. package/build-style/style-rtl.css +20 -1
  125. package/build-style/style.css +20 -1
  126. package/build-style/table/editor-rtl.css +1 -0
  127. package/build-style/table/editor.css +1 -0
  128. package/build-style/table/style-rtl.css +5 -0
  129. package/build-style/table/style.css +5 -0
  130. package/build-style/table/theme-rtl.css +1 -3
  131. package/build-style/table/theme.css +1 -3
  132. package/build-style/theme-rtl.css +1 -3
  133. package/build-style/theme.css +1 -3
  134. package/package.json +28 -28
  135. package/src/avatar/index.php +1 -1
  136. package/src/block/test/edit.native.js +8 -8
  137. package/src/button/block.json +4 -1
  138. package/src/button/deprecated.js +18 -2
  139. package/src/button/edit.js +11 -9
  140. package/src/button/save.js +12 -2
  141. package/src/buttons/test/edit.native.js +19 -19
  142. package/src/columns/test/edit.native.js +32 -32
  143. package/src/columns/transforms.js +8 -0
  144. package/src/cover/edit/index.js +3 -1
  145. package/src/cover/test/edit.native.js +26 -26
  146. package/src/embed/test/index.native.js +43 -43
  147. package/src/gallery/test/index.native.js +11 -11
  148. package/src/gallery/v1/edit.js +19 -24
  149. package/src/group/block.json +3 -0
  150. package/src/group/edit.js +95 -44
  151. package/src/group/editor.scss +48 -0
  152. package/src/group/placeholder.js +187 -0
  153. package/src/group/test/edit.native.js +3 -3
  154. package/src/group/test/placeholder.js +78 -0
  155. package/src/group/variations.js +3 -3
  156. package/src/image/test/edit.native.js +17 -17
  157. package/src/latest-comments/block.json +5 -1
  158. package/src/latest-comments/edit.js +1 -0
  159. package/src/latest-comments/style.scss +3 -0
  160. package/src/latest-posts/block.json +13 -0
  161. package/src/latest-posts/style.scss +3 -0
  162. package/src/list/test/edit.native.js +36 -36
  163. package/src/list-item/edit.js +1 -0
  164. package/src/missing/test/edit-integration.native.js +5 -5
  165. package/src/navigation/edit/index.js +173 -146
  166. package/src/navigation/edit/manage-menus-button.js +21 -0
  167. package/src/navigation/edit/navigation-menu-selector.js +20 -5
  168. package/src/navigation/edit/responsive-wrapper.js +2 -10
  169. package/src/navigation/edit/unsaved-inner-blocks.js +5 -29
  170. package/src/navigation/editor.scss +25 -0
  171. package/src/navigation/style.scss +16 -0
  172. package/src/navigation-link/edit.js +8 -0
  173. package/src/navigation-link/editor.scss +8 -0
  174. package/src/post-author/edit.js +44 -20
  175. package/src/post-content/block.json +3 -0
  176. package/src/query/editor.scss +1 -1
  177. package/src/query-pagination/style.scss +1 -1
  178. package/src/read-more/index.php +9 -2
  179. package/src/shortcode/test/edit.native.js +5 -5
  180. package/src/site-logo/edit.js +1 -1
  181. package/src/social-link/test/index.native.js +10 -10
  182. package/src/social-links/test/edit.native.js +4 -4
  183. package/src/spacer/test/index.native.js +17 -17
  184. package/src/table/editor.scss +1 -0
  185. package/src/table/style.scss +7 -0
  186. package/src/table/theme.scss +1 -3
  187. package/src/template-part/index.php +5 -0
  188. package/src/template-part/variations.js +4 -0
@@ -6,9 +6,15 @@ import classnames from 'classnames';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { useState, useEffect, useRef, Platform } from '@wordpress/element';
10
- import { addQueryArgs } from '@wordpress/url';
11
9
  import {
10
+ useState,
11
+ useEffect,
12
+ useRef,
13
+ Platform,
14
+ useMemo,
15
+ } from '@wordpress/element';
16
+ import {
17
+ __experimentalOffCanvasEditor as OffCanvasEditor,
12
18
  InspectorControls,
13
19
  useBlockProps,
14
20
  __experimentalRecursionProvider as RecursionProvider,
@@ -31,6 +37,8 @@ import {
31
37
  __experimentalToggleGroupControlOption as ToggleGroupControlOption,
32
38
  Button,
33
39
  Spinner,
40
+ __experimentalHStack as HStack,
41
+ __experimentalHeading as Heading,
34
42
  } from '@wordpress/components';
35
43
  import { __, sprintf } from '@wordpress/i18n';
36
44
  import { speak } from '@wordpress/a11y';
@@ -60,6 +68,7 @@ import useConvertClassicToBlockMenu, {
60
68
  import useCreateNavigationMenu from './use-create-navigation-menu';
61
69
  import { useInnerBlocks } from './use-inner-blocks';
62
70
  import { detectColors } from './utils';
71
+ import ManageMenusButton from './manage-menus-button';
63
72
 
64
73
  function Navigation( {
65
74
  attributes,
@@ -82,6 +91,9 @@ function Navigation( {
82
91
  hasColorSettings = true,
83
92
  customPlaceholder: CustomPlaceholder = null,
84
93
  } ) {
94
+ const isOffCanvasNavigationEditorEnabled =
95
+ window?.__experimentalEnableOffCanvasNavigationEditor === true;
96
+
85
97
  const {
86
98
  openSubmenusOnClick,
87
99
  overlayMenu,
@@ -191,9 +203,6 @@ function Navigation( {
191
203
  __unstableMarkNextChangeAsNotPersistent,
192
204
  } = useDispatch( blockEditorStore );
193
205
 
194
- const [ hasSavedUnsavedInnerBlocks, setHasSavedUnsavedInnerBlocks ] =
195
- useState( false );
196
-
197
206
  const [ isResponsiveMenuOpen, setResponsiveMenuVisibility ] =
198
207
  useState( false );
199
208
 
@@ -227,8 +236,16 @@ function Navigation( {
227
236
  classicMenuConversionStatus === CLASSIC_MENU_CONVERSION_PENDING;
228
237
 
229
238
  // Only autofallback to published menus.
230
- const fallbackNavigationMenus = navigationMenus?.filter(
231
- ( menu ) => menu.status === 'publish'
239
+ const fallbackNavigationMenus = useMemo(
240
+ () =>
241
+ navigationMenus
242
+ ?.filter( ( menu ) => menu.status === 'publish' )
243
+ ?.sort( ( menuA, menuB ) => {
244
+ const menuADate = new Date( menuA.date );
245
+ const menuBDate = new Date( menuB.date );
246
+ return menuADate.getTime() < menuBDate.getTime();
247
+ } ),
248
+ [ navigationMenus ]
232
249
  );
233
250
 
234
251
  // Attempt to retrieve and prioritize any existing navigation menu unless:
@@ -248,12 +265,6 @@ function Navigation( {
248
265
  return;
249
266
  }
250
267
 
251
- fallbackNavigationMenus.sort( ( menuA, menuB ) => {
252
- const menuADate = new Date( menuA.date );
253
- const menuBDate = new Date( menuB.date );
254
- return menuADate.getTime() < menuBDate.getTime();
255
- } );
256
-
257
268
  /**
258
269
  * This fallback displays (both in editor and on front)
259
270
  * a list of pages only if no menu (user assigned or
@@ -263,7 +274,12 @@ function Navigation( {
263
274
  */
264
275
  __unstableMarkNextChangeAsNotPersistent();
265
276
  setRef( fallbackNavigationMenus[ 0 ].id );
266
- }, [ navigationMenus ] );
277
+ }, [
278
+ ref,
279
+ isCreatingNavigationMenu,
280
+ fallbackNavigationMenus,
281
+ hasUncontrolledInnerBlocks,
282
+ ] );
267
283
 
268
284
  useEffect( () => {
269
285
  if (
@@ -646,48 +662,77 @@ function Navigation( {
646
662
  // Consider this state as 'unsaved' and offer an uncontrolled version of inner blocks,
647
663
  // that automatically saves the menu as an entity when changes are made to the inner blocks.
648
664
  const hasUnsavedBlocks = hasUncontrolledInnerBlocks && ! isEntityAvailable;
649
- if ( hasUnsavedBlocks ) {
665
+
666
+ const WrappedNavigationMenuSelector = ( { currentMenuId } ) => (
667
+ <NavigationMenuSelector
668
+ currentMenuId={ currentMenuId }
669
+ clientId={ clientId }
670
+ onSelectNavigationMenu={ ( menuId ) => {
671
+ handleUpdateMenu( menuId );
672
+ } }
673
+ onSelectClassicMenu={ async ( classicMenu ) => {
674
+ const navMenu = await convertClassicMenu(
675
+ classicMenu.id,
676
+ classicMenu.name,
677
+ 'draft'
678
+ );
679
+ if ( navMenu ) {
680
+ handleUpdateMenu( navMenu.id, {
681
+ focusNavigationBlock: true,
682
+ } );
683
+ }
684
+ } }
685
+ onCreateNew={ createUntitledEmptyNavigationMenu }
686
+ createNavigationMenuIsSuccess={ createNavigationMenuIsSuccess }
687
+ createNavigationMenuIsError={ createNavigationMenuIsError }
688
+ /* translators: %s: The name of a menu. */
689
+ actionLabel={ __( "Switch to '%s'" ) }
690
+ />
691
+ );
692
+
693
+ const isManageMenusButtonDisabled =
694
+ ! hasManagePermissions || ! hasResolvedNavigationMenus;
695
+
696
+ if ( hasUnsavedBlocks && ! isCreatingNavigationMenu ) {
650
697
  return (
651
698
  <TagName { ...blockProps }>
652
699
  <InspectorControls>
653
- <PanelBody title={ __( 'Menu' ) }>
654
- <NavigationMenuSelector
655
- currentMenuId={ ref }
656
- clientId={ clientId }
657
- onSelectNavigationMenu={ ( menuId ) => {
658
- handleUpdateMenu( menuId );
659
- } }
660
- onSelectClassicMenu={ async ( classicMenu ) => {
661
- const navMenu = await convertClassicMenu(
662
- classicMenu.id,
663
- classicMenu.name,
664
- 'draft'
665
- );
666
- if ( navMenu ) {
667
- handleUpdateMenu( navMenu.id, {
668
- focusNavigationBlock: true,
669
- } );
670
- }
671
- } }
672
- onCreateNew={ createUntitledEmptyNavigationMenu }
673
- createNavigationMenuIsSuccess={
674
- createNavigationMenuIsSuccess
675
- }
676
- /* translators: %s: The name of a menu. */
677
- actionLabel={ __( "Switch to '%s'" ) }
678
- />
679
- <Button
680
- variant="link"
681
- disabled={
682
- ! hasManagePermissions ||
683
- ! hasResolvedNavigationMenus
684
- }
685
- href={ addQueryArgs( 'edit.php', {
686
- post_type: 'wp_navigation',
687
- } ) }
688
- >
689
- { __( 'Manage menus' ) }
690
- </Button>
700
+ <PanelBody
701
+ title={
702
+ isOffCanvasNavigationEditorEnabled
703
+ ? null
704
+ : __( 'Menu' )
705
+ }
706
+ >
707
+ { isOffCanvasNavigationEditorEnabled ? (
708
+ <>
709
+ <HStack className="wp-block-navigation-off-canvas-editor__header">
710
+ <Heading
711
+ className="wp-block-navigation-off-canvas-editor__title"
712
+ level={ 2 }
713
+ >
714
+ { __( 'Menu' ) }
715
+ </Heading>
716
+ <WrappedNavigationMenuSelector
717
+ currentMenuId={ ref }
718
+ />
719
+ </HStack>
720
+ <OffCanvasEditor
721
+ blocks={ innerBlocks }
722
+ isExpanded={ true }
723
+ selectBlockInCanvas={ false }
724
+ />
725
+ </>
726
+ ) : (
727
+ <>
728
+ <WrappedNavigationMenuSelector
729
+ currentMenuId={ ref }
730
+ />
731
+ <ManageMenusButton
732
+ disabled={ isManageMenusButtonDisabled }
733
+ />
734
+ </>
735
+ ) }
691
736
  </PanelBody>
692
737
  </InspectorControls>
693
738
  { stylingInspectorControls }
@@ -703,24 +748,11 @@ function Navigation( {
703
748
  overlayTextColor={ overlayTextColor }
704
749
  >
705
750
  <UnsavedInnerBlocks
751
+ createNavigationMenu={ createNavigationMenu }
706
752
  blocks={ uncontrolledInnerBlocks }
707
- clientId={ clientId }
708
753
  templateLock={ templateLock }
709
754
  navigationMenus={ navigationMenus }
710
755
  hasSelection={ isSelected || isInnerBlockSelected }
711
- hasSavedUnsavedInnerBlocks={
712
- hasSavedUnsavedInnerBlocks
713
- }
714
- onSave={ ( post ) => {
715
- // Set some state used as a guard to prevent the creation of multiple posts.
716
- setHasSavedUnsavedInnerBlocks( true );
717
- // Switch to using the wp_navigation entity.
718
- setRef( post.id );
719
-
720
- showNavigationMenuStatusNotice(
721
- __( `New Navigation Menu created.` )
722
- );
723
- } }
724
756
  />
725
757
  </ResponsiveWrapper>
726
758
  </TagName>
@@ -733,44 +765,38 @@ function Navigation( {
733
765
  return (
734
766
  <TagName { ...blockProps }>
735
767
  <InspectorControls>
736
- <PanelBody title={ __( 'Menu' ) }>
737
- <NavigationMenuSelector
738
- currentMenuId={ null }
739
- clientId={ clientId }
740
- onSelectNavigationMenu={ ( menuId ) => {
741
- handleUpdateMenu( menuId );
742
- } }
743
- onSelectClassicMenu={ async ( classicMenu ) => {
744
- const navMenu = await convertClassicMenu(
745
- classicMenu.id,
746
- classicMenu.name,
747
- 'draft'
748
- );
749
- if ( navMenu ) {
750
- handleUpdateMenu( navMenu.id, {
751
- focusNavigationBlock: true,
752
- } );
753
- }
754
- } }
755
- onCreateNew={ createUntitledEmptyNavigationMenu }
756
- createNavigationMenuIsSuccess={
757
- createNavigationMenuIsSuccess
758
- }
759
- /* translators: %s: The name of a menu. */
760
- actionLabel={ __( "Switch to '%s'" ) }
761
- />
762
- <Button
763
- variant="link"
764
- disabled={
765
- ! hasManagePermissions ||
766
- ! hasResolvedNavigationMenus
767
- }
768
- href={ addQueryArgs( 'edit.php', {
769
- post_type: 'wp_navigation',
770
- } ) }
771
- >
772
- { __( 'Manage menus' ) }
773
- </Button>
768
+ <PanelBody
769
+ title={
770
+ isOffCanvasNavigationEditorEnabled
771
+ ? null
772
+ : __( 'Menu' )
773
+ }
774
+ >
775
+ { isOffCanvasNavigationEditorEnabled ? (
776
+ <>
777
+ <HStack className="wp-block-navigation-off-canvas-editor__header">
778
+ <Heading
779
+ className="wp-block-navigation-off-canvas-editor__title"
780
+ level={ 2 }
781
+ >
782
+ { __( 'Menu' ) }
783
+ </Heading>
784
+ <WrappedNavigationMenuSelector
785
+ currentMenuId={ null }
786
+ />
787
+ </HStack>
788
+ <p>Select or create a menu</p>
789
+ </>
790
+ ) : (
791
+ <>
792
+ <WrappedNavigationMenuSelector
793
+ currentMenuId={ null }
794
+ />
795
+ <ManageMenusButton
796
+ disabled={ isManageMenusButtonDisabled }
797
+ />
798
+ </>
799
+ ) }
774
800
  </PanelBody>
775
801
  </InspectorControls>
776
802
  <Warning>
@@ -848,47 +874,42 @@ function Navigation( {
848
874
  <EntityProvider kind="postType" type="wp_navigation" id={ ref }>
849
875
  <RecursionProvider uniqueId={ recursionId }>
850
876
  <InspectorControls>
851
- <PanelBody title={ __( 'Menu' ) }>
852
- <NavigationMenuSelector
853
- currentMenuId={ ref }
854
- clientId={ clientId }
855
- onSelectNavigationMenu={ ( menuId ) => {
856
- handleUpdateMenu( menuId );
857
- } }
858
- onSelectClassicMenu={ async ( classicMenu ) => {
859
- const navMenu = await convertClassicMenu(
860
- classicMenu.id,
861
- classicMenu.name,
862
- 'draft'
863
- );
864
- if ( navMenu ) {
865
- handleUpdateMenu( navMenu.id, {
866
- focusNavigationBlock: true,
867
- } );
868
- }
869
- } }
870
- onCreateNew={ createUntitledEmptyNavigationMenu }
871
- createNavigationMenuIsSuccess={
872
- createNavigationMenuIsSuccess
873
- }
874
- createNavigationMenuIsError={
875
- createNavigationMenuIsError
876
- }
877
- /* translators: %s: The name of a menu. */
878
- actionLabel={ __( "Switch to '%s'" ) }
879
- />
880
- <Button
881
- variant="link"
882
- disabled={
883
- ! hasManagePermissions ||
884
- ! hasResolvedNavigationMenus
885
- }
886
- href={ addQueryArgs( 'edit.php', {
887
- post_type: 'wp_navigation',
888
- } ) }
889
- >
890
- { __( 'Manage menus' ) }
891
- </Button>
877
+ <PanelBody
878
+ title={
879
+ isOffCanvasNavigationEditorEnabled
880
+ ? null
881
+ : __( 'Menu' )
882
+ }
883
+ >
884
+ { isOffCanvasNavigationEditorEnabled ? (
885
+ <>
886
+ <HStack className="wp-block-navigation-off-canvas-editor__header">
887
+ <Heading
888
+ className="wp-block-navigation-off-canvas-editor__title"
889
+ level={ 2 }
890
+ >
891
+ { __( 'Menu' ) }
892
+ </Heading>
893
+ <WrappedNavigationMenuSelector
894
+ currentMenuId={ ref }
895
+ />
896
+ </HStack>
897
+ <OffCanvasEditor
898
+ blocks={ innerBlocks }
899
+ isExpanded={ true }
900
+ selectBlockInCanvas={ false }
901
+ />
902
+ </>
903
+ ) : (
904
+ <>
905
+ <WrappedNavigationMenuSelector
906
+ currentMenuId={ ref }
907
+ />
908
+ <ManageMenusButton
909
+ disabled={ isManageMenusButtonDisabled }
910
+ />
911
+ </>
912
+ ) }
892
913
  </PanelBody>
893
914
  </InspectorControls>
894
915
  { stylingInspectorControls }
@@ -915,6 +936,12 @@ function Navigation( {
915
936
  } }
916
937
  />
917
938
  ) }
939
+ { isOffCanvasNavigationEditorEnabled && (
940
+ <ManageMenusButton
941
+ disabled={ isManageMenusButtonDisabled }
942
+ className="wp-block-navigation-manage-menus-button"
943
+ />
944
+ ) }
918
945
  </InspectorControls>
919
946
  ) }
920
947
 
@@ -0,0 +1,21 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { addQueryArgs } from '@wordpress/url';
5
+ import { Button } from '@wordpress/components';
6
+ import { __ } from '@wordpress/i18n';
7
+
8
+ const ManageMenusButton = ( { className = '', disabled } ) => (
9
+ <Button
10
+ variant="link"
11
+ disabled={ disabled }
12
+ className={ className }
13
+ href={ addQueryArgs( 'edit.php', {
14
+ post_type: 'wp_navigation',
15
+ } ) }
16
+ >
17
+ { __( 'Manage menus' ) }
18
+ </Button>
19
+ );
20
+
21
+ export default ManageMenusButton;
@@ -10,7 +10,7 @@ import {
10
10
  VisuallyHidden,
11
11
  } from '@wordpress/components';
12
12
  import { useEntityProp } from '@wordpress/core-data';
13
- import { Icon, chevronUp, chevronDown } from '@wordpress/icons';
13
+ import { Icon, chevronUp, chevronDown, moreVertical } from '@wordpress/icons';
14
14
  import { __, sprintf } from '@wordpress/i18n';
15
15
  import { decodeEntities } from '@wordpress/html-entities';
16
16
  import { useEffect, useMemo, useState } from '@wordpress/element';
@@ -31,6 +31,9 @@ function NavigationMenuSelector( {
31
31
  createNavigationMenuIsError,
32
32
  toggleProps = {},
33
33
  } ) {
34
+ const isOffCanvasNavigationEditorEnabled =
35
+ window?.__experimentalEnableOffCanvasNavigationEditor === true;
36
+
34
37
  /* translators: %s: The name of a menu. */
35
38
  const createActionLabel = __( "Create from '%s'" );
36
39
 
@@ -161,11 +164,23 @@ function NavigationMenuSelector( {
161
164
 
162
165
  return (
163
166
  <DropdownMenu
164
- className="wp-block-navigation__navigation-selector"
167
+ className={
168
+ isOffCanvasNavigationEditorEnabled
169
+ ? ''
170
+ : 'wp-block-navigation__navigation-selector'
171
+ }
165
172
  label={ selectorLabel }
166
- text={ selectorLabel }
167
- icon={ null }
168
- toggleProps={ toggleProps }
173
+ text={
174
+ <span className="wp-block-navigation__navigation-selector-button__label">
175
+ { isOffCanvasNavigationEditorEnabled ? '' : selectorLabel }
176
+ </span>
177
+ }
178
+ icon={ isOffCanvasNavigationEditorEnabled ? moreVertical : null }
179
+ toggleProps={
180
+ isOffCanvasNavigationEditorEnabled
181
+ ? { isSmall: true }
182
+ : toggleProps
183
+ }
169
184
  >
170
185
  { ( { onClose } ) => (
171
186
  <>
@@ -85,11 +85,7 @@ export default function ResponsiveWrapper( {
85
85
  onClick={ () => onToggle( true ) }
86
86
  >
87
87
  { hasIcon && <OverlayMenuIcon icon={ icon } /> }
88
- { ! hasIcon && (
89
- <span className="wp-block-navigation__toggle_button_label">
90
- { __( 'Menu' ) }
91
- </span>
92
- ) }
88
+ { ! hasIcon && __( 'Menu' ) }
93
89
  </Button>
94
90
  ) }
95
91
 
@@ -109,11 +105,7 @@ export default function ResponsiveWrapper( {
109
105
  onClick={ () => onToggle( false ) }
110
106
  >
111
107
  { hasIcon && <Icon icon={ close } /> }
112
- { ! hasIcon && (
113
- <span className="wp-block-navigation__toggle_button_label">
114
- { __( 'Close' ) }
115
- </span>
116
- ) }
108
+ { ! hasIcon && __( 'Close' ) }
117
109
  </Button>
118
110
  <div
119
111
  className="wp-block-navigation__responsive-container-content"
@@ -2,7 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { useInnerBlocksProps } from '@wordpress/block-editor';
5
- import { Disabled, Spinner } from '@wordpress/components';
5
+ import { Disabled } from '@wordpress/components';
6
6
  import { store as coreStore } from '@wordpress/core-data';
7
7
  import { useSelect } from '@wordpress/data';
8
8
  import { useContext, useEffect, useRef, useMemo } from '@wordpress/element';
@@ -11,7 +11,6 @@ import { useContext, useEffect, useRef, useMemo } from '@wordpress/element';
11
11
  * Internal dependencies
12
12
  */
13
13
  import useNavigationMenu from '../use-navigation-menu';
14
- import useCreateNavigationMenu from './use-create-navigation-menu';
15
14
 
16
15
  const EMPTY_OBJECT = {};
17
16
  const DRAFT_MENU_PARAMS = [
@@ -38,9 +37,8 @@ const ALLOWED_BLOCKS = [
38
37
 
39
38
  export default function UnsavedInnerBlocks( {
40
39
  blocks,
41
- clientId,
42
- hasSavedUnsavedInnerBlocks,
43
- onSave,
40
+ createNavigationMenu,
41
+
44
42
  hasSelection,
45
43
  } ) {
46
44
  const originalBlocks = useRef();
@@ -75,7 +73,6 @@ export default function UnsavedInnerBlocks( {
75
73
  // The block will be disabled in a block preview, use this as a way of
76
74
  // avoiding the side-effects of this component for block previews.
77
75
  const isDisabled = useContext( Disabled.Context );
78
- const savingLock = useRef( false );
79
76
 
80
77
  const innerBlocksProps = useInnerBlocksProps(
81
78
  {
@@ -121,9 +118,6 @@ export default function UnsavedInnerBlocks( {
121
118
 
122
119
  const { hasResolvedNavigationMenus, navigationMenus } = useNavigationMenu();
123
120
 
124
- const { create: createNavigationMenu } =
125
- useCreateNavigationMenu( clientId );
126
-
127
121
  // Automatically save the uncontrolled blocks.
128
122
  useEffect( () => {
129
123
  // The block will be disabled when used in a BlockPreview.
@@ -140,9 +134,7 @@ export default function UnsavedInnerBlocks( {
140
134
  // which is an indication they want to start editing.
141
135
  if (
142
136
  isDisabled ||
143
- hasSavedUnsavedInnerBlocks ||
144
137
  isSaving ||
145
- savingLock.current ||
146
138
  ! hasResolvedDraftNavigationMenus ||
147
139
  ! hasResolvedNavigationMenus ||
148
140
  ! hasSelection ||
@@ -151,11 +143,7 @@ export default function UnsavedInnerBlocks( {
151
143
  return;
152
144
  }
153
145
 
154
- savingLock.current = true;
155
- createNavigationMenu( null, blocks ).then( ( menu ) => {
156
- onSave( menu );
157
- savingLock.current = false;
158
- } );
146
+ createNavigationMenu( null, blocks );
159
147
  }, [
160
148
  isDisabled,
161
149
  isSaving,
@@ -170,17 +158,5 @@ export default function UnsavedInnerBlocks( {
170
158
 
171
159
  const Wrapper = isSaving ? Disabled : 'div';
172
160
 
173
- return (
174
- <>
175
- { isSaving ? (
176
- <Spinner
177
- className={
178
- 'wp-block-navigation__uncontrolled-inner-blocks-loading-indicator'
179
- }
180
- />
181
- ) : (
182
- <Wrapper { ...innerBlocksProps } />
183
- ) }
184
- </>
185
- );
161
+ return <Wrapper { ...innerBlocksProps } />;
186
162
  }
@@ -540,6 +540,13 @@ body.editor-styles-wrapper
540
540
  color: inherit;
541
541
  }
542
542
 
543
+ .components-heading.wp-block-navigation-off-canvas-editor__title {
544
+ margin: 0;
545
+ }
546
+ .wp-block-navigation-off-canvas-editor__header {
547
+ margin-bottom: $grid-unit-10;
548
+ }
549
+
543
550
  // Customize the mobile editing.
544
551
  // This can be revisited in the future, but for now, inherit design from the parent.
545
552
  .is-menu-open .wp-block-navigation__responsive-container-content * {
@@ -582,6 +589,13 @@ body.editor-styles-wrapper
582
589
  margin-bottom: $grid-unit-20;
583
590
  }
584
591
 
592
+ // increased specificity to override button variant
593
+ // for the manage menus button in the advanced area
594
+ // of the navigation block
595
+ .components-button.is-link.wp-block-navigation-manage-menus-button {
596
+ margin-bottom: $grid-unit-20;
597
+ }
598
+
585
599
  .wp-block-navigation__overlay-menu-preview {
586
600
  display: flex;
587
601
  align-items: center;
@@ -625,6 +639,17 @@ body.editor-styles-wrapper
625
639
  width: 100%;
626
640
  }
627
641
 
642
+ .wp-block-navigation__navigation-selector-button__icon {
643
+ flex: 0 0 auto;
644
+ }
645
+
646
+ .wp-block-navigation__navigation-selector-button__label {
647
+ flex: 0 1 auto;
648
+ overflow: hidden;
649
+ text-overflow: ellipsis;
650
+ white-space: nowrap;
651
+ }
652
+
628
653
  .wp-block-navigation__navigation-selector-button--createnew {
629
654
  border: 1px solid;
630
655
  margin-bottom: $grid-unit-20;
@@ -655,6 +655,14 @@ button.wp-block-navigation-item__content {
655
655
  .wp-block-navigation__responsive-container-open {
656
656
  display: flex;
657
657
 
658
+ // When set to collapse into a text button, it should inherit the parent font.
659
+ // This needs specificity to override inherited properties by the button element and component.
660
+ &.wp-block-navigation__responsive-container-open.wp-block-navigation__responsive-container-open {
661
+ font-family: inherit;
662
+ font-weight: inherit;
663
+ font-size: inherit;
664
+ }
665
+
658
666
  &:not(.always-shown) {
659
667
  @include break-small {
660
668
  display: none;
@@ -668,6 +676,14 @@ button.wp-block-navigation-item__content {
668
676
  top: 0;
669
677
  right: 0;
670
678
  z-index: 2; // Needs to be above the modal z index itself.
679
+
680
+ // When set to collapse into a text button, it should inherit the parent font.
681
+ // This needs specificity to override inherited properties by the button element and component.
682
+ &.wp-block-navigation__responsive-container-close.wp-block-navigation__responsive-container-close {
683
+ font-family: inherit;
684
+ font-weight: inherit;
685
+ font-size: inherit;
686
+ }
671
687
  }
672
688
 
673
689
  // The menu adds wrapping containers.
@@ -716,6 +716,14 @@ export default function NavigationLinkEdit( {
716
716
  </BlockControls>
717
717
  <InspectorControls>
718
718
  <PanelBody title={ __( 'Link settings' ) }>
719
+ <TextControl
720
+ value={ url || '' }
721
+ onChange={ ( urlValue ) => {
722
+ setAttributes( { url: urlValue } );
723
+ } }
724
+ label={ __( 'URL' ) }
725
+ autoComplete="off"
726
+ />
719
727
  <TextareaControl
720
728
  value={ description || '' }
721
729
  onChange={ ( descriptionValue ) => {