@wordpress/block-editor 10.2.0 → 10.3.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 (285) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +41 -0
  3. package/build/components/block-draggable/draggable-chip.js +4 -2
  4. package/build/components/block-draggable/draggable-chip.js.map +1 -1
  5. package/build/components/block-inspector/index.js +4 -4
  6. package/build/components/block-inspector/index.js.map +1 -1
  7. package/build/components/block-list/block-list-compact.native.js +1 -0
  8. package/build/components/block-list/block-list-compact.native.js.map +1 -1
  9. package/build/components/block-list/block.js +72 -14
  10. package/build/components/block-list/block.js.map +1 -1
  11. package/build/components/block-list/block.native.js +79 -12
  12. package/build/components/block-list/block.native.js.map +1 -1
  13. package/build/components/block-list/use-in-between-inserter.js +7 -23
  14. package/build/components/block-list/use-in-between-inserter.js.map +1 -1
  15. package/build/components/block-lock/modal.js +9 -6
  16. package/build/components/block-lock/modal.js.map +1 -1
  17. package/build/components/block-parent-selector/index.js +3 -3
  18. package/build/components/block-parent-selector/index.js.map +1 -1
  19. package/build/components/block-patterns-list/index.js +5 -4
  20. package/build/components/block-patterns-list/index.js.map +1 -1
  21. package/build/components/block-popover/drop-zone.js +85 -0
  22. package/build/components/block-popover/drop-zone.js.map +1 -0
  23. package/build/components/block-popover/index.js +2 -1
  24. package/build/components/block-popover/index.js.map +1 -1
  25. package/build/components/block-preview/auto.js +2 -2
  26. package/build/components/block-preview/auto.js.map +1 -1
  27. package/build/components/block-preview/index.js +6 -9
  28. package/build/components/block-preview/index.js.map +1 -1
  29. package/build/components/block-preview/live.js +3 -7
  30. package/build/components/block-preview/live.js.map +1 -1
  31. package/build/components/block-selection-clearer/index.js +9 -1
  32. package/build/components/block-selection-clearer/index.js.map +1 -1
  33. package/build/components/block-settings-menu/block-settings-dropdown.js +17 -11
  34. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  35. package/build/components/block-styles/index.js +18 -42
  36. package/build/components/block-styles/index.js.map +1 -1
  37. package/build/components/block-toolbar/index.js +4 -4
  38. package/build/components/block-toolbar/index.js.map +1 -1
  39. package/build/components/block-tools/back-compat.js +2 -1
  40. package/build/components/block-tools/back-compat.js.map +1 -1
  41. package/build/components/block-tools/insertion-point.js +50 -20
  42. package/build/components/block-tools/insertion-point.js.map +1 -1
  43. package/build/components/block-tools/selected-block-popover.js +15 -3
  44. package/build/components/block-tools/selected-block-popover.js.map +1 -1
  45. package/build/components/colors-gradients/control.js +1 -1
  46. package/build/components/colors-gradients/control.js.map +1 -1
  47. package/build/components/colors-gradients/panel-color-gradient-settings.js +2 -2
  48. package/build/components/colors-gradients/panel-color-gradient-settings.js.map +1 -1
  49. package/build/components/font-sizes/fluid-utils.js +256 -0
  50. package/build/components/font-sizes/fluid-utils.js.map +1 -0
  51. package/build/components/font-sizes/index.js +8 -0
  52. package/build/components/font-sizes/index.js.map +1 -1
  53. package/build/components/index.js +0 -9
  54. package/build/components/index.js.map +1 -1
  55. package/build/components/inner-blocks/use-inner-block-template-sync.js +3 -2
  56. package/build/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
  57. package/build/components/inserter/block-patterns-tab.js +151 -78
  58. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  59. package/build/components/inserter/menu.js +14 -3
  60. package/build/components/inserter/menu.js.map +1 -1
  61. package/build/components/inserter-draggable-blocks/index.js +4 -2
  62. package/build/components/inserter-draggable-blocks/index.js.map +1 -1
  63. package/build/components/list-view/use-list-view-drop-zone.js +1 -14
  64. package/build/components/list-view/use-list-view-drop-zone.js.map +1 -1
  65. package/build/components/preview-options/index.js +2 -3
  66. package/build/components/preview-options/index.js.map +1 -1
  67. package/build/components/spacing-sizes-control/spacing-input-control.js +35 -5
  68. package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  69. package/build/components/use-block-drop-zone/index.js +98 -57
  70. package/build/components/use-block-drop-zone/index.js.map +1 -1
  71. package/build/components/use-on-block-drop/index.js +12 -12
  72. package/build/components/use-on-block-drop/index.js.map +1 -1
  73. package/build/components/use-on-block-drop/types.js +6 -0
  74. package/build/components/use-on-block-drop/types.js.map +1 -0
  75. package/build/hooks/align.js +1 -3
  76. package/build/hooks/align.js.map +1 -1
  77. package/build/hooks/align.native.js +1 -7
  78. package/build/hooks/align.native.js.map +1 -1
  79. package/build/hooks/font-size.js +60 -0
  80. package/build/hooks/font-size.js.map +1 -1
  81. package/build/hooks/margin.js +6 -5
  82. package/build/hooks/margin.js.map +1 -1
  83. package/build/hooks/padding.js +2 -1
  84. package/build/hooks/padding.js.map +1 -1
  85. package/build/hooks/style.js +126 -4
  86. package/build/hooks/style.js.map +1 -1
  87. package/build/hooks/use-typography-props.js +17 -3
  88. package/build/hooks/use-typography-props.js.map +1 -1
  89. package/build/hooks/utils.js +1 -1
  90. package/build/hooks/utils.js.map +1 -1
  91. package/build/store/actions.js +59 -45
  92. package/build/store/actions.js.map +1 -1
  93. package/build/store/defaults.js +3 -0
  94. package/build/store/defaults.js.map +1 -1
  95. package/build/store/reducer.js +31 -15
  96. package/build/store/reducer.js.map +1 -1
  97. package/build/utils/math.js +14 -0
  98. package/build/utils/math.js.map +1 -1
  99. package/build/utils/pre-parse-patterns.js +19 -2
  100. package/build/utils/pre-parse-patterns.js.map +1 -1
  101. package/build-module/components/block-draggable/draggable-chip.js +7 -3
  102. package/build-module/components/block-draggable/draggable-chip.js.map +1 -1
  103. package/build-module/components/block-inspector/index.js +4 -4
  104. package/build-module/components/block-inspector/index.js.map +1 -1
  105. package/build-module/components/block-list/block-list-compact.native.js +1 -0
  106. package/build-module/components/block-list/block-list-compact.native.js.map +1 -1
  107. package/build-module/components/block-list/block.js +72 -14
  108. package/build-module/components/block-list/block.js.map +1 -1
  109. package/build-module/components/block-list/block.native.js +80 -13
  110. package/build-module/components/block-list/block.native.js.map +1 -1
  111. package/build-module/components/block-list/use-in-between-inserter.js +8 -24
  112. package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
  113. package/build-module/components/block-lock/modal.js +10 -8
  114. package/build-module/components/block-lock/modal.js.map +1 -1
  115. package/build-module/components/block-parent-selector/index.js +3 -3
  116. package/build-module/components/block-parent-selector/index.js.map +1 -1
  117. package/build-module/components/block-patterns-list/index.js +5 -4
  118. package/build-module/components/block-patterns-list/index.js.map +1 -1
  119. package/build-module/components/block-popover/drop-zone.js +70 -0
  120. package/build-module/components/block-popover/drop-zone.js.map +1 -0
  121. package/build-module/components/block-popover/index.js +2 -1
  122. package/build-module/components/block-popover/index.js.map +1 -1
  123. package/build-module/components/block-preview/auto.js +1 -1
  124. package/build-module/components/block-preview/auto.js.map +1 -1
  125. package/build-module/components/block-preview/index.js +6 -9
  126. package/build-module/components/block-preview/index.js.map +1 -1
  127. package/build-module/components/block-preview/live.js +3 -6
  128. package/build-module/components/block-preview/live.js.map +1 -1
  129. package/build-module/components/block-selection-clearer/index.js +9 -1
  130. package/build-module/components/block-selection-clearer/index.js.map +1 -1
  131. package/build-module/components/block-settings-menu/block-settings-dropdown.js +18 -12
  132. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  133. package/build-module/components/block-styles/index.js +19 -44
  134. package/build-module/components/block-styles/index.js.map +1 -1
  135. package/build-module/components/block-toolbar/index.js +4 -4
  136. package/build-module/components/block-toolbar/index.js.map +1 -1
  137. package/build-module/components/block-tools/back-compat.js +2 -1
  138. package/build-module/components/block-tools/back-compat.js.map +1 -1
  139. package/build-module/components/block-tools/insertion-point.js +48 -20
  140. package/build-module/components/block-tools/insertion-point.js.map +1 -1
  141. package/build-module/components/block-tools/selected-block-popover.js +15 -3
  142. package/build-module/components/block-tools/selected-block-popover.js.map +1 -1
  143. package/build-module/components/colors-gradients/control.js +2 -2
  144. package/build-module/components/colors-gradients/control.js.map +1 -1
  145. package/build-module/components/colors-gradients/panel-color-gradient-settings.js +3 -3
  146. package/build-module/components/colors-gradients/panel-color-gradient-settings.js.map +1 -1
  147. package/build-module/components/font-sizes/fluid-utils.js +245 -0
  148. package/build-module/components/font-sizes/fluid-utils.js.map +1 -0
  149. package/build-module/components/font-sizes/index.js +1 -0
  150. package/build-module/components/font-sizes/index.js.map +1 -1
  151. package/build-module/components/index.js +0 -1
  152. package/build-module/components/index.js.map +1 -1
  153. package/build-module/components/inner-blocks/use-inner-block-template-sync.js +3 -2
  154. package/build-module/components/inner-blocks/use-inner-block-template-sync.js.map +1 -1
  155. package/build-module/components/inserter/block-patterns-tab.js +148 -81
  156. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  157. package/build-module/components/inserter/menu.js +10 -3
  158. package/build-module/components/inserter/menu.js.map +1 -1
  159. package/build-module/components/inserter-draggable-blocks/index.js +4 -2
  160. package/build-module/components/inserter-draggable-blocks/index.js.map +1 -1
  161. package/build-module/components/list-view/use-list-view-drop-zone.js +1 -14
  162. package/build-module/components/list-view/use-list-view-drop-zone.js.map +1 -1
  163. package/build-module/components/preview-options/index.js +2 -3
  164. package/build-module/components/preview-options/index.js.map +1 -1
  165. package/build-module/components/spacing-sizes-control/spacing-input-control.js +34 -5
  166. package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  167. package/build-module/components/use-block-drop-zone/index.js +98 -58
  168. package/build-module/components/use-block-drop-zone/index.js.map +1 -1
  169. package/build-module/components/use-on-block-drop/index.js +12 -12
  170. package/build-module/components/use-on-block-drop/index.js.map +1 -1
  171. package/build-module/components/use-on-block-drop/types.js +2 -0
  172. package/build-module/components/use-on-block-drop/types.js.map +1 -0
  173. package/build-module/hooks/align.js +1 -2
  174. package/build-module/hooks/align.js.map +1 -1
  175. package/build-module/hooks/align.native.js +1 -6
  176. package/build-module/hooks/align.native.js.map +1 -1
  177. package/build-module/hooks/font-size.js +59 -1
  178. package/build-module/hooks/font-size.js.map +1 -1
  179. package/build-module/hooks/margin.js +6 -5
  180. package/build-module/hooks/margin.js.map +1 -1
  181. package/build-module/hooks/padding.js +2 -1
  182. package/build-module/hooks/padding.js.map +1 -1
  183. package/build-module/hooks/style.js +124 -3
  184. package/build-module/hooks/style.js.map +1 -1
  185. package/build-module/hooks/use-typography-props.js +17 -4
  186. package/build-module/hooks/use-typography-props.js.map +1 -1
  187. package/build-module/hooks/utils.js +2 -2
  188. package/build-module/hooks/utils.js.map +1 -1
  189. package/build-module/store/actions.js +55 -42
  190. package/build-module/store/actions.js.map +1 -1
  191. package/build-module/store/defaults.js +3 -0
  192. package/build-module/store/defaults.js.map +1 -1
  193. package/build-module/store/reducer.js +32 -16
  194. package/build-module/store/reducer.js.map +1 -1
  195. package/build-module/utils/math.js +12 -0
  196. package/build-module/utils/math.js.map +1 -1
  197. package/build-module/utils/pre-parse-patterns.js +19 -2
  198. package/build-module/utils/pre-parse-patterns.js.map +1 -1
  199. package/build-style/style-rtl.css +243 -144
  200. package/build-style/style.css +243 -144
  201. package/package.json +28 -28
  202. package/src/components/block-breadcrumb/test/index.js +1 -1
  203. package/src/components/block-draggable/draggable-chip.js +4 -2
  204. package/src/components/block-inspector/index.js +8 -7
  205. package/src/components/block-list/block-list-compact.native.js +1 -0
  206. package/src/components/block-list/block.js +111 -7
  207. package/src/components/block-list/block.native.js +123 -9
  208. package/src/components/block-list/style.scss +93 -126
  209. package/src/components/block-list/use-in-between-inserter.js +8 -19
  210. package/src/components/block-lock/modal.js +12 -7
  211. package/src/components/block-mover/style.scss +0 -1
  212. package/src/components/block-parent-selector/index.js +3 -3
  213. package/src/components/block-patterns-list/index.js +9 -5
  214. package/src/components/block-patterns-list/style.scss +7 -3
  215. package/src/components/block-popover/README.md +8 -0
  216. package/src/components/block-popover/drop-zone.js +63 -0
  217. package/src/components/block-popover/index.js +2 -1
  218. package/src/components/block-popover/style.scss +17 -1
  219. package/src/components/block-preview/auto.js +1 -1
  220. package/src/components/block-preview/index.js +7 -8
  221. package/src/components/block-preview/live.js +2 -7
  222. package/src/components/block-preview/test/index.js +1 -7
  223. package/src/components/block-selection-clearer/index.js +7 -2
  224. package/src/components/block-selection-clearer/test/index.js +118 -0
  225. package/src/components/block-settings-menu/block-settings-dropdown.js +25 -11
  226. package/src/components/block-settings-menu/test/block-mode-toggle.js +17 -17
  227. package/src/components/block-styles/index.js +26 -49
  228. package/src/components/block-switcher/test/index.js +2 -2
  229. package/src/components/block-toolbar/index.js +4 -6
  230. package/src/components/block-toolbar/style.scss +38 -14
  231. package/src/components/block-tools/back-compat.js +1 -0
  232. package/src/components/block-tools/insertion-point.js +42 -17
  233. package/src/components/block-tools/selected-block-popover.js +14 -1
  234. package/src/components/button-block-appender/style.scss +4 -2
  235. package/src/components/color-palette/test/__snapshots__/control.js.snap +32 -52
  236. package/src/components/color-palette/test/control.js +11 -15
  237. package/src/components/colors-gradients/control.js +2 -2
  238. package/src/components/colors-gradients/panel-color-gradient-settings.js +3 -4
  239. package/src/components/colors-gradients/test/control.js +49 -77
  240. package/src/components/font-sizes/fluid-utils.js +296 -0
  241. package/src/components/font-sizes/index.js +1 -0
  242. package/src/components/font-sizes/test/fluid-utils.js +168 -0
  243. package/src/components/image-size-control/test/index.js +47 -60
  244. package/src/components/index.js +0 -1
  245. package/src/components/inner-blocks/use-inner-block-template-sync.js +3 -2
  246. package/src/components/inserter/block-patterns-tab.js +232 -98
  247. package/src/components/inserter/menu.js +15 -2
  248. package/src/components/inserter/style.scss +94 -9
  249. package/src/components/inserter/test/reusable-blocks-tab.js +6 -6
  250. package/src/components/inserter-draggable-blocks/index.js +12 -2
  251. package/src/components/inserter-list-item/style.scss +20 -1
  252. package/src/components/link-control/test/index.js +1 -1
  253. package/src/components/list-view/use-list-view-drop-zone.js +4 -18
  254. package/src/components/panel-color-settings/test/index.js +4 -4
  255. package/src/components/preview-options/index.js +2 -2
  256. package/src/components/preview-options/style.scss +1 -1
  257. package/src/components/provider/test/use-block-sync.js +131 -165
  258. package/src/components/responsive-block-control/test/index.js +4 -4
  259. package/src/components/spacing-sizes-control/spacing-input-control.js +16 -2
  260. package/src/components/spacing-sizes-control/style.scss +26 -19
  261. package/src/components/use-block-drop-zone/index.js +136 -79
  262. package/src/components/use-block-drop-zone/test/index.js +333 -81
  263. package/src/components/use-on-block-drop/index.js +11 -12
  264. package/src/components/use-on-block-drop/types.ts +1 -0
  265. package/src/hooks/align.js +3 -2
  266. package/src/hooks/align.native.js +5 -8
  267. package/src/hooks/font-size.js +75 -0
  268. package/src/hooks/margin.js +5 -4
  269. package/src/hooks/padding.js +1 -0
  270. package/src/hooks/style.js +122 -3
  271. package/src/hooks/test/style.js +206 -1
  272. package/src/hooks/test/use-typography-props.js +22 -0
  273. package/src/hooks/use-typography-props.js +18 -3
  274. package/src/hooks/utils.js +6 -2
  275. package/src/store/actions.js +20 -12
  276. package/src/store/defaults.js +3 -0
  277. package/src/store/reducer.js +31 -24
  278. package/src/store/test/actions.js +0 -9
  279. package/src/utils/math.js +17 -0
  280. package/src/utils/pre-parse-patterns.js +12 -7
  281. package/build/components/inserter/pattern-panel.js +0 -87
  282. package/build/components/inserter/pattern-panel.js.map +0 -1
  283. package/build-module/components/inserter/pattern-panel.js +0 -74
  284. package/build-module/components/inserter/pattern-panel.js.map +0 -1
  285. package/src/components/inserter/pattern-panel.js +0 -93
@@ -0,0 +1,296 @@
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
+ // Defaults.
8
+ const DEFAULT_MAXIMUM_VIEWPORT_WIDTH = '1600px';
9
+ const DEFAULT_MINIMUM_VIEWPORT_WIDTH = '768px';
10
+ const DEFAULT_SCALE_FACTOR = 1;
11
+ const DEFAULT_MINIMUM_FONT_SIZE_FACTOR = 0.75;
12
+ const DEFAULT_MAXIMUM_FONT_SIZE_FACTOR = 1.5;
13
+ const DEFAULT_MINIMUM_FONT_SIZE_LIMIT = '14px';
14
+
15
+ /**
16
+ * Computes a fluid font-size value that uses clamp(). A minimum and maxinmum
17
+ * font size OR a single font size can be specified.
18
+ *
19
+ * If a single font size is specified, it is scaled up and down by
20
+ * minimumFontSizeFactor and maximumFontSizeFactor to arrive at the minimum and
21
+ * maximum sizes.
22
+ *
23
+ * @example
24
+ * ```js
25
+ * // Calculate fluid font-size value from a minimum and maximum value.
26
+ * const fontSize = getComputedFluidTypographyValue( {
27
+ * minimumFontSize: '20px',
28
+ * maximumFontSize: '45px'
29
+ * } );
30
+ * // Calculate fluid font-size value from a single font size.
31
+ * const fontSize = getComputedFluidTypographyValue( {
32
+ * fontSize: '30px',
33
+ * } );
34
+ * ```
35
+ *
36
+ * @param {Object} args
37
+ * @param {?string} args.minimumViewPortWidth Minimum viewport size from which type will have fluidity. Optional if fontSize is specified.
38
+ * @param {?string} args.maximumViewPortWidth Maximum size up to which type will have fluidity. Optional if fontSize is specified.
39
+ * @param {string|number} [args.fontSize] Size to derive maximumFontSize and minimumFontSize from, if necessary. Optional if minimumFontSize and maximumFontSize are specified.
40
+ * @param {?string} args.maximumFontSize Maximum font size for any clamp() calculation. Optional.
41
+ * @param {?string} args.minimumFontSize Minimum font size for any clamp() calculation. Optional.
42
+ * @param {?number} args.scaleFactor A scale factor to determine how fast a font scales within boundaries. Optional.
43
+ * @param {?number} args.minimumFontSizeFactor How much to scale defaultFontSize by to derive minimumFontSize. Optional.
44
+ * @param {?number} args.maximumFontSizeFactor How much to scale defaultFontSize by to derive maximumFontSize. Optional.
45
+ *
46
+ * @return {string|null} A font-size value using clamp().
47
+ */
48
+ export function getComputedFluidTypographyValue( {
49
+ minimumFontSize,
50
+ maximumFontSize,
51
+ fontSize,
52
+ minimumViewPortWidth = DEFAULT_MINIMUM_VIEWPORT_WIDTH,
53
+ maximumViewPortWidth = DEFAULT_MAXIMUM_VIEWPORT_WIDTH,
54
+ scaleFactor = DEFAULT_SCALE_FACTOR,
55
+ minimumFontSizeFactor = DEFAULT_MINIMUM_FONT_SIZE_FACTOR,
56
+ maximumFontSizeFactor = DEFAULT_MAXIMUM_FONT_SIZE_FACTOR,
57
+ minimumFontSizeLimit = DEFAULT_MINIMUM_FONT_SIZE_LIMIT,
58
+ } ) {
59
+ /*
60
+ * Caches minimumFontSize in minimumFontSizeValue
61
+ * so we can check if minimumFontSize exists later.
62
+ */
63
+ let minimumFontSizeValue = minimumFontSize;
64
+
65
+ /*
66
+ * Calculates missing minimumFontSize and maximumFontSize from
67
+ * defaultFontSize if provided.
68
+ */
69
+ if ( fontSize ) {
70
+ // Parses default font size.
71
+ const fontSizeParsed = getTypographyValueAndUnit( fontSize );
72
+
73
+ // Protect against invalid units.
74
+ if ( ! fontSizeParsed?.unit ) {
75
+ return null;
76
+ }
77
+
78
+ // If no minimumFontSize is provided, derive using min scale factor.
79
+ if ( ! minimumFontSizeValue ) {
80
+ minimumFontSizeValue =
81
+ roundToPrecision(
82
+ fontSizeParsed.value * minimumFontSizeFactor,
83
+ 3
84
+ ) + fontSizeParsed.unit;
85
+ }
86
+
87
+ // Parses the minimum font size limit, so we can perform checks using it.
88
+ const minimumFontSizeLimitParsed = getTypographyValueAndUnit(
89
+ minimumFontSizeLimit,
90
+ {
91
+ coerceTo: fontSizeParsed.unit,
92
+ }
93
+ );
94
+
95
+ if ( !! minimumFontSizeLimitParsed?.value ) {
96
+ /*
97
+ * If a minimum size was not passed to this function
98
+ * and the user-defined font size is lower than `minimumFontSizeLimit`,
99
+ * then uses the user-defined font size as the minimum font-size.
100
+ */
101
+ if (
102
+ ! minimumFontSize &&
103
+ fontSizeParsed?.value < minimumFontSizeLimitParsed?.value
104
+ ) {
105
+ minimumFontSizeValue = `${ fontSizeParsed.value }${ fontSizeParsed.unit }`;
106
+ } else {
107
+ const minimumFontSizeParsed = getTypographyValueAndUnit(
108
+ minimumFontSizeValue,
109
+ {
110
+ coerceTo: fontSizeParsed.unit,
111
+ }
112
+ );
113
+
114
+ /*
115
+ * Otherwise, if the passed or calculated minimum font size is lower than `minimumFontSizeLimit`
116
+ * use `minimumFontSizeLimit` instead.
117
+ */
118
+ if (
119
+ !! minimumFontSizeParsed?.value &&
120
+ minimumFontSizeParsed.value <
121
+ minimumFontSizeLimitParsed.value
122
+ ) {
123
+ minimumFontSizeValue = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`;
124
+ }
125
+ }
126
+ }
127
+
128
+ // If no maximumFontSize is provided, derive using max scale factor.
129
+ if ( ! maximumFontSize ) {
130
+ maximumFontSize =
131
+ roundToPrecision(
132
+ fontSizeParsed.value * maximumFontSizeFactor,
133
+ 3
134
+ ) + fontSizeParsed.unit;
135
+ }
136
+ }
137
+
138
+ // Return early if one of the provided inputs is not provided.
139
+ if ( ! minimumFontSizeValue || ! maximumFontSize ) {
140
+ return null;
141
+ }
142
+
143
+ // Grab the minimum font size and normalize it in order to use the value for calculations.
144
+ const minimumFontSizeParsed =
145
+ getTypographyValueAndUnit( minimumFontSizeValue );
146
+
147
+ // We get a 'preferred' unit to keep units consistent when calculating,
148
+ // otherwise the result will not be accurate.
149
+ const fontSizeUnit = minimumFontSizeParsed?.unit || 'rem';
150
+
151
+ // Grabs the maximum font size and normalize it in order to use the value for calculations.
152
+ const maximumFontSizeParsed = getTypographyValueAndUnit( maximumFontSize, {
153
+ coerceTo: fontSizeUnit,
154
+ } );
155
+
156
+ // Checks for mandatory min and max sizes, and protects against unsupported units.
157
+ if ( ! minimumFontSizeParsed || ! maximumFontSizeParsed ) {
158
+ return null;
159
+ }
160
+
161
+ // Uses rem for accessible fluid target font scaling.
162
+ const minimumFontSizeRem = getTypographyValueAndUnit(
163
+ minimumFontSizeValue,
164
+ {
165
+ coerceTo: 'rem',
166
+ }
167
+ );
168
+
169
+ // Viewport widths defined for fluid typography. Normalize units
170
+ const maximumViewPortWidthParsed = getTypographyValueAndUnit(
171
+ maximumViewPortWidth,
172
+ { coerceTo: fontSizeUnit }
173
+ );
174
+ const minumumViewPortWidthParsed = getTypographyValueAndUnit(
175
+ minimumViewPortWidth,
176
+ { coerceTo: fontSizeUnit }
177
+ );
178
+
179
+ // Protect against unsupported units.
180
+ if (
181
+ ! maximumViewPortWidthParsed ||
182
+ ! minumumViewPortWidthParsed ||
183
+ ! minimumFontSizeRem
184
+ ) {
185
+ return null;
186
+ }
187
+
188
+ // Build CSS rule.
189
+ // Borrowed from https://websemantics.uk/tools/responsive-font-calculator/.
190
+ const minViewPortWidthOffsetValue = roundToPrecision(
191
+ minumumViewPortWidthParsed.value / 100,
192
+ 3
193
+ );
194
+
195
+ const viewPortWidthOffset =
196
+ roundToPrecision( minViewPortWidthOffsetValue, 3 ) + fontSizeUnit;
197
+ const linearFactor =
198
+ 100 *
199
+ ( ( maximumFontSizeParsed.value - minimumFontSizeParsed.value ) /
200
+ ( maximumViewPortWidthParsed.value -
201
+ minumumViewPortWidthParsed.value ) );
202
+ const linearFactorScaled = roundToPrecision(
203
+ ( linearFactor || 1 ) * scaleFactor,
204
+ 3
205
+ );
206
+ const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewPortWidthOffset }) * ${ linearFactorScaled })`;
207
+
208
+ return `clamp(${ minimumFontSizeValue }, ${ fluidTargetFontSize }, ${ maximumFontSize })`;
209
+ }
210
+
211
+ /**
212
+ * Internal method that checks a string for a unit and value and returns an array consisting of `'value'` and `'unit'`, e.g., [ '42', 'rem' ].
213
+ * A raw font size of `value + unit` is expected. If the value is an integer, it will convert to `value + 'px'`.
214
+ *
215
+ * @param {string|number} rawValue Raw size value from theme.json.
216
+ * @param {Object|undefined} options Calculation options.
217
+ *
218
+ * @return {{ unit: string, value: number }|null} An object consisting of `'value'` and `'unit'` properties.
219
+ */
220
+ export function getTypographyValueAndUnit( rawValue, options = {} ) {
221
+ if ( typeof rawValue !== 'string' && typeof rawValue !== 'number' ) {
222
+ return null;
223
+ }
224
+
225
+ // Converts numeric values to pixel values by default.
226
+ if ( isFinite( rawValue ) ) {
227
+ rawValue = `${ rawValue }px`;
228
+ }
229
+
230
+ const { coerceTo, rootSizeValue, acceptableUnits } = {
231
+ coerceTo: '',
232
+ // Default browser font size. Later we could inject some JS to compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`.
233
+ rootSizeValue: 16,
234
+ acceptableUnits: [ 'rem', 'px', 'em' ],
235
+ ...options,
236
+ };
237
+
238
+ const acceptableUnitsGroup = acceptableUnits?.join( '|' );
239
+ const regexUnits = new RegExp(
240
+ `^(\\d*\\.?\\d+)(${ acceptableUnitsGroup }){1,1}$`
241
+ );
242
+
243
+ const matches = rawValue.match( regexUnits );
244
+
245
+ // We need a number value and a unit.
246
+ if ( ! matches || matches.length < 3 ) {
247
+ return null;
248
+ }
249
+
250
+ let [ , value, unit ] = matches;
251
+
252
+ let returnValue = parseFloat( value );
253
+
254
+ if ( 'px' === coerceTo && ( 'em' === unit || 'rem' === unit ) ) {
255
+ returnValue = returnValue * rootSizeValue;
256
+ unit = coerceTo;
257
+ }
258
+
259
+ if ( 'px' === unit && ( 'em' === coerceTo || 'rem' === coerceTo ) ) {
260
+ returnValue = returnValue / rootSizeValue;
261
+ unit = coerceTo;
262
+ }
263
+
264
+ /*
265
+ * No calculation is required if swapping between em and rem yet,
266
+ * since we assume a root size value. Later we might like to differentiate between
267
+ * :root font size (rem) and parent element font size (em) relativity.
268
+ */
269
+ if (
270
+ ( 'em' === coerceTo || 'rem' === coerceTo ) &&
271
+ ( 'em' === unit || 'rem' === unit )
272
+ ) {
273
+ unit = coerceTo;
274
+ }
275
+
276
+ return {
277
+ value: roundToPrecision( returnValue, 3 ),
278
+ unit,
279
+ };
280
+ }
281
+
282
+ /**
283
+ * Returns a value rounded to defined precision.
284
+ * Returns `undefined` if the value is not a valid finite number.
285
+ *
286
+ * @param {number} value Raw value.
287
+ * @param {number} digits The number of digits to appear after the decimal point
288
+ *
289
+ * @return {number|undefined} Value rounded to standard precision.
290
+ */
291
+ export function roundToPrecision( value, digits = 3 ) {
292
+ const base = Math.pow( 10, digits );
293
+ return Number.isFinite( value )
294
+ ? parseFloat( Math.round( value * base ) / base )
295
+ : undefined;
296
+ }
@@ -3,5 +3,6 @@ export {
3
3
  getFontSizeClass,
4
4
  getFontSizeObjectByValue,
5
5
  } from './utils';
6
+ export { getComputedFluidTypographyValue } from './fluid-utils';
6
7
  export { default as FontSizePicker } from './font-size-picker';
7
8
  export { default as withFontSizes } from './with-font-sizes';
@@ -0,0 +1,168 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { logged } from '@wordpress/deprecated';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import {
10
+ getComputedFluidTypographyValue,
11
+ getTypographyValueAndUnit,
12
+ } from '../fluid-utils';
13
+
14
+ describe( 'getComputedFluidTypographyValue()', () => {
15
+ afterEach( () => {
16
+ for ( const key in logged ) {
17
+ delete logged[ key ];
18
+ }
19
+ } );
20
+
21
+ it( 'should return a fluid font size when given a min and max font size', () => {
22
+ const fluidTypographyValues = getComputedFluidTypographyValue( {
23
+ minimumFontSize: '20px',
24
+ maximumFontSize: '45px',
25
+ } );
26
+ expect( fluidTypographyValues ).toBe(
27
+ 'clamp(20px, 1.25rem + ((1vw - 7.68px) * 3.005), 45px)'
28
+ );
29
+ } );
30
+
31
+ it( 'should return a fluid font size when given a font size', () => {
32
+ const fluidTypographyValues = getComputedFluidTypographyValue( {
33
+ fontSize: '30px',
34
+ } );
35
+ expect( fluidTypographyValues ).toBe(
36
+ 'clamp(22.5px, 1.406rem + ((1vw - 7.68px) * 2.704), 45px)'
37
+ );
38
+ } );
39
+
40
+ it( 'should return a fluid font size based on px when given a numerical font size', () => {
41
+ const fluidTypographyValues = getComputedFluidTypographyValue( {
42
+ fontSize: '30px',
43
+ } );
44
+ expect( fluidTypographyValues ).toBe(
45
+ 'clamp(22.5px, 1.406rem + ((1vw - 7.68px) * 2.704), 45px)'
46
+ );
47
+ } );
48
+
49
+ it( 'should return a fluid font size when given a min and max viewport width', () => {
50
+ const fluidTypographyValues = getComputedFluidTypographyValue( {
51
+ fontSize: '30px',
52
+ minimumViewPortWidth: '500px',
53
+ maximumViewPortWidth: '1000px',
54
+ } );
55
+ expect( fluidTypographyValues ).toBe(
56
+ 'clamp(22.5px, 1.406rem + ((1vw - 5px) * 4.5), 45px)'
57
+ );
58
+ } );
59
+
60
+ it( 'should return a fluid font size when given a scale factor', () => {
61
+ const fluidTypographyValues = getComputedFluidTypographyValue( {
62
+ fontSize: '30px',
63
+ scaleFactor: '2',
64
+ } );
65
+ expect( fluidTypographyValues ).toBe(
66
+ 'clamp(22.5px, 1.406rem + ((1vw - 7.68px) * 5.409), 45px)'
67
+ );
68
+ } );
69
+
70
+ it( 'should return a fluid font size when given a min and max font size factor', () => {
71
+ const fluidTypographyValues = getComputedFluidTypographyValue( {
72
+ fontSize: '30px',
73
+ minimumFontSizeFactor: '0.5',
74
+ maximumFontSizeFactor: '2',
75
+ } );
76
+ expect( fluidTypographyValues ).toBe(
77
+ 'clamp(15px, 0.938rem + ((1vw - 7.68px) * 5.409), 60px)'
78
+ );
79
+ } );
80
+
81
+ describe( 'getTypographyValueAndUnit', () => {
82
+ it( 'should return the expected return values', () => {
83
+ [
84
+ {
85
+ value: null,
86
+ expected: null,
87
+ },
88
+ {
89
+ value: false,
90
+ expected: null,
91
+ },
92
+ {
93
+ value: true,
94
+ expected: null,
95
+ },
96
+ {
97
+ value: [ '10' ],
98
+ expected: null,
99
+ },
100
+ {
101
+ value: '10vh',
102
+ expected: null,
103
+ },
104
+ {
105
+ value: 'calc(2 * 10px)',
106
+ expected: null,
107
+ },
108
+ {
109
+ value: 'clamp(15px, 0.9375rem + ((1vw - 7.68px) * 5.409), 60px)',
110
+ expected: null,
111
+ },
112
+ {
113
+ value: '10',
114
+ expected: {
115
+ value: 10,
116
+ unit: 'px',
117
+ },
118
+ },
119
+ {
120
+ value: 11,
121
+ expected: {
122
+ value: 11,
123
+ unit: 'px',
124
+ },
125
+ },
126
+ {
127
+ value: 11.234,
128
+ expected: {
129
+ value: 11.234,
130
+ unit: 'px',
131
+ },
132
+ },
133
+ {
134
+ value: '12rem',
135
+ expected: {
136
+ value: 12,
137
+ unit: 'rem',
138
+ },
139
+ },
140
+ {
141
+ value: '12px',
142
+ expected: {
143
+ value: 12,
144
+ unit: 'px',
145
+ },
146
+ },
147
+ {
148
+ value: '12em',
149
+ expected: {
150
+ value: 12,
151
+ unit: 'em',
152
+ },
153
+ },
154
+ {
155
+ value: '12.74em',
156
+ expected: {
157
+ value: 12.74,
158
+ unit: 'em',
159
+ },
160
+ },
161
+ ].forEach( ( { value, expected } ) => {
162
+ expect( getTypographyValueAndUnit( value ) ).toEqual(
163
+ expected
164
+ );
165
+ } );
166
+ } );
167
+ } );
168
+ } );
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
4
+ import { render, screen, fireEvent } from '@testing-library/react';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -85,7 +85,7 @@ describe( 'ImageSizeControl', () => {
85
85
  } );
86
86
 
87
87
  describe( 'updating dimension inputs', () => {
88
- it( 'updates height and calls onChange', async () => {
88
+ it( 'updates height and calls onChange', () => {
89
89
  render( <ImageSizeControl onChange={ mockOnChange } /> );
90
90
 
91
91
  const heightInput = getHeightInput();
@@ -96,16 +96,14 @@ describe( 'ImageSizeControl', () => {
96
96
 
97
97
  fireEvent.change( heightInput, { target: { value: '500' } } );
98
98
 
99
- await waitFor( () => {
100
- expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
101
- expect( mockOnChange ).toHaveBeenCalledWith( { height: 500 } );
102
- } );
99
+ expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
100
+ expect( mockOnChange ).toHaveBeenCalledWith( { height: 500 } );
103
101
 
104
102
  expect( heightInput.value ).toBe( '500' );
105
103
  expect( widthInput.value ).toBe( '' );
106
104
  } );
107
105
 
108
- it( 'updates width and calls onChange', async () => {
106
+ it( 'updates width and calls onChange', () => {
109
107
  render( <ImageSizeControl onChange={ mockOnChange } /> );
110
108
 
111
109
  const heightInput = getHeightInput();
@@ -115,16 +113,15 @@ describe( 'ImageSizeControl', () => {
115
113
  expect( widthInput.value ).toBe( '' );
116
114
 
117
115
  fireEvent.change( widthInput, { target: { value: '500' } } );
118
- await waitFor( () => {
119
- expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
120
- expect( mockOnChange ).toHaveBeenCalledWith( { width: 500 } );
121
- } );
116
+
117
+ expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
118
+ expect( mockOnChange ).toHaveBeenCalledWith( { width: 500 } );
122
119
 
123
120
  expect( heightInput.value ).toBe( '' );
124
121
  expect( widthInput.value ).toBe( '500' );
125
122
  } );
126
123
 
127
- it( 'updates height and calls onChange for empty value', async () => {
124
+ it( 'updates height and calls onChange for empty value', () => {
128
125
  render(
129
126
  <ImageSizeControl
130
127
  imageHeight="100"
@@ -141,20 +138,19 @@ describe( 'ImageSizeControl', () => {
141
138
 
142
139
  fireEvent.change( heightInput, { target: { value: '' } } );
143
140
 
144
- await waitFor( () => {
145
- // onChange is called and sets the dimension to undefined rather than
146
- // the empty string.
147
- expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
148
- expect( mockOnChange ).toHaveBeenCalledWith( {
149
- height: undefined,
150
- } );
141
+ // onChange is called and sets the dimension to undefined rather than
142
+ // the empty string.
143
+ expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
144
+ expect( mockOnChange ).toHaveBeenCalledWith( {
145
+ height: undefined,
151
146
  } );
147
+
152
148
  // Height is updated to empty value and does not reset to default.
153
149
  expect( heightInput.value ).toBe( '' );
154
150
  expect( widthInput.value ).toBe( '100' );
155
151
  } );
156
152
 
157
- it( 'updates width and calls onChange for empty value', async () => {
153
+ it( 'updates width and calls onChange for empty value', () => {
158
154
  render(
159
155
  <ImageSizeControl
160
156
  imageHeight="100"
@@ -171,14 +167,13 @@ describe( 'ImageSizeControl', () => {
171
167
 
172
168
  fireEvent.change( widthInput, { target: { value: '' } } );
173
169
 
174
- await waitFor( () => {
175
- // onChange is called and sets the dimension to undefined rather than
176
- // the empty string.
177
- expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
178
- expect( mockOnChange ).toHaveBeenCalledWith( {
179
- width: undefined,
180
- } );
170
+ // onChange is called and sets the dimension to undefined rather than
171
+ // the empty string.
172
+ expect( mockOnChange ).toHaveBeenCalledTimes( 1 );
173
+ expect( mockOnChange ).toHaveBeenCalledWith( {
174
+ width: undefined,
181
175
  } );
176
+
182
177
  // Width is updated to empty value and does not reset to default.
183
178
  expect( heightInput.value ).toBe( '100' );
184
179
  expect( widthInput.value ).toBe( '' );
@@ -186,7 +181,7 @@ describe( 'ImageSizeControl', () => {
186
181
  } );
187
182
 
188
183
  describe( 'reset button', () => {
189
- it( 'resets both height and width to default values', async () => {
184
+ it( 'resets both height and width to default values', () => {
190
185
  render(
191
186
  <ImageSizeControl
192
187
  imageHeight="100"
@@ -206,22 +201,20 @@ describe( 'ImageSizeControl', () => {
206
201
 
207
202
  fireEvent.click( screen.getByText( 'Reset' ) );
208
203
 
209
- await waitFor( () => {
210
- // Both attributes are set to undefined to clear custom values.
211
- expect( mockOnChange ).toHaveBeenCalledWith( {
212
- height: undefined,
213
- width: undefined,
214
- } );
215
-
216
- // The inputs display the default values once more.
217
- expect( heightInput.value ).toBe( '100' );
218
- expect( widthInput.value ).toBe( '200' );
204
+ // Both attributes are set to undefined to clear custom values.
205
+ expect( mockOnChange ).toHaveBeenCalledWith( {
206
+ height: undefined,
207
+ width: undefined,
219
208
  } );
209
+
210
+ // The inputs display the default values once more.
211
+ expect( heightInput.value ).toBe( '100' );
212
+ expect( widthInput.value ).toBe( '200' );
220
213
  } );
221
214
  } );
222
215
 
223
216
  describe( 'image size percentage presets', () => {
224
- it( 'updates height and width attributes on selection', async () => {
217
+ it( 'updates height and width attributes on selection', () => {
225
218
  render(
226
219
  <ImageSizeControl
227
220
  imageHeight="100"
@@ -232,18 +225,16 @@ describe( 'ImageSizeControl', () => {
232
225
 
233
226
  fireEvent.click( screen.getByText( '50%' ) );
234
227
 
235
- await waitFor( () => {
236
- expect( screen.getByText( '50%' ) ).toHaveClass( 'is-pressed' );
228
+ expect( screen.getByText( '50%' ) ).toHaveClass( 'is-pressed' );
237
229
 
238
- // Both attributes are set to the rounded scaled value.
239
- expect( mockOnChange ).toHaveBeenCalledWith( {
240
- height: 50,
241
- width: 101,
242
- } );
230
+ // Both attributes are set to the rounded scaled value.
231
+ expect( mockOnChange ).toHaveBeenCalledWith( {
232
+ height: 50,
233
+ width: 101,
243
234
  } );
244
235
  } );
245
236
 
246
- it( 'updates height and width inputs on selection', async () => {
237
+ it( 'updates height and width inputs on selection', () => {
247
238
  render(
248
239
  <ImageSizeControl
249
240
  imageHeight="100"
@@ -254,11 +245,9 @@ describe( 'ImageSizeControl', () => {
254
245
 
255
246
  fireEvent.click( screen.getByText( '50%' ) );
256
247
 
257
- await waitFor( () => {
258
- // Both attributes are set to the rounded scaled value.
259
- expect( getHeightInput().value ).toBe( '50' );
260
- expect( getWidthInput().value ).toBe( '101' );
261
- } );
248
+ // Both attributes are set to the rounded scaled value.
249
+ expect( getHeightInput().value ).toBe( '50' );
250
+ expect( getWidthInput().value ).toBe( '101' );
262
251
  } );
263
252
  } );
264
253
 
@@ -284,7 +273,7 @@ describe( 'ImageSizeControl', () => {
284
273
  );
285
274
  } );
286
275
 
287
- it( 'calls onChangeImage with selected slug on selection', async () => {
276
+ it( 'calls onChangeImage with selected slug on selection', () => {
288
277
  render(
289
278
  <ImageSizeControl
290
279
  imageSizeOptions={ IMAGE_SIZE_OPTIONS }
@@ -298,13 +287,11 @@ describe( 'ImageSizeControl', () => {
298
287
  target: { value: 'thumbnail' },
299
288
  } );
300
289
 
301
- await waitFor( () => {
302
- // onChangeImage is called with the slug and the event.
303
- expect( mockOnChangeImage ).toHaveBeenCalledWith(
304
- 'thumbnail',
305
- expect.any( Object )
306
- );
307
- } );
290
+ // onChangeImage is called with the slug and the event.
291
+ expect( mockOnChangeImage ).toHaveBeenCalledWith(
292
+ 'thumbnail',
293
+ expect.any( Object )
294
+ );
308
295
  } );
309
296
  } );
310
297
  } );
@@ -155,7 +155,6 @@ export {
155
155
  export { default as __experimentalBlockPatternsList } from './block-patterns-list';
156
156
  export { default as __experimentalPublishDateTimePicker } from './publish-date-time-picker';
157
157
  export { default as __experimentalInspectorPopoverHeader } from './inspector-popover-header';
158
- export { default as __experimentalUseOnBlockDrop } from './use-on-block-drop';
159
158
 
160
159
  /*
161
160
  * State Related Components