@wordpress/components 21.0.2 → 21.1.2-next.4d3b314fd5.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 (255) hide show
  1. package/CHANGELOG.md +31 -4
  2. package/build/autocomplete/get-default-use-items.js +3 -3
  3. package/build/autocomplete/get-default-use-items.js.map +1 -1
  4. package/build/box-control/unit-control.js +0 -1
  5. package/build/box-control/unit-control.js.map +1 -1
  6. package/build/button/index.js +5 -1
  7. package/build/button/index.js.map +1 -1
  8. package/build/draggable/index.js +3 -6
  9. package/build/draggable/index.js.map +1 -1
  10. package/build/drop-zone/index.js +7 -1
  11. package/build/drop-zone/index.js.map +1 -1
  12. package/build/higher-order/with-filters/index.js +1 -1
  13. package/build/higher-order/with-filters/index.js.map +1 -1
  14. package/build/index.js +6 -0
  15. package/build/index.js.map +1 -1
  16. package/build/menu-item/index.js +4 -3
  17. package/build/menu-item/index.js.map +1 -1
  18. package/build/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js +10 -3
  19. package/build/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js.map +1 -1
  20. package/build/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js +15 -6
  21. package/build/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js.map +1 -1
  22. package/build/mobile/bottom-sheet/sub-sheet/index.native.js +4 -1
  23. package/build/mobile/bottom-sheet/sub-sheet/index.native.js.map +1 -1
  24. package/build/mobile/color-settings/index.native.js +3 -1
  25. package/build/mobile/color-settings/index.native.js.map +1 -1
  26. package/build/mobile/color-settings/picker-screen.native.js +3 -1
  27. package/build/mobile/color-settings/picker-screen.native.js.map +1 -1
  28. package/build/mobile/image/index.native.js +3 -1
  29. package/build/mobile/image/index.native.js.map +1 -1
  30. package/build/mobile/keyboard-avoiding-view/index.ios.js +3 -1
  31. package/build/mobile/keyboard-avoiding-view/index.ios.js.map +1 -1
  32. package/build/mobile/link-picker/index.native.js +3 -1
  33. package/build/mobile/link-picker/index.native.js.map +1 -1
  34. package/build/mobile/link-picker/link-picker-results.native.js +6 -4
  35. package/build/mobile/link-picker/link-picker-results.native.js.map +1 -1
  36. package/build/mobile/link-picker/link-picker-screen.native.js +3 -1
  37. package/build/mobile/link-picker/link-picker-screen.native.js.map +1 -1
  38. package/build/mobile/link-settings/index.native.js +24 -6
  39. package/build/mobile/link-settings/index.native.js.map +1 -1
  40. package/build/mobile/link-settings/link-settings-screen.native.js +3 -1
  41. package/build/mobile/link-settings/link-settings-screen.native.js.map +1 -1
  42. package/build/mobile/segmented-control/index.native.js +6 -2
  43. package/build/mobile/segmented-control/index.native.js.map +1 -1
  44. package/build/mobile/utils/use-unit-converter-to-mobile.native.js +6 -2
  45. package/build/mobile/utils/use-unit-converter-to-mobile.native.js.map +1 -1
  46. package/build/notice/index.native.js +15 -19
  47. package/build/notice/index.native.js.map +1 -1
  48. package/build/notice/list.native.js +2 -3
  49. package/build/notice/list.native.js.map +1 -1
  50. package/build/palette-edit/index.js +1 -1
  51. package/build/palette-edit/index.js.map +1 -1
  52. package/build/popover/index.js +29 -32
  53. package/build/popover/index.js.map +1 -1
  54. package/build/popover/limit-shift.js +145 -0
  55. package/build/popover/limit-shift.js.map +1 -0
  56. package/build/popover/utils.js +55 -15
  57. package/build/popover/utils.js.map +1 -1
  58. package/build/range-control/input-range.js +1 -15
  59. package/build/range-control/input-range.js.map +1 -1
  60. package/build/range-control/tooltip.js +1 -1
  61. package/build/range-control/tooltip.js.map +1 -1
  62. package/build/range-control/utils.js +2 -58
  63. package/build/range-control/utils.js.map +1 -1
  64. package/build/tools-panel/styles.js +27 -12
  65. package/build/tools-panel/styles.js.map +1 -1
  66. package/build/tools-panel/tools-panel-header/component.js +19 -6
  67. package/build/tools-panel/tools-panel-header/component.js.map +1 -1
  68. package/build/tools-panel/tools-panel-header/hook.js +4 -0
  69. package/build/tools-panel/tools-panel-header/hook.js.map +1 -1
  70. package/build/tree-grid/index.js +13 -8
  71. package/build/tree-grid/index.js.map +1 -1
  72. package/build/unit-control/index.js +2 -2
  73. package/build/unit-control/index.js.map +1 -1
  74. package/build/unit-control/index.native.js +10 -2
  75. package/build/unit-control/index.native.js.map +1 -1
  76. package/build/unit-control/styles/unit-control-styles.js +21 -32
  77. package/build/unit-control/styles/unit-control-styles.js.map +1 -1
  78. package/build/utils/hooks/use-controlled-state.js +2 -3
  79. package/build/utils/hooks/use-controlled-state.js.map +1 -1
  80. package/build-module/autocomplete/get-default-use-items.js +1 -1
  81. package/build-module/autocomplete/get-default-use-items.js.map +1 -1
  82. package/build-module/box-control/unit-control.js +0 -1
  83. package/build-module/box-control/unit-control.js.map +1 -1
  84. package/build-module/button/index.js +5 -1
  85. package/build-module/button/index.js.map +1 -1
  86. package/build-module/draggable/index.js +2 -5
  87. package/build-module/draggable/index.js.map +1 -1
  88. package/build-module/drop-zone/index.js +7 -1
  89. package/build-module/drop-zone/index.js.map +1 -1
  90. package/build-module/higher-order/with-filters/index.js +2 -2
  91. package/build-module/higher-order/with-filters/index.js.map +1 -1
  92. package/build-module/index.js +1 -1
  93. package/build-module/index.js.map +1 -1
  94. package/build-module/menu-item/index.js +4 -3
  95. package/build-module/menu-item/index.js.map +1 -1
  96. package/build-module/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js +10 -3
  97. package/build-module/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js.map +1 -1
  98. package/build-module/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js +13 -4
  99. package/build-module/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js.map +1 -1
  100. package/build-module/mobile/bottom-sheet/sub-sheet/index.native.js +4 -1
  101. package/build-module/mobile/bottom-sheet/sub-sheet/index.native.js.map +1 -1
  102. package/build-module/mobile/color-settings/index.native.js +3 -1
  103. package/build-module/mobile/color-settings/index.native.js.map +1 -1
  104. package/build-module/mobile/color-settings/picker-screen.native.js +3 -1
  105. package/build-module/mobile/color-settings/picker-screen.native.js.map +1 -1
  106. package/build-module/mobile/image/index.native.js +3 -1
  107. package/build-module/mobile/image/index.native.js.map +1 -1
  108. package/build-module/mobile/keyboard-avoiding-view/index.ios.js +3 -1
  109. package/build-module/mobile/keyboard-avoiding-view/index.ios.js.map +1 -1
  110. package/build-module/mobile/link-picker/index.native.js +3 -1
  111. package/build-module/mobile/link-picker/index.native.js.map +1 -1
  112. package/build-module/mobile/link-picker/link-picker-results.native.js +4 -2
  113. package/build-module/mobile/link-picker/link-picker-results.native.js.map +1 -1
  114. package/build-module/mobile/link-picker/link-picker-screen.native.js +3 -1
  115. package/build-module/mobile/link-picker/link-picker-screen.native.js.map +1 -1
  116. package/build-module/mobile/link-settings/index.native.js +24 -6
  117. package/build-module/mobile/link-settings/index.native.js.map +1 -1
  118. package/build-module/mobile/link-settings/link-settings-screen.native.js +3 -1
  119. package/build-module/mobile/link-settings/link-settings-screen.native.js.map +1 -1
  120. package/build-module/mobile/segmented-control/index.native.js +6 -2
  121. package/build-module/mobile/segmented-control/index.native.js.map +1 -1
  122. package/build-module/mobile/utils/use-unit-converter-to-mobile.native.js +6 -2
  123. package/build-module/mobile/utils/use-unit-converter-to-mobile.native.js.map +1 -1
  124. package/build-module/notice/index.native.js +16 -21
  125. package/build-module/notice/index.native.js.map +1 -1
  126. package/build-module/notice/list.native.js +3 -3
  127. package/build-module/notice/list.native.js.map +1 -1
  128. package/build-module/palette-edit/index.js +1 -1
  129. package/build-module/palette-edit/index.js.map +1 -1
  130. package/build-module/popover/index.js +31 -35
  131. package/build-module/popover/index.js.map +1 -1
  132. package/build-module/popover/limit-shift.js +136 -0
  133. package/build-module/popover/limit-shift.js.map +1 -0
  134. package/build-module/popover/utils.js +55 -15
  135. package/build-module/popover/utils.js.map +1 -1
  136. package/build-module/range-control/input-range.js +1 -14
  137. package/build-module/range-control/input-range.js.map +1 -1
  138. package/build-module/range-control/tooltip.js +1 -1
  139. package/build-module/range-control/tooltip.js.map +1 -1
  140. package/build-module/range-control/utils.js +2 -57
  141. package/build-module/range-control/utils.js.map +1 -1
  142. package/build-module/tools-panel/styles.js +23 -12
  143. package/build-module/tools-panel/styles.js.map +1 -1
  144. package/build-module/tools-panel/tools-panel-header/component.js +19 -7
  145. package/build-module/tools-panel/tools-panel-header/component.js.map +1 -1
  146. package/build-module/tools-panel/tools-panel-header/hook.js +4 -0
  147. package/build-module/tools-panel/tools-panel-header/hook.js.map +1 -1
  148. package/build-module/tree-grid/index.js +13 -8
  149. package/build-module/tree-grid/index.js.map +1 -1
  150. package/build-module/unit-control/index.js +2 -2
  151. package/build-module/unit-control/index.js.map +1 -1
  152. package/build-module/unit-control/index.native.js +10 -2
  153. package/build-module/unit-control/index.native.js.map +1 -1
  154. package/build-module/unit-control/styles/unit-control-styles.js +20 -31
  155. package/build-module/unit-control/styles/unit-control-styles.js.map +1 -1
  156. package/build-module/utils/hooks/use-controlled-state.js +3 -4
  157. package/build-module/utils/hooks/use-controlled-state.js.map +1 -1
  158. package/build-style/style-rtl.css +13 -2
  159. package/build-style/style.css +13 -2
  160. package/build-types/button/index.d.ts.map +1 -1
  161. package/build-types/draggable/index.d.ts.map +1 -1
  162. package/build-types/drop-zone/index.d.ts.map +1 -1
  163. package/build-types/external-link/styles/external-link-styles.d.ts +1 -1
  164. package/build-types/focal-point-picker/styles/focal-point-style.d.ts +3 -3
  165. package/build-types/menu-item/index.d.ts.map +1 -1
  166. package/build-types/popover/index.d.ts.map +1 -1
  167. package/build-types/popover/limit-shift.d.ts +87 -0
  168. package/build-types/popover/limit-shift.d.ts.map +1 -0
  169. package/build-types/popover/stories/e2e/index.d.ts +8 -0
  170. package/build-types/popover/stories/e2e/index.d.ts.map +1 -0
  171. package/build-types/popover/test/index.d.ts +2 -0
  172. package/build-types/popover/test/index.d.ts.map +1 -0
  173. package/build-types/popover/types.d.ts +1 -1
  174. package/build-types/popover/types.d.ts.map +1 -1
  175. package/build-types/popover/utils.d.ts.map +1 -1
  176. package/build-types/range-control/input-range.d.ts.map +1 -1
  177. package/build-types/range-control/stories/index.d.ts.map +1 -1
  178. package/build-types/range-control/types.d.ts +0 -34
  179. package/build-types/range-control/types.d.ts.map +1 -1
  180. package/build-types/range-control/utils.d.ts +1 -12
  181. package/build-types/range-control/utils.d.ts.map +1 -1
  182. package/build-types/spinner/index.d.ts +1 -1
  183. package/build-types/tools-panel/styles.d.ts +6 -0
  184. package/build-types/tools-panel/styles.d.ts.map +1 -1
  185. package/build-types/tools-panel/tools-panel-header/component.d.ts.map +1 -1
  186. package/build-types/tools-panel/tools-panel-header/hook.d.ts +1 -0
  187. package/build-types/tools-panel/tools-panel-header/hook.d.ts.map +1 -1
  188. package/build-types/tools-panel/types.d.ts +1 -0
  189. package/build-types/tools-panel/types.d.ts.map +1 -1
  190. package/build-types/unit-control/styles/unit-control-styles.d.ts +1 -4
  191. package/build-types/unit-control/styles/unit-control-styles.d.ts.map +1 -1
  192. package/build-types/utils/hooks/use-controlled-state.d.ts.map +1 -1
  193. package/package.json +17 -17
  194. package/src/autocomplete/get-default-use-items.js +1 -1
  195. package/src/box-control/unit-control.js +0 -1
  196. package/src/button/index.js +7 -1
  197. package/src/button/test/index.js +36 -0
  198. package/src/color-palette/test/__snapshots__/index.js.snap +169 -1106
  199. package/src/color-palette/test/index.js +107 -61
  200. package/src/draggable/index.js +2 -5
  201. package/src/drop-zone/index.tsx +4 -1
  202. package/src/font-size-picker/stories/e2e/index.js +47 -0
  203. package/src/higher-order/with-filters/index.js +2 -2
  204. package/src/index.js +1 -1
  205. package/src/menu-item/README.md +7 -0
  206. package/src/menu-item/index.js +11 -5
  207. package/src/menu-item/style.scss +1 -0
  208. package/src/menu-item/test/index.js +36 -0
  209. package/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-container.native.js +9 -0
  210. package/src/mobile/bottom-sheet/bottom-sheet-navigation/navigation-screen.native.js +12 -2
  211. package/src/mobile/bottom-sheet/sub-sheet/index.native.js +3 -0
  212. package/src/mobile/color-settings/index.native.js +3 -0
  213. package/src/mobile/color-settings/picker-screen.native.js +3 -0
  214. package/src/mobile/image/index.native.js +3 -0
  215. package/src/mobile/keyboard-avoiding-view/index.ios.js +3 -0
  216. package/src/mobile/link-picker/index.native.js +3 -0
  217. package/src/mobile/link-picker/link-picker-results.native.js +4 -1
  218. package/src/mobile/link-picker/link-picker-screen.native.js +3 -0
  219. package/src/mobile/link-settings/index.native.js +18 -0
  220. package/src/mobile/link-settings/link-settings-screen.native.js +3 -0
  221. package/src/mobile/segmented-control/index.native.js +6 -0
  222. package/src/mobile/utils/use-unit-converter-to-mobile.native.js +6 -0
  223. package/src/notice/index.native.js +17 -20
  224. package/src/notice/list.native.js +7 -3
  225. package/src/palette-edit/index.js +1 -1
  226. package/src/placeholder/style.scss +1 -1
  227. package/src/popover/index.tsx +26 -42
  228. package/src/popover/limit-shift.ts +205 -0
  229. package/src/popover/stories/e2e/index.tsx +25 -0
  230. package/src/popover/test/index.tsx +230 -0
  231. package/src/popover/types.ts +1 -0
  232. package/src/popover/utils.ts +58 -16
  233. package/src/range-control/README.md +6 -7
  234. package/src/range-control/input-range.tsx +1 -21
  235. package/src/range-control/stories/index.tsx +2 -1
  236. package/src/range-control/tooltip.tsx +1 -1
  237. package/src/range-control/types.ts +0 -35
  238. package/src/range-control/utils.ts +3 -75
  239. package/src/tools-panel/stories/index.js +27 -0
  240. package/src/tools-panel/styles.ts +28 -1
  241. package/src/tools-panel/tools-panel-header/component.tsx +12 -5
  242. package/src/tools-panel/tools-panel-header/hook.ts +5 -0
  243. package/src/tools-panel/types.ts +1 -0
  244. package/src/tree-grid/index.js +23 -14
  245. package/src/tree-grid/test/__snapshots__/cell.js.snap +21 -17
  246. package/src/tree-grid/test/__snapshots__/index.js.snap +1 -1
  247. package/src/unit-control/index.native.js +8 -0
  248. package/src/unit-control/index.tsx +2 -2
  249. package/src/unit-control/styles/unit-control-styles.ts +0 -20
  250. package/src/unit-control/test/index.tsx +6 -3
  251. package/src/utils/hooks/use-controlled-state.js +9 -6
  252. package/tsconfig.tsbuildinfo +1 -1
  253. package/src/popover/test/__snapshots__/index.js.snap +0 -34
  254. package/src/popover/test/index.js +0 -164
  255. package/src/unit-control/test/__snapshots__/index.tsx.snap +0 -31
@@ -0,0 +1,230 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+ import type { CSSProperties } from 'react';
6
+
7
+ /**
8
+ * WordPress dependencies
9
+ */
10
+ import { useState } from '@wordpress/element';
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import { positionToPlacement, placementToMotionAnimationProps } from '../utils';
16
+ import Popover from '..';
17
+ import type { PopoverProps } from '../types';
18
+
19
+ type PositionToPlacementTuple = [
20
+ NonNullable< PopoverProps[ 'position' ] >,
21
+ NonNullable< PopoverProps[ 'placement' ] >
22
+ ];
23
+ type PlacementToAnimationOriginTuple = [
24
+ NonNullable< PopoverProps[ 'placement' ] >,
25
+ number,
26
+ number
27
+ ];
28
+ type PlacementToInitialTranslationTuple = [
29
+ NonNullable< PopoverProps[ 'placement' ] >,
30
+ 'translateY' | 'translateX',
31
+ CSSProperties[ 'translate' ]
32
+ ];
33
+
34
+ // There's no matching `placement` for 'middle center' positions,
35
+ // fallback to 'bottom' (same as `floating-ui`'s default.)
36
+ const FALLBACK_FOR_MIDDLE_CENTER_POSITIONS = 'bottom';
37
+
38
+ const ALL_POSITIONS_TO_EXPECTED_PLACEMENTS: PositionToPlacementTuple[] = [
39
+ // Format: [yAxis]
40
+ [ 'middle', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
41
+ [ 'bottom', 'bottom' ],
42
+ [ 'top', 'top' ],
43
+ // Format: [yAxis] [xAxis]
44
+ [ 'middle left', 'left' ],
45
+ [ 'middle center', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
46
+ [ 'middle right', 'right' ],
47
+ [ 'bottom left', 'bottom-end' ],
48
+ [ 'bottom center', 'bottom' ],
49
+ [ 'bottom right', 'bottom-start' ],
50
+ [ 'top left', 'top-end' ],
51
+ [ 'top center', 'top' ],
52
+ [ 'top right', 'top-start' ],
53
+ // Format: [yAxis] [xAxis] [corner]
54
+ [ 'middle left left', 'left' ],
55
+ [ 'middle left right', 'left' ],
56
+ [ 'middle left bottom', 'left-end' ],
57
+ [ 'middle left top', 'left-start' ],
58
+ [ 'middle center left', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
59
+ [ 'middle center right', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
60
+ [ 'middle center bottom', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
61
+ [ 'middle center top', FALLBACK_FOR_MIDDLE_CENTER_POSITIONS ],
62
+ [ 'middle right left', 'right' ],
63
+ [ 'middle right right', 'right' ],
64
+ [ 'middle right bottom', 'right-end' ],
65
+ [ 'middle right top', 'right-start' ],
66
+ [ 'bottom left left', 'bottom-end' ],
67
+ [ 'bottom left right', 'bottom-end' ],
68
+ [ 'bottom left bottom', 'bottom-end' ],
69
+ [ 'bottom left top', 'bottom-end' ],
70
+ [ 'bottom center left', 'bottom' ],
71
+ [ 'bottom center right', 'bottom' ],
72
+ [ 'bottom center bottom', 'bottom' ],
73
+ [ 'bottom center top', 'bottom' ],
74
+ [ 'bottom right left', 'bottom-start' ],
75
+ [ 'bottom right right', 'bottom-start' ],
76
+ [ 'bottom right bottom', 'bottom-start' ],
77
+ [ 'bottom right top', 'bottom-start' ],
78
+ [ 'top left left', 'top-end' ],
79
+ [ 'top left right', 'top-end' ],
80
+ [ 'top left bottom', 'top-end' ],
81
+ [ 'top left top', 'top-end' ],
82
+ [ 'top center left', 'top' ],
83
+ [ 'top center right', 'top' ],
84
+ [ 'top center bottom', 'top' ],
85
+ [ 'top center top', 'top' ],
86
+ [ 'top right left', 'top-start' ],
87
+ [ 'top right right', 'top-start' ],
88
+ [ 'top right bottom', 'top-start' ],
89
+ [ 'top right top', 'top-start' ],
90
+ ];
91
+
92
+ describe( 'Popover', () => {
93
+ describe( 'Component', () => {
94
+ describe( 'basic behavior', () => {
95
+ it( 'should render content', () => {
96
+ render( <Popover>Hello</Popover> );
97
+
98
+ expect( screen.getByText( 'Hello' ) ).toBeInTheDocument();
99
+ } );
100
+
101
+ it( 'should forward additional props to portaled element', () => {
102
+ render( <Popover role="tooltip">Hello</Popover> );
103
+
104
+ expect( screen.getByRole( 'tooltip' ) ).toBeInTheDocument();
105
+ } );
106
+ } );
107
+
108
+ describe( 'anchor', () => {
109
+ it( 'should render correctly when anchor is provided', () => {
110
+ const PopoverWithAnchor = ( args: PopoverProps ) => {
111
+ // Use internal state instead of a ref to make sure that the component
112
+ // re-renders when the popover's anchor updates.
113
+ const [ anchor, setAnchor ] =
114
+ useState< HTMLParagraphElement | null >( null );
115
+
116
+ return (
117
+ <div>
118
+ <p ref={ setAnchor }>Anchor</p>
119
+ <Popover { ...args } anchor={ anchor } />
120
+ </div>
121
+ );
122
+ };
123
+
124
+ render(
125
+ <PopoverWithAnchor>Popover content</PopoverWithAnchor>
126
+ );
127
+
128
+ expect(
129
+ screen.getByText( 'Popover content' )
130
+ ).toBeInTheDocument();
131
+ } );
132
+ } );
133
+
134
+ describe( 'focus behavior', () => {
135
+ it( 'should focus the popover by default when opened', () => {
136
+ render( <Popover>Popover content</Popover> );
137
+
138
+ expect(
139
+ screen.getByText( 'Popover content' ).parentElement
140
+ ).toHaveFocus();
141
+ } );
142
+
143
+ it( 'should allow focus-on-open behavior to be disabled', () => {
144
+ render(
145
+ <Popover focusOnMount={ false }>Popover content</Popover>
146
+ );
147
+
148
+ expect( document.body ).toHaveFocus();
149
+ } );
150
+ } );
151
+ } );
152
+
153
+ describe( 'positionToPlacement', () => {
154
+ it.each( ALL_POSITIONS_TO_EXPECTED_PLACEMENTS )(
155
+ 'converts `%s` to `%s`',
156
+ ( inputPosition, expectedPlacement ) => {
157
+ expect( positionToPlacement( inputPosition ) ).toEqual(
158
+ expectedPlacement
159
+ );
160
+ }
161
+ );
162
+ } );
163
+
164
+ describe( 'placementToMotionAnimationProps', () => {
165
+ describe( 'animation origin', () => {
166
+ it.each( [
167
+ [ 'top', 0.5, 1 ],
168
+ [ 'top-start', 0, 1 ],
169
+ [ 'top-end', 1, 1 ],
170
+ [ 'right', 0, 0.5 ],
171
+ [ 'right-start', 0, 0 ],
172
+ [ 'right-end', 0, 1 ],
173
+ [ 'bottom', 0.5, 0 ],
174
+ [ 'bottom-start', 0, 0 ],
175
+ [ 'bottom-end', 1, 0 ],
176
+ [ 'left', 1, 0.5 ],
177
+ [ 'left-start', 1, 0 ],
178
+ [ 'left-end', 1, 1 ],
179
+ ] as PlacementToAnimationOriginTuple[] )(
180
+ 'for the `%s` placement computes an animation origin of (%d, %d)',
181
+ ( inputPlacement, expectedOriginX, expectedOriginY ) => {
182
+ expect(
183
+ placementToMotionAnimationProps( inputPlacement )
184
+ ).toEqual(
185
+ expect.objectContaining( {
186
+ style: expect.objectContaining( {
187
+ originX: expectedOriginX,
188
+ originY: expectedOriginY,
189
+ } ),
190
+ } )
191
+ );
192
+ }
193
+ );
194
+ } );
195
+ describe( 'initial translation', () => {
196
+ it.each( [
197
+ [ 'top', 'translateY', '2em' ],
198
+ [ 'top-start', 'translateY', '2em' ],
199
+ [ 'top-end', 'translateY', '2em' ],
200
+ [ 'right', 'translateX', '-2em' ],
201
+ [ 'right-start', 'translateX', '-2em' ],
202
+ [ 'right-end', 'translateX', '-2em' ],
203
+ [ 'bottom', 'translateY', '-2em' ],
204
+ [ 'bottom-start', 'translateY', '-2em' ],
205
+ [ 'bottom-end', 'translateY', '-2em' ],
206
+ [ 'left', 'translateX', '2em' ],
207
+ [ 'left-start', 'translateX', '2em' ],
208
+ [ 'left-end', 'translateX', '2em' ],
209
+ ] as PlacementToInitialTranslationTuple[] )(
210
+ 'for the `%s` placement computes an initial `%s` of `%s',
211
+ (
212
+ inputPlacement,
213
+ expectedTranslationProp,
214
+ expectedTranslationValue
215
+ ) => {
216
+ expect(
217
+ placementToMotionAnimationProps( inputPlacement )
218
+ ).toEqual(
219
+ expect.objectContaining( {
220
+ initial: expect.objectContaining( {
221
+ [ expectedTranslationProp ]:
222
+ expectedTranslationValue,
223
+ } ),
224
+ } )
225
+ );
226
+ }
227
+ );
228
+ } );
229
+ } );
230
+ } );
@@ -121,6 +121,7 @@ export type PopoverProps = {
121
121
  * _Note: this prop is deprecated. Use the `placement` prop instead._
122
122
  */
123
123
  position?:
124
+ | `${ PositionYAxis }`
124
125
  | `${ PositionYAxis } ${ PositionXAxis }`
125
126
  | `${ PositionYAxis } ${ PositionXAxis } ${ PositionCorner }`;
126
127
  /**
@@ -14,6 +14,62 @@ import type {
14
14
  PopoverAnchorRefTopBottom,
15
15
  } from './types';
16
16
 
17
+ const POSITION_TO_PLACEMENT: Record<
18
+ NonNullable< PopoverProps[ 'position' ] >,
19
+ NonNullable< PopoverProps[ 'placement' ] >
20
+ > = {
21
+ bottom: 'bottom',
22
+ top: 'top',
23
+ 'middle left': 'left',
24
+ 'middle right': 'right',
25
+ 'bottom left': 'bottom-end',
26
+ 'bottom center': 'bottom',
27
+ 'bottom right': 'bottom-start',
28
+ 'top left': 'top-end',
29
+ 'top center': 'top',
30
+ 'top right': 'top-start',
31
+ 'middle left left': 'left',
32
+ 'middle left right': 'left',
33
+ 'middle left bottom': 'left-end',
34
+ 'middle left top': 'left-start',
35
+ 'middle right left': 'right',
36
+ 'middle right right': 'right',
37
+ 'middle right bottom': 'right-end',
38
+ 'middle right top': 'right-start',
39
+ 'bottom left left': 'bottom-end',
40
+ 'bottom left right': 'bottom-end',
41
+ 'bottom left bottom': 'bottom-end',
42
+ 'bottom left top': 'bottom-end',
43
+ 'bottom center left': 'bottom',
44
+ 'bottom center right': 'bottom',
45
+ 'bottom center bottom': 'bottom',
46
+ 'bottom center top': 'bottom',
47
+ 'bottom right left': 'bottom-start',
48
+ 'bottom right right': 'bottom-start',
49
+ 'bottom right bottom': 'bottom-start',
50
+ 'bottom right top': 'bottom-start',
51
+ 'top left left': 'top-end',
52
+ 'top left right': 'top-end',
53
+ 'top left bottom': 'top-end',
54
+ 'top left top': 'top-end',
55
+ 'top center left': 'top',
56
+ 'top center right': 'top',
57
+ 'top center bottom': 'top',
58
+ 'top center top': 'top',
59
+ 'top right left': 'top-start',
60
+ 'top right right': 'top-start',
61
+ 'top right bottom': 'top-start',
62
+ 'top right top': 'top-start',
63
+ // `middle`/`middle center [corner?]` positions are associated to a fallback
64
+ // `bottom` placement because there aren't any corresponding placement values.
65
+ middle: 'bottom',
66
+ 'middle center': 'bottom',
67
+ 'middle center bottom': 'bottom',
68
+ 'middle center left': 'bottom',
69
+ 'middle center right': 'bottom',
70
+ 'middle center top': 'bottom',
71
+ };
72
+
17
73
  /**
18
74
  * Converts the `Popover`'s legacy "position" prop to the new "placement" prop
19
75
  * (used by `floating-ui`).
@@ -23,22 +79,8 @@ import type {
23
79
  */
24
80
  export const positionToPlacement = (
25
81
  position: NonNullable< PopoverProps[ 'position' ] >
26
- ): NonNullable< PopoverProps[ 'placement' ] > => {
27
- const [ x, y, z ] = position.split( ' ' );
28
-
29
- if ( [ 'top', 'bottom' ].includes( x ) ) {
30
- let suffix = '';
31
- if ( ( !! z && z === 'left' ) || y === 'right' ) {
32
- suffix = '-start';
33
- } else if ( ( !! z && z === 'right' ) || y === 'left' ) {
34
- suffix = '-end';
35
- }
36
-
37
- return ( x + suffix ) as NonNullable< PopoverProps[ 'placement' ] >;
38
- }
39
-
40
- return y as NonNullable< PopoverProps[ 'placement' ] >;
41
- };
82
+ ): NonNullable< PopoverProps[ 'placement' ] > =>
83
+ POSITION_TO_PLACEMENT[ position ] ?? 'bottom';
42
84
 
43
85
  /**
44
86
  * @typedef AnimationOrigin
@@ -16,15 +16,14 @@ A RangeControl for volume
16
16
 
17
17
  ### Anatomy
18
18
 
19
- ![](https://make.wordpress.org/design/files/2018/12/rangecontrol-anatomy.png)
20
-
21
19
  A RangeControl can contain the following elements:
22
20
 
23
- 1. **Track**: The track shows the range available for user selection. For left-to-right (LTR) languages, the smallest value appears on the far left, and the largest value on the far right. For right-to-left (RTL) languages this orientation is reversed, with the smallest value on the far right and the largest value on the far left.
24
- 2. **Thumb**: The thumb slides along the track, displaying the selected value through its position.
25
- 3. **Value entry field**: The value entry field displays the currently selected, specific numerical value.
26
- 4. **Icon** (optional): An icon can be displayed before or after the slider.
27
- 5. **Tick mark** (optional): Tick marks represent predetermined values to which the user can move the slider.
21
+ 1. **Rail**: The rail represents the entire surface area of the slider, from the minimum value selectable by the user to the maximum value selectable by the user. For left-to-right (LTR) languages, the minimum value appears on the far left, and the maximum value on the far right. For right-to-left (RTL) languages this orientation is reversed, with the minimum value on the far right and the maximum value on the far left.
22
+ 2. **Track**: The track represents the portion of the rail from the minimum value to the currently selected value.
23
+ 3. **Thumb**: The thumb slides along the track, displaying the selected value through its position.
24
+ 4. **Value entry field**: The value entry field displays the currently selected, specific numerical value.
25
+ 5. **Icon** (optional): An icon can be displayed before or after the slider.
26
+ 6. **Tick mark** (optional): Tick marks represent predetermined values to which the user can move the slider.
28
27
 
29
28
  ### Types
30
29
 
@@ -7,39 +7,19 @@ import { forwardRef } from '@wordpress/element';
7
7
  * Internal dependencies
8
8
  */
9
9
  import { InputRange as BaseInputRange } from './styles/range-control-styles';
10
- import { useDebouncedHoverInteraction } from './utils';
11
10
 
12
11
  import type { InputRangeProps } from './types';
13
12
  import type { WordPressComponentProps } from '../ui/context';
14
13
 
15
- const noop = () => {};
16
-
17
14
  function InputRange(
18
15
  props: WordPressComponentProps< InputRangeProps, 'input' >,
19
16
  ref: React.ForwardedRef< HTMLInputElement >
20
17
  ) {
21
- const {
22
- describedBy,
23
- label,
24
- onHideTooltip = noop,
25
- onMouseLeave = noop,
26
- onMouseMove = noop,
27
- onShowTooltip = noop,
28
- value,
29
- ...otherProps
30
- } = props;
31
-
32
- const hoverInteractions = useDebouncedHoverInteraction( {
33
- onHide: onHideTooltip,
34
- onMouseLeave,
35
- onMouseMove,
36
- onShow: onShowTooltip,
37
- } );
18
+ const { describedBy, label, value, ...otherProps } = props;
38
19
 
39
20
  return (
40
21
  <BaseInputRange
41
22
  { ...otherProps }
42
- { ...hoverInteractions }
43
23
  aria-describedby={ describedBy }
44
24
  aria-label={ label }
45
25
  aria-hidden={ false }
@@ -35,7 +35,7 @@ const meta: ComponentMeta< typeof RangeControl > = {
35
35
  icon: { control: { type: null } },
36
36
  marks: { control: { type: 'object' } },
37
37
  onBlur: { control: { type: null } },
38
- onChange: { action: 'onChange' },
38
+ onChange: { control: { type: null } },
39
39
  onFocus: { control: { type: null } },
40
40
  onMouseLeave: { control: { type: null } },
41
41
  onMouseMove: { control: { type: null } },
@@ -46,6 +46,7 @@ const meta: ComponentMeta< typeof RangeControl > = {
46
46
  value: { control: { type: null } },
47
47
  },
48
48
  parameters: {
49
+ actions: { argTypesRegex: '^on.*' },
49
50
  controls: { expanded: true },
50
51
  docs: { source: { state: 'open' } },
51
52
  },
@@ -59,7 +59,7 @@ function useTooltipPosition( { inputRef, tooltipPosition }: TooltipProps ) {
59
59
  if ( inputRef && inputRef.current ) {
60
60
  setPosition( tooltipPosition );
61
61
  }
62
- }, [ tooltipPosition ] );
62
+ }, [ tooltipPosition, inputRef ] );
63
63
 
64
64
  useEffect( () => {
65
65
  setTooltipPosition();
@@ -236,10 +236,8 @@ export type RailProps = MarksProps & {
236
236
  export type InputRangeProps = {
237
237
  describedBy?: string;
238
238
  label?: string;
239
- onHideTooltip?: () => void;
240
239
  onMouseLeave?: MouseEventHandler< HTMLInputElement >;
241
240
  onMouseMove?: MouseEventHandler< HTMLInputElement >;
242
- onShowTooltip?: () => void;
243
241
  value?: number | '';
244
242
  };
245
243
 
@@ -292,39 +290,6 @@ export type UseControlledRangeValueArgs = {
292
290
  value: number | null;
293
291
  };
294
292
 
295
- export type UseDebouncedHoverInteractionArgs = {
296
- /**
297
- * A callback function invoked when the element is hidden.
298
- *
299
- * @default () => {}
300
- */
301
- onHide?: () => void;
302
- /**
303
- * A callback function invoked when the mouse is moved out of the element.
304
- *
305
- * @default () => {}
306
- */
307
- onMouseLeave?: MouseEventHandler< HTMLInputElement >;
308
- /**
309
- * A callback function invoked when the mouse is moved.
310
- *
311
- * @default () => {}
312
- */
313
- onMouseMove?: MouseEventHandler< HTMLInputElement >;
314
- /**
315
- * A callback function invoked when the element is shown.
316
- *
317
- * @default () => {}
318
- */
319
- onShow?: () => void;
320
- /**
321
- * Timeout before the element is shown or hidden.
322
- *
323
- * @default 300
324
- */
325
- timeout?: number;
326
- };
327
-
328
293
  export type UseMarksArgs = NumericProps & {
329
294
  marks: RangeMarks;
330
295
  step: number;
@@ -1,12 +1,7 @@
1
- /**
2
- * External dependencies
3
- */
4
- import type { MouseEventHandler } from 'react';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
9
- import { useCallback, useRef, useEffect, useState } from '@wordpress/element';
4
+ import { useCallback } from '@wordpress/element';
10
5
 
11
6
  /**
12
7
  * Internal dependencies
@@ -14,12 +9,7 @@ import { useCallback, useRef, useEffect, useState } from '@wordpress/element';
14
9
  import { useControlledState } from '../utils/hooks';
15
10
  import { clamp } from '../utils/math';
16
11
 
17
- import type {
18
- UseControlledRangeValueArgs,
19
- UseDebouncedHoverInteractionArgs,
20
- } from './types';
21
-
22
- const noop = () => {};
12
+ import type { UseControlledRangeValueArgs } from './types';
23
13
 
24
14
  /**
25
15
  * A float supported clamp function for a specific value.
@@ -64,72 +54,10 @@ export function useControlledRangeValue(
64
54
  setInternalState( floatClamp( nextValue, min, max ) );
65
55
  }
66
56
  },
67
- [ min, max ]
57
+ [ min, max, setInternalState ]
68
58
  );
69
59
 
70
60
  // `state` can't be an empty string because we specified a fallback value of
71
61
  // `null` in `useControlledState`
72
62
  return [ state as Exclude< typeof state, '' >, setState ] as const;
73
63
  }
74
-
75
- /**
76
- * Hook to encapsulate the debouncing "hover" to better handle the showing
77
- * and hiding of the Tooltip.
78
- *
79
- * @param settings
80
- * @return Bound properties for use on a React.Node.
81
- */
82
- export function useDebouncedHoverInteraction(
83
- settings: UseDebouncedHoverInteractionArgs
84
- ) {
85
- const {
86
- onHide = noop,
87
- onMouseLeave = noop as MouseEventHandler,
88
- onMouseMove = noop as MouseEventHandler,
89
- onShow = noop,
90
- timeout = 300,
91
- } = settings;
92
-
93
- const [ show, setShow ] = useState( false );
94
- const timeoutRef = useRef< number | undefined >();
95
-
96
- const setDebouncedTimeout = useCallback(
97
- ( callback ) => {
98
- window.clearTimeout( timeoutRef.current );
99
-
100
- timeoutRef.current = window.setTimeout( callback, timeout );
101
- },
102
- [ timeout ]
103
- );
104
-
105
- const handleOnMouseMove = useCallback( ( event ) => {
106
- onMouseMove( event );
107
-
108
- setDebouncedTimeout( () => {
109
- if ( ! show ) {
110
- setShow( true );
111
- onShow();
112
- }
113
- } );
114
- }, [] );
115
-
116
- const handleOnMouseLeave = useCallback( ( event ) => {
117
- onMouseLeave( event );
118
-
119
- setDebouncedTimeout( () => {
120
- setShow( false );
121
- onHide();
122
- } );
123
- }, [] );
124
-
125
- useEffect( () => {
126
- return () => {
127
- window.clearTimeout( timeoutRef.current );
128
- };
129
- } );
130
-
131
- return {
132
- onMouseMove: handleOnMouseMove,
133
- onMouseLeave: handleOnMouseLeave,
134
- };
135
- }
@@ -29,11 +29,13 @@ export const _default = () => {
29
29
  const [ height, setHeight ] = useState();
30
30
  const [ minHeight, setMinHeight ] = useState();
31
31
  const [ width, setWidth ] = useState();
32
+ const [ scale, setScale ] = useState();
32
33
 
33
34
  const resetAll = () => {
34
35
  setHeight( undefined );
35
36
  setWidth( undefined );
36
37
  setMinHeight( undefined );
38
+ setScale( undefined );
37
39
  };
38
40
 
39
41
  return (
@@ -79,6 +81,31 @@ export const _default = () => {
79
81
  onChange={ ( next ) => setMinHeight( next ) }
80
82
  />
81
83
  </ToolsPanelItem>
84
+ <ToolsPanelItem
85
+ hasValue={ () => !! scale }
86
+ label="Scale"
87
+ onDeselect={ () => setScale( undefined ) }
88
+ >
89
+ <ToggleGroupControl
90
+ label="Scale"
91
+ value={ scale }
92
+ onChange={ ( next ) => setScale( next ) }
93
+ isBlock
94
+ >
95
+ <ToggleGroupControlOption
96
+ value="cover"
97
+ label="Cover"
98
+ />
99
+ <ToggleGroupControlOption
100
+ value="contain"
101
+ label="Contain"
102
+ />
103
+ <ToggleGroupControlOption
104
+ value="fill"
105
+ label="Fill"
106
+ />
107
+ </ToggleGroupControl>
108
+ </ToolsPanelItem>
82
109
  </ToolsPanel>
83
110
  </Panel>
84
111
  </PanelWrapperView>
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
+ import styled from '@emotion/styled';
4
5
  import { css } from '@emotion/react';
5
6
 
6
7
  /**
@@ -12,7 +13,7 @@ import {
12
13
  Wrapper as BaseControlWrapper,
13
14
  } from '../base-control/styles/base-control-styles';
14
15
  import { LabelWrapper } from '../input-control/styles/input-control-styles';
15
- import { COLORS, CONFIG } from '../utils';
16
+ import { COLORS, CONFIG, rtl } from '../utils';
16
17
  import { space } from '../ui/utils/space';
17
18
 
18
19
  const toolsPanelGrid = {
@@ -145,3 +146,29 @@ export const ToolsPanelItemPlaceholder = css`
145
146
  export const DropdownMenu = css`
146
147
  min-width: 200px;
147
148
  `;
149
+
150
+ export const ResetLabel = styled.span`
151
+ color: var( --wp-admin-theme-color-darker-10 );
152
+ font-size: 11px;
153
+ font-weight: 500;
154
+ line-height: 1.4;
155
+ ${ rtl( { marginLeft: space( 3 ) } ) }
156
+ text-transform: uppercase;
157
+ `;
158
+
159
+ export const DefaultControlsItem = css`
160
+ color: ${ COLORS.gray[ 900 ] };
161
+
162
+ &&[aria-disabled='true'] {
163
+ color: ${ COLORS.gray[ 700 ] };
164
+ opacity: 1;
165
+
166
+ &:hover {
167
+ color: ${ COLORS.gray[ 700 ] };
168
+ }
169
+
170
+ ${ ResetLabel } {
171
+ opacity: 0.3;
172
+ }
173
+ }
174
+ `;