@wordpress/components 21.2.0 → 21.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 (302) hide show
  1. package/CHANGELOG.md +35 -3
  2. package/CONTRIBUTING.md +20 -0
  3. package/build/border-box-control/border-box-control/component.js +2 -0
  4. package/build/border-box-control/border-box-control/component.js.map +1 -1
  5. package/build/border-box-control/border-box-control/hook.js +4 -1
  6. package/build/border-box-control/border-box-control/hook.js.map +1 -1
  7. package/build/border-control/border-control/component.js +2 -0
  8. package/build/border-control/border-control/component.js.map +1 -1
  9. package/build/disabled/index.js +6 -26
  10. package/build/disabled/index.js.map +1 -1
  11. package/build/font-size-picker/index.js +1 -1
  12. package/build/font-size-picker/index.js.map +1 -1
  13. package/build/font-size-picker/styles.js +5 -13
  14. package/build/font-size-picker/styles.js.map +1 -1
  15. package/build/font-size-picker/utils.js +1 -1
  16. package/build/font-size-picker/utils.js.map +1 -1
  17. package/build/form-token-field/suggestions-list.js +5 -5
  18. package/build/form-token-field/suggestions-list.js.map +1 -1
  19. package/build/higher-order/with-fallback-styles/index.js +1 -1
  20. package/build/higher-order/with-fallback-styles/index.js.map +1 -1
  21. package/build/index.js +8 -6
  22. package/build/index.js.map +1 -1
  23. package/build/modal/aria-helper.js +2 -3
  24. package/build/modal/aria-helper.js.map +1 -1
  25. package/build/modal/index.js +42 -11
  26. package/build/modal/index.js.map +1 -1
  27. package/build/modal/types.js +6 -0
  28. package/build/modal/types.js.map +1 -0
  29. package/build/navigator/index.js +8 -8
  30. package/build/navigator/index.js.map +1 -1
  31. package/build/navigator/navigator-back-button/component.js +5 -4
  32. package/build/navigator/navigator-back-button/component.js.map +1 -1
  33. package/build/navigator/navigator-back-button/index.js +1 -1
  34. package/build/navigator/navigator-back-button/index.js.map +1 -1
  35. package/build/navigator/navigator-button/component.js +5 -4
  36. package/build/navigator/navigator-button/component.js.map +1 -1
  37. package/build/navigator/navigator-button/index.js +1 -1
  38. package/build/navigator/navigator-button/index.js.map +1 -1
  39. package/build/navigator/navigator-provider/component.js +10 -7
  40. package/build/navigator/navigator-provider/component.js.map +1 -1
  41. package/build/navigator/navigator-provider/index.js +1 -1
  42. package/build/navigator/navigator-provider/index.js.map +1 -1
  43. package/build/navigator/navigator-screen/component.js +24 -27
  44. package/build/navigator/navigator-screen/component.js.map +1 -1
  45. package/build/navigator/navigator-screen/index.js +1 -1
  46. package/build/navigator/navigator-screen/index.js.map +1 -1
  47. package/build/sandbox/index.js +55 -59
  48. package/build/sandbox/index.js.map +1 -1
  49. package/build/sandbox/index.native.js +63 -62
  50. package/build/sandbox/index.native.js.map +1 -1
  51. package/build/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
  52. package/build/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
  53. package/build/tab-panel/index.js +4 -4
  54. package/build/tab-panel/index.js.map +1 -1
  55. package/build/theme/index.js +62 -0
  56. package/build/theme/index.js.map +1 -0
  57. package/build/theme/styles.js +33 -0
  58. package/build/theme/styles.js.map +1 -0
  59. package/build/theme/types.js +6 -0
  60. package/build/theme/types.js.map +1 -0
  61. package/build/tools-panel/tools-panel/hook.js +3 -3
  62. package/build/tools-panel/tools-panel/hook.js.map +1 -1
  63. package/build/tools-panel/tools-panel-item/hook.js +6 -6
  64. package/build/tools-panel/tools-panel-item/hook.js.map +1 -1
  65. package/build/tooltip/index.js +4 -1
  66. package/build/tooltip/index.js.map +1 -1
  67. package/build/tooltip/index.native.js +17 -4
  68. package/build/tooltip/index.native.js.map +1 -1
  69. package/build-module/border-box-control/border-box-control/component.js +2 -0
  70. package/build-module/border-box-control/border-box-control/component.js.map +1 -1
  71. package/build-module/border-box-control/border-box-control/hook.js +4 -1
  72. package/build-module/border-box-control/border-box-control/hook.js.map +1 -1
  73. package/build-module/border-control/border-control/component.js +2 -0
  74. package/build-module/border-control/border-control/component.js.map +1 -1
  75. package/build-module/disabled/index.js +7 -26
  76. package/build-module/disabled/index.js.map +1 -1
  77. package/build-module/font-size-picker/index.js +1 -1
  78. package/build-module/font-size-picker/index.js.map +1 -1
  79. package/build-module/font-size-picker/styles.js +5 -13
  80. package/build-module/font-size-picker/styles.js.map +1 -1
  81. package/build-module/font-size-picker/utils.js +1 -1
  82. package/build-module/font-size-picker/utils.js.map +1 -1
  83. package/build-module/form-token-field/suggestions-list.js +5 -5
  84. package/build-module/form-token-field/suggestions-list.js.map +1 -1
  85. package/build-module/higher-order/with-fallback-styles/index.js +2 -2
  86. package/build-module/higher-order/with-fallback-styles/index.js.map +1 -1
  87. package/build-module/index.js +2 -1
  88. package/build-module/index.js.map +1 -1
  89. package/build-module/modal/aria-helper.js +2 -3
  90. package/build-module/modal/aria-helper.js.map +1 -1
  91. package/build-module/modal/index.js +44 -12
  92. package/build-module/modal/index.js.map +1 -1
  93. package/build-module/modal/types.js +2 -0
  94. package/build-module/modal/types.js.map +1 -0
  95. package/build-module/navigator/index.js +4 -4
  96. package/build-module/navigator/index.js.map +1 -1
  97. package/build-module/navigator/navigator-back-button/component.js +3 -3
  98. package/build-module/navigator/navigator-back-button/component.js.map +1 -1
  99. package/build-module/navigator/navigator-back-button/index.js +1 -1
  100. package/build-module/navigator/navigator-back-button/index.js.map +1 -1
  101. package/build-module/navigator/navigator-button/component.js +3 -3
  102. package/build-module/navigator/navigator-button/component.js.map +1 -1
  103. package/build-module/navigator/navigator-button/index.js +1 -1
  104. package/build-module/navigator/navigator-button/index.js.map +1 -1
  105. package/build-module/navigator/navigator-provider/component.js +8 -6
  106. package/build-module/navigator/navigator-provider/component.js.map +1 -1
  107. package/build-module/navigator/navigator-provider/index.js +1 -1
  108. package/build-module/navigator/navigator-provider/index.js.map +1 -1
  109. package/build-module/navigator/navigator-screen/component.js +12 -26
  110. package/build-module/navigator/navigator-screen/component.js.map +1 -1
  111. package/build-module/navigator/navigator-screen/index.js +1 -1
  112. package/build-module/navigator/navigator-screen/index.js.map +1 -1
  113. package/build-module/sandbox/index.js +56 -59
  114. package/build-module/sandbox/index.js.map +1 -1
  115. package/build-module/sandbox/index.native.js +54 -52
  116. package/build-module/sandbox/index.native.js.map +1 -1
  117. package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
  118. package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
  119. package/build-module/tab-panel/index.js +4 -4
  120. package/build-module/tab-panel/index.js.map +1 -1
  121. package/build-module/theme/index.js +52 -0
  122. package/build-module/theme/index.js.map +1 -0
  123. package/build-module/theme/styles.js +25 -0
  124. package/build-module/theme/styles.js.map +1 -0
  125. package/build-module/theme/types.js +2 -0
  126. package/build-module/theme/types.js.map +1 -0
  127. package/build-module/tools-panel/tools-panel/hook.js +3 -3
  128. package/build-module/tools-panel/tools-panel/hook.js.map +1 -1
  129. package/build-module/tools-panel/tools-panel-item/hook.js +6 -6
  130. package/build-module/tools-panel/tools-panel-item/hook.js.map +1 -1
  131. package/build-module/tooltip/index.js +4 -1
  132. package/build-module/tooltip/index.js.map +1 -1
  133. package/build-module/tooltip/index.native.js +17 -4
  134. package/build-module/tooltip/index.native.js.map +1 -1
  135. package/build-style/style-rtl.css +26 -22
  136. package/build-style/style.css +26 -22
  137. package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
  138. package/build-types/border-box-control/border-box-control/hook.d.ts +1 -0
  139. package/build-types/border-box-control/border-box-control/hook.d.ts.map +1 -1
  140. package/build-types/border-control/border-control/component.d.ts +1 -0
  141. package/build-types/border-control/border-control/component.d.ts.map +1 -1
  142. package/build-types/border-control/border-control/hook.d.ts +1 -0
  143. package/build-types/border-control/border-control/hook.d.ts.map +1 -1
  144. package/build-types/border-control/stories/index.d.ts +6 -0
  145. package/build-types/border-control/stories/index.d.ts.map +1 -1
  146. package/build-types/border-control/types.d.ts +4 -0
  147. package/build-types/border-control/types.d.ts.map +1 -1
  148. package/build-types/confirm-dialog/types.d.ts +5 -1
  149. package/build-types/confirm-dialog/types.d.ts.map +1 -1
  150. package/build-types/disabled/index.d.ts.map +1 -1
  151. package/build-types/font-size-picker/styles.d.ts.map +1 -1
  152. package/build-types/modal/aria-helper.d.ts +4 -4
  153. package/build-types/modal/aria-helper.d.ts.map +1 -1
  154. package/build-types/modal/index.d.ts +35 -2
  155. package/build-types/modal/index.d.ts.map +1 -1
  156. package/build-types/modal/stories/index.d.ts +9 -0
  157. package/build-types/modal/stories/index.d.ts.map +1 -0
  158. package/build-types/modal/test/aria-helper.d.ts +2 -0
  159. package/build-types/modal/test/aria-helper.d.ts.map +1 -0
  160. package/build-types/modal/test/index.d.ts +2 -0
  161. package/build-types/modal/test/index.d.ts.map +1 -0
  162. package/build-types/modal/types.d.ts +134 -0
  163. package/build-types/modal/types.d.ts.map +1 -0
  164. package/build-types/navigator/index.d.ts +4 -4
  165. package/build-types/navigator/index.d.ts.map +1 -1
  166. package/build-types/navigator/navigator-back-button/component.d.ts +4 -2
  167. package/build-types/navigator/navigator-back-button/component.d.ts.map +1 -1
  168. package/build-types/navigator/navigator-back-button/hook.d.ts +1 -0
  169. package/build-types/navigator/navigator-back-button/hook.d.ts.map +1 -1
  170. package/build-types/navigator/navigator-back-button/index.d.ts +1 -1
  171. package/build-types/navigator/navigator-back-button/index.d.ts.map +1 -1
  172. package/build-types/navigator/navigator-button/component.d.ts +4 -2
  173. package/build-types/navigator/navigator-button/component.d.ts.map +1 -1
  174. package/build-types/navigator/navigator-button/hook.d.ts +1 -0
  175. package/build-types/navigator/navigator-button/hook.d.ts.map +1 -1
  176. package/build-types/navigator/navigator-button/index.d.ts +1 -1
  177. package/build-types/navigator/navigator-button/index.d.ts.map +1 -1
  178. package/build-types/navigator/navigator-provider/component.d.ts +2 -2
  179. package/build-types/navigator/navigator-provider/component.d.ts.map +1 -1
  180. package/build-types/navigator/navigator-provider/index.d.ts +1 -1
  181. package/build-types/navigator/navigator-provider/index.d.ts.map +1 -1
  182. package/build-types/navigator/navigator-screen/component.d.ts +2 -2
  183. package/build-types/navigator/navigator-screen/component.d.ts.map +1 -1
  184. package/build-types/navigator/navigator-screen/index.d.ts +1 -1
  185. package/build-types/navigator/navigator-screen/index.d.ts.map +1 -1
  186. package/build-types/navigator/stories/index.d.ts +9 -0
  187. package/build-types/navigator/stories/index.d.ts.map +1 -0
  188. package/build-types/navigator/test/index.d.ts +2 -0
  189. package/build-types/navigator/test/index.d.ts.map +1 -0
  190. package/build-types/navigator/types.d.ts +4 -1
  191. package/build-types/navigator/types.d.ts.map +1 -1
  192. package/build-types/slot-fill/bubbles-virtually/slot-fill-provider.d.ts.map +1 -1
  193. package/build-types/tab-panel/index.d.ts.map +1 -1
  194. package/build-types/theme/index.d.ts +31 -0
  195. package/build-types/theme/index.d.ts.map +1 -0
  196. package/build-types/theme/stories/index.d.ts +13 -0
  197. package/build-types/theme/stories/index.d.ts.map +1 -0
  198. package/build-types/theme/styles.d.ts +10 -0
  199. package/build-types/theme/styles.d.ts.map +1 -0
  200. package/build-types/theme/test/index.d.ts +2 -0
  201. package/build-types/theme/test/index.d.ts.map +1 -0
  202. package/build-types/theme/types.d.ts +21 -0
  203. package/build-types/theme/types.d.ts.map +1 -0
  204. package/build-types/tools-panel/tools-panel/hook.d.ts.map +1 -1
  205. package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
  206. package/build-types/tooltip/index.d.ts.map +1 -1
  207. package/package.json +17 -17
  208. package/src/base-field/test/index.js +4 -6
  209. package/src/border-box-control/border-box-control/component.tsx +2 -0
  210. package/src/border-box-control/border-box-control/hook.ts +4 -0
  211. package/src/border-box-control/test/index.js +7 -2
  212. package/src/border-control/border-control/README.md +6 -0
  213. package/src/border-control/border-control/component.tsx +2 -0
  214. package/src/border-control/types.ts +4 -0
  215. package/src/button/style.scss +25 -25
  216. package/src/button/test/index.js +3 -5
  217. package/src/combobox-control/test/index.js +1 -1
  218. package/src/confirm-dialog/types.ts +6 -0
  219. package/src/date-time/time/test/index.tsx +2 -6
  220. package/src/disabled/index.tsx +11 -33
  221. package/src/disabled/test/index.tsx +14 -82
  222. package/src/dropdown/test/index.js +4 -3
  223. package/src/font-size-picker/index.tsx +1 -1
  224. package/src/font-size-picker/styles.ts +3 -1
  225. package/src/font-size-picker/test/index.tsx +2 -2
  226. package/src/font-size-picker/test/utils.ts +5 -5
  227. package/src/font-size-picker/utils.ts +1 -1
  228. package/src/form-file-upload/test/index.tsx +1 -1
  229. package/src/form-token-field/suggestions-list.tsx +5 -5
  230. package/src/higher-order/with-fallback-styles/index.js +6 -2
  231. package/src/higher-order/with-focus-outside/test/index.js +44 -45
  232. package/src/higher-order/with-focus-return/test/index.js +34 -30
  233. package/src/higher-order/with-notices/test/index.js +1 -1
  234. package/src/index.js +2 -1
  235. package/src/input-control/test/index.js +2 -2
  236. package/src/item-group/test/index.js +2 -2
  237. package/src/menu-item/test/index.js +0 -3
  238. package/src/mobile/bottom-sheet/test/range-cell.native.js +16 -14
  239. package/src/modal/README.md +53 -54
  240. package/src/modal/{aria-helper.js → aria-helper.ts} +5 -7
  241. package/src/modal/{index.js → index.tsx} +48 -12
  242. package/src/modal/stories/{index.js → index.tsx} +47 -42
  243. package/src/modal/test/{aria-helper.js → aria-helper.ts} +0 -0
  244. package/src/modal/test/{index.js → index.tsx} +13 -3
  245. package/src/modal/types.ts +144 -0
  246. package/src/navigation/test/index.js +1 -1
  247. package/src/navigator/index.ts +4 -4
  248. package/src/navigator/navigator-back-button/component.tsx +4 -4
  249. package/src/navigator/navigator-back-button/index.ts +1 -1
  250. package/src/navigator/navigator-button/component.tsx +4 -4
  251. package/src/navigator/navigator-button/index.ts +1 -1
  252. package/src/navigator/navigator-provider/component.tsx +6 -4
  253. package/src/navigator/navigator-provider/index.ts +1 -1
  254. package/src/navigator/navigator-screen/component.tsx +20 -26
  255. package/src/navigator/navigator-screen/index.ts +1 -1
  256. package/src/navigator/stories/index.tsx +210 -0
  257. package/src/navigator/test/index.tsx +509 -0
  258. package/src/navigator/types.ts +2 -0
  259. package/src/notice/test/__snapshots__/index.js.snap +39 -38
  260. package/src/notice/test/index.js +15 -36
  261. package/src/notice/test/list.js +6 -14
  262. package/src/number-control/test/index.js +3 -2
  263. package/src/panel/test/body.js +2 -2
  264. package/src/placeholder/style.scss +5 -0
  265. package/src/sandbox/index.js +62 -47
  266. package/src/sandbox/index.native.js +72 -52
  267. package/src/sandbox/test/index.js +7 -10
  268. package/src/shortcut/test/index.tsx +1 -1
  269. package/src/slot-fill/bubbles-virtually/slot-fill-provider.js +5 -3
  270. package/src/style.scss +4 -0
  271. package/src/tab-panel/index.tsx +4 -7
  272. package/src/text-highlight/test/index.tsx +1 -3
  273. package/src/theme/README.md +34 -0
  274. package/src/theme/index.tsx +51 -0
  275. package/src/theme/stories/index.tsx +47 -0
  276. package/src/theme/styles.ts +28 -0
  277. package/src/theme/test/index.tsx +101 -0
  278. package/src/theme/types.ts +21 -0
  279. package/src/toolbar/test/index.js +2 -2
  280. package/src/toolbar-group/test/index.js +6 -10
  281. package/src/tools-panel/test/index.js +4 -6
  282. package/src/tools-panel/tools-panel/hook.ts +2 -9
  283. package/src/tools-panel/tools-panel-item/hook.ts +17 -3
  284. package/src/tooltip/index.js +3 -0
  285. package/src/tooltip/index.native.js +15 -0
  286. package/src/tooltip/test/index.native.js +1 -2
  287. package/src/tree-grid/test/__snapshots__/cell.js.snap +1 -3
  288. package/src/tree-grid/test/__snapshots__/roving-tab-index-item.js.snap +17 -15
  289. package/src/tree-grid/test/__snapshots__/row.js.snap +25 -21
  290. package/src/tree-grid/test/cell.js +4 -4
  291. package/src/tree-grid/test/roving-tab-index-item.js +8 -8
  292. package/src/tree-grid/test/roving-tab-index.js +3 -3
  293. package/src/tree-grid/test/row.js +20 -16
  294. package/src/truncate/test/index.tsx +4 -4
  295. package/src/ui/shortcut/test/index.js +2 -1
  296. package/src/ui/spinner/test/index.js +14 -13
  297. package/src/ui/tooltip/test/index.js +16 -14
  298. package/src/utils/theme-variables.scss +8 -0
  299. package/src/visually-hidden/README.md +4 -0
  300. package/tsconfig.tsbuildinfo +1 -1
  301. package/src/navigator/stories/index.js +0 -194
  302. package/src/navigator/test/index.js +0 -472
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { every, isEqual } from 'lodash';
4
+ import { isEqual } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -45,10 +45,14 @@ export default ( mapNodeToProps ) =>
45
45
  this.nodeRef,
46
46
  this.props
47
47
  );
48
+
48
49
  if ( ! isEqual( newFallbackStyles, fallbackStyles ) ) {
49
50
  this.setState( {
50
51
  fallbackStyles: newFallbackStyles,
51
- grabStylesCompleted: !! every( newFallbackStyles ),
52
+ grabStylesCompleted:
53
+ Object.values( newFallbackStyles ).every(
54
+ Boolean
55
+ ),
52
56
  } );
53
57
  }
54
58
  }
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import TestUtils from 'react-dom/test-utils';
4
+ import { render, screen } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
5
6
 
6
7
  /**
7
8
  * WordPress dependencies
@@ -12,9 +13,8 @@ import { Component } from '@wordpress/element';
12
13
  * Internal dependencies
13
14
  */
14
15
  import withFocusOutside from '../';
15
- import ReactDOM from 'react-dom';
16
16
 
17
- let wrapper, onFocusOutside;
17
+ let onFocusOutside;
18
18
 
19
19
  describe( 'withFocusOutside', () => {
20
20
  let origHasFocus;
@@ -28,7 +28,7 @@ describe( 'withFocusOutside', () => {
28
28
  render() {
29
29
  return (
30
30
  <div>
31
- <input />
31
+ <input type="text" />
32
32
  <input type="button" />
33
33
  </div>
34
34
  );
@@ -36,24 +36,11 @@ describe( 'withFocusOutside', () => {
36
36
  }
37
37
  );
38
38
 
39
- // This is needed because TestUtils does not accept a stateless component.
40
- // anything run through a HOC ends up as a stateless component.
41
- const getTestComponent = ( WrappedComponent, props ) => {
42
- class TestComponent extends Component {
43
- render() {
44
- return <WrappedComponent { ...props } />;
45
- }
39
+ class TestComponent extends Component {
40
+ render() {
41
+ return <EnhancedComponent { ...this.props } />;
46
42
  }
47
- return <TestComponent />;
48
- };
49
-
50
- const simulateEvent = ( event, index = 0 ) => {
51
- const element = TestUtils.scryRenderedDOMComponentsWithTag(
52
- wrapper,
53
- 'input'
54
- );
55
- TestUtils.Simulate[ event ]( element[ index ] );
56
- };
43
+ }
57
44
 
58
45
  beforeEach( () => {
59
46
  // Mock document.hasFocus() to always be true for testing
@@ -62,9 +49,6 @@ describe( 'withFocusOutside', () => {
62
49
  document.hasFocus = () => true;
63
50
 
64
51
  onFocusOutside = jest.fn();
65
- wrapper = TestUtils.renderIntoDocument(
66
- getTestComponent( EnhancedComponent, { onFocusOutside } )
67
- );
68
52
  } );
69
53
 
70
54
  afterEach( () => {
@@ -72,24 +56,31 @@ describe( 'withFocusOutside', () => {
72
56
  } );
73
57
 
74
58
  it( 'should not call handler if focus shifts to element within component', () => {
75
- simulateEvent( 'focus' );
76
- simulateEvent( 'blur' );
77
- simulateEvent( 'focus', 1 );
59
+ render( <TestComponent onFocusOutside={ onFocusOutside } /> );
60
+
61
+ const input = screen.getByRole( 'textbox' );
62
+ const button = screen.getByRole( 'button' );
63
+
64
+ input.focus();
65
+ input.blur();
66
+ button.focus();
78
67
 
79
68
  jest.runAllTimers();
80
69
 
81
70
  expect( onFocusOutside ).not.toHaveBeenCalled();
82
71
  } );
83
72
 
84
- it( 'should not call handler if focus transitions via click to button', () => {
85
- simulateEvent( 'focus' );
86
- simulateEvent( 'mouseDown', 1 );
87
- simulateEvent( 'blur' );
73
+ it( 'should not call handler if focus transitions via click to button', async () => {
74
+ const user = userEvent.setup( {
75
+ advanceTimers: jest.advanceTimersByTime,
76
+ } );
77
+ render( <TestComponent onFocusOutside={ onFocusOutside } /> );
88
78
 
89
- // In most browsers, the input at index 1 would receive a focus event
90
- // at this point, but this is not guaranteed, which is the intention of
91
- // the normalization behavior tested here.
92
- simulateEvent( 'mouseUp', 1 );
79
+ const input = screen.getByRole( 'textbox' );
80
+ const button = screen.getByRole( 'button' );
81
+
82
+ input.focus();
83
+ await user.click( button );
93
84
 
94
85
  jest.runAllTimers();
95
86
 
@@ -97,8 +88,11 @@ describe( 'withFocusOutside', () => {
97
88
  } );
98
89
 
99
90
  it( 'should call handler if focus doesn’t shift to element within component', () => {
100
- simulateEvent( 'focus' );
101
- simulateEvent( 'blur' );
91
+ render( <TestComponent onFocusOutside={ onFocusOutside } /> );
92
+
93
+ const input = screen.getByRole( 'textbox' );
94
+ input.focus();
95
+ input.blur();
102
96
 
103
97
  jest.runAllTimers();
104
98
 
@@ -106,12 +100,15 @@ describe( 'withFocusOutside', () => {
106
100
  } );
107
101
 
108
102
  it( 'should not call handler if focus shifts outside the component when the document does not have focus', () => {
103
+ render( <TestComponent onFocusOutside={ onFocusOutside } /> );
104
+
109
105
  // Force document.hasFocus() to return false to simulate the window/document losing focus
110
106
  // See https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus.
111
107
  document.hasFocus = () => false;
112
108
 
113
- simulateEvent( 'focus' );
114
- simulateEvent( 'blur' );
109
+ const input = screen.getByRole( 'textbox' );
110
+ input.focus();
111
+ input.blur();
115
112
 
116
113
  jest.runAllTimers();
117
114
 
@@ -119,14 +116,16 @@ describe( 'withFocusOutside', () => {
119
116
  } );
120
117
 
121
118
  it( 'should cancel check when unmounting while queued', () => {
122
- simulateEvent( 'focus' );
123
- simulateEvent( 'input' );
124
-
125
- ReactDOM.unmountComponentAtNode(
126
- // eslint-disable-next-line react/no-find-dom-node
127
- ReactDOM.findDOMNode( wrapper ).parentNode
119
+ const { rerender } = render(
120
+ <TestComponent onFocusOutside={ onFocusOutside } />
128
121
  );
129
122
 
123
+ const input = screen.getByRole( 'textbox' );
124
+ input.focus();
125
+ input.blur();
126
+
127
+ rerender( <div /> );
128
+
130
129
  jest.runAllTimers();
131
130
 
132
131
  expect( onFocusOutside ).not.toHaveBeenCalled();
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import renderer from 'react-test-renderer';
5
- import { render, fireEvent } from '@testing-library/react';
4
+ import { render, screen } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
@@ -16,9 +16,14 @@ import withFocusReturn from '../';
16
16
 
17
17
  class Test extends Component {
18
18
  render() {
19
+ const { className, focusHistory } = this.props;
19
20
  return (
20
- <div className="test">
21
- <textarea />
21
+ <div
22
+ className={ className }
23
+ data-testid="test-element"
24
+ data-focus-history={ focusHistory }
25
+ >
26
+ <textarea aria-label="Textarea" />
22
27
  </div>
23
28
  );
24
29
  }
@@ -41,32 +46,25 @@ describe( 'withFocusReturn()', () => {
41
46
  } );
42
47
 
43
48
  it( 'should render a basic Test component inside the HOC', () => {
44
- const renderedComposite = renderer.create( <Composite /> );
45
- const wrappedElement = renderedComposite.root.findByType( Test );
46
- const wrappedElementShallow = wrappedElement.children[ 0 ];
47
- expect( wrappedElementShallow.props.className ).toBe( 'test' );
48
- expect( wrappedElementShallow.type ).toBe( 'div' );
49
- expect( wrappedElementShallow.children[ 0 ].type ).toBe(
50
- 'textarea'
51
- );
49
+ render( <Composite /> );
50
+
51
+ expect( screen.getByTestId( 'test-element' ) ).toBeVisible();
52
52
  } );
53
53
 
54
54
  it( 'should pass own props through to the wrapped element', () => {
55
- const renderedComposite = renderer.create(
56
- <Composite test="test" />
55
+ render( <Composite className="test" /> );
56
+
57
+ expect( screen.getByTestId( 'test-element' ) ).toHaveClass(
58
+ 'test'
57
59
  );
58
- const wrappedElement = renderedComposite.root.findByType( Test );
59
- // Ensure that the wrapped Test element has the appropriate props.
60
- expect( wrappedElement.props.test ).toBe( 'test' );
61
60
  } );
62
61
 
63
62
  it( 'should not pass any withFocusReturn context props through to the wrapped element', () => {
64
- const renderedComposite = renderer.create(
65
- <Composite test="test" />
63
+ render( <Composite className="test" /> );
64
+
65
+ expect( screen.getByTestId( 'test-element' ) ).not.toHaveAttribute(
66
+ 'data-focus-history'
66
67
  );
67
- const wrappedElement = renderedComposite.root.findByType( Test );
68
- // Ensure that the wrapped Test element has the appropriate props.
69
- expect( wrappedElement.props.focusHistory ).toBeUndefined();
70
68
  } );
71
69
 
72
70
  it( 'should not switch focus back to the bound focus element', () => {
@@ -78,31 +76,37 @@ describe( 'withFocusReturn()', () => {
78
76
 
79
77
  // Change activeElement.
80
78
  switchFocusTo.focus();
81
- expect( document.activeElement ).toBe( switchFocusTo );
79
+ expect( switchFocusTo ).toHaveFocus();
82
80
 
83
81
  // Should keep focus on switchFocusTo, because it is not within HOC.
84
82
  unmount();
85
- expect( document.activeElement ).toBe( switchFocusTo );
83
+ expect( switchFocusTo ).toHaveFocus();
86
84
  } );
87
85
 
88
- it( 'should switch focus back when unmounted while having focus', () => {
86
+ it( 'should switch focus back when unmounted while having focus', async () => {
87
+ const user = userEvent.setup( {
88
+ advanceTimers: jest.advanceTimersByTime,
89
+ } );
90
+
89
91
  const { container, unmount } = render( <Composite />, {
90
92
  container: document.body.appendChild(
91
93
  document.createElement( 'div' )
92
94
  ),
93
95
  } );
94
96
 
95
- const textarea = container.querySelector( 'textarea' );
96
- fireEvent.focusIn( textarea, { target: textarea } );
97
- textarea.focus();
98
- expect( document.activeElement ).toBe( textarea );
97
+ // Click inside the textarea to focus it.
98
+ await user.click(
99
+ screen.getByRole( 'textbox', {
100
+ name: 'Textarea',
101
+ } )
102
+ );
99
103
 
100
104
  // Should return to the activeElement saved with this component.
101
105
  unmount();
102
106
  render( <div></div>, {
103
107
  container,
104
108
  } );
105
- expect( document.activeElement ).toBe( activeElement );
109
+ expect( activeElement ).toHaveFocus();
106
110
  } );
107
111
  } );
108
112
  } );
@@ -91,7 +91,7 @@ describe( 'withNotices operations', () => {
91
91
  act( () => {
92
92
  handle.current.createNotice( { content: message } );
93
93
  } );
94
- expect( getByText( message ) ).not.toBeNull();
94
+ expect( getByText( message ) ).toBeInTheDocument();
95
95
  } );
96
96
 
97
97
  it( 'should create notices of error status with createErrorNotice', () => {
package/src/index.js CHANGED
@@ -16,7 +16,7 @@ export {
16
16
  default as Animate,
17
17
  getAnimateClassName as __unstableGetAnimateClassName,
18
18
  } from './animate';
19
- export { __unstableMotion, __unstableAnimatePresence } from './animation';
19
+ export { __unstableMotion } from './animation';
20
20
  export { default as AnglePickerControl } from './angle-picker-control';
21
21
  export {
22
22
  default as Autocomplete,
@@ -146,6 +146,7 @@ export { Text as __experimentalText } from './text';
146
146
  export { default as TextControl } from './text-control';
147
147
  export { default as TextareaControl } from './textarea-control';
148
148
  export { default as TextHighlight } from './text-highlight';
149
+ export { default as __experimentalTheme } from './theme';
149
150
  export { default as Tip } from './tip';
150
151
  export { default as ToggleControl } from './toggle-control';
151
152
  export {
@@ -40,7 +40,7 @@ describe( 'InputControl', () => {
40
40
 
41
41
  const input = getInput();
42
42
 
43
- expect( input.getAttribute( 'type' ) ).toBe( 'number' );
43
+ expect( input ).toHaveAttribute( 'type', 'number' );
44
44
  } );
45
45
 
46
46
  it( 'should render label', () => {
@@ -48,7 +48,7 @@ describe( 'InputControl', () => {
48
48
 
49
49
  const input = screen.getByText( 'Hello' );
50
50
 
51
- expect( input ).toBeTruthy();
51
+ expect( input ).toBeInTheDocument();
52
52
  } );
53
53
  } );
54
54
 
@@ -11,12 +11,12 @@ import { Item, ItemGroup } from '..';
11
11
  describe( 'ItemGroup', () => {
12
12
  describe( 'ItemGroup component', () => {
13
13
  it( 'should render correctly', () => {
14
- const wrapper = render(
14
+ const { container } = render(
15
15
  <ItemGroup>
16
16
  <Item>Code is poetry</Item>
17
17
  </ItemGroup>
18
18
  );
19
- expect( wrapper.container.firstChild ).toMatchSnapshot();
19
+ expect( container.firstChild ).toMatchSnapshot();
20
20
  } );
21
21
 
22
22
  it( 'should show borders when the isBordered prop is true', () => {
@@ -83,7 +83,6 @@ describe( 'MenuItem', () => {
83
83
 
84
84
  const menuItem = screen.getByRole( 'menuitem' );
85
85
  expect( menuItem ).not.toBeChecked();
86
- expect( menuItem ).not.toHaveAttribute( 'aria-checked' );
87
86
  } );
88
87
 
89
88
  it( 'should use aria-checked if menuitemradio or menuitemcheckbox is set as aria-role', () => {
@@ -95,7 +94,6 @@ describe( 'MenuItem', () => {
95
94
 
96
95
  const radioMenuItem = screen.getByRole( 'menuitemradio' );
97
96
  expect( radioMenuItem ).toBeChecked();
98
- expect( radioMenuItem ).toHaveAttribute( 'aria-checked', 'true' );
99
97
 
100
98
  rerender(
101
99
  <MenuItem role="menuitemcheckbox" isSelected>
@@ -105,7 +103,6 @@ describe( 'MenuItem', () => {
105
103
 
106
104
  const checkboxMenuItem = screen.getByRole( 'menuitemcheckbox' );
107
105
  expect( checkboxMenuItem ).toBeChecked();
108
- expect( checkboxMenuItem ).toHaveAttribute( 'aria-checked', 'true' );
109
106
  } );
110
107
 
111
108
  it( 'should not render shortcut or right icon if suffix provided', () => {
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import { AccessibilityInfo } from 'react-native';
5
- import { create, act } from 'react-test-renderer';
5
+ import { render, fireEvent } from 'test/helpers';
6
6
 
7
7
  /**
8
8
  * Internal dependencies
@@ -21,17 +21,19 @@ jest.mock( '@wordpress/compose', () => ( {
21
21
  ) ),
22
22
  } ) );
23
23
 
24
- const isScreenReaderEnabled = Promise.resolve( true );
25
24
  beforeAll( () => {
26
- // Mock async native module to avoid act warning
27
- AccessibilityInfo.isScreenReaderEnabled = jest.fn(
28
- () => isScreenReaderEnabled
25
+ AccessibilityInfo.isScreenReaderEnabled.mockResolvedValue(
26
+ Promise.resolve( true )
29
27
  );
30
28
  } );
31
29
 
30
+ afterAll( () => {
31
+ AccessibilityInfo.isScreenReaderEnabled.mockReset();
32
+ } );
33
+
32
34
  it( 'allows modifying units via a11y actions', async () => {
33
35
  const mockOpenUnitPicker = jest.fn();
34
- const renderer = create(
36
+ const { getByA11yLabel } = render(
35
37
  <RangeCell
36
38
  label="Opacity"
37
39
  minimumValue={ 0 }
@@ -41,17 +43,18 @@ it( 'allows modifying units via a11y actions', async () => {
41
43
  openUnitPicker={ mockOpenUnitPicker }
42
44
  />
43
45
  );
44
- // Await async update to component state to avoid act warning
45
- await act( () => isScreenReaderEnabled );
46
- const { onAccessibilityAction } = renderer.toJSON().props;
47
46
 
48
- onAccessibilityAction( { nativeEvent: { actionName: 'activate' } } );
47
+ const opacityControl = getByA11yLabel( /Opacity/ );
48
+ fireEvent( opacityControl, 'accessibilityAction', {
49
+ nativeEvent: { actionName: 'activate' },
50
+ } );
51
+
49
52
  expect( mockOpenUnitPicker ).toHaveBeenCalled();
50
53
  } );
51
54
 
52
55
  describe( 'when range lacks an adjustable unit', () => {
53
56
  it( 'disallows modifying units via a11y actions', async () => {
54
- const renderer = create(
57
+ const { getByA11yLabel } = render(
55
58
  <RangeCell
56
59
  label="Opacity"
57
60
  minimumValue={ 0 }
@@ -60,10 +63,9 @@ describe( 'when range lacks an adjustable unit', () => {
60
63
  onChange={ jest.fn() }
61
64
  />
62
65
  );
63
- // Await async update to component state to avoid act warning
64
- await act( () => isScreenReaderEnabled );
65
- const { onAccessibilityAction } = renderer.toJSON().props;
66
66
 
67
+ const opacityControl = getByA11yLabel( /Opacity/ );
68
+ const { onAccessibilityAction } = opacityControl.props;
67
69
  expect( () =>
68
70
  onAccessibilityAction( { nativeEvent: { actionName: 'activate' } } )
69
71
  ).not.toThrow();
@@ -150,118 +150,117 @@ const MyModal = () => {
150
150
  The set of props accepted by the component will be specified below.
151
151
  Props not included in this set will be applied to the input elements.
152
152
 
153
- #### title
153
+ #### `aria.describedby`: `string`
154
154
 
155
- This property is used as the modal header's title.
156
-
157
- Titles are required for accessibility reasons, see `aria.labelledby` and `contentLabel` for other ways to provide a title.
155
+ If this property is added, it will be added to the modal content `div` as `aria-describedby`.
158
156
 
159
- - Type: `String`
160
157
  - Required: No
161
158
 
162
- #### onRequestClose
159
+ #### `aria.labelledby`: `string`
163
160
 
164
- This function is called to indicate that the modal should be closed.
161
+ If this property is added, it will be added to the modal content `div` as `aria-labelledby`.
162
+ Use this when you are rendering the title yourself within the modal's content area instead of using the `title` prop. This ensures the title is usable by assistive technology.
165
163
 
166
- - Type: `function`
167
- - Required: Yes
164
+ Titles are required for accessibility reasons, see `contentLabel` and `title` for other ways to provide a title.
168
165
 
169
- #### contentLabel
166
+ - Required: No
167
+ - Default: if the `title` prop is provided, this will default to the id of the element that renders `title`
170
168
 
171
- If this property is added, it will be added to the modal content `div` as `aria-label`.
169
+ #### `bodyOpenClassName`: `string`
172
170
 
173
- Titles are required for accessibility reasons, see `aria.labelledby` and `title` for other ways to provide a title.
171
+ Class name added to the body element when the modal is open.
174
172
 
175
- - Type: `String`
176
173
  - Required: No
174
+ - Default: `modal-open`
177
175
 
178
- #### aria.labelledby
176
+ #### `className`: `string`
179
177
 
180
- If this property is added, it will be added to the modal content `div` as `aria-labelledby`.
181
- Use this when you are rendering the title yourself within the modal's content area instead of using the `title` prop. This ensures the title is usable by assistive technology.
182
-
183
- Titles are required for accessibility reasons, see `contentLabel` and `title` for other ways to provide a title.
178
+ If this property is added, it will an additional class name to the modal content `div`.
184
179
 
185
- - Type: `String`
186
180
  - Required: No
187
- - Default: if the `title` prop is provided, this will default to the id of the element that renders `title`
188
181
 
189
- #### aria.describedby
182
+ #### `contentLabel`: `string`
190
183
 
191
- If this property is added, it will be added to the modal content `div` as `aria-describedby`.
184
+ If this property is added, it will be added to the modal content `div` as `aria-label`.
185
+
186
+ Titles are required for accessibility reasons, see `aria.labelledby` and `title` for other ways to provide a title.
192
187
 
193
- - Type: `String`
194
188
  - Required: No
195
189
 
196
- #### focusOnMount
190
+ #### `focusOnMount`: `boolean | 'firstElement'`
197
191
 
198
192
  If this property is true, it will focus the first tabbable element rendered in the modal.
199
193
 
200
- - Type: `boolean`
201
194
  - Required: No
202
- - Default: true
195
+ - Default: `true`
203
196
 
204
- #### shouldCloseOnEsc
197
+ #### `isDismissible`: `boolean`
205
198
 
206
- If this property is added, it will determine whether the modal requests to close when the escape key is pressed.
199
+ If this property is set to false, the modal will not display a close icon and cannot be dismissed.
207
200
 
208
- - Type: `boolean`
209
201
  - Required: No
210
- - Default: true
202
+ - Default: `true`
211
203
 
212
- #### shouldCloseOnClickOutside
204
+ #### `isFullScreen`: `boolean`
213
205
 
214
- If this property is added, it will determine whether the modal requests to close when a mouse click occurs outside of the modal content.
206
+ This property when set to `true` will render a full screen modal.
215
207
 
216
- - Type: `boolean`
217
208
  - Required: No
218
- - Default: true
209
+ - Default: `false`
219
210
 
220
- #### isDismissible
211
+ #### `onRequestClose`: ``
221
212
 
222
- If this property is set to false, the modal will not display a close icon and cannot be dismissed.
213
+ This function is called to indicate that the modal should be closed.
223
214
 
224
- - Type: `boolean`
225
- - Required: No
226
- - Default: true
215
+ - Required: Yes
227
216
 
228
- #### className
217
+ #### `overlayClassName`: `string`
229
218
 
230
- If this property is added, it will an additional class name to the modal content `div`.
219
+ If this property is added, it will an additional class name to the modal overlay `div`.
231
220
 
232
- - Type: `String`
233
221
  - Required: No
234
222
 
235
- #### role
223
+ #### `role`: `AriaRole`
236
224
 
237
225
  If this property is added, it will override the default role of the modal.
238
226
 
239
- - Type: `String`
240
227
  - Required: No
241
228
  - Default: `dialog`
242
229
 
243
- #### overlayClassName
230
+ #### `shouldCloseOnClickOutside`: `boolean`
244
231
 
245
- If this property is added, it will an additional class name to the modal overlay `div`.
232
+ If this property is added, it will determine whether the modal requests to close when a mouse click occurs outside of the modal content.
246
233
 
247
- - Type: `String`
248
234
  - Required: No
235
+ - Default: `true`
249
236
 
250
- #### isFullScreen
237
+ #### `shouldCloseOnEsc`: `boolean`
251
238
 
252
- This property when set to `true` will render a full screen modal.
239
+ If this property is added, it will determine whether the modal requests to close when the escape key is pressed.
240
+
241
+ - Required: No
242
+ - Default: `true`
243
+
244
+ #### `style`: `CSSProperties`
245
+
246
+ If this property is added, it will be added to the modal frame `div`.
247
+
248
+ - Required: No
249
+
250
+ #### `title`: `string`
251
+
252
+ This property is used as the modal header's title.
253
+
254
+ Titles are required for accessibility reasons, see `aria.labelledby` and `contentLabel` for other ways to provide a title.
253
255
 
254
- - Type: `boolean`
255
256
  - Required: No
256
- - Default: `false`
257
257
 
258
- #### __experimentalHideHeader
258
+ #### `__experimentalHideHeader`: `boolean`
259
259
 
260
260
  When set to `true`, the Modal's header (including the icon, title and close button) will not be rendered.
261
261
 
262
- *Warning*: This property is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
262
+ _Warning_: This property is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
263
263
 
264
- - Type: `boolean`
265
264
  - Required: No
266
265
  - Default: `false`
267
266