@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,194 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { css } from '@emotion/react';
5
-
6
- /**
7
- * Internal dependencies
8
- */
9
- import Button from '../../button';
10
- import { Card, CardBody, CardFooter, CardHeader } from '../../card';
11
- import { HStack } from '../../h-stack';
12
- import Dropdown from '../../dropdown';
13
- import { useCx } from '../../utils/hooks/use-cx';
14
- import {
15
- NavigatorProvider,
16
- NavigatorScreen,
17
- NavigatorButton,
18
- NavigatorBackButton,
19
- } from '../';
20
-
21
- export default {
22
- title: 'Components (Experimental)/Navigator',
23
- component: NavigatorProvider,
24
- };
25
-
26
- const MyNavigation = () => {
27
- const cx = useCx();
28
- return (
29
- <NavigatorProvider
30
- initialPath="/"
31
- className={ cx( css( `height: 100vh; max-height: 450px;` ) ) }
32
- >
33
- <NavigatorScreen path="/">
34
- <Card>
35
- <CardBody>
36
- <p>This is the home screen.</p>
37
-
38
- <HStack justify="flex-start" wrap>
39
- <NavigatorButton variant="secondary" path="/child">
40
- Navigate to child screen.
41
- </NavigatorButton>
42
-
43
- <NavigatorButton
44
- variant="secondary"
45
- path="/overflow-child"
46
- >
47
- Navigate to screen with horizontal overflow.
48
- </NavigatorButton>
49
-
50
- <NavigatorButton
51
- variant="secondary"
52
- path="/stickies"
53
- >
54
- Navigate to screen with sticky content.
55
- </NavigatorButton>
56
-
57
- <Dropdown
58
- renderToggle={ ( { isOpen, onToggle } ) => (
59
- <Button
60
- onClick={ onToggle }
61
- aria-expanded={ isOpen }
62
- variant="primary"
63
- >
64
- Open test dialog
65
- </Button>
66
- ) }
67
- renderContent={ () => (
68
- <Card>
69
- <CardHeader>Go</CardHeader>
70
- <CardBody>Stuff</CardBody>
71
- </Card>
72
- ) }
73
- />
74
- </HStack>
75
- </CardBody>
76
- </Card>
77
- </NavigatorScreen>
78
-
79
- <NavigatorScreen path="/child">
80
- <Card>
81
- <CardBody>
82
- <p>This is the child screen.</p>
83
- <NavigatorBackButton variant="secondary">
84
- Go back
85
- </NavigatorBackButton>
86
- </CardBody>
87
- </Card>
88
- </NavigatorScreen>
89
-
90
- <NavigatorScreen path="/overflow-child">
91
- <Card>
92
- <CardBody>
93
- <NavigatorBackButton variant="secondary">
94
- Go back
95
- </NavigatorBackButton>
96
- <div
97
- className={ cx(
98
- css( `
99
- display: inline-block;
100
- background: papayawhip;
101
- ` )
102
- ) }
103
- >
104
- <span
105
- className={ cx(
106
- css( `
107
- color: palevioletred;
108
- white-space: nowrap;
109
- font-size: 42vw;
110
- ` )
111
- ) }
112
- >
113
- ¯\_(ツ)_/¯
114
- </span>
115
- </div>
116
- </CardBody>
117
- </Card>
118
- </NavigatorScreen>
119
-
120
- <NavigatorScreen path="/stickies">
121
- <Card>
122
- <Sticky as={ CardHeader } z="2">
123
- <NavigatorBackButton variant="secondary">
124
- Go back
125
- </NavigatorBackButton>
126
- </Sticky>
127
- <CardBody>
128
- <Sticky top="69px" colors="papayawhip/peachpuff">
129
- <h2>A wild sticky element appears</h2>
130
- </Sticky>
131
- <MetaphorIpsum quantity={ 3 } />
132
- </CardBody>
133
- <CardBody>
134
- <Sticky top="69px" colors="azure/paleturquoise">
135
- <h2>Another wild sticky element appears</h2>
136
- </Sticky>
137
- <MetaphorIpsum quantity={ 3 } />
138
- </CardBody>
139
- <Sticky as={ CardFooter } colors="mistyrose/pink">
140
- <Button variant="primary">Primary noop</Button>
141
- </Sticky>
142
- </Card>
143
- </NavigatorScreen>
144
- </NavigatorProvider>
145
- );
146
- };
147
-
148
- export const _default = () => {
149
- return <MyNavigation />;
150
- };
151
-
152
- function Sticky( {
153
- as: Tag = 'div',
154
- bottom = 0,
155
- colors = 'whitesmoke/lightgrey',
156
- top = 0,
157
- z: zIndex = 1,
158
- ...props
159
- } ) {
160
- const cx = useCx();
161
- const [ bgColor, dotColor ] = colors.split( '/' );
162
- const className = cx(
163
- css( {
164
- top,
165
- bottom,
166
- zIndex,
167
- display: 'flex',
168
- position: 'sticky',
169
- background: `radial-gradient(${ dotColor } 1px, ${ bgColor } 2px) 50%/1em 1em`,
170
- } ),
171
- props.className
172
- );
173
- const propsOut = { ...props, className };
174
- return <Tag { ...propsOut } />;
175
- }
176
-
177
- function MetaphorIpsum( { quantity } ) {
178
- const cx = useCx();
179
- const list = [
180
- 'A loopy clarinet’s year comes with it the thought that the fenny step-son is an ophthalmologist. The literature would have us believe that a glabrate country is not but a rhythm. A beech is a rub from the right perspective. In ancient times few can name an unglossed walrus that isn’t an unspilt trial.',
181
- 'Authors often misinterpret the afterthought as a roseless mother-in-law, when in actuality it feels more like an uncapped thunderstorm. In recent years, some posit the tarry bottle to be less than acerb. They were lost without the unkissed timbale that composed their customer. A donna is a springtime breath.',
182
- 'It’s an undeniable fact, really; their museum was, in this moment, a snotty beef. The swordfishes could be said to resemble prowessed lasagnas. However, the rainier authority comes from a cureless soup. Unfortunately, that is wrong; on the contrary, the cover is a powder.',
183
- ];
184
- quantity = Math.min( list.length, quantity );
185
- return (
186
- <>
187
- { list.slice( 0, quantity ).map( ( text, key ) => (
188
- <p className={ cx( css( `max-width: 20em;` ) ) } key={ key }>
189
- { text }
190
- </p>
191
- ) ) }
192
- </>
193
- );
194
- }
@@ -1,472 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { render, screen, fireEvent } from '@testing-library/react';
5
- import userEvent from '@testing-library/user-event';
6
-
7
- /**
8
- * WordPress dependencies
9
- */
10
- import { useState } from '@wordpress/element';
11
-
12
- /**
13
- * Internal dependencies
14
- */
15
- import {
16
- NavigatorProvider,
17
- NavigatorScreen,
18
- NavigatorButton,
19
- NavigatorBackButton,
20
- } from '../';
21
-
22
- jest.mock( 'framer-motion', () => {
23
- const actual = jest.requireActual( 'framer-motion' );
24
- return {
25
- __esModule: true,
26
- ...actual,
27
- AnimatePresence: ( { children } ) => <div>{ children }</div>,
28
- motion: {
29
- ...actual.motion,
30
- div: require( 'react' ).forwardRef( ( { children }, ref ) => (
31
- <div ref={ ref }>{ children }</div>
32
- ) ),
33
- },
34
- };
35
- } );
36
-
37
- const INVALID_HTML_ATTRIBUTE = {
38
- raw: ' "\'><=invalid_path',
39
- escaped: " &quot;'&gt;<=invalid_path",
40
- };
41
-
42
- const PATHS = {
43
- HOME: '/',
44
- CHILD: '/child',
45
- NESTED: '/child/nested',
46
- INVALID_HTML_ATTRIBUTE: INVALID_HTML_ATTRIBUTE.raw,
47
- NOT_FOUND: '/not-found',
48
- };
49
-
50
- function CustomNavigatorButton( { path, onClick, ...props } ) {
51
- return (
52
- <NavigatorButton
53
- onClick={ () => {
54
- // Used to spy on the values passed to `navigator.goTo`.
55
- onClick?.( { type: 'goTo', path } );
56
- } }
57
- path={ path }
58
- { ...props }
59
- />
60
- );
61
- }
62
-
63
- function CustomNavigatorButtonWithFocusRestoration( {
64
- path,
65
- onClick,
66
- ...props
67
- } ) {
68
- return (
69
- <NavigatorButton
70
- onClick={ () => {
71
- // Used to spy on the values passed to `navigator.goTo`.
72
- onClick?.( { type: 'goTo', path } );
73
- } }
74
- path={ path }
75
- { ...props }
76
- />
77
- );
78
- }
79
-
80
- function CustomNavigatorBackButton( { onClick, ...props } ) {
81
- return (
82
- <NavigatorBackButton
83
- onClick={ () => {
84
- // Used to spy on the values passed to `navigator.goBack`.
85
- onClick?.( { type: 'goBack' } );
86
- } }
87
- { ...props }
88
- />
89
- );
90
- }
91
-
92
- const MyNavigation = ( {
93
- initialPath = PATHS.HOME,
94
- onNavigatorButtonClick,
95
- } ) => {
96
- const [ inputValue, setInputValue ] = useState( '' );
97
- return (
98
- <NavigatorProvider initialPath={ initialPath }>
99
- <NavigatorScreen path={ PATHS.HOME }>
100
- <p>This is the home screen.</p>
101
- <CustomNavigatorButton
102
- path={ PATHS.NOT_FOUND }
103
- onClick={ onNavigatorButtonClick }
104
- >
105
- Navigate to non-existing screen.
106
- </CustomNavigatorButton>
107
- <CustomNavigatorButton
108
- path={ PATHS.CHILD }
109
- onClick={ onNavigatorButtonClick }
110
- >
111
- Navigate to child screen.
112
- </CustomNavigatorButton>
113
- <CustomNavigatorButton
114
- path={ PATHS.INVALID_HTML_ATTRIBUTE }
115
- onClick={ onNavigatorButtonClick }
116
- >
117
- Navigate to screen with an invalid HTML value as a path.
118
- </CustomNavigatorButton>
119
- </NavigatorScreen>
120
-
121
- <NavigatorScreen path={ PATHS.CHILD }>
122
- <p>This is the child screen.</p>
123
- <CustomNavigatorButtonWithFocusRestoration
124
- path={ PATHS.NESTED }
125
- onClick={ onNavigatorButtonClick }
126
- >
127
- Navigate to nested screen.
128
- </CustomNavigatorButtonWithFocusRestoration>
129
- <CustomNavigatorBackButton onClick={ onNavigatorButtonClick }>
130
- Go back
131
- </CustomNavigatorBackButton>
132
-
133
- <label htmlFor="test-input">This is a test input</label>
134
- <input
135
- name="test-input"
136
- // eslint-disable-next-line no-restricted-syntax
137
- id="test-input"
138
- onChange={ ( e ) => {
139
- setInputValue( e.target.value );
140
- } }
141
- value={ inputValue }
142
- />
143
- </NavigatorScreen>
144
-
145
- <NavigatorScreen path={ PATHS.NESTED }>
146
- <p>This is the nested screen.</p>
147
- <CustomNavigatorBackButton onClick={ onNavigatorButtonClick }>
148
- Go back
149
- </CustomNavigatorBackButton>
150
- </NavigatorScreen>
151
-
152
- <NavigatorScreen path={ PATHS.INVALID_HTML_ATTRIBUTE }>
153
- <p>This is the screen with an invalid HTML value as a path.</p>
154
- <CustomNavigatorBackButton onClick={ onNavigatorButtonClick }>
155
- Go back
156
- </CustomNavigatorBackButton>
157
- </NavigatorScreen>
158
-
159
- { /* A `NavigatorScreen` with `path={ PATHS.NOT_FOUND }` is purposefully not included. */ }
160
- </NavigatorProvider>
161
- );
162
- };
163
-
164
- const getNavigationScreenByText = ( text, { throwIfNotFound = true } = {} ) => {
165
- const fnName = throwIfNotFound ? 'getByText' : 'queryByText';
166
- return screen[ fnName ]( text );
167
- };
168
- const getHomeScreen = ( { throwIfNotFound } = {} ) =>
169
- getNavigationScreenByText( 'This is the home screen.', {
170
- throwIfNotFound,
171
- } );
172
- const getChildScreen = ( { throwIfNotFound } = {} ) =>
173
- getNavigationScreenByText( 'This is the child screen.', {
174
- throwIfNotFound,
175
- } );
176
- const getNestedScreen = ( { throwIfNotFound } = {} ) =>
177
- getNavigationScreenByText( 'This is the nested screen.', {
178
- throwIfNotFound,
179
- } );
180
- const getInvalidHTMLPathScreen = ( { throwIfNotFound } = {} ) =>
181
- getNavigationScreenByText(
182
- 'This is the screen with an invalid HTML value as a path.',
183
- {
184
- throwIfNotFound,
185
- }
186
- );
187
-
188
- const getNavigationButtonByText = ( text, { throwIfNotFound = true } = {} ) => {
189
- const fnName = throwIfNotFound ? 'getByRole' : 'queryByRole';
190
- return screen[ fnName ]( 'button', { name: text } );
191
- };
192
- const getToNonExistingScreenButton = ( { throwIfNotFound } = {} ) =>
193
- getNavigationButtonByText( 'Navigate to non-existing screen.', {
194
- throwIfNotFound,
195
- } );
196
- const getToChildScreenButton = ( { throwIfNotFound } = {} ) =>
197
- getNavigationButtonByText( 'Navigate to child screen.', {
198
- throwIfNotFound,
199
- } );
200
- const getToNestedScreenButton = ( { throwIfNotFound } = {} ) =>
201
- getNavigationButtonByText( 'Navigate to nested screen.', {
202
- throwIfNotFound,
203
- } );
204
- const getToInvalidHTMLPathScreenButton = ( { throwIfNotFound } = {} ) =>
205
- getNavigationButtonByText(
206
- 'Navigate to screen with an invalid HTML value as a path.',
207
- {
208
- throwIfNotFound,
209
- }
210
- );
211
- const getBackButton = ( { throwIfNotFound } = {} ) =>
212
- getNavigationButtonByText( 'Go back', {
213
- throwIfNotFound,
214
- } );
215
-
216
- describe( 'Navigator', () => {
217
- const originalGetClientRects = window.Element.prototype.getClientRects;
218
-
219
- // `getClientRects` needs to be mocked so that `isVisible` from the `@wordpress/dom`
220
- // `focusable` module can pass, in a JSDOM env where the DOM elements have no width/height.
221
- const mockedGetClientRects = jest.fn( () => [
222
- {
223
- x: 0,
224
- y: 0,
225
- width: 100,
226
- height: 100,
227
- },
228
- ] );
229
-
230
- beforeAll( () => {
231
- window.Element.prototype.getClientRects =
232
- jest.fn( mockedGetClientRects );
233
- } );
234
-
235
- afterAll( () => {
236
- window.Element.prototype.getClientRects = originalGetClientRects;
237
- } );
238
-
239
- it( 'should render', () => {
240
- render( <MyNavigation /> );
241
-
242
- expect( getHomeScreen() ).toBeInTheDocument();
243
- expect(
244
- getChildScreen( { throwIfNotFound: false } )
245
- ).not.toBeInTheDocument();
246
- expect(
247
- getNestedScreen( { throwIfNotFound: false } )
248
- ).not.toBeInTheDocument();
249
- } );
250
-
251
- it( 'should show a different screen on the first render depending on the value of `initialPath`', () => {
252
- render( <MyNavigation initialPath={ PATHS.CHILD } /> );
253
-
254
- expect(
255
- getHomeScreen( { throwIfNotFound: false } )
256
- ).not.toBeInTheDocument();
257
- expect( getChildScreen() ).toBeInTheDocument();
258
- expect(
259
- getNestedScreen( { throwIfNotFound: false } )
260
- ).not.toBeInTheDocument();
261
- } );
262
-
263
- it( 'should ignore changes to `initialPath` after the first render', () => {
264
- const { rerender } = render( <MyNavigation /> );
265
-
266
- expect( getHomeScreen() ).toBeInTheDocument();
267
- expect(
268
- getChildScreen( { throwIfNotFound: false } )
269
- ).not.toBeInTheDocument();
270
- expect(
271
- getNestedScreen( { throwIfNotFound: false } )
272
- ).not.toBeInTheDocument();
273
-
274
- rerender( <MyNavigation initialPath={ PATHS.CHILD } /> );
275
-
276
- expect( getHomeScreen() ).toBeInTheDocument();
277
- expect(
278
- getChildScreen( { throwIfNotFound: false } )
279
- ).not.toBeInTheDocument();
280
- expect(
281
- getNestedScreen( { throwIfNotFound: false } )
282
- ).not.toBeInTheDocument();
283
- } );
284
-
285
- it( 'should not rended anything if the `initialPath` does not match any available screen', () => {
286
- render( <MyNavigation initialPath={ PATHS.NOT_FOUND } /> );
287
-
288
- expect(
289
- getHomeScreen( { throwIfNotFound: false } )
290
- ).not.toBeInTheDocument();
291
- expect(
292
- getChildScreen( { throwIfNotFound: false } )
293
- ).not.toBeInTheDocument();
294
- expect(
295
- getNestedScreen( { throwIfNotFound: false } )
296
- ).not.toBeInTheDocument();
297
- } );
298
-
299
- it( 'should navigate across screens', () => {
300
- const spy = jest.fn();
301
-
302
- render( <MyNavigation onNavigatorButtonClick={ spy } /> );
303
-
304
- expect( getHomeScreen() ).toBeInTheDocument();
305
- expect( getToChildScreenButton() ).toBeInTheDocument();
306
-
307
- // Navigate to child screen.
308
- fireEvent.click( getToChildScreenButton() );
309
-
310
- expect( getChildScreen() ).toBeInTheDocument();
311
- expect( getBackButton() ).toBeInTheDocument();
312
-
313
- // Navigate back to home screen.
314
- fireEvent.click( getBackButton() );
315
- expect( getHomeScreen() ).toBeInTheDocument();
316
- expect( getToChildScreenButton() ).toBeInTheDocument();
317
-
318
- // Navigate again to child screen.
319
- fireEvent.click( getToChildScreenButton() );
320
-
321
- expect( getChildScreen() ).toBeInTheDocument();
322
- expect( getToNestedScreenButton() ).toBeInTheDocument();
323
-
324
- // Navigate to nested screen.
325
- fireEvent.click( getToNestedScreenButton() );
326
-
327
- expect( getNestedScreen() ).toBeInTheDocument();
328
- expect( getBackButton() ).toBeInTheDocument();
329
-
330
- // Navigate back to child screen.
331
- fireEvent.click( getBackButton() );
332
-
333
- expect( getChildScreen() ).toBeInTheDocument();
334
- expect( getToNestedScreenButton() ).toBeInTheDocument();
335
-
336
- // Navigate back to home screen.
337
- fireEvent.click( getBackButton() );
338
-
339
- expect( getHomeScreen() ).toBeInTheDocument();
340
- expect( getToChildScreenButton() ).toBeInTheDocument();
341
-
342
- // Check the values passed to `navigator.goTo()`.
343
- expect( spy ).toHaveBeenCalledTimes( 6 );
344
- expect( spy ).toHaveBeenNthCalledWith( 1, {
345
- path: PATHS.CHILD,
346
- type: 'goTo',
347
- } );
348
- expect( spy ).toHaveBeenNthCalledWith( 2, {
349
- type: 'goBack',
350
- } );
351
- expect( spy ).toHaveBeenNthCalledWith( 3, {
352
- path: PATHS.CHILD,
353
- type: 'goTo',
354
- } );
355
- expect( spy ).toHaveBeenNthCalledWith( 4, {
356
- path: PATHS.NESTED,
357
- type: 'goTo',
358
- } );
359
- expect( spy ).toHaveBeenNthCalledWith( 5, {
360
- type: 'goBack',
361
- } );
362
- expect( spy ).toHaveBeenNthCalledWith( 6, {
363
- type: 'goBack',
364
- } );
365
- } );
366
-
367
- it( 'should not rended anything if the path does not match any available screen', () => {
368
- const spy = jest.fn();
369
-
370
- render( <MyNavigation onNavigatorButtonClick={ spy } /> );
371
-
372
- expect( getToNonExistingScreenButton() ).toBeInTheDocument();
373
-
374
- // Attempt to navigate to non-existing screen. No screens get rendered.
375
- fireEvent.click( getToNonExistingScreenButton() );
376
-
377
- expect(
378
- getHomeScreen( { throwIfNotFound: false } )
379
- ).not.toBeInTheDocument();
380
- expect(
381
- getChildScreen( { throwIfNotFound: false } )
382
- ).not.toBeInTheDocument();
383
- expect(
384
- getNestedScreen( { throwIfNotFound: false } )
385
- ).not.toBeInTheDocument();
386
-
387
- // Check the values passed to `navigator.goTo()`.
388
- expect( spy ).toHaveBeenCalledTimes( 1 );
389
- expect( spy ).toHaveBeenNthCalledWith( 1, {
390
- path: PATHS.NOT_FOUND,
391
- type: 'goTo',
392
- } );
393
- } );
394
-
395
- it( 'should restore focus correctly', () => {
396
- render( <MyNavigation /> );
397
-
398
- expect( getHomeScreen() ).toBeInTheDocument();
399
-
400
- // Navigate to child screen.
401
- fireEvent.click( getToChildScreenButton() );
402
-
403
- expect( getChildScreen() ).toBeInTheDocument();
404
-
405
- // Navigate to nested screen.
406
- fireEvent.click( getToNestedScreenButton() );
407
-
408
- expect( getNestedScreen() ).toBeInTheDocument();
409
-
410
- // Navigate back to child screen, check that focus was correctly restored.
411
- fireEvent.click( getBackButton() );
412
-
413
- expect( getChildScreen() ).toBeInTheDocument();
414
- expect( getToNestedScreenButton() ).toHaveFocus();
415
-
416
- // Navigate back to home screen, check that focus was correctly restored.
417
- fireEvent.click( getBackButton() );
418
-
419
- expect( getHomeScreen() ).toBeInTheDocument();
420
- expect( getToChildScreenButton() ).toHaveFocus();
421
- } );
422
-
423
- it( 'should escape the value of the `path` prop', () => {
424
- render( <MyNavigation /> );
425
-
426
- expect( getHomeScreen() ).toBeInTheDocument();
427
- expect( getToInvalidHTMLPathScreenButton() ).toBeInTheDocument();
428
-
429
- // The following line tests the implementation details, but it's necessary
430
- // as this would be otherwise transparent to the user.
431
- expect( getToInvalidHTMLPathScreenButton() ).toHaveAttribute(
432
- 'id',
433
- INVALID_HTML_ATTRIBUTE.escaped
434
- );
435
-
436
- // Navigate to screen with an invalid HTML value for its `path`.
437
- fireEvent.click( getToInvalidHTMLPathScreenButton() );
438
-
439
- expect( getInvalidHTMLPathScreen() ).toBeInTheDocument();
440
- expect( getBackButton() ).toBeInTheDocument();
441
-
442
- // Navigate back to home screen, check that the focus restoration selector
443
- // worked correctly despite the escaping.
444
- fireEvent.click( getBackButton() );
445
-
446
- expect( getHomeScreen() ).toBeInTheDocument();
447
- expect( getToInvalidHTMLPathScreenButton() ).toHaveFocus();
448
- } );
449
-
450
- it( 'should keep focus on the element that is being interacted with, while re-rendering', async () => {
451
- const user = userEvent.setup( {
452
- advanceTimers: jest.advanceTimersByTime,
453
- } );
454
-
455
- render( <MyNavigation /> );
456
-
457
- expect( getHomeScreen() ).toBeInTheDocument();
458
- expect( getToChildScreenButton() ).toBeInTheDocument();
459
-
460
- // Navigate to child screen.
461
- await user.click( getToChildScreenButton() );
462
-
463
- expect( getChildScreen() ).toBeInTheDocument();
464
- expect( getBackButton() ).toBeInTheDocument();
465
- expect( getToNestedScreenButton() ).toHaveFocus();
466
-
467
- // Interact with the input, the focus should stay on the input element.
468
- const input = screen.getByLabelText( 'This is a test input' );
469
- await user.type( input, 'd' );
470
- expect( input ).toHaveFocus();
471
- } );
472
- } );