@wordpress/block-library 9.37.2-next.79a2f3cdd.0 → 9.37.2-next.ba3aee3a2.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 (76) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/build/code/transforms.cjs +1 -1
  3. package/build/code/transforms.cjs.map +1 -1
  4. package/build/image/block.json +3 -0
  5. package/build/image/image.cjs +42 -4
  6. package/build/image/image.cjs.map +2 -2
  7. package/build/image/save.cjs +3 -0
  8. package/build/image/save.cjs.map +2 -2
  9. package/build/image/utils.cjs +5 -0
  10. package/build/image/utils.cjs.map +2 -2
  11. package/build/navigation/constants.cjs +3 -0
  12. package/build/navigation/constants.cjs.map +2 -2
  13. package/build/navigation/edit/overlay-template-part-selector.cjs +2 -1
  14. package/build/navigation/edit/overlay-template-part-selector.cjs.map +2 -2
  15. package/build/navigation/edit/use-create-overlay.cjs +2 -1
  16. package/build/navigation/edit/use-create-overlay.cjs.map +2 -2
  17. package/build/navigation/view.cjs +14 -2
  18. package/build/navigation/view.cjs.map +2 -2
  19. package/build/private-apis.cjs +3 -1
  20. package/build/private-apis.cjs.map +2 -2
  21. package/build/quote/transforms.cjs +30 -6
  22. package/build/quote/transforms.cjs.map +2 -2
  23. package/build/separator/transforms.cjs +5 -2
  24. package/build/separator/transforms.cjs.map +2 -2
  25. package/build/template-part/edit/index.cjs +9 -2
  26. package/build/template-part/edit/index.cjs.map +2 -2
  27. package/build-module/code/transforms.mjs +1 -1
  28. package/build-module/code/transforms.mjs.map +1 -1
  29. package/build-module/image/block.json +3 -0
  30. package/build-module/image/image.mjs +44 -5
  31. package/build-module/image/image.mjs.map +2 -2
  32. package/build-module/image/save.mjs +3 -0
  33. package/build-module/image/save.mjs.map +2 -2
  34. package/build-module/image/utils.mjs +4 -0
  35. package/build-module/image/utils.mjs.map +2 -2
  36. package/build-module/navigation/constants.mjs +2 -0
  37. package/build-module/navigation/constants.mjs.map +2 -2
  38. package/build-module/navigation/edit/overlay-template-part-selector.mjs +2 -1
  39. package/build-module/navigation/edit/overlay-template-part-selector.mjs.map +2 -2
  40. package/build-module/navigation/edit/use-create-overlay.mjs +2 -1
  41. package/build-module/navigation/edit/use-create-overlay.mjs.map +2 -2
  42. package/build-module/navigation/view.mjs +14 -2
  43. package/build-module/navigation/view.mjs.map +2 -2
  44. package/build-module/private-apis.mjs +3 -1
  45. package/build-module/private-apis.mjs.map +2 -2
  46. package/build-module/quote/transforms.mjs +30 -6
  47. package/build-module/quote/transforms.mjs.map +2 -2
  48. package/build-module/separator/transforms.mjs +6 -3
  49. package/build-module/separator/transforms.mjs.map +2 -2
  50. package/build-module/template-part/edit/index.mjs +9 -2
  51. package/build-module/template-part/edit/index.mjs.map +2 -2
  52. package/build-style/navigation/style-rtl.css +25 -6
  53. package/build-style/navigation/style.css +25 -6
  54. package/build-style/navigation-overlay-close/style-rtl.css +0 -1
  55. package/build-style/navigation-overlay-close/style.css +0 -1
  56. package/build-style/style-rtl.css +25 -7
  57. package/build-style/style.css +25 -7
  58. package/package.json +37 -37
  59. package/src/code/transforms.js +1 -1
  60. package/src/image/block.json +3 -0
  61. package/src/image/image.js +43 -2
  62. package/src/image/save.js +10 -0
  63. package/src/image/utils.js +4 -0
  64. package/src/navigation/constants.js +9 -0
  65. package/src/navigation/edit/overlay-template-part-selector.js +3 -1
  66. package/src/navigation/edit/test/overlay-template-part-selector.js +3 -3
  67. package/src/navigation/edit/test/use-create-overlay.js +5 -5
  68. package/src/navigation/edit/use-create-overlay.js +2 -1
  69. package/src/navigation/index.php +271 -13
  70. package/src/navigation/style.scss +46 -9
  71. package/src/navigation/view.js +24 -4
  72. package/src/navigation-overlay-close/style.scss +0 -1
  73. package/src/private-apis.js +2 -0
  74. package/src/quote/transforms.js +31 -5
  75. package/src/separator/transforms.js +6 -3
  76. package/src/template-part/edit/index.js +21 -4
@@ -2733,16 +2733,20 @@ button.wp-block-navigation-item__content {
2733
2733
  animation-fill-mode: forwards;
2734
2734
  }
2735
2735
  }
2736
- .wp-block-navigation__responsive-container.is-menu-open {
2736
+ .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
2737
2737
  padding-top: clamp(1rem, var(--wp--style--root--padding-top), 20rem);
2738
2738
  padding-left: clamp(1rem, var(--wp--style--root--padding-right), 20rem);
2739
2739
  padding-bottom: clamp(1rem, var(--wp--style--root--padding-bottom), 20rem);
2740
2740
  padding-right: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
2741
+ }
2742
+ .wp-block-navigation__responsive-container.is-menu-open {
2741
2743
  overflow: auto;
2742
2744
  z-index: 100000;
2743
2745
  }
2744
- .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
2746
+ .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content {
2745
2747
  padding-top: calc(2rem + 24px);
2748
+ }
2749
+ .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
2746
2750
  overflow: visible;
2747
2751
  display: flex;
2748
2752
  flex-direction: column;
@@ -2797,6 +2801,16 @@ button.wp-block-navigation-item__content {
2797
2801
  left: auto;
2798
2802
  right: auto;
2799
2803
  }
2804
+ .wp-block-navigation__responsive-container.disable-default-overlay .wp-block-navigation__overlay-container {
2805
+ display: none;
2806
+ width: 100%;
2807
+ }
2808
+ .wp-block-navigation__responsive-container.disable-default-overlay.is-menu-open .wp-block-navigation__responsive-container-content > .wp-block-navigation__container {
2809
+ display: none;
2810
+ }
2811
+ .wp-block-navigation__responsive-container.disable-default-overlay.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__overlay-container {
2812
+ display: block;
2813
+ }
2800
2814
  @media (min-width: 600px) {
2801
2815
  .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
2802
2816
  display: block;
@@ -2813,11 +2827,11 @@ button.wp-block-navigation-item__content {
2813
2827
  }
2814
2828
  }
2815
2829
 
2816
- .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open {
2830
+ .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
2817
2831
  background-color: #fff;
2818
2832
  }
2819
2833
 
2820
- .wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open {
2834
+ .wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
2821
2835
  color: #000;
2822
2836
  }
2823
2837
 
@@ -2872,6 +2886,11 @@ button.wp-block-navigation-item__content {
2872
2886
  font-size: inherit;
2873
2887
  }
2874
2888
 
2889
+ .disable-default-overlay .wp-block-navigation__responsive-container-close {
2890
+ top: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
2891
+ left: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
2892
+ }
2893
+
2875
2894
  .wp-block-navigation__responsive-close {
2876
2895
  width: 100%;
2877
2896
  }
@@ -2894,11 +2913,11 @@ button.wp-block-navigation-item__content {
2894
2913
  position: relative;
2895
2914
  }
2896
2915
 
2897
- .has-modal-open .admin-bar .is-menu-open .wp-block-navigation__responsive-dialog {
2916
+ .has-modal-open .admin-bar .is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-dialog {
2898
2917
  margin-top: 46px;
2899
2918
  }
2900
2919
  @media (min-width: 782px) {
2901
- .has-modal-open .admin-bar .is-menu-open .wp-block-navigation__responsive-dialog {
2920
+ .has-modal-open .admin-bar .is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-dialog {
2902
2921
  margin-top: 32px;
2903
2922
  }
2904
2923
  }
@@ -2940,7 +2959,6 @@ html.has-modal-open {
2940
2959
  text-decoration: none;
2941
2960
  }
2942
2961
  .wp-block-navigation-overlay-close:focus {
2943
- outline: 2px solid currentColor;
2944
2962
  outline-offset: 2px;
2945
2963
  }
2946
2964
  .wp-block-navigation-overlay-close svg {
@@ -2763,16 +2763,20 @@ button.wp-block-navigation-item__content {
2763
2763
  animation-fill-mode: forwards;
2764
2764
  }
2765
2765
  }
2766
- .wp-block-navigation__responsive-container.is-menu-open {
2766
+ .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
2767
2767
  padding-top: clamp(1rem, var(--wp--style--root--padding-top), 20rem);
2768
2768
  padding-right: clamp(1rem, var(--wp--style--root--padding-right), 20rem);
2769
2769
  padding-bottom: clamp(1rem, var(--wp--style--root--padding-bottom), 20rem);
2770
2770
  padding-left: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
2771
+ }
2772
+ .wp-block-navigation__responsive-container.is-menu-open {
2771
2773
  overflow: auto;
2772
2774
  z-index: 100000;
2773
2775
  }
2774
- .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
2776
+ .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content {
2775
2777
  padding-top: calc(2rem + 24px);
2778
+ }
2779
+ .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
2776
2780
  overflow: visible;
2777
2781
  display: flex;
2778
2782
  flex-direction: column;
@@ -2827,6 +2831,16 @@ button.wp-block-navigation-item__content {
2827
2831
  right: auto;
2828
2832
  left: auto;
2829
2833
  }
2834
+ .wp-block-navigation__responsive-container.disable-default-overlay .wp-block-navigation__overlay-container {
2835
+ display: none;
2836
+ width: 100%;
2837
+ }
2838
+ .wp-block-navigation__responsive-container.disable-default-overlay.is-menu-open .wp-block-navigation__responsive-container-content > .wp-block-navigation__container {
2839
+ display: none;
2840
+ }
2841
+ .wp-block-navigation__responsive-container.disable-default-overlay.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__overlay-container {
2842
+ display: block;
2843
+ }
2830
2844
  @media (min-width: 600px) {
2831
2845
  .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
2832
2846
  display: block;
@@ -2843,11 +2857,11 @@ button.wp-block-navigation-item__content {
2843
2857
  }
2844
2858
  }
2845
2859
 
2846
- .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open {
2860
+ .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
2847
2861
  background-color: #fff;
2848
2862
  }
2849
2863
 
2850
- .wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open {
2864
+ .wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
2851
2865
  color: #000;
2852
2866
  }
2853
2867
 
@@ -2902,6 +2916,11 @@ button.wp-block-navigation-item__content {
2902
2916
  font-size: inherit;
2903
2917
  }
2904
2918
 
2919
+ .disable-default-overlay .wp-block-navigation__responsive-container-close {
2920
+ top: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
2921
+ right: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
2922
+ }
2923
+
2905
2924
  .wp-block-navigation__responsive-close {
2906
2925
  width: 100%;
2907
2926
  }
@@ -2924,11 +2943,11 @@ button.wp-block-navigation-item__content {
2924
2943
  position: relative;
2925
2944
  }
2926
2945
 
2927
- .has-modal-open .admin-bar .is-menu-open .wp-block-navigation__responsive-dialog {
2946
+ .has-modal-open .admin-bar .is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-dialog {
2928
2947
  margin-top: 46px;
2929
2948
  }
2930
2949
  @media (min-width: 782px) {
2931
- .has-modal-open .admin-bar .is-menu-open .wp-block-navigation__responsive-dialog {
2950
+ .has-modal-open .admin-bar .is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-dialog {
2932
2951
  margin-top: 32px;
2933
2952
  }
2934
2953
  }
@@ -2970,7 +2989,6 @@ html.has-modal-open {
2970
2989
  text-decoration: none;
2971
2990
  }
2972
2991
  .wp-block-navigation-overlay-close:focus {
2973
- outline: 2px solid currentColor;
2974
2992
  outline-offset: 2px;
2975
2993
  }
2976
2994
  .wp-block-navigation-overlay-close svg {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-library",
3
- "version": "9.37.2-next.79a2f3cdd.0",
3
+ "version": "9.37.2-next.ba3aee3a2.0",
4
4
  "description": "Block library for the WordPress editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -93,41 +93,41 @@
93
93
  "build-module/*/init.mjs"
94
94
  ],
95
95
  "dependencies": {
96
- "@wordpress/a11y": "^4.37.1-next.79a2f3cdd.0",
97
- "@wordpress/api-fetch": "^7.37.1-next.79a2f3cdd.0",
98
- "@wordpress/autop": "^4.37.1-next.79a2f3cdd.0",
99
- "@wordpress/base-styles": "^6.13.2-next.79a2f3cdd.0",
100
- "@wordpress/blob": "^4.37.1-next.79a2f3cdd.0",
101
- "@wordpress/block-editor": "^15.10.1-next.79a2f3cdd.0",
102
- "@wordpress/blocks": "^15.10.1-next.79a2f3cdd.0",
103
- "@wordpress/components": "^32.0.1-next.79a2f3cdd.0",
104
- "@wordpress/compose": "^7.37.1-next.79a2f3cdd.0",
105
- "@wordpress/core-data": "^7.37.1-next.79a2f3cdd.0",
106
- "@wordpress/data": "^10.37.1-next.79a2f3cdd.0",
107
- "@wordpress/date": "^5.37.2-next.79a2f3cdd.0",
108
- "@wordpress/deprecated": "^4.37.1-next.79a2f3cdd.0",
109
- "@wordpress/dom": "^4.37.1-next.79a2f3cdd.0",
110
- "@wordpress/element": "^6.37.1-next.79a2f3cdd.0",
111
- "@wordpress/escape-html": "^3.37.1-next.79a2f3cdd.0",
112
- "@wordpress/hooks": "^4.37.1-next.79a2f3cdd.0",
113
- "@wordpress/html-entities": "^4.37.1-next.79a2f3cdd.0",
114
- "@wordpress/i18n": "^6.10.1-next.79a2f3cdd.0",
115
- "@wordpress/icons": "^11.4.1-next.79a2f3cdd.0",
116
- "@wordpress/interactivity": "^6.37.1-next.79a2f3cdd.0",
117
- "@wordpress/interactivity-router": "^2.37.1-next.79a2f3cdd.0",
118
- "@wordpress/keyboard-shortcuts": "^5.37.1-next.79a2f3cdd.0",
119
- "@wordpress/keycodes": "^4.38.1-next.79a2f3cdd.0",
120
- "@wordpress/latex-to-mathml": "^1.5.1-next.79a2f3cdd.0",
121
- "@wordpress/notices": "^5.37.1-next.79a2f3cdd.0",
122
- "@wordpress/patterns": "^2.37.1-next.79a2f3cdd.0",
123
- "@wordpress/primitives": "^4.37.1-next.79a2f3cdd.0",
124
- "@wordpress/private-apis": "^1.37.1-next.79a2f3cdd.0",
125
- "@wordpress/reusable-blocks": "^5.37.1-next.79a2f3cdd.0",
126
- "@wordpress/rich-text": "^7.37.1-next.79a2f3cdd.0",
127
- "@wordpress/server-side-render": "^6.13.1-next.79a2f3cdd.0",
128
- "@wordpress/url": "^4.37.1-next.79a2f3cdd.0",
129
- "@wordpress/viewport": "^6.37.1-next.79a2f3cdd.0",
130
- "@wordpress/wordcount": "^4.37.1-next.79a2f3cdd.0",
96
+ "@wordpress/a11y": "^4.37.1-next.ba3aee3a2.0",
97
+ "@wordpress/api-fetch": "^7.37.1-next.ba3aee3a2.0",
98
+ "@wordpress/autop": "^4.37.1-next.ba3aee3a2.0",
99
+ "@wordpress/base-styles": "^6.13.2-next.ba3aee3a2.0",
100
+ "@wordpress/blob": "^4.37.1-next.ba3aee3a2.0",
101
+ "@wordpress/block-editor": "^15.10.1-next.ba3aee3a2.0",
102
+ "@wordpress/blocks": "^15.10.1-next.ba3aee3a2.0",
103
+ "@wordpress/components": "^32.0.1-next.ba3aee3a2.0",
104
+ "@wordpress/compose": "^7.37.1-next.ba3aee3a2.0",
105
+ "@wordpress/core-data": "^7.37.1-next.ba3aee3a2.0",
106
+ "@wordpress/data": "^10.37.1-next.ba3aee3a2.0",
107
+ "@wordpress/date": "^5.37.2-next.ba3aee3a2.0",
108
+ "@wordpress/deprecated": "^4.37.1-next.ba3aee3a2.0",
109
+ "@wordpress/dom": "^4.37.1-next.ba3aee3a2.0",
110
+ "@wordpress/element": "^6.37.1-next.ba3aee3a2.0",
111
+ "@wordpress/escape-html": "^3.37.1-next.ba3aee3a2.0",
112
+ "@wordpress/hooks": "^4.37.1-next.ba3aee3a2.0",
113
+ "@wordpress/html-entities": "^4.37.1-next.ba3aee3a2.0",
114
+ "@wordpress/i18n": "^6.10.1-next.ba3aee3a2.0",
115
+ "@wordpress/icons": "^11.4.1-next.ba3aee3a2.0",
116
+ "@wordpress/interactivity": "^6.37.2-next.ba3aee3a2.0",
117
+ "@wordpress/interactivity-router": "^2.37.1-next.ba3aee3a2.0",
118
+ "@wordpress/keyboard-shortcuts": "^5.37.1-next.ba3aee3a2.0",
119
+ "@wordpress/keycodes": "^4.38.1-next.ba3aee3a2.0",
120
+ "@wordpress/latex-to-mathml": "^1.5.1-next.ba3aee3a2.0",
121
+ "@wordpress/notices": "^5.37.1-next.ba3aee3a2.0",
122
+ "@wordpress/patterns": "^2.37.1-next.ba3aee3a2.0",
123
+ "@wordpress/primitives": "^4.37.1-next.ba3aee3a2.0",
124
+ "@wordpress/private-apis": "^1.37.1-next.ba3aee3a2.0",
125
+ "@wordpress/reusable-blocks": "^5.37.1-next.ba3aee3a2.0",
126
+ "@wordpress/rich-text": "^7.37.1-next.ba3aee3a2.0",
127
+ "@wordpress/server-side-render": "^6.13.1-next.ba3aee3a2.0",
128
+ "@wordpress/url": "^4.37.1-next.ba3aee3a2.0",
129
+ "@wordpress/viewport": "^6.37.1-next.ba3aee3a2.0",
130
+ "@wordpress/wordcount": "^4.37.1-next.ba3aee3a2.0",
131
131
  "change-case": "^4.1.2",
132
132
  "clsx": "^2.1.1",
133
133
  "colord": "^2.7.0",
@@ -149,5 +149,5 @@
149
149
  "publishConfig": {
150
150
  "access": "public"
151
151
  },
152
- "gitHead": "6a324496a37d9a333a11d4d7fe5fb93b8152a5ba"
152
+ "gitHead": "67d2e486fcd40c753591cf911ca0659132f519ca"
153
153
  }
@@ -12,7 +12,7 @@ import { getTransformedAttributes } from '../utils/get-transformed-attributes';
12
12
  const transforms = {
13
13
  from: [
14
14
  {
15
- type: 'enter',
15
+ type: 'input',
16
16
  regExp: /^```$/,
17
17
  transform: () => createBlock( 'core/code' ),
18
18
  },
@@ -89,6 +89,9 @@
89
89
  "scale": {
90
90
  "type": "string"
91
91
  },
92
+ "focalPoint": {
93
+ "type": "object"
94
+ },
92
95
  "sizeSlug": {
93
96
  "type": "string"
94
97
  },
@@ -4,6 +4,7 @@
4
4
  import { isBlobURL } from '@wordpress/blob';
5
5
  import {
6
6
  ExternalLink,
7
+ FocalPointPicker,
7
8
  ResizableBox,
8
9
  Spinner,
9
10
  TextareaControl,
@@ -61,7 +62,7 @@ import {
61
62
  SIZED_LAYOUTS,
62
63
  DEFAULT_MEDIA_SIZE_SLUG,
63
64
  } from './constants';
64
- import { evalAspectRatio } from './utils';
65
+ import { evalAspectRatio, mediaPosition } from './utils';
65
66
 
66
67
  const { DimensionsTool, ResolutionTool } = unlock( blockEditorPrivateApis );
67
68
 
@@ -279,6 +280,7 @@ export default function Image( {
279
280
  height,
280
281
  aspectRatio,
281
282
  scale,
283
+ focalPoint,
282
284
  linkTarget,
283
285
  sizeSlug,
284
286
  lightbox,
@@ -468,6 +470,15 @@ export default function Image( {
468
470
  setAttributes( { alt: newAlt } );
469
471
  }
470
472
 
473
+ const imperativeFocalPointPreview = ( value ) => {
474
+ if ( imageElement ) {
475
+ imageElement.style.setProperty(
476
+ 'object-position',
477
+ mediaPosition( value )
478
+ );
479
+ }
480
+ };
481
+
471
482
  function updateImage( newSizeSlug ) {
472
483
  const newUrl = image?.media_details?.sizes?.[ newSizeSlug ]?.source_url;
473
484
  if ( ! newUrl ) {
@@ -713,7 +724,6 @@ export default function Image( {
713
724
  );
714
725
 
715
726
  const hasDataFormBlockFields =
716
- window?.__experimentalContentOnlyPatternInsertion &&
717
727
  window?.__experimentalContentOnlyInspectorFields;
718
728
 
719
729
  const controls = (
@@ -864,9 +874,36 @@ export default function Image( {
864
874
  width: undefined,
865
875
  height: undefined,
866
876
  scale: undefined,
877
+ focalPoint: undefined,
867
878
  } ) }
868
879
  >
869
880
  { dimensionsControl }
881
+ { url && scale && (
882
+ <ToolsPanelItem
883
+ label={ __( 'Focal point' ) }
884
+ isShownByDefault
885
+ hasValue={ () => !! focalPoint }
886
+ onDeselect={ () =>
887
+ setAttributes( {
888
+ focalPoint: undefined,
889
+ } )
890
+ }
891
+ panelId={ clientId }
892
+ >
893
+ <FocalPointPicker
894
+ label={ __( 'Focal point' ) }
895
+ url={ url }
896
+ value={ focalPoint }
897
+ onDragStart={ imperativeFocalPointPreview }
898
+ onDrag={ imperativeFocalPointPreview }
899
+ onChange={ ( newFocalPoint ) =>
900
+ setAttributes( {
901
+ focalPoint: newFocalPoint,
902
+ } )
903
+ }
904
+ />
905
+ </ToolsPanelItem>
906
+ ) }
870
907
  </InspectorControls>
871
908
  { !! imageSizeOptions.length && (
872
909
  <InspectorControls>
@@ -965,6 +1002,10 @@ export default function Image( {
965
1002
  }
966
1003
  : { width, height } ),
967
1004
  objectFit: scale,
1005
+ objectPosition:
1006
+ focalPoint && scale
1007
+ ? mediaPosition( focalPoint )
1008
+ : undefined,
968
1009
  ...borderProps.style,
969
1010
  ...shadowProps.style,
970
1011
  } }
package/src/image/save.js CHANGED
@@ -14,6 +14,11 @@ import {
14
14
  __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
15
15
  } from '@wordpress/block-editor';
16
16
 
17
+ /**
18
+ * Internal dependencies
19
+ */
20
+ import { mediaPosition } from './utils';
21
+
17
22
  export default function save( { attributes } ) {
18
23
  const {
19
24
  url,
@@ -27,6 +32,7 @@ export default function save( { attributes } ) {
27
32
  height,
28
33
  aspectRatio,
29
34
  scale,
35
+ focalPoint,
30
36
  id,
31
37
  linkTarget,
32
38
  sizeSlug,
@@ -64,6 +70,10 @@ export default function save( { attributes } ) {
64
70
  ...shadowProps.style,
65
71
  aspectRatio,
66
72
  objectFit: scale,
73
+ objectPosition:
74
+ focalPoint && scale
75
+ ? mediaPosition( focalPoint )
76
+ : undefined,
67
77
  width,
68
78
  height,
69
79
  } }
@@ -93,3 +93,7 @@ export function isValidFileType( file ) {
93
93
  ( mediaType ) => file.type.indexOf( mediaType ) === 0
94
94
  );
95
95
  }
96
+
97
+ export function mediaPosition( { x, y } = { x: 0.5, y: 0.5 } ) {
98
+ return `${ Math.round( x * 100 ) }% ${ Math.round( y * 100 ) }%`;
99
+ }
@@ -27,3 +27,12 @@ export const SELECT_NAVIGATION_MENUS_ARGS = [
27
27
  'wp_navigation',
28
28
  PRELOADED_NAVIGATION_MENUS_QUERY,
29
29
  ];
30
+
31
+ /**
32
+ * Template part area identifier for navigation overlays.
33
+ * This constant defines the area name used when registering and filtering
34
+ * template parts that are specifically designed for navigation overlay layouts.
35
+ *
36
+ * @type {string}
37
+ */
38
+ export const NAVIGATION_OVERLAY_TEMPLATE_PART_AREA = 'navigation-overlay';
@@ -21,6 +21,7 @@ import { plus } from '@wordpress/icons';
21
21
  */
22
22
  import { createTemplatePartId } from '../../template-part/edit/utils/create-template-part-id';
23
23
  import useCreateOverlayTemplatePart from './use-create-overlay';
24
+ import { NAVIGATION_OVERLAY_TEMPLATE_PART_AREA } from '../constants';
24
25
 
25
26
  /**
26
27
  * Overlay Template Part Selector component.
@@ -55,7 +56,8 @@ export default function OverlayTemplatePartSelector( {
55
56
  return [];
56
57
  }
57
58
  return templateParts.filter(
58
- ( templatePart ) => templatePart.area === 'overlay'
59
+ ( templatePart ) =>
60
+ templatePart.area === NAVIGATION_OVERLAY_TEMPLATE_PART_AREA
59
61
  );
60
62
  }, [ templateParts ] );
61
63
 
@@ -60,7 +60,7 @@ const templatePart1 = {
60
60
  title: {
61
61
  rendered: 'My Overlay',
62
62
  },
63
- area: 'overlay',
63
+ area: 'navigation-overlay',
64
64
  };
65
65
 
66
66
  const templatePart2 = {
@@ -70,7 +70,7 @@ const templatePart2 = {
70
70
  title: {
71
71
  rendered: 'Another Overlay',
72
72
  },
73
- area: 'overlay',
73
+ area: 'navigation-overlay',
74
74
  };
75
75
 
76
76
  const templatePartOtherArea = {
@@ -470,7 +470,7 @@ describe( 'OverlayTemplatePartSelector', () => {
470
470
  title: {
471
471
  rendered: 'Overlay',
472
472
  },
473
- area: 'overlay',
473
+ area: 'navigation-overlay',
474
474
  };
475
475
 
476
476
  mockCreateOverlayTemplatePart.mockResolvedValue( newOverlay );
@@ -42,7 +42,7 @@ describe( 'useCreateOverlayTemplatePart', () => {
42
42
  title: {
43
43
  rendered: 'Overlay',
44
44
  },
45
- area: 'overlay',
45
+ area: 'navigation-overlay',
46
46
  };
47
47
 
48
48
  mockSaveEntityRecord.mockResolvedValue( createdOverlay );
@@ -62,7 +62,7 @@ describe( 'useCreateOverlayTemplatePart', () => {
62
62
  expect.objectContaining( {
63
63
  slug: 'overlay',
64
64
  title: 'Overlay',
65
- area: 'overlay',
65
+ area: 'navigation-overlay',
66
66
  } ),
67
67
  { throwOnError: true }
68
68
  );
@@ -77,7 +77,7 @@ describe( 'useCreateOverlayTemplatePart', () => {
77
77
  title: {
78
78
  rendered: 'Overlay',
79
79
  },
80
- area: 'overlay',
80
+ area: 'navigation-overlay',
81
81
  };
82
82
  const overlayTemplateParts = [ existingOverlay ];
83
83
  const createdOverlay = {
@@ -87,7 +87,7 @@ describe( 'useCreateOverlayTemplatePart', () => {
87
87
  title: {
88
88
  rendered: 'Overlay 2',
89
89
  },
90
- area: 'overlay',
90
+ area: 'navigation-overlay',
91
91
  };
92
92
 
93
93
  mockSaveEntityRecord.mockResolvedValue( createdOverlay );
@@ -107,7 +107,7 @@ describe( 'useCreateOverlayTemplatePart', () => {
107
107
  expect.objectContaining( {
108
108
  title: 'Overlay 2',
109
109
  slug: 'overlay-2',
110
- area: 'overlay',
110
+ area: 'navigation-overlay',
111
111
  } ),
112
112
  { throwOnError: true }
113
113
  );
@@ -10,6 +10,7 @@ import { __ } from '@wordpress/i18n';
10
10
  * Internal dependencies
11
11
  */
12
12
  import { getUniqueTemplatePartTitle, getCleanTemplatePartSlug } from './utils';
13
+ import { NAVIGATION_OVERLAY_TEMPLATE_PART_AREA } from '../constants';
13
14
 
14
15
  /**
15
16
  * Hook to create a new overlay template part.
@@ -40,7 +41,7 @@ export default function useCreateOverlayTemplatePart( overlayTemplateParts ) {
40
41
  {
41
42
  slug: cleanSlug,
42
43
  title: uniqueTitle,
43
- area: 'overlay',
44
+ area: NAVIGATION_OVERLAY_TEMPLATE_PART_AREA,
44
45
  },
45
46
  { throwOnError: true }
46
47
  );