@wordpress/components 23.7.0 → 23.9.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 (274) hide show
  1. package/CHANGELOG.md +52 -6
  2. package/build/checkbox-control/index.js +2 -2
  3. package/build/checkbox-control/index.js.map +1 -1
  4. package/build/color-palette/index.native.js +12 -0
  5. package/build/color-palette/index.native.js.map +1 -1
  6. package/build/custom-gradient-picker/index.native.js +3 -1
  7. package/build/custom-gradient-picker/index.native.js.map +1 -1
  8. package/build/custom-gradient-picker/serializer.js +0 -4
  9. package/build/custom-gradient-picker/serializer.js.map +1 -1
  10. package/build/draggable/index.js +6 -1
  11. package/build/draggable/index.js.map +1 -1
  12. package/build/drop-zone/index.js +8 -8
  13. package/build/drop-zone/index.js.map +1 -1
  14. package/build/index.js.map +1 -1
  15. package/build/mobile/bottom-sheet/cell.native.js +6 -6
  16. package/build/mobile/bottom-sheet/cell.native.js.map +1 -1
  17. package/build/mobile/color-settings/palette.screen.native.js +0 -8
  18. package/build/mobile/color-settings/palette.screen.native.js.map +1 -1
  19. package/build/mobile/global-styles-context/utils.native.js +21 -4
  20. package/build/mobile/global-styles-context/utils.native.js.map +1 -1
  21. package/build/mobile/keyboard-aware-flat-list/index.android.js +0 -4
  22. package/build/mobile/keyboard-aware-flat-list/index.android.js.map +1 -1
  23. package/build/mobile/keyboard-aware-flat-list/index.ios.js +100 -55
  24. package/build/mobile/keyboard-aware-flat-list/index.ios.js.map +1 -1
  25. package/build/mobile/keyboard-aware-flat-list/use-keyboard-offset.native.js +82 -0
  26. package/build/mobile/keyboard-aware-flat-list/use-keyboard-offset.native.js.map +1 -0
  27. package/build/mobile/keyboard-aware-flat-list/use-scroll-to-text-input.native.js +85 -0
  28. package/build/mobile/keyboard-aware-flat-list/use-scroll-to-text-input.native.js.map +1 -0
  29. package/build/mobile/keyboard-aware-flat-list/use-text-input-caret-position.native.js +44 -0
  30. package/build/mobile/keyboard-aware-flat-list/use-text-input-caret-position.native.js.map +1 -0
  31. package/build/mobile/keyboard-aware-flat-list/use-text-input-offset.native.js +53 -0
  32. package/build/mobile/keyboard-aware-flat-list/use-text-input-offset.native.js.map +1 -0
  33. package/build/mobile/segmented-control/index.native.js +4 -2
  34. package/build/mobile/segmented-control/index.native.js.map +1 -1
  35. package/build/navigator/navigator-provider/component.js +4 -2
  36. package/build/navigator/navigator-provider/component.js.map +1 -1
  37. package/build/navigator/navigator-screen/component.js +4 -3
  38. package/build/navigator/navigator-screen/component.js.map +1 -1
  39. package/build/popover/index.js +1 -8
  40. package/build/popover/index.js.map +1 -1
  41. package/build/private-apis.js +4 -1
  42. package/build/private-apis.js.map +1 -1
  43. package/build/query-controls/author-select.js +2 -1
  44. package/build/query-controls/author-select.js.map +1 -1
  45. package/build/query-controls/category-select.js +3 -1
  46. package/build/query-controls/category-select.js.map +1 -1
  47. package/build/query-controls/index.js +7 -1
  48. package/build/query-controls/index.js.map +1 -1
  49. package/build/sandbox/index.native.js +55 -29
  50. package/build/sandbox/index.native.js.map +1 -1
  51. package/build/slot-fill/index.js +20 -7
  52. package/build/slot-fill/index.js.map +1 -1
  53. package/build/spinner/styles.js +4 -4
  54. package/build/spinner/styles.js.map +1 -1
  55. package/build/tree-grid/index.js +3 -3
  56. package/build/tree-grid/index.js.map +1 -1
  57. package/build/view/component.js +1 -2
  58. package/build/view/component.js.map +1 -1
  59. package/build-module/checkbox-control/index.js +2 -2
  60. package/build-module/checkbox-control/index.js.map +1 -1
  61. package/build-module/color-palette/index.native.js +13 -1
  62. package/build-module/color-palette/index.native.js.map +1 -1
  63. package/build-module/custom-gradient-picker/index.native.js +3 -1
  64. package/build-module/custom-gradient-picker/index.native.js.map +1 -1
  65. package/build-module/custom-gradient-picker/serializer.js +0 -4
  66. package/build-module/custom-gradient-picker/serializer.js.map +1 -1
  67. package/build-module/draggable/index.js +6 -1
  68. package/build-module/draggable/index.js.map +1 -1
  69. package/build-module/drop-zone/index.js +8 -8
  70. package/build-module/drop-zone/index.js.map +1 -1
  71. package/build-module/index.js.map +1 -1
  72. package/build-module/mobile/bottom-sheet/cell.native.js +6 -5
  73. package/build-module/mobile/bottom-sheet/cell.native.js.map +1 -1
  74. package/build-module/mobile/color-settings/palette.screen.native.js +0 -8
  75. package/build-module/mobile/color-settings/palette.screen.native.js.map +1 -1
  76. package/build-module/mobile/global-styles-context/utils.native.js +21 -3
  77. package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
  78. package/build-module/mobile/keyboard-aware-flat-list/index.android.js +0 -4
  79. package/build-module/mobile/keyboard-aware-flat-list/index.android.js.map +1 -1
  80. package/build-module/mobile/keyboard-aware-flat-list/index.ios.js +97 -54
  81. package/build-module/mobile/keyboard-aware-flat-list/index.ios.js.map +1 -1
  82. package/build-module/mobile/keyboard-aware-flat-list/use-keyboard-offset.native.js +73 -0
  83. package/build-module/mobile/keyboard-aware-flat-list/use-keyboard-offset.native.js.map +1 -0
  84. package/build-module/mobile/keyboard-aware-flat-list/use-scroll-to-text-input.native.js +76 -0
  85. package/build-module/mobile/keyboard-aware-flat-list/use-scroll-to-text-input.native.js.map +1 -0
  86. package/build-module/mobile/keyboard-aware-flat-list/use-text-input-caret-position.native.js +33 -0
  87. package/build-module/mobile/keyboard-aware-flat-list/use-text-input-caret-position.native.js.map +1 -0
  88. package/build-module/mobile/keyboard-aware-flat-list/use-text-input-offset.native.js +40 -0
  89. package/build-module/mobile/keyboard-aware-flat-list/use-text-input-offset.native.js.map +1 -0
  90. package/build-module/mobile/segmented-control/index.native.js +4 -2
  91. package/build-module/mobile/segmented-control/index.native.js.map +1 -1
  92. package/build-module/navigator/navigator-provider/component.js +4 -2
  93. package/build-module/navigator/navigator-provider/component.js.map +1 -1
  94. package/build-module/navigator/navigator-screen/component.js +4 -3
  95. package/build-module/navigator/navigator-screen/component.js.map +1 -1
  96. package/build-module/popover/index.js +1 -8
  97. package/build-module/popover/index.js.map +1 -1
  98. package/build-module/private-apis.js +3 -1
  99. package/build-module/private-apis.js.map +1 -1
  100. package/build-module/query-controls/author-select.js +2 -1
  101. package/build-module/query-controls/author-select.js.map +1 -1
  102. package/build-module/query-controls/category-select.js +3 -1
  103. package/build-module/query-controls/category-select.js.map +1 -1
  104. package/build-module/query-controls/index.js +7 -2
  105. package/build-module/query-controls/index.js.map +1 -1
  106. package/build-module/sandbox/index.native.js +56 -31
  107. package/build-module/sandbox/index.native.js.map +1 -1
  108. package/build-module/slot-fill/index.js +16 -6
  109. package/build-module/slot-fill/index.js.map +1 -1
  110. package/build-module/spinner/styles.js +4 -4
  111. package/build-module/spinner/styles.js.map +1 -1
  112. package/build-module/tree-grid/index.js +3 -3
  113. package/build-module/tree-grid/index.js.map +1 -1
  114. package/build-module/view/component.js +1 -2
  115. package/build-module/view/component.js.map +1 -1
  116. package/build-style/style-rtl.css +26 -16
  117. package/build-style/style.css +26 -16
  118. package/build-types/angle-picker-control/styles/angle-picker-control-styles.d.ts +1 -1
  119. package/build-types/border-box-control/border-box-control/hook.d.ts +2 -2
  120. package/build-types/border-box-control/border-box-control-linked-button/hook.d.ts +2 -2
  121. package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts +2 -2
  122. package/build-types/border-box-control/border-box-control-visualizer/hook.d.ts +2 -2
  123. package/build-types/border-control/border-control/hook.d.ts +2 -2
  124. package/build-types/border-control/border-control-dropdown/hook.d.ts +2 -2
  125. package/build-types/border-control/border-control-style-picker/hook.d.ts +2 -2
  126. package/build-types/box-control/styles/box-control-styles.d.ts +5 -5
  127. package/build-types/button/deprecated.d.ts +8 -8
  128. package/build-types/card/card/hook.d.ts +2 -2
  129. package/build-types/card/card-body/hook.d.ts +2 -2
  130. package/build-types/card/card-divider/hook.d.ts +2 -2
  131. package/build-types/card/card-footer/hook.d.ts +2 -2
  132. package/build-types/card/card-header/hook.d.ts +2 -2
  133. package/build-types/card/card-media/hook.d.ts +2 -2
  134. package/build-types/checkbox-control/index.d.ts.map +1 -1
  135. package/build-types/color-palette/styles.d.ts +1 -1
  136. package/build-types/color-picker/styles.d.ts +7 -7
  137. package/build-types/combobox-control/styles.d.ts +1 -1
  138. package/build-types/custom-gradient-picker/serializer.d.ts +1 -5
  139. package/build-types/custom-gradient-picker/serializer.d.ts.map +1 -1
  140. package/build-types/custom-gradient-picker/types.d.ts +0 -2
  141. package/build-types/custom-gradient-picker/types.d.ts.map +1 -1
  142. package/build-types/date-time/date/styles.d.ts +2 -2
  143. package/build-types/date-time/date-time/styles.d.ts +1 -1
  144. package/build-types/date-time/time/styles.d.ts +8 -8
  145. package/build-types/draggable/index.d.ts +1 -1
  146. package/build-types/draggable/index.d.ts.map +1 -1
  147. package/build-types/draggable/stories/index.d.ts +8 -0
  148. package/build-types/draggable/stories/index.d.ts.map +1 -1
  149. package/build-types/draggable/types.d.ts +7 -0
  150. package/build-types/draggable/types.d.ts.map +1 -1
  151. package/build-types/drop-zone/index.d.ts.map +1 -1
  152. package/build-types/elevation/hook.d.ts +2 -2
  153. package/build-types/external-link/styles/external-link-styles.d.ts +1 -1
  154. package/build-types/flex/flex/hook.d.ts +2 -2
  155. package/build-types/flex/flex-block/hook.d.ts +2 -2
  156. package/build-types/flex/flex-item/hook.d.ts +2 -2
  157. package/build-types/focal-point-picker/styles/focal-point-picker-style.d.ts +2 -2
  158. package/build-types/form-token-field/styles.d.ts +1 -1
  159. package/build-types/grid/hook.d.ts +2 -2
  160. package/build-types/h-stack/hook.d.ts +2 -2
  161. package/build-types/heading/hook.d.ts +2 -2
  162. package/build-types/index.d.ts +129 -0
  163. package/build-types/index.d.ts.map +1 -0
  164. package/build-types/input-control/styles/input-control-styles.d.ts +2 -2
  165. package/build-types/item-group/item/hook.d.ts +2 -2
  166. package/build-types/item-group/item-group/hook.d.ts +2 -2
  167. package/build-types/navigation/styles/navigation-styles.d.ts +2 -2
  168. package/build-types/navigator/navigator-back-button/component.d.ts +1 -1
  169. package/build-types/navigator/navigator-back-button/hook.d.ts +3 -3
  170. package/build-types/navigator/navigator-button/component.d.ts +1 -1
  171. package/build-types/navigator/navigator-button/hook.d.ts +3 -3
  172. package/build-types/navigator/navigator-provider/component.d.ts.map +1 -1
  173. package/build-types/navigator/navigator-screen/component.d.ts +1 -1
  174. package/build-types/navigator/navigator-screen/component.d.ts.map +1 -1
  175. package/build-types/navigator/navigator-to-parent-button/component.d.ts +1 -1
  176. package/build-types/navigator/stories/index.d.ts +1 -0
  177. package/build-types/navigator/stories/index.d.ts.map +1 -1
  178. package/build-types/navigator/types.d.ts +2 -2
  179. package/build-types/navigator/types.d.ts.map +1 -1
  180. package/build-types/number-control/index.d.ts +2 -2
  181. package/build-types/number-control/stories/index.d.ts +2 -2
  182. package/build-types/palette-edit/styles.d.ts +18 -12
  183. package/build-types/palette-edit/styles.d.ts.map +1 -1
  184. package/build-types/popover/index.d.ts +1 -1
  185. package/build-types/popover/index.d.ts.map +1 -1
  186. package/build-types/popover/stories/e2e/index.d.ts +1 -1
  187. package/build-types/private-apis.d.ts +2 -3
  188. package/build-types/private-apis.d.ts.map +1 -1
  189. package/build-types/query-controls/author-select.d.ts.map +1 -1
  190. package/build-types/query-controls/category-select.d.ts.map +1 -1
  191. package/build-types/query-controls/index.d.ts.map +1 -1
  192. package/build-types/range-control/index.d.ts +1 -1
  193. package/build-types/range-control/styles/range-control-styles.d.ts +2 -2
  194. package/build-types/resizable-box/index.d.ts +1 -1
  195. package/build-types/resizable-box/resize-tooltip/index.d.ts +1 -1
  196. package/build-types/resizable-box/stories/index.d.ts +2 -2
  197. package/build-types/scrollable/hook.d.ts +2 -2
  198. package/build-types/search-control/index.d.ts +1 -1
  199. package/build-types/search-control/stories/index.d.ts +2 -2
  200. package/build-types/slot-fill/index.d.ts +13 -1
  201. package/build-types/slot-fill/index.d.ts.map +1 -1
  202. package/build-types/spacer/hook.d.ts +2 -2
  203. package/build-types/spinner/index.d.ts +1 -1
  204. package/build-types/spinner/styles.d.ts.map +1 -1
  205. package/build-types/surface/hook.d.ts +2 -2
  206. package/build-types/text/hook.d.ts +2 -2
  207. package/build-types/text-control/index.d.ts +1 -1
  208. package/build-types/toolbar/toolbar-button/index.d.ts +8 -8
  209. package/build-types/tools-panel/tools-panel/hook.d.ts +2 -2
  210. package/build-types/tools-panel/tools-panel-header/hook.d.ts +2 -2
  211. package/build-types/tools-panel/tools-panel-item/hook.d.ts +2 -2
  212. package/build-types/tree-grid/index.d.ts.map +1 -1
  213. package/build-types/truncate/hook.d.ts +2 -2
  214. package/build-types/ui/context/wordpress-component.d.ts +1 -1
  215. package/build-types/ui/context/wordpress-component.d.ts.map +1 -1
  216. package/build-types/ui/control-group/hook.d.ts +2 -2
  217. package/build-types/ui/control-label/hook.d.ts +2 -2
  218. package/build-types/ui/form-group/form-group.d.ts +2 -2
  219. package/build-types/ui/form-group/use-form-group.d.ts +2 -2
  220. package/build-types/unit-control/index.d.ts +1 -1
  221. package/build-types/unit-control/styles/unit-control-styles.d.ts +2 -2
  222. package/build-types/v-stack/hook.d.ts +2 -2
  223. package/build-types/view/component.d.ts +1 -1
  224. package/build-types/view/component.d.ts.map +1 -1
  225. package/package.json +22 -22
  226. package/src/autocomplete/README.md +4 -2
  227. package/src/checkbox-control/index.tsx +6 -2
  228. package/src/color-palette/index.native.js +20 -1
  229. package/src/color-picker/test/index.tsx +99 -99
  230. package/src/custom-gradient-picker/index.native.js +1 -1
  231. package/src/custom-gradient-picker/serializer.ts +2 -6
  232. package/src/custom-gradient-picker/types.ts +0 -18
  233. package/src/dimension-control/README.md +1 -1
  234. package/src/draggable/README.md +8 -1
  235. package/src/draggable/index.tsx +6 -1
  236. package/src/draggable/stories/index.tsx +69 -33
  237. package/src/draggable/types.ts +7 -0
  238. package/src/drop-zone/index.tsx +12 -8
  239. package/src/drop-zone/style.scss +1 -1
  240. package/src/{index.js → index.ts} +1 -0
  241. package/src/mobile/bottom-sheet/cell.native.js +4 -5
  242. package/src/mobile/color-settings/palette.screen.native.js +0 -7
  243. package/src/mobile/global-styles-context/utils.native.js +18 -3
  244. package/src/mobile/keyboard-aware-flat-list/index.android.js +0 -4
  245. package/src/mobile/keyboard-aware-flat-list/index.ios.js +118 -67
  246. package/src/mobile/keyboard-aware-flat-list/test/use-keyboard-offset.native.js +203 -0
  247. package/src/mobile/keyboard-aware-flat-list/test/use-scroll-to-text-input.native.js +140 -0
  248. package/src/mobile/keyboard-aware-flat-list/test/use-text-input-caret-position.native.js +82 -0
  249. package/src/mobile/keyboard-aware-flat-list/test/use-text-input-offset.native.js +147 -0
  250. package/src/mobile/keyboard-aware-flat-list/use-keyboard-offset.native.js +87 -0
  251. package/src/mobile/keyboard-aware-flat-list/use-scroll-to-text-input.native.js +105 -0
  252. package/src/mobile/keyboard-aware-flat-list/use-text-input-caret-position.native.js +36 -0
  253. package/src/mobile/keyboard-aware-flat-list/use-text-input-offset.native.js +54 -0
  254. package/src/mobile/segmented-control/index.native.js +2 -2
  255. package/src/modal/style.scss +20 -12
  256. package/src/navigator/navigator-provider/component.tsx +2 -0
  257. package/src/navigator/navigator-screen/component.tsx +5 -2
  258. package/src/navigator/stories/index.tsx +68 -0
  259. package/src/navigator/test/index.tsx +52 -0
  260. package/src/navigator/types.ts +2 -1
  261. package/src/popover/index.tsx +2 -15
  262. package/src/{private-apis.js → private-apis.ts} +2 -0
  263. package/src/query-controls/author-select.tsx +1 -0
  264. package/src/query-controls/category-select.tsx +1 -0
  265. package/src/query-controls/index.tsx +4 -2
  266. package/src/sandbox/index.native.js +78 -37
  267. package/src/slot-fill/index.js +14 -6
  268. package/src/snackbar/style.scss +2 -1
  269. package/src/spinner/styles.ts +2 -0
  270. package/src/tree-grid/index.tsx +7 -2
  271. package/src/ui/context/wordpress-component.ts +1 -1
  272. package/src/view/component.tsx +2 -2
  273. package/tsconfig.json +3 -4
  274. package/tsconfig.tsbuildinfo +1 -1
@@ -298,3 +298,71 @@ export const NestedNavigator: ComponentStory< typeof NavigatorProvider > =
298
298
  NestedNavigator.args = {
299
299
  initialPath: '/child2/grandchild',
300
300
  };
301
+
302
+ const NavigatorButtonWithSkipFocus = ( {
303
+ path,
304
+ onClick,
305
+ ...props
306
+ }: React.ComponentProps< typeof NavigatorButton > ) => {
307
+ const { goTo } = useNavigator();
308
+
309
+ return (
310
+ <Button
311
+ { ...props }
312
+ onClick={ ( e: React.MouseEvent< HTMLButtonElement > ) => {
313
+ goTo( path, { skipFocus: true } );
314
+ onClick?.( e );
315
+ } }
316
+ />
317
+ );
318
+ };
319
+
320
+ export const SkipFocus: ComponentStory< typeof NavigatorProvider > = (
321
+ args
322
+ ) => {
323
+ return <NavigatorProvider { ...args } />;
324
+ };
325
+ SkipFocus.args = {
326
+ initialPath: '/',
327
+ children: (
328
+ <>
329
+ <div
330
+ style={ {
331
+ height: 250,
332
+ border: '1px solid black',
333
+ } }
334
+ >
335
+ <NavigatorScreen
336
+ path="/"
337
+ style={ {
338
+ height: '100%',
339
+ } }
340
+ >
341
+ <h1>Home screen</h1>
342
+ <NavigatorButton variant="secondary" path="/child">
343
+ Go to child screen.
344
+ </NavigatorButton>
345
+ </NavigatorScreen>
346
+ <NavigatorScreen
347
+ path="/child"
348
+ style={ {
349
+ height: '100%',
350
+ } }
351
+ >
352
+ <h2>Child screen</h2>
353
+ <NavigatorToParentButton variant="secondary">
354
+ Go to parent screen.
355
+ </NavigatorToParentButton>
356
+ </NavigatorScreen>
357
+ </div>
358
+
359
+ <NavigatorButtonWithSkipFocus
360
+ variant="secondary"
361
+ path="/child"
362
+ style={ { margin: '1rem 2rem' } }
363
+ >
364
+ Go to child screen, but keep focus on this button
365
+ </NavigatorButtonWithSkipFocus>
366
+ </>
367
+ ),
368
+ };
@@ -22,6 +22,7 @@ import {
22
22
  NavigatorToParentButton,
23
23
  useNavigator,
24
24
  } from '..';
25
+ import type { NavigateOptions } from '../types';
25
26
 
26
27
  const INVALID_HTML_ATTRIBUTE = {
27
28
  raw: ' "\'><=invalid_path',
@@ -57,6 +58,7 @@ const BUTTON_TEXT = {
57
58
  'Navigate to screen with an invalid HTML value as a path.',
58
59
  back: 'Go back',
59
60
  backUsingGoTo: 'Go back using goTo',
61
+ goToWithSkipFocus: 'Go to with skipFocus',
60
62
  };
61
63
 
62
64
  type CustomTestOnClickHandler = (
@@ -64,6 +66,7 @@ type CustomTestOnClickHandler = (
64
66
  | {
65
67
  type: 'goTo';
66
68
  path: string;
69
+ options?: NavigateOptions;
67
70
  }
68
71
  | { type: 'goBack' }
69
72
  | { type: 'goToParent' }
@@ -108,6 +111,26 @@ function CustomNavigatorGoToBackButton( {
108
111
  );
109
112
  }
110
113
 
114
+ function CustomNavigatorGoToSkipFocusButton( {
115
+ path,
116
+ onClick,
117
+ ...props
118
+ }: Omit< ComponentPropsWithoutRef< typeof NavigatorButton >, 'onClick' > & {
119
+ onClick?: CustomTestOnClickHandler;
120
+ } ) {
121
+ const { goTo } = useNavigator();
122
+ return (
123
+ <Button
124
+ onClick={ () => {
125
+ goTo( path, { skipFocus: true } );
126
+ // Used to spy on the values passed to `navigator.goTo`.
127
+ onClick?.( { type: 'goTo', path } );
128
+ } }
129
+ { ...props }
130
+ />
131
+ );
132
+ }
133
+
111
134
  function CustomNavigatorBackButton( {
112
135
  onClick,
113
136
  ...props
@@ -342,6 +365,12 @@ const MyHierarchicalNavigation = ( {
342
365
  { BUTTON_TEXT.backUsingGoTo }
343
366
  </CustomNavigatorGoToBackButton>
344
367
  </NavigatorScreen>
368
+ <CustomNavigatorGoToSkipFocusButton
369
+ path={ PATHS.NESTED }
370
+ onClick={ onNavigatorButtonClick }
371
+ >
372
+ { BUTTON_TEXT.goToWithSkipFocus }
373
+ </CustomNavigatorGoToSkipFocusButton>
345
374
  </NavigatorProvider>
346
375
  </>
347
376
  );
@@ -716,6 +745,29 @@ describe( 'Navigator', () => {
716
745
  await user.click( getNavigationButton( 'back' ) );
717
746
  expect( getNavigationButton( 'toChildScreen' ) ).toHaveFocus();
718
747
  } );
748
+
749
+ it( 'should skip focus based on location `skipFocus` option', async () => {
750
+ const user = userEvent.setup();
751
+ render( <MyHierarchicalNavigation /> );
752
+
753
+ // Navigate to child screen with skipFocus.
754
+ await user.click( getNavigationButton( 'goToWithSkipFocus' ) );
755
+ expect( queryScreen( 'home' ) ).not.toBeInTheDocument();
756
+ expect( getScreen( 'nested' ) ).toBeInTheDocument();
757
+
758
+ // The clicked button should remain focused.
759
+ expect( getNavigationButton( 'goToWithSkipFocus' ) ).toHaveFocus();
760
+
761
+ // Navigate back to parent screen.
762
+ await user.click( getNavigationButton( 'back' ) );
763
+ expect( getScreen( 'child' ) ).toBeInTheDocument();
764
+ // The first tabbable element receives focus.
765
+ expect(
766
+ screen.getByRole( 'button', {
767
+ name: 'First tabbable child screen button',
768
+ } )
769
+ ).toHaveFocus();
770
+ } );
719
771
  } );
720
772
 
721
773
  describe( 'animation', () => {
@@ -10,9 +10,10 @@ import type { ButtonAsButtonProps } from '../button/types';
10
10
 
11
11
  export type MatchParams = Record< string, string | string[] >;
12
12
 
13
- type NavigateOptions = {
13
+ export type NavigateOptions = {
14
14
  focusTargetSelector?: string;
15
15
  isBack?: boolean;
16
+ skipFocus?: boolean;
16
17
  };
17
18
 
18
19
  export type NavigatorLocation = NavigateOptions & {
@@ -109,10 +109,6 @@ const AnimatedWrapper = forwardRef(
109
109
  }: HTMLMotionProps< 'div' > & AnimatedWrapperProps,
110
110
  forwardedRef: ForwardedRef< any >
111
111
  ) => {
112
- // When animating, animate only once (i.e. when the popover is opened), and
113
- // do not animate on subsequent prop changes (as it conflicts with
114
- // floating-ui's positioning updates).
115
- const [ hasAnimatedOnce, setHasAnimatedOnce ] = useState( false );
116
112
  const shouldReduceMotion = useReducedMotion();
117
113
 
118
114
  const { style: motionInlineStyles, ...otherMotionProps } = useMemo(
@@ -120,11 +116,6 @@ const AnimatedWrapper = forwardRef(
120
116
  [ placement ]
121
117
  );
122
118
 
123
- const onAnimationComplete = useCallback(
124
- () => setHasAnimatedOnce( true ),
125
- []
126
- );
127
-
128
119
  const computedAnimationProps: HTMLMotionProps< 'div' > =
129
120
  shouldAnimate && ! shouldReduceMotion
130
121
  ? {
@@ -133,10 +124,6 @@ const AnimatedWrapper = forwardRef(
133
124
  ...receivedInlineStyles,
134
125
  },
135
126
  ...otherMotionProps,
136
- onAnimationComplete,
137
- animate: hasAnimatedOnce
138
- ? false
139
- : otherMotionProps.animate,
140
127
  }
141
128
  : {
142
129
  animate: false,
@@ -160,8 +147,8 @@ const UnforwardedPopover = (
160
147
  WordPressComponentProps< PopoverProps, 'div', false >,
161
148
  // To avoid overlaps between the standard HTML attributes and the props
162
149
  // expected by `framer-motion`, omit all framer motion props from popover
163
- // props (except for `animate`, which is re-defined in `PopoverProps`).
164
- keyof Omit< MotionProps, 'animate' >
150
+ // props (except for `animate` and `children`, which are re-defined in `PopoverProps`).
151
+ keyof Omit< MotionProps, 'animate' | 'children' >
165
152
  >,
166
153
  forwardedRef: ForwardedRef< any >
167
154
  ) => {
@@ -8,6 +8,7 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri
8
8
  */
9
9
  import { default as CustomSelectControl } from './custom-select-control';
10
10
  import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils';
11
+ import { createPrivateSlotFill } from './slot-fill';
11
12
 
12
13
  export const { lock, unlock } =
13
14
  __dangerousOptInToUnstableAPIsOnlyForCoreModules(
@@ -19,4 +20,5 @@ export const privateApis = {};
19
20
  lock( privateApis, {
20
21
  CustomSelectControl,
21
22
  __experimentalPopoverLegacyPositionToPlacement,
23
+ createPrivateSlotFill,
22
24
  } );
@@ -27,6 +27,7 @@ export default function AuthorSelect( {
27
27
  ? String( selectedAuthorId )
28
28
  : undefined
29
29
  }
30
+ __nextHasNoMarginBottom
30
31
  />
31
32
  );
32
33
  }
@@ -36,6 +36,7 @@ export default function CategorySelect( {
36
36
  : undefined
37
37
  }
38
38
  { ...props }
39
+ __nextHasNoMarginBottom
39
40
  />
40
41
  );
41
42
  }
@@ -11,6 +11,7 @@ import CategorySelect from './category-select';
11
11
  import FormTokenField from '../form-token-field';
12
12
  import RangeControl from '../range-control';
13
13
  import SelectControl from '../select-control';
14
+ import { VStack } from '../v-stack';
14
15
  import type {
15
16
  QueryControlsProps,
16
17
  QueryControlsWithMultipleCategorySelectionProps,
@@ -75,7 +76,7 @@ export function QueryControls( {
75
76
  ...props
76
77
  }: QueryControlsProps ) {
77
78
  return (
78
- <>
79
+ <VStack spacing="4" className="components-query-controls">
79
80
  { [
80
81
  onOrderChange && onOrderByChange && (
81
82
  <SelectControl
@@ -142,6 +143,7 @@ export function QueryControls( {
142
143
  props.categorySuggestions &&
143
144
  props.onCategoryChange && (
144
145
  <FormTokenField
146
+ __nextHasNoMarginBottom
145
147
  key="query-controls-categories-select"
146
148
  label={ __( 'Categories' ) }
147
149
  value={
@@ -185,7 +187,7 @@ export function QueryControls( {
185
187
  />
186
188
  ),
187
189
  ] }
188
- </>
190
+ </VStack>
189
191
  );
190
192
  }
191
193
 
@@ -14,6 +14,8 @@ import {
14
14
  useRef,
15
15
  useState,
16
16
  useEffect,
17
+ forwardRef,
18
+ useCallback,
17
19
  } from '@wordpress/element';
18
20
  import { usePreferredColorScheme } from '@wordpress/compose';
19
21
 
@@ -98,7 +100,6 @@ const observeAndResizeJS = `
98
100
  // get an DOM mutations for that, so do the resize when the window is resized, too.
99
101
  window.addEventListener( 'resize', sendResize, true );
100
102
  window.addEventListener( 'orientationchange', sendResize, true );
101
- widow.addEventListener( 'click', sendResize, true );
102
103
  })();
103
104
  `;
104
105
 
@@ -171,20 +172,24 @@ const style = `
171
172
 
172
173
  const EMPTY_ARRAY = [];
173
174
 
174
- function Sandbox( {
175
- containerStyle,
176
- customJS,
177
- html = '',
178
- lang = 'en',
179
- providerUrl = '',
180
- scripts = EMPTY_ARRAY,
181
- styles = EMPTY_ARRAY,
182
- title = '',
183
- type,
184
- url,
185
- } ) {
175
+ const Sandbox = forwardRef( function Sandbox(
176
+ {
177
+ containerStyle,
178
+ customJS,
179
+ html = '',
180
+ lang = 'en',
181
+ providerUrl = '',
182
+ scripts = EMPTY_ARRAY,
183
+ styles = EMPTY_ARRAY,
184
+ title = '',
185
+ type,
186
+ url,
187
+ onWindowEvents = {},
188
+ viewportProps = '',
189
+ },
190
+ ref
191
+ ) {
186
192
  const colorScheme = usePreferredColorScheme();
187
- const ref = useRef();
188
193
  const [ height, setHeight ] = useState( 0 );
189
194
  const [ contentHtml, setContentHtml ] = useState( getHtmlDoc() );
190
195
 
@@ -209,13 +214,19 @@ function Sandbox( {
209
214
  // we can use this in the future to inject custom styles or scripts.
210
215
  // Scripts go into the body rather than the head, to support embedded content such as Instagram
211
216
  // that expect the scripts to be part of the body.
217
+
218
+ // Avoid comma issues with props.viewportProps.
219
+ const addViewportProps = viewportProps
220
+ .trim()
221
+ .replace( /(^[^,])/, ', $1' );
222
+
212
223
  const htmlDoc = (
213
224
  <html lang={ lang }>
214
225
  <head>
215
226
  <title>{ title }</title>
216
227
  <meta
217
228
  name="viewport"
218
- content="width=device-width, initial-scale=1"
229
+ content={ `width=device-width, initial-scale=1${ addViewportProps }` }
219
230
  ></meta>
220
231
  <style dangerouslySetInnerHTML={ { __html: style } } />
221
232
  { styles.map( ( rules, i ) => (
@@ -239,6 +250,21 @@ function Sandbox( {
239
250
  return '<!DOCTYPE html>' + renderToString( htmlDoc );
240
251
  }
241
252
 
253
+ const getInjectedJavaScript = useCallback( () => {
254
+ // Allow parent to override the resize observers with prop.customJS (legacy support)
255
+ let injectedJS = customJS || observeAndResizeJS;
256
+
257
+ // Add any event listeners that were passed in.
258
+ Object.keys( onWindowEvents ).forEach( ( eventType ) => {
259
+ injectedJS += `
260
+ window.addEventListener( '${ eventType }', function( event ) {
261
+ window.ReactNativeWebView.postMessage( JSON.stringify( { type: '${ eventType }', ...event.data } ) );
262
+ });`;
263
+ } );
264
+
265
+ return injectedJS;
266
+ }, [ customJS, onWindowEvents ] );
267
+
242
268
  function updateContentHtml( forceRerender = false ) {
243
269
  const newContentHtml = getHtmlDoc();
244
270
 
@@ -253,25 +279,6 @@ function Sandbox( {
253
279
  }
254
280
  }
255
281
 
256
- function checkMessageForResize( event ) {
257
- // Attempt to parse the message data as JSON if passed as string.
258
- let data = event.nativeEvent.data || {};
259
-
260
- if ( 'string' === typeof data ) {
261
- try {
262
- data = JSON.parse( data );
263
- } catch ( e ) {}
264
- }
265
-
266
- // Update the state only if the message is formatted as we expect,
267
- // i.e. as an object with a 'resize' action.
268
- if ( 'resize' !== data.action ) {
269
- return;
270
- }
271
-
272
- setHeight( data.height );
273
- }
274
-
275
282
  function getSizeStyle() {
276
283
  const contentHeight = Math.ceil( height );
277
284
 
@@ -282,6 +289,39 @@ function Sandbox( {
282
289
  setIsLandscape( dimensions.window.width >= dimensions.window.height );
283
290
  }
284
291
 
292
+ const onMessage = useCallback(
293
+ ( message ) => {
294
+ let data = message?.nativeEvent?.data;
295
+
296
+ try {
297
+ data = JSON.parse( data );
298
+ } catch ( e ) {
299
+ return;
300
+ }
301
+
302
+ // check for resize event
303
+ if ( 'resize' === data?.action ) {
304
+ setHeight( data.height );
305
+ }
306
+
307
+ // Forward the event to parent event listeners
308
+ Object.keys( onWindowEvents ).forEach( ( eventType ) => {
309
+ if ( data?.type === eventType ) {
310
+ try {
311
+ onWindowEvents[ eventType ]( data );
312
+ } catch ( e ) {
313
+ // eslint-disable-next-line no-console
314
+ console.warn(
315
+ `Error handling event ${ eventType }`,
316
+ e
317
+ );
318
+ }
319
+ }
320
+ } );
321
+ },
322
+ [ onWindowEvents ]
323
+ );
324
+
285
325
  useEffect( () => {
286
326
  const dimensionsChangeSubscription = Dimensions.addEventListener(
287
327
  'change',
@@ -314,7 +354,7 @@ function Sandbox( {
314
354
  sandboxStyles[ 'sandbox-webview__container' ],
315
355
  containerStyle,
316
356
  ] }
317
- injectedJavaScript={ customJS || observeAndResizeJS }
357
+ injectedJavaScript={ getInjectedJavaScript() }
318
358
  key={ key }
319
359
  ref={ ref }
320
360
  source={ { baseUrl: providerUrl, html: contentHtml } }
@@ -326,14 +366,15 @@ function Sandbox( {
326
366
  getSizeStyle(),
327
367
  Platform.isAndroid && workaroundStyles.webView,
328
368
  ] }
329
- onMessage={ checkMessageForResize }
369
+ onMessage={ onMessage }
330
370
  scrollEnabled={ false }
331
371
  setBuiltInZoomControls={ false }
332
372
  showsHorizontalScrollIndicator={ false }
333
373
  showsVerticalScrollIndicator={ false }
374
+ mediaPlaybackRequiresUserAction={ false }
334
375
  />
335
376
  );
336
- }
377
+ } );
337
378
 
338
379
  const workaroundStyles = StyleSheet.create( {
339
380
  webView: {
@@ -44,13 +44,14 @@ export function Provider( { children, ...props } ) {
44
44
  );
45
45
  }
46
46
 
47
- export function createSlotFill( name ) {
48
- const FillComponent = ( props ) => <Fill name={ name } { ...props } />;
49
- FillComponent.displayName = name + 'Fill';
47
+ export function createSlotFill( key ) {
48
+ const baseName = typeof key === 'symbol' ? key.description : key;
49
+ const FillComponent = ( props ) => <Fill name={ key } { ...props } />;
50
+ FillComponent.displayName = `${ baseName }Fill`;
50
51
 
51
- const SlotComponent = ( props ) => <Slot name={ name } { ...props } />;
52
- SlotComponent.displayName = name + 'Slot';
53
- SlotComponent.__unstableName = name;
52
+ const SlotComponent = ( props ) => <Slot name={ key } { ...props } />;
53
+ SlotComponent.displayName = `${ baseName }Slot`;
54
+ SlotComponent.__unstableName = key;
54
55
 
55
56
  return {
56
57
  Fill: FillComponent,
@@ -58,4 +59,11 @@ export function createSlotFill( name ) {
58
59
  };
59
60
  }
60
61
 
62
+ export const createPrivateSlotFill = ( name ) => {
63
+ const privateKey = Symbol( name );
64
+ const privateSlotFill = createSlotFill( privateKey );
65
+
66
+ return { privateKey, ...privateSlotFill };
67
+ };
68
+
61
69
  export { useSlot };
@@ -64,7 +64,8 @@
64
64
  }
65
65
 
66
66
  &:hover {
67
- color: $components-color-accent;
67
+ text-decoration: none;
68
+ color: $white;
68
69
  }
69
70
  }
70
71
  }
@@ -26,6 +26,8 @@ export const StyledSpinner = styled.svg`
26
26
  position: relative;
27
27
  color: ${ COLORS.ui.theme };
28
28
  overflow: visible;
29
+ opacity: 1;
30
+ background-color: transparent;
29
31
  `;
30
32
 
31
33
  const commonPathProps = css`
@@ -91,7 +91,8 @@ function UnforwardedTreeGrid(
91
91
  const canExpandCollapse = 0 === currentColumnIndex;
92
92
  const cannotFocusNextColumn =
93
93
  canExpandCollapse &&
94
- activeRow.getAttribute( 'aria-expanded' ) === 'false' &&
94
+ ( activeRow.getAttribute( 'data-expanded' ) === 'false' ||
95
+ activeRow.getAttribute( 'aria-expanded' ) === 'false' ) &&
95
96
  keyCode === RIGHT;
96
97
 
97
98
  if ( ( [ LEFT, RIGHT ] as number[] ).includes( keyCode ) ) {
@@ -112,6 +113,8 @@ function UnforwardedTreeGrid(
112
113
  // Left:
113
114
  // If a row is focused, and it is expanded, collapses the current row.
114
115
  if (
116
+ activeRow.getAttribute( 'data-expanded' ) ===
117
+ 'true' ||
115
118
  activeRow.getAttribute( 'aria-expanded' ) === 'true'
116
119
  ) {
117
120
  onCollapseRow( activeRow );
@@ -151,8 +154,10 @@ function UnforwardedTreeGrid(
151
154
  // Right:
152
155
  // If a row is focused, and it is collapsed, expands the current row.
153
156
  if (
157
+ activeRow.getAttribute( 'data-expanded' ) ===
158
+ 'false' ||
154
159
  activeRow.getAttribute( 'aria-expanded' ) ===
155
- 'false'
160
+ 'false'
156
161
  ) {
157
162
  onExpandRow( activeRow );
158
163
  event.preventDefault();
@@ -44,7 +44,7 @@ export type WordPressComponent<
44
44
  * We restrict it to a class to align with the already existing class names that
45
45
  * are generated by the context system.
46
46
  */
47
- selector: `.${ string }`;
47
+ selector?: `.${ string }`;
48
48
  };
49
49
 
50
50
  export type WordPressComponentFromProps<
@@ -27,10 +27,10 @@ import type { ViewProps } from './types';
27
27
  * }
28
28
  * ```
29
29
  */
30
- // @ts-expect-error
31
30
  export const View: WordPressComponent<
32
31
  'div',
33
- ViewProps & RefAttributes< any >
32
+ ViewProps & RefAttributes< any >,
33
+ true
34
34
  > = styled.div``;
35
35
 
36
36
  View.selector = '.components-view';
package/tsconfig.json CHANGED
@@ -12,8 +12,8 @@
12
12
  "snapshot-diff",
13
13
  "@wordpress/jest-console"
14
14
  ],
15
- // Some errors in Reakit types with TypeScript 4.3
16
- // Remove the following line when they've been addressed.
15
+ // TODO: Remove `skipLibCheck` after resolving duplicate declaration of the `process` variable
16
+ // between `@types/webpack-env` (from @storybook packages) and `gutenberg-env`.
17
17
  "skipLibCheck": true,
18
18
  "strictNullChecks": true
19
19
  },
@@ -43,7 +43,6 @@
43
43
  "src/**/*.native.js",
44
44
  "src/**/react-native-*",
45
45
  "src/**/stories/**/*.js", // only exclude js files, tsx files should be checked
46
- "src/**/test/**/*.js", // only exclude js files, ts{x} files should be checked
47
- "src/index.js"
46
+ "src/**/test/**/*.js" // only exclude js files, ts{x} files should be checked
48
47
  ]
49
48
  }