@wordpress/edit-site 4.10.0 → 4.12.1-next.d6164808d3.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 (204) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/add-new-template/add-custom-template-modal.js +26 -44
  3. package/build/components/add-new-template/add-custom-template-modal.js.map +1 -1
  4. package/build/components/add-new-template/new-template.js +45 -23
  5. package/build/components/add-new-template/new-template.js.map +1 -1
  6. package/build/components/add-new-template/utils.js +493 -242
  7. package/build/components/add-new-template/utils.js.map +1 -1
  8. package/build/components/block-editor/index.js +1 -3
  9. package/build/components/block-editor/index.js.map +1 -1
  10. package/build/components/block-editor/resizable-editor.js +26 -12
  11. package/build/components/block-editor/resizable-editor.js.map +1 -1
  12. package/build/components/global-styles/border-panel.js +3 -3
  13. package/build/components/global-styles/border-panel.js.map +1 -1
  14. package/build/components/global-styles/dimensions-panel.js +280 -20
  15. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  16. package/build/components/global-styles/hooks.js +4 -4
  17. package/build/components/global-styles/hooks.js.map +1 -1
  18. package/build/components/global-styles/screen-color-palette.js +1 -1
  19. package/build/components/global-styles/screen-color-palette.js.map +1 -1
  20. package/build/components/global-styles/screen-colors.js +51 -7
  21. package/build/components/global-styles/screen-colors.js.map +1 -1
  22. package/build/components/global-styles/screen-heading-color.js +157 -0
  23. package/build/components/global-styles/screen-heading-color.js.map +1 -0
  24. package/build/components/global-styles/screen-typography-element.js +4 -0
  25. package/build/components/global-styles/screen-typography-element.js.map +1 -1
  26. package/build/components/global-styles/screen-typography.js +5 -0
  27. package/build/components/global-styles/screen-typography.js.map +1 -1
  28. package/build/components/global-styles/typography-panel.js +82 -14
  29. package/build/components/global-styles/typography-panel.js.map +1 -1
  30. package/build/components/global-styles/typography-utils.js +217 -0
  31. package/build/components/global-styles/typography-utils.js.map +1 -0
  32. package/build/components/global-styles/ui.js +11 -0
  33. package/build/components/global-styles/ui.js.map +1 -1
  34. package/build/components/global-styles/use-global-styles-output.js +183 -52
  35. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  36. package/build/components/global-styles/utils.js +85 -5
  37. package/build/components/global-styles/utils.js.map +1 -1
  38. package/build/components/header/document-actions/index.js +1 -0
  39. package/build/components/header/document-actions/index.js.map +1 -1
  40. package/build/components/header/index.js +27 -12
  41. package/build/components/header/index.js.map +1 -1
  42. package/build/components/header/mode-switcher/index.js +0 -4
  43. package/build/components/header/mode-switcher/index.js.map +1 -1
  44. package/build/components/header/more-menu/index.js +13 -3
  45. package/build/components/header/more-menu/index.js.map +1 -1
  46. package/build/components/header/undo-redo/redo.js +2 -1
  47. package/build/components/header/undo-redo/redo.js.map +1 -1
  48. package/build/components/list/actions/index.js +1 -1
  49. package/build/components/list/actions/index.js.map +1 -1
  50. package/build/components/save-button/index.js +2 -3
  51. package/build/components/save-button/index.js.map +1 -1
  52. package/build/components/sidebar/default-sidebar.js +11 -1
  53. package/build/components/sidebar/default-sidebar.js.map +1 -1
  54. package/build/components/sidebar/navigation-menu-sidebar/navigation-menu.js +2 -2
  55. package/build/components/sidebar/navigation-menu-sidebar/navigation-menu.js.map +1 -1
  56. package/build/components/sidebar/plugin-sidebar/index.js +11 -1
  57. package/build/components/sidebar/plugin-sidebar/index.js.map +1 -1
  58. package/build/components/sidebar/template-card/template-actions.js +1 -1
  59. package/build/components/sidebar/template-card/template-actions.js.map +1 -1
  60. package/build/components/template-details/edit-template-title.js +1 -1
  61. package/build/components/template-details/edit-template-title.js.map +1 -1
  62. package/build/components/template-details/index.js +19 -9
  63. package/build/components/template-details/index.js.map +1 -1
  64. package/build/components/template-details/template-areas.js +1 -1
  65. package/build/components/template-details/template-areas.js.map +1 -1
  66. package/build/components/template-details/template-part-area-selector.js +47 -0
  67. package/build/components/template-details/template-part-area-selector.js.map +1 -0
  68. package/build/components/template-part-converter/convert-to-template-part.js +4 -1
  69. package/build/components/template-part-converter/convert-to-template-part.js.map +1 -1
  70. package/build/hooks/index.js +2 -0
  71. package/build/hooks/index.js.map +1 -1
  72. package/build/hooks/template-part-edit.js +86 -0
  73. package/build/hooks/template-part-edit.js.map +1 -0
  74. package/build/index.js +1 -1
  75. package/build/index.js.map +1 -1
  76. package/build-module/components/add-new-template/add-custom-template-modal.js +27 -45
  77. package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -1
  78. package/build-module/components/add-new-template/new-template.js +45 -25
  79. package/build-module/components/add-new-template/new-template.js.map +1 -1
  80. package/build-module/components/add-new-template/utils.js +489 -230
  81. package/build-module/components/add-new-template/utils.js.map +1 -1
  82. package/build-module/components/block-editor/index.js +1 -2
  83. package/build-module/components/block-editor/index.js.map +1 -1
  84. package/build-module/components/block-editor/resizable-editor.js +26 -12
  85. package/build-module/components/block-editor/resizable-editor.js.map +1 -1
  86. package/build-module/components/global-styles/border-panel.js +3 -3
  87. package/build-module/components/global-styles/border-panel.js.map +1 -1
  88. package/build-module/components/global-styles/dimensions-panel.js +278 -22
  89. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  90. package/build-module/components/global-styles/hooks.js +4 -4
  91. package/build-module/components/global-styles/hooks.js.map +1 -1
  92. package/build-module/components/global-styles/screen-color-palette.js +1 -1
  93. package/build-module/components/global-styles/screen-color-palette.js.map +1 -1
  94. package/build-module/components/global-styles/screen-colors.js +51 -7
  95. package/build-module/components/global-styles/screen-colors.js.map +1 -1
  96. package/build-module/components/global-styles/screen-heading-color.js +143 -0
  97. package/build-module/components/global-styles/screen-heading-color.js.map +1 -0
  98. package/build-module/components/global-styles/screen-typography-element.js +4 -0
  99. package/build-module/components/global-styles/screen-typography-element.js.map +1 -1
  100. package/build-module/components/global-styles/screen-typography.js +5 -0
  101. package/build-module/components/global-styles/screen-typography.js.map +1 -1
  102. package/build-module/components/global-styles/typography-panel.js +83 -15
  103. package/build-module/components/global-styles/typography-panel.js.map +1 -1
  104. package/build-module/components/global-styles/typography-utils.js +204 -0
  105. package/build-module/components/global-styles/typography-utils.js.map +1 -0
  106. package/build-module/components/global-styles/ui.js +10 -0
  107. package/build-module/components/global-styles/ui.js.map +1 -1
  108. package/build-module/components/global-styles/use-global-styles-output.js +182 -61
  109. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  110. package/build-module/components/global-styles/utils.js +82 -5
  111. package/build-module/components/global-styles/utils.js.map +1 -1
  112. package/build-module/components/header/document-actions/index.js +1 -0
  113. package/build-module/components/header/document-actions/index.js.map +1 -1
  114. package/build-module/components/header/index.js +30 -14
  115. package/build-module/components/header/index.js.map +1 -1
  116. package/build-module/components/header/mode-switcher/index.js +0 -4
  117. package/build-module/components/header/mode-switcher/index.js.map +1 -1
  118. package/build-module/components/header/more-menu/index.js +13 -3
  119. package/build-module/components/header/more-menu/index.js.map +1 -1
  120. package/build-module/components/header/undo-redo/redo.js +3 -2
  121. package/build-module/components/header/undo-redo/redo.js.map +1 -1
  122. package/build-module/components/list/actions/index.js +1 -1
  123. package/build-module/components/list/actions/index.js.map +1 -1
  124. package/build-module/components/save-button/index.js +3 -4
  125. package/build-module/components/save-button/index.js.map +1 -1
  126. package/build-module/components/sidebar/default-sidebar.js +9 -1
  127. package/build-module/components/sidebar/default-sidebar.js.map +1 -1
  128. package/build-module/components/sidebar/navigation-menu-sidebar/navigation-menu.js +3 -3
  129. package/build-module/components/sidebar/navigation-menu-sidebar/navigation-menu.js.map +1 -1
  130. package/build-module/components/sidebar/plugin-sidebar/index.js +9 -1
  131. package/build-module/components/sidebar/plugin-sidebar/index.js.map +1 -1
  132. package/build-module/components/sidebar/template-card/template-actions.js +1 -1
  133. package/build-module/components/sidebar/template-card/template-actions.js.map +1 -1
  134. package/build-module/components/template-details/edit-template-title.js +1 -1
  135. package/build-module/components/template-details/edit-template-title.js.map +1 -1
  136. package/build-module/components/template-details/index.js +19 -10
  137. package/build-module/components/template-details/index.js.map +1 -1
  138. package/build-module/components/template-details/template-areas.js +1 -1
  139. package/build-module/components/template-details/template-areas.js.map +1 -1
  140. package/build-module/components/template-details/template-part-area-selector.js +35 -0
  141. package/build-module/components/template-details/template-part-area-selector.js.map +1 -0
  142. package/build-module/components/template-part-converter/convert-to-template-part.js +3 -1
  143. package/build-module/components/template-part-converter/convert-to-template-part.js.map +1 -1
  144. package/build-module/hooks/index.js +1 -0
  145. package/build-module/hooks/index.js.map +1 -1
  146. package/build-module/hooks/template-part-edit.js +67 -0
  147. package/build-module/hooks/template-part-edit.js.map +1 -0
  148. package/build-module/index.js +1 -1
  149. package/build-module/index.js.map +1 -1
  150. package/build-style/style-rtl.css +40 -33
  151. package/build-style/style.css +40 -33
  152. package/package.json +29 -29
  153. package/src/components/add-new-template/add-custom-template-modal.js +39 -48
  154. package/src/components/add-new-template/new-template.js +50 -58
  155. package/src/components/add-new-template/style.scss +20 -8
  156. package/src/components/add-new-template/utils.js +529 -231
  157. package/src/components/block-editor/index.js +0 -2
  158. package/src/components/block-editor/resizable-editor.js +28 -18
  159. package/src/components/editor/style.scss +1 -0
  160. package/src/components/global-styles/border-panel.js +3 -3
  161. package/src/components/global-styles/dimensions-panel.js +344 -45
  162. package/src/components/global-styles/hooks.js +6 -3
  163. package/src/components/global-styles/screen-color-palette.js +1 -1
  164. package/src/components/global-styles/screen-colors.js +46 -4
  165. package/src/components/global-styles/screen-heading-color.js +201 -0
  166. package/src/components/global-styles/screen-typography-element.js +4 -0
  167. package/src/components/global-styles/screen-typography.js +6 -0
  168. package/src/components/global-styles/style.scss +14 -6
  169. package/src/components/global-styles/test/typography-utils.js +130 -0
  170. package/src/components/global-styles/test/use-global-styles-output.js +143 -4
  171. package/src/components/global-styles/test/utils.js +68 -8
  172. package/src/components/global-styles/typography-panel.js +119 -48
  173. package/src/components/global-styles/typography-utils.js +228 -0
  174. package/src/components/global-styles/ui.js +13 -0
  175. package/src/components/global-styles/use-global-styles-output.js +203 -53
  176. package/src/components/global-styles/utils.js +70 -4
  177. package/src/components/header/document-actions/index.js +3 -0
  178. package/src/components/header/index.js +41 -14
  179. package/src/components/header/mode-switcher/index.js +0 -3
  180. package/src/components/header/more-menu/index.js +7 -2
  181. package/src/components/header/style.scss +5 -3
  182. package/src/components/header/undo-redo/redo.js +6 -2
  183. package/src/components/list/actions/index.js +3 -1
  184. package/src/components/save-button/index.js +10 -13
  185. package/src/components/sidebar/default-sidebar.js +12 -0
  186. package/src/components/sidebar/navigation-menu-sidebar/navigation-menu.js +1 -5
  187. package/src/components/sidebar/plugin-sidebar/index.js +12 -0
  188. package/src/components/sidebar/style.scss +4 -0
  189. package/src/components/sidebar/template-card/template-actions.js +3 -1
  190. package/src/components/template-details/edit-template-title.js +7 -3
  191. package/src/components/template-details/index.js +23 -8
  192. package/src/components/template-details/style.scss +0 -5
  193. package/src/components/template-details/template-areas.js +3 -1
  194. package/src/components/template-details/template-part-area-selector.js +38 -0
  195. package/src/components/template-part-converter/convert-to-template-part.js +3 -1
  196. package/src/hooks/index.js +1 -0
  197. package/src/hooks/template-part-edit.js +82 -0
  198. package/src/index.js +1 -1
  199. package/src/style.scss +0 -1
  200. package/build/components/edit-template-part-menu-button/index.js +0 -90
  201. package/build/components/edit-template-part-menu-button/index.js.map +0 -1
  202. package/build-module/components/edit-template-part-menu-button/index.js +0 -72
  203. package/build-module/components/edit-template-part-menu-button/index.js.map +0 -1
  204. package/src/components/edit-template-part-menu-button/index.js +0 -82
@@ -4,7 +4,7 @@
4
4
  import { getPresetVariableFromValue, getValueFromVariable } from '../utils';
5
5
 
6
6
  describe( 'editor utils', () => {
7
- const styles = {
7
+ const themeJson = {
8
8
  version: 1,
9
9
  settings: {
10
10
  color: {
@@ -57,7 +57,7 @@ describe( 'editor utils', () => {
57
57
  describe( 'when a provided global style (e.g. fontFamily, color,etc.) does not exist', () => {
58
58
  it( 'returns the originally provided value', () => {
59
59
  const actual = getPresetVariableFromValue(
60
- styles.settings,
60
+ themeJson.settings,
61
61
  context,
62
62
  'fakePropertyName',
63
63
  value
@@ -69,7 +69,7 @@ describe( 'editor utils', () => {
69
69
  describe( 'when a global style is cleared by the user', () => {
70
70
  it( 'returns an undefined preset variable', () => {
71
71
  const actual = getPresetVariableFromValue(
72
- styles.settings,
72
+ themeJson.settings,
73
73
  context,
74
74
  propertyName,
75
75
  undefined
@@ -83,7 +83,7 @@ describe( 'editor utils', () => {
83
83
  it( 'returns the originally provided value', () => {
84
84
  const customValue = '#6e4545';
85
85
  const actual = getPresetVariableFromValue(
86
- styles.settings,
86
+ themeJson.settings,
87
87
  context,
88
88
  propertyName,
89
89
  customValue
@@ -95,7 +95,7 @@ describe( 'editor utils', () => {
95
95
  describe( 'and it is a preset value', () => {
96
96
  it( 'returns the preset variable', () => {
97
97
  const actual = getPresetVariableFromValue(
98
- styles.settings,
98
+ themeJson.settings,
99
99
  context,
100
100
  propertyName,
101
101
  value
@@ -110,7 +110,7 @@ describe( 'editor utils', () => {
110
110
  describe( 'when provided an invalid variable', () => {
111
111
  it( 'returns the originally provided value', () => {
112
112
  const actual = getValueFromVariable(
113
- styles.settings,
113
+ themeJson,
114
114
  'root',
115
115
  undefined
116
116
  );
@@ -122,7 +122,7 @@ describe( 'editor utils', () => {
122
122
  describe( 'when provided a preset variable', () => {
123
123
  it( 'retrieves the correct preset value', () => {
124
124
  const actual = getValueFromVariable(
125
- styles.settings,
125
+ themeJson,
126
126
  'root',
127
127
  'var:preset|color|primary'
128
128
  );
@@ -134,7 +134,7 @@ describe( 'editor utils', () => {
134
134
  describe( 'when provided a custom variable', () => {
135
135
  it( 'retrieves the correct custom value', () => {
136
136
  const actual = getValueFromVariable(
137
- styles.settings,
137
+ themeJson,
138
138
  'root',
139
139
  'var(--wp--custom--color--secondary)'
140
140
  );
@@ -142,5 +142,65 @@ describe( 'editor utils', () => {
142
142
  expect( actual ).toBe( '#a65555' );
143
143
  } );
144
144
  } );
145
+
146
+ describe( 'when provided a dynamic reference', () => {
147
+ it( 'retrieves the referenced value', () => {
148
+ const stylesWithRefs = {
149
+ ...themeJson,
150
+ styles: {
151
+ color: {
152
+ background: {
153
+ ref: 'styles.color.text',
154
+ },
155
+ text: 'purple-rain',
156
+ },
157
+ },
158
+ };
159
+ const actual = getValueFromVariable( stylesWithRefs, 'root', {
160
+ ref: 'styles.color.text',
161
+ } );
162
+
163
+ expect( actual ).toBe( stylesWithRefs.styles.color.text );
164
+ } );
165
+
166
+ it( 'returns the originally provided value where value is dynamic reference and reference does not exist', () => {
167
+ const stylesWithRefs = {
168
+ ...themeJson,
169
+ styles: {
170
+ color: {
171
+ text: {
172
+ ref: 'styles.background.text',
173
+ },
174
+ },
175
+ },
176
+ };
177
+ const actual = getValueFromVariable( stylesWithRefs, 'root', {
178
+ ref: 'styles.color.text',
179
+ } );
180
+
181
+ expect( actual ).toBe( stylesWithRefs.styles.color.text );
182
+ } );
183
+
184
+ it( 'returns the originally provided value where value is dynamic reference', () => {
185
+ const stylesWithRefs = {
186
+ ...themeJson,
187
+ styles: {
188
+ color: {
189
+ background: {
190
+ ref: 'styles.color.text',
191
+ },
192
+ text: {
193
+ ref: 'styles.background.text',
194
+ },
195
+ },
196
+ },
197
+ };
198
+ const actual = getValueFromVariable( stylesWithRefs, 'root', {
199
+ ref: 'styles.color.text',
200
+ } );
201
+
202
+ expect( actual ).toBe( stylesWithRefs.styles.color.text );
203
+ } );
204
+ } );
145
205
  } );
146
206
  } );
@@ -10,9 +10,12 @@ import {
10
10
  import {
11
11
  PanelBody,
12
12
  FontSizePicker,
13
- __experimentalSpacer as Spacer,
13
+ __experimentalToggleGroupControl as ToggleGroupControl,
14
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
15
+ __experimentalGrid as Grid,
14
16
  } from '@wordpress/components';
15
-
17
+ import { __ } from '@wordpress/i18n';
18
+ import { useState } from '@wordpress/element';
16
19
  /**
17
20
  * Internal dependencies
18
21
  */
@@ -59,9 +62,14 @@ function useHasLetterSpacingControl( name ) {
59
62
  }
60
63
 
61
64
  export default function TypographyPanel( { name, element } ) {
65
+ const [ selectedLevel, setCurrentTab ] = useState( 'heading' );
62
66
  const supports = getSupportedGlobalStylesPanels( name );
63
- const prefix =
64
- element === 'text' || ! element ? '' : `elements.${ element }.`;
67
+ let prefix = '';
68
+ if ( element === 'heading' ) {
69
+ prefix = `elements.${ selectedLevel }.`;
70
+ } else if ( element && element !== 'text' ) {
71
+ prefix = `elements.${ element }.`;
72
+ }
65
73
  const [ fontSizes ] = useSetting( 'typography.fontSizes', name );
66
74
  const disableCustomFontSizes = ! useSetting(
67
75
  'typography.customFontSize',
@@ -78,6 +86,12 @@ export default function TypographyPanel( { name, element } ) {
78
86
  const hasAppearanceControl = useHasAppearanceControl( name );
79
87
  const hasLetterSpacingControl = useHasLetterSpacingControl( name );
80
88
 
89
+ /* Disable font size controls when the option to style all headings is selected. */
90
+ let hasFontSizeEnabled = supports.includes( 'fontSize' );
91
+ if ( element === 'heading' && selectedLevel === 'heading' ) {
92
+ hasFontSizeEnabled = false;
93
+ }
94
+
81
95
  const [ fontFamily, setFontFamily ] = useStyle(
82
96
  prefix + 'typography.fontFamily',
83
97
  name
@@ -130,54 +144,111 @@ export default function TypographyPanel( { name, element } ) {
130
144
  >
131
145
  Aa
132
146
  </div>
133
-
134
- { supports.includes( 'fontFamily' ) && (
135
- <FontFamilyControl
136
- fontFamilies={ fontFamilies }
137
- value={ fontFamily }
138
- onChange={ setFontFamily }
139
- />
140
- ) }
141
- { supports.includes( 'fontSize' ) && (
142
- <FontSizePicker
143
- value={ fontSize }
144
- onChange={ setFontSize }
145
- fontSizes={ fontSizes }
146
- disableCustomFontSizes={ disableCustomFontSizes }
147
- />
148
- ) }
149
- { hasLineHeightEnabled && (
150
- <Spacer marginBottom={ 6 }>
147
+ <Grid columns={ 2 } rowGap={ 16 } columnGap={ 8 }>
148
+ { element === 'heading' && (
149
+ <div className="edit-site-typography-panel__full-width-control">
150
+ <ToggleGroupControl
151
+ label={ __( 'Select heading level' ) }
152
+ hideLabelFromVision
153
+ value={ selectedLevel }
154
+ onChange={ setCurrentTab }
155
+ isBlock
156
+ size="__unstable-large"
157
+ __nextHasNoMarginBottom
158
+ >
159
+ <ToggleGroupControlOption
160
+ value="heading"
161
+ /* translators: 'All' refers to selecting all heading levels
162
+ and applying the same style to h1-h6. */
163
+ label={ __( 'All' ) }
164
+ />
165
+ <ToggleGroupControlOption
166
+ value="h1"
167
+ label={ __( 'H1' ) }
168
+ />
169
+ <ToggleGroupControlOption
170
+ value="h2"
171
+ label={ __( 'H2' ) }
172
+ />
173
+ <ToggleGroupControlOption
174
+ value="h3"
175
+ label={ __( 'H3' ) }
176
+ />
177
+ <ToggleGroupControlOption
178
+ value="h4"
179
+ label={ __( 'H4' ) }
180
+ />
181
+ <ToggleGroupControlOption
182
+ value="h5"
183
+ label={ __( 'H5' ) }
184
+ />
185
+ <ToggleGroupControlOption
186
+ value="h6"
187
+ label={ __( 'H6' ) }
188
+ />
189
+ </ToggleGroupControl>
190
+ </div>
191
+ ) }
192
+ { supports.includes( 'fontFamily' ) && (
193
+ <div className="edit-site-typography-panel__full-width-control">
194
+ <FontFamilyControl
195
+ fontFamilies={ fontFamilies }
196
+ value={ fontFamily }
197
+ onChange={ setFontFamily }
198
+ size="__unstable-large"
199
+ __nextHasNoMarginBottom
200
+ />
201
+ </div>
202
+ ) }
203
+ { hasFontSizeEnabled && (
204
+ <div className="edit-site-typography-panel__full-width-control">
205
+ <FontSizePicker
206
+ value={ fontSize }
207
+ onChange={ setFontSize }
208
+ fontSizes={ fontSizes }
209
+ disableCustomFontSizes={ disableCustomFontSizes }
210
+ size="__unstable-large"
211
+ __nextHasNoMarginBottom
212
+ />
213
+ </div>
214
+ ) }
215
+ { hasAppearanceControl && (
216
+ <FontAppearanceControl
217
+ value={ {
218
+ fontStyle,
219
+ fontWeight,
220
+ } }
221
+ onChange={ ( {
222
+ fontStyle: newFontStyle,
223
+ fontWeight: newFontWeight,
224
+ } ) => {
225
+ setFontStyle( newFontStyle );
226
+ setFontWeight( newFontWeight );
227
+ } }
228
+ hasFontStyles={ hasFontStyles }
229
+ hasFontWeights={ hasFontWeights }
230
+ size="__unstable-large"
231
+ __nextHasNoMarginBottom
232
+ />
233
+ ) }
234
+ { hasLineHeightEnabled && (
151
235
  <LineHeightControl
152
- __nextHasNoMarginBottom={ true }
236
+ __nextHasNoMarginBottom
237
+ __unstableInputWidth="auto"
153
238
  value={ lineHeight }
154
239
  onChange={ setLineHeight }
240
+ size="__unstable-large"
241
+ />
242
+ ) }
243
+ { hasLetterSpacingControl && (
244
+ <LetterSpacingControl
245
+ value={ letterSpacing }
246
+ onChange={ setLetterSpacing }
247
+ size="__unstable-large"
248
+ __unstableInputWidth="auto"
155
249
  />
156
- </Spacer>
157
- ) }
158
- { hasAppearanceControl && (
159
- <FontAppearanceControl
160
- value={ {
161
- fontStyle,
162
- fontWeight,
163
- } }
164
- onChange={ ( {
165
- fontStyle: newFontStyle,
166
- fontWeight: newFontWeight,
167
- } ) => {
168
- setFontStyle( newFontStyle );
169
- setFontWeight( newFontWeight );
170
- } }
171
- hasFontStyles={ hasFontStyles }
172
- hasFontWeights={ hasFontWeights }
173
- />
174
- ) }
175
- { hasLetterSpacingControl && (
176
- <LetterSpacingControl
177
- value={ letterSpacing }
178
- onChange={ setLetterSpacing }
179
- />
180
- ) }
250
+ ) }
251
+ </Grid>
181
252
  </PanelBody>
182
253
  );
183
254
  }
@@ -0,0 +1,228 @@
1
+ /**
2
+ * The fluid utilities must match the backend equivalent.
3
+ * See: gutenberg_get_typography_font_size_value() in lib/block-supports/typography.php
4
+ * ---------------------------------------------------------------
5
+ */
6
+
7
+ /**
8
+ * Returns a font-size value based on a given font-size preset.
9
+ * Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values.
10
+ *
11
+ * @param {Object} preset
12
+ * @param {string} preset.size A default font size.
13
+ * @param {string} preset.name A font size name, displayed in the UI.
14
+ * @param {string} preset.slug A font size slug.
15
+ * @param {Object} preset.fluid
16
+ * @param {string|undefined} preset.fluid.max A maximum font size value.
17
+ * @param {string|undefined} preset.fluid.min A minimum font size value.
18
+ * @param {Object} typographySettings
19
+ * @param {boolean} typographySettings.fluid Whether fluid typography is enabled.
20
+ *
21
+ * @return {string} An font-size value
22
+ */
23
+ export function getTypographyFontSizeValue( preset, typographySettings ) {
24
+ const { size: defaultSize } = preset;
25
+
26
+ if ( true !== typographySettings?.fluid ) {
27
+ return defaultSize;
28
+ }
29
+
30
+ // Defaults.
31
+ const DEFAULT_MAXIMUM_VIEWPORT_WIDTH = '1600px';
32
+ const DEFAULT_MINIMUM_VIEWPORT_WIDTH = '768px';
33
+ const DEFAULT_MINIMUM_FONT_SIZE_FACTOR = 0.75;
34
+ const DEFAULT_MAXIMUM_FONT_SIZE_FACTOR = 1.5;
35
+ const DEFAULT_SCALE_FACTOR = 1;
36
+
37
+ // Font sizes.
38
+ // A font size has explicitly bypassed fluid calculations.
39
+ if ( false === preset?.fluid ) {
40
+ return defaultSize;
41
+ }
42
+
43
+ const fluidFontSizeSettings = preset?.fluid || {};
44
+
45
+ // Try to grab explicit min and max fluid font sizes.
46
+ let minimumFontSizeRaw = fluidFontSizeSettings?.min;
47
+ let maximumFontSizeRaw = fluidFontSizeSettings?.max;
48
+ const preferredSize = getTypographyValueAndUnit( defaultSize );
49
+
50
+ // Protect against unsupported units.
51
+ if ( ! preferredSize?.unit ) {
52
+ return defaultSize;
53
+ }
54
+
55
+ // If no fluid min or max font sizes are available, create some using min/max font size factors.
56
+ if ( ! minimumFontSizeRaw ) {
57
+ minimumFontSizeRaw =
58
+ preferredSize.value * DEFAULT_MINIMUM_FONT_SIZE_FACTOR +
59
+ preferredSize.unit;
60
+ }
61
+
62
+ if ( ! maximumFontSizeRaw ) {
63
+ maximumFontSizeRaw =
64
+ preferredSize.value * DEFAULT_MAXIMUM_FONT_SIZE_FACTOR +
65
+ preferredSize.unit;
66
+ }
67
+
68
+ const fluidFontSizeValue = getComputedFluidTypographyValue( {
69
+ maximumViewPortWidth: DEFAULT_MAXIMUM_VIEWPORT_WIDTH,
70
+ minimumViewPortWidth: DEFAULT_MINIMUM_VIEWPORT_WIDTH,
71
+ maximumFontSize: maximumFontSizeRaw,
72
+ minimumFontSize: minimumFontSizeRaw,
73
+ scaleFactor: DEFAULT_SCALE_FACTOR,
74
+ } );
75
+
76
+ if ( !! fluidFontSizeValue ) {
77
+ return fluidFontSizeValue;
78
+ }
79
+
80
+ return defaultSize;
81
+ }
82
+
83
+ /**
84
+ * Internal implementation of clamp() based on available min/max viewport width, and min/max font sizes.
85
+ *
86
+ * @param {Object} args
87
+ * @param {string} args.maximumViewPortWidth Maximum size up to which type will have fluidity.
88
+ * @param {string} args.minimumViewPortWidth Minimum viewport size from which type will have fluidity.
89
+ * @param {string} args.maximumFontSize Maximum font size for any clamp() calculation.
90
+ * @param {string} args.minimumFontSize Minimum font size for any clamp() calculation.
91
+ * @param {number} args.scaleFactor A scale factor to determine how fast a font scales within boundaries.
92
+ *
93
+ * @return {string|null} A font-size value using clamp().
94
+ */
95
+ export function getComputedFluidTypographyValue( {
96
+ maximumViewPortWidth,
97
+ minimumViewPortWidth,
98
+ maximumFontSize,
99
+ minimumFontSize,
100
+ scaleFactor,
101
+ } ) {
102
+ // Grab the minimum font size and normalize it in order to use the value for calculations.
103
+ const minimumFontSizeParsed = getTypographyValueAndUnit( minimumFontSize );
104
+
105
+ // We get a 'preferred' unit to keep units consistent when calculating,
106
+ // otherwise the result will not be accurate.
107
+ const fontSizeUnit = minimumFontSizeParsed?.unit || 'rem';
108
+
109
+ // Grab the maximum font size and normalize it in order to use the value for calculations.
110
+ const maximumFontSizeParsed = getTypographyValueAndUnit( maximumFontSize, {
111
+ coerceTo: fontSizeUnit,
112
+ } );
113
+
114
+ // Protect against unsupported units.
115
+ if ( ! minimumFontSizeParsed || ! maximumFontSizeParsed ) {
116
+ return null;
117
+ }
118
+
119
+ // Use rem for accessible fluid target font scaling.
120
+ const minimumFontSizeRem = getTypographyValueAndUnit( minimumFontSize, {
121
+ coerceTo: 'rem',
122
+ } );
123
+
124
+ // Viewport widths defined for fluid typography. Normalize units
125
+ const maximumViewPortWidthParsed = getTypographyValueAndUnit(
126
+ maximumViewPortWidth,
127
+ { coerceTo: fontSizeUnit }
128
+ );
129
+ const minumumViewPortWidthParsed = getTypographyValueAndUnit(
130
+ minimumViewPortWidth,
131
+ { coerceTo: fontSizeUnit }
132
+ );
133
+
134
+ // Protect against unsupported units.
135
+ if (
136
+ ! maximumViewPortWidthParsed ||
137
+ ! minumumViewPortWidthParsed ||
138
+ ! minimumFontSizeRem
139
+ ) {
140
+ return null;
141
+ }
142
+
143
+ // Build CSS rule.
144
+ // Borrowed from https://websemantics.uk/tools/responsive-font-calculator/.
145
+ const minViewPortWidthOffsetValue = roundToPrecision(
146
+ minumumViewPortWidthParsed.value / 100,
147
+ 3
148
+ );
149
+
150
+ const viewPortWidthOffset = minViewPortWidthOffsetValue + fontSizeUnit;
151
+ let linearFactor =
152
+ 100 *
153
+ ( ( maximumFontSizeParsed.value - minimumFontSizeParsed.value ) /
154
+ ( maximumViewPortWidthParsed.value -
155
+ minumumViewPortWidthParsed.value ) );
156
+ linearFactor = roundToPrecision( linearFactor, 3 ) || 1;
157
+ const linearFactorScaled = linearFactor * scaleFactor;
158
+ const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewPortWidthOffset }) * ${ linearFactorScaled })`;
159
+
160
+ return `clamp(${ minimumFontSize }, ${ fluidTargetFontSize }, ${ maximumFontSize })`;
161
+ }
162
+
163
+ /**
164
+ *
165
+ * @param {string} rawValue Raw size value from theme.json.
166
+ * @param {Object|undefined} options Calculation options.
167
+ *
168
+ * @return {{ unit: string, value: number }|null} An object consisting of `'value'` and `'unit'` properties.
169
+ */
170
+ export function getTypographyValueAndUnit( rawValue, options = {} ) {
171
+ if ( ! rawValue ) {
172
+ return null;
173
+ }
174
+
175
+ const { coerceTo, rootSizeValue, acceptableUnits } = {
176
+ coerceTo: '',
177
+ // Default browser font size. Later we could inject some JS to compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`.
178
+ rootSizeValue: 16,
179
+ acceptableUnits: [ 'rem', 'px', 'em' ],
180
+ ...options,
181
+ };
182
+
183
+ const acceptableUnitsGroup = acceptableUnits?.join( '|' );
184
+ const regexUnits = new RegExp(
185
+ `^(\\d*\\.?\\d+)(${ acceptableUnitsGroup }){1,1}$`
186
+ );
187
+
188
+ const matches = rawValue.match( regexUnits );
189
+
190
+ // We need a number value and a unit.
191
+ if ( ! matches || matches.length < 3 ) {
192
+ return null;
193
+ }
194
+
195
+ let [ , value, unit ] = matches;
196
+
197
+ let returnValue = parseFloat( value );
198
+
199
+ if ( 'px' === coerceTo && ( 'em' === unit || 'rem' === unit ) ) {
200
+ returnValue = returnValue * rootSizeValue;
201
+ unit = coerceTo;
202
+ }
203
+
204
+ if ( 'px' === unit && ( 'em' === coerceTo || 'rem' === coerceTo ) ) {
205
+ returnValue = returnValue / rootSizeValue;
206
+ unit = coerceTo;
207
+ }
208
+
209
+ return {
210
+ value: returnValue,
211
+ unit,
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Returns a value rounded to defined precision.
217
+ * Returns `undefined` if the value is not a valid finite number.
218
+ *
219
+ * @param {number} value Raw value.
220
+ * @param {number} digits The number of digits to appear after the decimal point
221
+ *
222
+ * @return {number|undefined} Value rounded to standard precision.
223
+ */
224
+ export function roundToPrecision( value, digits = 3 ) {
225
+ return Number.isFinite( value )
226
+ ? parseFloat( value.toFixed( digits ) )
227
+ : undefined;
228
+ }
@@ -20,6 +20,7 @@ import ScreenColorPalette from './screen-color-palette';
20
20
  import ScreenBackgroundColor from './screen-background-color';
21
21
  import ScreenTextColor from './screen-text-color';
22
22
  import ScreenLinkColor from './screen-link-color';
23
+ import ScreenHeadingColor from './screen-heading-color';
23
24
  import ScreenButtonColor from './screen-button-color';
24
25
  import ScreenLayout from './screen-layout';
25
26
  import ScreenStyleVariations from './screen-style-variations';
@@ -59,6 +60,12 @@ function ContextScreens( { name } ) {
59
60
  <ScreenTypographyElement name={ name } element="link" />
60
61
  </GlobalStylesNavigationScreen>
61
62
 
63
+ <GlobalStylesNavigationScreen
64
+ path={ parentMenu + '/typography/heading' }
65
+ >
66
+ <ScreenTypographyElement name={ name } element="heading" />
67
+ </GlobalStylesNavigationScreen>
68
+
62
69
  <GlobalStylesNavigationScreen
63
70
  path={ parentMenu + '/typography/button' }
64
71
  >
@@ -89,6 +96,12 @@ function ContextScreens( { name } ) {
89
96
  <ScreenLinkColor name={ name } />
90
97
  </GlobalStylesNavigationScreen>
91
98
 
99
+ <GlobalStylesNavigationScreen
100
+ path={ parentMenu + '/colors/heading' }
101
+ >
102
+ <ScreenHeadingColor name={ name } />
103
+ </GlobalStylesNavigationScreen>
104
+
92
105
  <GlobalStylesNavigationScreen
93
106
  path={ parentMenu + '/colors/button' }
94
107
  >