@wordpress/components 23.0.0 → 23.2.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 (457) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/CONTRIBUTING.md +0 -21
  3. package/LICENSE.md +1 -1
  4. package/build/autocomplete/index.js +1 -3
  5. package/build/autocomplete/index.js.map +1 -1
  6. package/build/border-box-control/border-box-control/component.js +0 -3
  7. package/build/border-box-control/border-box-control/component.js.map +1 -1
  8. package/build/border-box-control/border-box-control/hook.js +0 -2
  9. package/build/border-box-control/border-box-control/hook.js.map +1 -1
  10. package/build/border-box-control/border-box-control-split-controls/component.js +0 -2
  11. package/build/border-box-control/border-box-control-split-controls/component.js.map +1 -1
  12. package/build/border-box-control/border-box-control-split-controls/hook.js +0 -2
  13. package/build/border-box-control/border-box-control-split-controls/hook.js.map +1 -1
  14. package/build/border-control/border-control/component.js +0 -2
  15. package/build/border-control/border-control/component.js.map +1 -1
  16. package/build/border-control/border-control/hook.js +0 -2
  17. package/build/border-control/border-control/hook.js.map +1 -1
  18. package/build/border-control/border-control-dropdown/component.js +6 -11
  19. package/build/border-control/border-control-dropdown/component.js.map +1 -1
  20. package/build/border-control/border-control-dropdown/hook.js +0 -2
  21. package/build/border-control/border-control-dropdown/hook.js.map +1 -1
  22. package/build/color-palette/index.js +5 -8
  23. package/build/color-palette/index.js.map +1 -1
  24. package/build/color-picker/component.js +1 -0
  25. package/build/color-picker/component.js.map +1 -1
  26. package/build/color-picker/styles.js +8 -10
  27. package/build/color-picker/styles.js.map +1 -1
  28. package/build/combobox-control/index.js +5 -1
  29. package/build/combobox-control/index.js.map +1 -1
  30. package/build/dimension-control/index.js.map +1 -1
  31. package/build/dropdown/index.js +45 -10
  32. package/build/dropdown/index.js.map +1 -1
  33. package/build/focal-point-picker/utils.js +1 -1
  34. package/build/focal-point-picker/utils.js.map +1 -1
  35. package/build/gradient-picker/index.js +1 -2
  36. package/build/gradient-picker/index.js.map +1 -1
  37. package/build/higher-order/navigate-regions/index.js +4 -3
  38. package/build/higher-order/navigate-regions/index.js.map +1 -1
  39. package/build/index.js +7 -25
  40. package/build/index.js.map +1 -1
  41. package/build/index.native.js +8 -18
  42. package/build/index.native.js.map +1 -1
  43. package/build/item-group/item/component.js +27 -3
  44. package/build/item-group/item/component.js.map +1 -1
  45. package/build/item-group/item-group/component.js +26 -3
  46. package/build/item-group/item-group/component.js.map +1 -1
  47. package/build/item-group/styles.js +14 -14
  48. package/build/item-group/styles.js.map +1 -1
  49. package/build/mobile/bottom-sheet/picker-cell.native.js +1 -9
  50. package/build/mobile/bottom-sheet/picker-cell.native.js.map +1 -1
  51. package/build/mobile/global-styles-context/utils.native.js +30 -12
  52. package/build/mobile/global-styles-context/utils.native.js.map +1 -1
  53. package/build/panel/row.js +5 -3
  54. package/build/panel/row.js.map +1 -1
  55. package/build/query-controls/index.js +1 -0
  56. package/build/query-controls/index.js.map +1 -1
  57. package/build/resizable-box/index.js +5 -4
  58. package/build/resizable-box/index.js.map +1 -1
  59. package/build/responsive-wrapper/index.js +18 -1
  60. package/build/responsive-wrapper/index.js.map +1 -1
  61. package/build/responsive-wrapper/types.js +6 -0
  62. package/build/responsive-wrapper/types.js.map +1 -0
  63. package/build/sandbox/index.js +35 -24
  64. package/build/sandbox/index.js.map +1 -1
  65. package/build/sandbox/types.js +6 -0
  66. package/build/sandbox/types.js.map +1 -0
  67. package/build/tab-panel/index.js +15 -9
  68. package/build/tab-panel/index.js.map +1 -1
  69. package/build/toolbar/index.js +42 -60
  70. package/build/toolbar/index.js.map +1 -1
  71. package/build/toolbar/toolbar/index.js +74 -0
  72. package/build/toolbar/toolbar/index.js.map +1 -0
  73. package/build/toolbar/{toolbar-container.js → toolbar/toolbar-container.js} +0 -0
  74. package/build/toolbar/toolbar/toolbar-container.js.map +1 -0
  75. package/build/toolbar/{toolbar-container.native.js → toolbar/toolbar-container.native.js} +0 -0
  76. package/build/toolbar/toolbar/toolbar-container.native.js.map +1 -0
  77. package/build/{toolbar-button → toolbar/toolbar-button}/index.js +1 -1
  78. package/build/toolbar/toolbar-button/index.js.map +1 -0
  79. package/build/{toolbar-button → toolbar/toolbar-button}/toolbar-button-container.js +0 -0
  80. package/build/toolbar/toolbar-button/toolbar-button-container.js.map +1 -0
  81. package/build/{toolbar-button → toolbar/toolbar-button}/toolbar-button-container.native.js +0 -0
  82. package/build/toolbar/toolbar-button/toolbar-button-container.native.js.map +1 -0
  83. package/build/{toolbar-context → toolbar/toolbar-context}/index.js +0 -0
  84. package/build/toolbar/toolbar-context/index.js.map +1 -0
  85. package/build/{toolbar-dropdown-menu → toolbar/toolbar-dropdown-menu}/index.js +1 -1
  86. package/build/toolbar/toolbar-dropdown-menu/index.js.map +1 -0
  87. package/build/{toolbar-group → toolbar/toolbar-group}/index.js +0 -0
  88. package/build/toolbar/toolbar-group/index.js.map +1 -0
  89. package/build/{toolbar-group → toolbar/toolbar-group}/toolbar-group-collapsed.js +1 -1
  90. package/build/toolbar/toolbar-group/toolbar-group-collapsed.js.map +1 -0
  91. package/build/{toolbar-group → toolbar/toolbar-group}/toolbar-group-collapsed.native.js +1 -1
  92. package/build/toolbar/toolbar-group/toolbar-group-collapsed.native.js.map +1 -0
  93. package/build/{toolbar-group → toolbar/toolbar-group}/toolbar-group-container.js +0 -0
  94. package/build/toolbar/toolbar-group/toolbar-group-container.js.map +1 -0
  95. package/build/{toolbar-group → toolbar/toolbar-group}/toolbar-group-container.native.js +0 -0
  96. package/build/toolbar/toolbar-group/toolbar-group-container.native.js.map +1 -0
  97. package/build/{toolbar-item → toolbar/toolbar-item}/index.js +0 -0
  98. package/build/toolbar/toolbar-item/index.js.map +1 -0
  99. package/build/{toolbar-item → toolbar/toolbar-item}/index.native.js +0 -0
  100. package/build/toolbar/toolbar-item/index.native.js.map +1 -0
  101. package/build/tree-grid/index.js +3 -3
  102. package/build/tree-grid/index.js.map +1 -1
  103. package/build-module/autocomplete/index.js +1 -2
  104. package/build-module/autocomplete/index.js.map +1 -1
  105. package/build-module/border-box-control/border-box-control/component.js +0 -3
  106. package/build-module/border-box-control/border-box-control/component.js.map +1 -1
  107. package/build-module/border-box-control/border-box-control/hook.js +0 -2
  108. package/build-module/border-box-control/border-box-control/hook.js.map +1 -1
  109. package/build-module/border-box-control/border-box-control-split-controls/component.js +0 -2
  110. package/build-module/border-box-control/border-box-control-split-controls/component.js.map +1 -1
  111. package/build-module/border-box-control/border-box-control-split-controls/hook.js +0 -2
  112. package/build-module/border-box-control/border-box-control-split-controls/hook.js.map +1 -1
  113. package/build-module/border-control/border-control/component.js +0 -2
  114. package/build-module/border-control/border-control/component.js.map +1 -1
  115. package/build-module/border-control/border-control/hook.js +0 -2
  116. package/build-module/border-control/border-control/hook.js.map +1 -1
  117. package/build-module/border-control/border-control-dropdown/component.js +6 -11
  118. package/build-module/border-control/border-control-dropdown/component.js.map +1 -1
  119. package/build-module/border-control/border-control-dropdown/hook.js +0 -2
  120. package/build-module/border-control/border-control-dropdown/hook.js.map +1 -1
  121. package/build-module/color-palette/index.js +5 -8
  122. package/build-module/color-palette/index.js.map +1 -1
  123. package/build-module/color-picker/component.js +1 -0
  124. package/build-module/color-picker/component.js.map +1 -1
  125. package/build-module/color-picker/styles.js +8 -9
  126. package/build-module/color-picker/styles.js.map +1 -1
  127. package/build-module/combobox-control/index.js +5 -1
  128. package/build-module/combobox-control/index.js.map +1 -1
  129. package/build-module/dimension-control/index.js +1 -2
  130. package/build-module/dimension-control/index.js.map +1 -1
  131. package/build-module/dropdown/index.js +44 -10
  132. package/build-module/dropdown/index.js.map +1 -1
  133. package/build-module/focal-point-picker/utils.js +1 -1
  134. package/build-module/focal-point-picker/utils.js.map +1 -1
  135. package/build-module/gradient-picker/index.js +1 -2
  136. package/build-module/gradient-picker/index.js.map +1 -1
  137. package/build-module/higher-order/navigate-regions/index.js +4 -3
  138. package/build-module/higher-order/navigate-regions/index.js.map +1 -1
  139. package/build-module/index.js +1 -7
  140. package/build-module/index.js.map +1 -1
  141. package/build-module/index.native.js +1 -6
  142. package/build-module/index.native.js.map +1 -1
  143. package/build-module/item-group/item/component.js +26 -2
  144. package/build-module/item-group/item/component.js.map +1 -1
  145. package/build-module/item-group/item-group/component.js +25 -2
  146. package/build-module/item-group/item-group/component.js.map +1 -1
  147. package/build-module/item-group/styles.js +14 -14
  148. package/build-module/item-group/styles.js.map +1 -1
  149. package/build-module/mobile/bottom-sheet/picker-cell.native.js +1 -8
  150. package/build-module/mobile/bottom-sheet/picker-cell.native.js.map +1 -1
  151. package/build-module/mobile/global-styles-context/utils.native.js +31 -13
  152. package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
  153. package/build-module/panel/row.js +5 -3
  154. package/build-module/panel/row.js.map +1 -1
  155. package/build-module/query-controls/index.js +1 -0
  156. package/build-module/query-controls/index.js.map +1 -1
  157. package/build-module/resizable-box/index.js +3 -2
  158. package/build-module/resizable-box/index.js.map +1 -1
  159. package/build-module/responsive-wrapper/index.js +20 -1
  160. package/build-module/responsive-wrapper/index.js.map +1 -1
  161. package/build-module/responsive-wrapper/types.js +2 -0
  162. package/build-module/responsive-wrapper/types.js.map +1 -0
  163. package/build-module/sandbox/index.js +37 -23
  164. package/build-module/sandbox/index.js.map +1 -1
  165. package/build-module/sandbox/types.js +2 -0
  166. package/build-module/sandbox/types.js.map +1 -0
  167. package/build-module/tab-panel/index.js +15 -8
  168. package/build-module/tab-panel/index.js.map +1 -1
  169. package/build-module/toolbar/index.js +6 -58
  170. package/build-module/toolbar/index.js.map +1 -1
  171. package/build-module/toolbar/toolbar/index.js +59 -0
  172. package/build-module/toolbar/toolbar/index.js.map +1 -0
  173. package/build-module/toolbar/{toolbar-container.js → toolbar/toolbar-container.js} +0 -0
  174. package/{build → build-module/toolbar}/toolbar/toolbar-container.js.map +1 -1
  175. package/build-module/toolbar/{toolbar-container.native.js → toolbar/toolbar-container.native.js} +0 -0
  176. package/build-module/toolbar/toolbar/toolbar-container.native.js.map +1 -0
  177. package/build-module/{toolbar-button → toolbar/toolbar-button}/index.js +1 -1
  178. package/build-module/toolbar/toolbar-button/index.js.map +1 -0
  179. package/build-module/{toolbar-button → toolbar/toolbar-button}/toolbar-button-container.js +0 -0
  180. package/build-module/toolbar/toolbar-button/toolbar-button-container.js.map +1 -0
  181. package/build-module/{toolbar-button → toolbar/toolbar-button}/toolbar-button-container.native.js +0 -0
  182. package/build-module/toolbar/toolbar-button/toolbar-button-container.native.js.map +1 -0
  183. package/build-module/{toolbar-context → toolbar/toolbar-context}/index.js +0 -0
  184. package/build-module/toolbar/toolbar-context/index.js.map +1 -0
  185. package/build-module/{toolbar-dropdown-menu → toolbar/toolbar-dropdown-menu}/index.js +1 -1
  186. package/build-module/toolbar/toolbar-dropdown-menu/index.js.map +1 -0
  187. package/build-module/{toolbar-group → toolbar/toolbar-group}/index.js +0 -0
  188. package/build-module/toolbar/toolbar-group/index.js.map +1 -0
  189. package/build-module/{toolbar-group → toolbar/toolbar-group}/toolbar-group-collapsed.js +1 -1
  190. package/build-module/toolbar/toolbar-group/toolbar-group-collapsed.js.map +1 -0
  191. package/build-module/{toolbar-group → toolbar/toolbar-group}/toolbar-group-collapsed.native.js +1 -1
  192. package/build-module/toolbar/toolbar-group/toolbar-group-collapsed.native.js.map +1 -0
  193. package/build-module/{toolbar-group → toolbar/toolbar-group}/toolbar-group-container.js +0 -0
  194. package/build-module/toolbar/toolbar-group/toolbar-group-container.js.map +1 -0
  195. package/build-module/{toolbar-group → toolbar/toolbar-group}/toolbar-group-container.native.js +0 -0
  196. package/build-module/toolbar/toolbar-group/toolbar-group-container.native.js.map +1 -0
  197. package/build-module/{toolbar-item → toolbar/toolbar-item}/index.js +0 -0
  198. package/build-module/toolbar/toolbar-item/index.js.map +1 -0
  199. package/build-module/{toolbar-item → toolbar/toolbar-item}/index.native.js +0 -0
  200. package/build-module/toolbar/toolbar-item/index.native.js.map +1 -0
  201. package/build-module/tree-grid/index.js +3 -3
  202. package/build-module/tree-grid/index.js.map +1 -1
  203. package/build-style/style-rtl.css +19 -32
  204. package/build-style/style.css +19 -32
  205. package/build-types/border-box-control/border-box-control/component.d.ts +1 -1
  206. package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
  207. package/build-types/border-box-control/border-box-control/hook.d.ts +0 -1
  208. package/build-types/border-box-control/border-box-control/hook.d.ts.map +1 -1
  209. package/build-types/border-box-control/border-box-control-split-controls/component.d.ts +1 -1
  210. package/build-types/border-box-control/border-box-control-split-controls/component.d.ts.map +1 -1
  211. package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts +0 -1
  212. package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts.map +1 -1
  213. package/build-types/border-box-control/stories/index.d.ts +1 -1
  214. package/build-types/border-control/border-control/component.d.ts +1 -1
  215. package/build-types/border-control/border-control/component.d.ts.map +1 -1
  216. package/build-types/border-control/border-control/hook.d.ts +0 -1
  217. package/build-types/border-control/border-control/hook.d.ts.map +1 -1
  218. package/build-types/border-control/border-control-dropdown/component.d.ts +1 -1
  219. package/build-types/border-control/border-control-dropdown/component.d.ts.map +1 -1
  220. package/build-types/border-control/border-control-dropdown/hook.d.ts +0 -1
  221. package/build-types/border-control/border-control-dropdown/hook.d.ts.map +1 -1
  222. package/build-types/border-control/stories/index.d.ts +6 -6
  223. package/build-types/border-control/stories/index.d.ts.map +1 -1
  224. package/build-types/border-control/types.d.ts +1 -1
  225. package/build-types/border-control/types.d.ts.map +1 -1
  226. package/build-types/color-palette/index.d.ts +2 -3
  227. package/build-types/color-palette/index.d.ts.map +1 -1
  228. package/build-types/color-palette/stories/index.d.ts +2 -9
  229. package/build-types/color-palette/stories/index.d.ts.map +1 -1
  230. package/build-types/color-palette/types.d.ts +3 -16
  231. package/build-types/color-palette/types.d.ts.map +1 -1
  232. package/build-types/color-picker/component.d.ts.map +1 -1
  233. package/build-types/color-picker/styles.d.ts.map +1 -1
  234. package/build-types/dashicon/types.d.ts +0 -4
  235. package/build-types/dashicon/types.d.ts.map +1 -1
  236. package/build-types/disabled/stories/index.d.ts.map +1 -1
  237. package/build-types/dropdown/index.d.ts +29 -1
  238. package/build-types/dropdown/index.d.ts.map +1 -1
  239. package/build-types/dropdown/stories/index.d.ts +23 -0
  240. package/build-types/dropdown/stories/index.d.ts.map +1 -0
  241. package/build-types/dropdown/test/index.d.ts +2 -0
  242. package/build-types/dropdown/test/index.d.ts.map +1 -0
  243. package/build-types/dropdown/types.d.ts +101 -0
  244. package/build-types/dropdown/types.d.ts.map +1 -1
  245. package/build-types/focal-point-picker/utils.d.ts.map +1 -1
  246. package/build-types/icon/stories/index.d.ts +22 -0
  247. package/build-types/icon/stories/index.d.ts.map +1 -0
  248. package/build-types/item-group/item/component.d.ts +24 -2
  249. package/build-types/item-group/item/component.d.ts.map +1 -1
  250. package/build-types/item-group/item-group/component.d.ts +23 -2
  251. package/build-types/item-group/item-group/component.d.ts.map +1 -1
  252. package/build-types/item-group/stories/index.d.ts +15 -0
  253. package/build-types/item-group/stories/index.d.ts.map +1 -0
  254. package/build-types/item-group/styles.d.ts.map +1 -1
  255. package/build-types/radio-context/index.d.ts +6 -0
  256. package/build-types/radio-context/index.d.ts.map +1 -0
  257. package/build-types/resizable-box/index.d.ts +6 -7
  258. package/build-types/resizable-box/index.d.ts.map +1 -1
  259. package/build-types/resizable-box/stories/index.d.ts +61 -0
  260. package/build-types/resizable-box/stories/index.d.ts.map +1 -0
  261. package/build-types/responsive-wrapper/index.d.ts +24 -0
  262. package/build-types/responsive-wrapper/index.d.ts.map +1 -0
  263. package/build-types/responsive-wrapper/stories/index.d.ts +12 -0
  264. package/build-types/responsive-wrapper/stories/index.d.ts.map +1 -0
  265. package/build-types/responsive-wrapper/types.d.ts +22 -0
  266. package/build-types/responsive-wrapper/types.d.ts.map +1 -0
  267. package/build-types/sandbox/index.d.ts +19 -0
  268. package/build-types/sandbox/index.d.ts.map +1 -0
  269. package/build-types/sandbox/stories/index.d.ts +12 -0
  270. package/build-types/sandbox/stories/index.d.ts.map +1 -0
  271. package/build-types/sandbox/test/index.d.ts +2 -0
  272. package/build-types/sandbox/test/index.d.ts.map +1 -0
  273. package/build-types/sandbox/types.d.ts +36 -0
  274. package/build-types/sandbox/types.d.ts.map +1 -0
  275. package/build-types/tab-panel/index.d.ts.map +1 -1
  276. package/build-types/tab-panel/stories/index.d.ts +1 -0
  277. package/build-types/tab-panel/stories/index.d.ts.map +1 -1
  278. package/build-types/tab-panel/types.d.ts +10 -4
  279. package/build-types/tab-panel/types.d.ts.map +1 -1
  280. package/package.json +17 -17
  281. package/src/autocomplete/index.js +1 -3
  282. package/src/autocomplete/test/index.js +2 -0
  283. package/src/base-control/test/index.tsx +1 -0
  284. package/src/border-box-control/border-box-control/component.tsx +0 -7
  285. package/src/border-box-control/border-box-control/hook.ts +0 -2
  286. package/src/border-box-control/border-box-control-split-controls/component.tsx +0 -2
  287. package/src/border-box-control/border-box-control-split-controls/hook.ts +0 -2
  288. package/src/border-box-control/test/index.js +2 -0
  289. package/src/border-control/border-control/component.tsx +0 -4
  290. package/src/border-control/border-control/hook.ts +0 -2
  291. package/src/border-control/border-control-dropdown/component.tsx +11 -17
  292. package/src/border-control/border-control-dropdown/hook.ts +0 -2
  293. package/src/border-control/stories/index.tsx +0 -1
  294. package/src/border-control/test/index.js +70 -67
  295. package/src/border-control/types.ts +1 -4
  296. package/src/box-control/test/index.js +2 -0
  297. package/src/checkbox-control/test/index.tsx +2 -0
  298. package/src/color-palette/index.tsx +12 -12
  299. package/src/color-palette/stories/index.tsx +0 -13
  300. package/src/color-palette/test/index.tsx +2 -0
  301. package/src/color-palette/types.ts +3 -17
  302. package/src/color-picker/component.tsx +1 -0
  303. package/src/color-picker/stories/index.js +20 -60
  304. package/src/color-picker/styles.ts +0 -5
  305. package/src/color-picker/test/index.js +2 -0
  306. package/src/combobox-control/index.js +9 -1
  307. package/src/combobox-control/test/index.js +2 -0
  308. package/src/confirm-dialog/test/index.js +2 -0
  309. package/src/dashicon/types.ts +0 -6
  310. package/src/date-time/date/test/index.tsx +2 -0
  311. package/src/date-time/time/test/index.tsx +2 -0
  312. package/src/dimension-control/index.js +2 -3
  313. package/src/dimension-control/test/index.test.js +2 -0
  314. package/src/disabled/stories/index.tsx +6 -2
  315. package/src/disabled/test/index.tsx +2 -0
  316. package/src/dropdown/README.md +41 -46
  317. package/src/dropdown/{index.js → index.tsx} +57 -13
  318. package/src/dropdown/stories/{index.js → index.tsx} +21 -8
  319. package/src/dropdown/test/{index.js → index.tsx} +9 -9
  320. package/src/dropdown/types.ts +107 -0
  321. package/src/dropdown-menu/README.md +2 -3
  322. package/src/dropdown-menu/test/index.js +2 -0
  323. package/src/external-link/test/index.tsx +2 -0
  324. package/src/focal-point-picker/stories/index.tsx +1 -1
  325. package/src/focal-point-picker/test/index.js +2 -0
  326. package/src/focal-point-picker/utils.ts +4 -1
  327. package/src/font-size-picker/test/index.tsx +2 -0
  328. package/src/form-file-upload/test/index.tsx +2 -0
  329. package/src/form-toggle/test/index.tsx +2 -0
  330. package/src/form-token-field/test/index.tsx +3 -0
  331. package/src/gradient-picker/index.js +1 -2
  332. package/src/gradient-picker/stories/index.js +0 -1
  333. package/src/guide/stories/index.js +14 -41
  334. package/src/guide/test/index.js +2 -0
  335. package/src/higher-order/navigate-regions/index.js +5 -2
  336. package/src/higher-order/navigate-regions/style.scss +13 -39
  337. package/src/higher-order/with-filters/test/index.js +70 -74
  338. package/src/higher-order/with-focus-outside/test/index.js +2 -0
  339. package/src/higher-order/with-focus-return/test/index.js +2 -0
  340. package/src/higher-order/with-notices/test/index.js +1 -0
  341. package/src/icon/stories/index.tsx +103 -0
  342. package/src/index.js +8 -7
  343. package/src/index.native.js +8 -6
  344. package/src/input-control/test/index.js +3 -0
  345. package/src/isolated-event-container/test/index.js +2 -0
  346. package/src/item-group/item/component.tsx +26 -2
  347. package/src/item-group/item-group/component.tsx +25 -2
  348. package/src/item-group/stories/index.tsx +103 -0
  349. package/src/item-group/styles.ts +1 -0
  350. package/src/item-group/test/__snapshots__/index.js.snap +11 -10
  351. package/src/mobile/bottom-sheet/picker-cell.native.js +1 -6
  352. package/src/mobile/global-styles-context/utils.native.js +17 -16
  353. package/src/modal/test/index.tsx +1 -3
  354. package/src/navigable-container/test/navigable-menu.js +2 -0
  355. package/src/navigable-container/test/tababble-container.js +2 -0
  356. package/src/navigation/test/index.js +2 -0
  357. package/src/navigator/test/index.tsx +2 -0
  358. package/src/notice/stories/index.js +30 -58
  359. package/src/notice/test/index.js +8 -3
  360. package/src/number-control/test/index.tsx +2 -0
  361. package/src/panel/row.js +3 -3
  362. package/src/panel/stories/index.js +62 -80
  363. package/src/panel/test/__snapshots__/body.js.snap +9 -0
  364. package/src/panel/test/body.js +71 -62
  365. package/src/placeholder/style.scss +1 -1
  366. package/src/placeholder/test/index.tsx +3 -0
  367. package/src/query-controls/index.js +1 -0
  368. package/src/resizable-box/README.md +2 -2
  369. package/src/resizable-box/index.tsx +7 -6
  370. package/src/resizable-box/stories/index.tsx +92 -0
  371. package/src/responsive-wrapper/README.md +29 -0
  372. package/src/responsive-wrapper/{index.js → index.tsx} +23 -2
  373. package/src/responsive-wrapper/stories/index.tsx +38 -0
  374. package/src/responsive-wrapper/types.ts +20 -0
  375. package/src/sandbox/README.md +45 -2
  376. package/src/sandbox/{index.js → index.tsx} +47 -24
  377. package/src/sandbox/stories/index.tsx +32 -0
  378. package/src/sandbox/test/{index.js → index.tsx} +9 -4
  379. package/src/sandbox/types.ts +34 -0
  380. package/src/select-control/test/select-control.tsx +2 -0
  381. package/src/slot-fill/stories/index.js +12 -17
  382. package/src/style.scss +3 -3
  383. package/src/tab-panel/README.md +1 -0
  384. package/src/tab-panel/index.tsx +20 -7
  385. package/src/tab-panel/stories/index.tsx +20 -0
  386. package/src/tab-panel/test/index.tsx +91 -0
  387. package/src/tab-panel/types.ts +10 -4
  388. package/src/text-highlight/test/index.tsx +1 -0
  389. package/src/toggle-group-control/test/index.tsx +2 -0
  390. package/src/toolbar/index.js +6 -52
  391. package/src/toolbar/stories/index.js +2 -9
  392. package/src/{toolbar-button/stories/index.js → toolbar/stories/toolbar-button.js} +1 -2
  393. package/src/{toolbar-group/stories/index.js → toolbar/stories/toolbar-group.js} +1 -1
  394. package/src/toolbar/test/index.js +1 -2
  395. package/src/{toolbar-group/test/index.js → toolbar/test/toolbar-group.js} +3 -1
  396. package/src/toolbar/{README.md → toolbar/README.md} +0 -0
  397. package/src/toolbar/toolbar/index.js +52 -0
  398. package/src/toolbar/{style.native.scss → toolbar/style.native.scss} +0 -0
  399. package/src/toolbar/{style.scss → toolbar/style.scss} +1 -1
  400. package/src/toolbar/{toolbar-container.js → toolbar/toolbar-container.js} +0 -0
  401. package/src/toolbar/{toolbar-container.native.js → toolbar/toolbar-container.native.js} +0 -0
  402. package/src/{toolbar-button → toolbar/toolbar-button}/README.md +0 -0
  403. package/src/{toolbar-button → toolbar/toolbar-button}/index.js +1 -1
  404. package/src/{toolbar-button → toolbar/toolbar-button}/style.scss +0 -0
  405. package/src/{toolbar-button → toolbar/toolbar-button}/toolbar-button-container.js +0 -0
  406. package/src/{toolbar-button → toolbar/toolbar-button}/toolbar-button-container.native.js +0 -0
  407. package/src/{toolbar-context → toolbar/toolbar-context}/index.js +0 -0
  408. package/src/{toolbar-dropdown-menu → toolbar/toolbar-dropdown-menu}/README.md +0 -0
  409. package/src/{toolbar-dropdown-menu → toolbar/toolbar-dropdown-menu}/index.js +1 -1
  410. package/src/{toolbar-group → toolbar/toolbar-group}/README.md +0 -0
  411. package/src/{toolbar-group → toolbar/toolbar-group}/index.js +0 -0
  412. package/src/{toolbar-group → toolbar/toolbar-group}/style.native.scss +0 -0
  413. package/src/{toolbar-group → toolbar/toolbar-group}/style.scss +0 -0
  414. package/src/{toolbar-group → toolbar/toolbar-group}/toolbar-group-collapsed.js +1 -1
  415. package/src/{toolbar-group → toolbar/toolbar-group}/toolbar-group-collapsed.native.js +1 -1
  416. package/src/{toolbar-group → toolbar/toolbar-group}/toolbar-group-container.js +0 -0
  417. package/src/{toolbar-group → toolbar/toolbar-group}/toolbar-group-container.native.js +0 -0
  418. package/src/{toolbar-item → toolbar/toolbar-item}/README.md +0 -0
  419. package/src/{toolbar-item → toolbar/toolbar-item}/index.js +0 -0
  420. package/src/{toolbar-item → toolbar/toolbar-item}/index.native.js +0 -0
  421. package/src/tooltip/stories/index.js +68 -78
  422. package/src/tooltip/test/index.js +2 -0
  423. package/src/tree-grid/index.js +2 -4
  424. package/src/unit-control/test/index.tsx +3 -0
  425. package/src/utils/hooks/test/use-latest-ref.js +2 -0
  426. package/tsconfig.json +0 -7
  427. package/tsconfig.tsbuildinfo +1 -1
  428. package/build/toolbar/toolbar-container.native.js.map +0 -1
  429. package/build/toolbar-button/index.js.map +0 -1
  430. package/build/toolbar-button/toolbar-button-container.js.map +0 -1
  431. package/build/toolbar-button/toolbar-button-container.native.js.map +0 -1
  432. package/build/toolbar-context/index.js.map +0 -1
  433. package/build/toolbar-dropdown-menu/index.js.map +0 -1
  434. package/build/toolbar-group/index.js.map +0 -1
  435. package/build/toolbar-group/toolbar-group-collapsed.js.map +0 -1
  436. package/build/toolbar-group/toolbar-group-collapsed.native.js.map +0 -1
  437. package/build/toolbar-group/toolbar-group-container.js.map +0 -1
  438. package/build/toolbar-group/toolbar-group-container.native.js.map +0 -1
  439. package/build/toolbar-item/index.js.map +0 -1
  440. package/build/toolbar-item/index.native.js.map +0 -1
  441. package/build-module/toolbar/toolbar-container.js.map +0 -1
  442. package/build-module/toolbar/toolbar-container.native.js.map +0 -1
  443. package/build-module/toolbar-button/index.js.map +0 -1
  444. package/build-module/toolbar-button/toolbar-button-container.js.map +0 -1
  445. package/build-module/toolbar-button/toolbar-button-container.native.js.map +0 -1
  446. package/build-module/toolbar-context/index.js.map +0 -1
  447. package/build-module/toolbar-dropdown-menu/index.js.map +0 -1
  448. package/build-module/toolbar-group/index.js.map +0 -1
  449. package/build-module/toolbar-group/toolbar-group-collapsed.js.map +0 -1
  450. package/build-module/toolbar-group/toolbar-group-collapsed.native.js.map +0 -1
  451. package/build-module/toolbar-group/toolbar-group-container.js.map +0 -1
  452. package/build-module/toolbar-group/toolbar-group-container.native.js.map +0 -1
  453. package/build-module/toolbar-item/index.js.map +0 -1
  454. package/build-module/toolbar-item/index.native.js.map +0 -1
  455. package/src/icon/stories/index.js +0 -128
  456. package/src/item-group/stories/index.js +0 -270
  457. package/src/resizable-box/stories/index.js +0 -97
@@ -9,6 +9,11 @@ import {
9
9
  } from '@wordpress/element';
10
10
  import { useFocusableIframe, useMergeRefs } from '@wordpress/compose';
11
11
 
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import type { SandBoxProps } from './types';
16
+
12
17
  const observeAndResizeJS = function () {
13
18
  const { MutationObserver } = window;
14
19
 
@@ -44,11 +49,11 @@ const observeAndResizeJS = function () {
44
49
  // Hack: Remove viewport unit styles, as these are relative
45
50
  // the iframe root and interfere with our mechanism for
46
51
  // determining the unconstrained page bounds.
47
- function removeViewportStyles( ruleOrNode ) {
52
+ function removeViewportStyles( ruleOrNode: ElementCSSInlineStyle ) {
48
53
  if ( ruleOrNode.style ) {
49
- [ 'width', 'height', 'minHeight', 'maxHeight' ].forEach( function (
50
- style
51
- ) {
54
+ (
55
+ [ 'width', 'height', 'minHeight', 'maxHeight' ] as const
56
+ ).forEach( function ( style ) {
52
57
  if (
53
58
  /^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] )
54
59
  ) {
@@ -83,6 +88,7 @@ const observeAndResizeJS = function () {
83
88
  window.addEventListener( 'resize', sendResize, true );
84
89
  };
85
90
 
91
+ // TODO: These styles shouldn't be coupled with WordPress.
86
92
  const style = `
87
93
  body {
88
94
  margin: 0;
@@ -106,37 +112,53 @@ const style = `
106
112
  }
107
113
  `;
108
114
 
109
- export default function Sandbox( {
115
+ /**
116
+ * This component provides an isolated environment for arbitrary HTML via iframes.
117
+ *
118
+ * ```jsx
119
+ * import { SandBox } from '@wordpress/components';
120
+ *
121
+ * const MySandBox = () => (
122
+ * <SandBox html="<p>Content</p>" title="SandBox" type="embed" />
123
+ * );
124
+ * ```
125
+ */
126
+ function SandBox( {
110
127
  html = '',
111
128
  title = '',
112
129
  type,
113
130
  styles = [],
114
131
  scripts = [],
115
132
  onFocus,
116
- } ) {
117
- const ref = useRef();
133
+ }: SandBoxProps ) {
134
+ const ref = useRef< HTMLIFrameElement >();
118
135
  const [ width, setWidth ] = useState( 0 );
119
136
  const [ height, setHeight ] = useState( 0 );
120
137
 
121
138
  function isFrameAccessible() {
122
139
  try {
123
- return !! ref.current.contentDocument.body;
140
+ return !! ref.current?.contentDocument?.body;
124
141
  } catch ( e ) {
125
142
  return false;
126
143
  }
127
144
  }
128
145
 
129
- function trySandbox( forceRerender = false ) {
146
+ function trySandBox( forceRerender = false ) {
130
147
  if ( ! isFrameAccessible() ) {
131
148
  return;
132
149
  }
133
150
 
134
- const { contentDocument, ownerDocument } = ref.current;
135
- const { body } = contentDocument;
151
+ const { contentDocument, ownerDocument } =
152
+ ref.current as HTMLIFrameElement & {
153
+ contentDocument: Document;
154
+ };
136
155
 
137
156
  if (
138
157
  ! forceRerender &&
139
- null !== body.getAttribute( 'data-resizable-iframe-connected' )
158
+ null !==
159
+ contentDocument?.body.getAttribute(
160
+ 'data-resizable-iframe-connected'
161
+ )
140
162
  ) {
141
163
  return;
142
164
  }
@@ -187,13 +209,13 @@ export default function Sandbox( {
187
209
  }
188
210
 
189
211
  useEffect( () => {
190
- trySandbox();
212
+ trySandBox();
191
213
 
192
- function tryNoForceSandbox() {
193
- trySandbox( false );
214
+ function tryNoForceSandBox() {
215
+ trySandBox( false );
194
216
  }
195
217
 
196
- function checkMessageForResize( event ) {
218
+ function checkMessageForResize( event: MessageEvent ) {
197
219
  const iframe = ref.current;
198
220
 
199
221
  // Verify that the mounted element is the source of the message.
@@ -221,19 +243,18 @@ export default function Sandbox( {
221
243
  }
222
244
 
223
245
  const iframe = ref.current;
224
- const { ownerDocument } = iframe;
225
- const { defaultView } = ownerDocument;
246
+ const defaultView = iframe?.ownerDocument?.defaultView;
226
247
 
227
248
  // This used to be registered using <iframe onLoad={} />, but it made the iframe blank
228
249
  // after reordering the containing block. See these two issues for more details:
229
250
  // https://github.com/WordPress/gutenberg/issues/6146
230
251
  // https://github.com/facebook/react/issues/18752
231
- iframe.addEventListener( 'load', tryNoForceSandbox, false );
232
- defaultView.addEventListener( 'message', checkMessageForResize );
252
+ iframe?.addEventListener( 'load', tryNoForceSandBox, false );
253
+ defaultView?.addEventListener( 'message', checkMessageForResize );
233
254
 
234
255
  return () => {
235
- iframe?.removeEventListener( 'load', tryNoForceSandbox, false );
236
- defaultView.addEventListener( 'message', checkMessageForResize );
256
+ iframe?.removeEventListener( 'load', tryNoForceSandBox, false );
257
+ defaultView?.addEventListener( 'message', checkMessageForResize );
237
258
  };
238
259
  // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor.
239
260
  // See https://github.com/WordPress/gutenberg/pull/44378
@@ -241,14 +262,14 @@ export default function Sandbox( {
241
262
  }, [] );
242
263
 
243
264
  useEffect( () => {
244
- trySandbox();
265
+ trySandBox();
245
266
  // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor.
246
267
  // See https://github.com/WordPress/gutenberg/pull/44378
247
268
  // eslint-disable-next-line react-hooks/exhaustive-deps
248
269
  }, [ title, styles, scripts ] );
249
270
 
250
271
  useEffect( () => {
251
- trySandbox( true );
272
+ trySandBox( true );
252
273
  // Ignore reason: passing `exhaustive-deps` will likely involve a more detailed refactor.
253
274
  // See https://github.com/WordPress/gutenberg/pull/44378
254
275
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -266,3 +287,5 @@ export default function Sandbox( {
266
287
  />
267
288
  );
268
289
  }
290
+
291
+ export default SandBox;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { ComponentMeta, ComponentStory } from '@storybook/react';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import SandBox from '..';
10
+
11
+ const meta: ComponentMeta< typeof SandBox > = {
12
+ component: SandBox,
13
+ title: 'Components/SandBox',
14
+ argTypes: {
15
+ onFocus: { control: { type: null } },
16
+ },
17
+ parameters: {
18
+ actions: { argTypesRegex: '^on.*' },
19
+ controls: { expanded: true },
20
+ docs: { source: { state: 'open' } },
21
+ },
22
+ };
23
+ export default meta;
24
+
25
+ const Template: ComponentStory< typeof SandBox > = ( args ) => (
26
+ <SandBox { ...args } />
27
+ );
28
+
29
+ export const Default = Template.bind( {} );
30
+ Default.args = {
31
+ html: '<p>Arbitrary HTML content</p>',
32
+ };
@@ -11,9 +11,9 @@ import { useState } from '@wordpress/element';
11
11
  /**
12
12
  * Internal dependencies
13
13
  */
14
- import Sandbox from '../';
14
+ import SandBox from '..';
15
15
 
16
- describe( 'Sandbox', () => {
16
+ describe( 'SandBox', () => {
17
17
  const TestWrapper = () => {
18
18
  const [ html, setHtml ] = useState(
19
19
  // MutationObserver implementation from JSDom does not work as intended
@@ -33,7 +33,7 @@ describe( 'Sandbox', () => {
33
33
  <button onClick={ updateHtml } className="mock-button">
34
34
  Mock Button
35
35
  </button>
36
- <Sandbox html={ html } title="Sandbox Title" />
36
+ <SandBox html={ html } title="SandBox Title" />
37
37
  </div>
38
38
  );
39
39
  };
@@ -41,7 +41,12 @@ describe( 'Sandbox', () => {
41
41
  it( 'should rerender with new emdeded content if html prop changes', () => {
42
42
  render( <TestWrapper /> );
43
43
 
44
- const iframe = screen.getByTitle( 'Sandbox Title' );
44
+ const iframe =
45
+ screen.getByTitle< HTMLIFrameElement >( 'SandBox Title' );
46
+
47
+ if ( ! iframe.contentWindow ) {
48
+ throw new Error();
49
+ }
45
50
 
46
51
  let sandboxedIframe = within(
47
52
  iframe.contentWindow.document.body
@@ -0,0 +1,34 @@
1
+ export type SandBoxProps = {
2
+ /**
3
+ * The HTML to render in the body of the iframe document.
4
+ *
5
+ * @default ''
6
+ */
7
+ html?: string;
8
+ /**
9
+ * The `<title>` of the iframe document.
10
+ *
11
+ * @default ''
12
+ */
13
+ title?: string;
14
+ /**
15
+ * The CSS class name to apply to the `<html>` and `<body>` elements of the iframe.
16
+ */
17
+ type?: string;
18
+ /**
19
+ * An array of CSS strings to inject into the `<head>` of the iframe document.
20
+ *
21
+ * @default []
22
+ */
23
+ styles?: string[];
24
+ /**
25
+ * An array of script URLs to inject as `<script>` tags into the bottom of the `<body>` of the iframe document.
26
+ *
27
+ * @default []
28
+ */
29
+ scripts?: string[];
30
+ /**
31
+ * The `onFocus` callback for the iframe.
32
+ */
33
+ onFocus?: React.DOMAttributes< HTMLIFrameElement >[ 'onFocus' ];
34
+ };
@@ -9,6 +9,8 @@ import userEvent from '@testing-library/user-event';
9
9
  */
10
10
  import SelectControl from '..';
11
11
 
12
+ jest.useFakeTimers();
13
+
12
14
  const setupUser = () =>
13
15
  userEvent.setup( {
14
16
  advanceTimers: jest.advanceTimersByTime,
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { text, number } from '@storybook/addon-knobs';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -11,19 +6,21 @@ import { createContext, useContext } from '@wordpress/element';
11
6
  /**
12
7
  * Internal dependencies
13
8
  */
14
- import { Slot, Fill, Provider } from '../';
9
+ import { Slot, Fill, Provider as SlotFillProvider } from '../';
15
10
 
16
11
  export default {
17
12
  title: 'Components/SlotFill',
13
+ subcomponents: { Fill, SlotFillProvider },
18
14
  component: Slot,
19
15
  parameters: {
20
- knobs: { disable: false },
16
+ controls: { expanded: true },
17
+ docs: { source: { state: 'open' } },
21
18
  },
22
19
  };
23
20
 
24
21
  export const _default = () => {
25
22
  return (
26
- <Provider>
23
+ <SlotFillProvider>
27
24
  <h2>Profile</h2>
28
25
  <p>
29
26
  Name: <Slot bubblesVirtually as="span" name="name" />
@@ -33,15 +30,13 @@ export const _default = () => {
33
30
  </p>
34
31
  <Fill name="name">Grace</Fill>
35
32
  <Fill name="age">33</Fill>
36
- </Provider>
33
+ </SlotFillProvider>
37
34
  );
38
35
  };
39
36
 
40
37
  export const withFillProps = () => {
41
- const name = text( 'name', 'Grace' );
42
- const age = number( 'age', 33 );
43
38
  return (
44
- <Provider>
39
+ <SlotFillProvider>
45
40
  <h2>Profile</h2>
46
41
  <p>
47
42
  Name:{ ' ' }
@@ -49,7 +44,7 @@ export const withFillProps = () => {
49
44
  bubblesVirtually
50
45
  as="span"
51
46
  name="name"
52
- fillProps={ { name } }
47
+ fillProps={ { name: 'Grace' } }
53
48
  />
54
49
  </p>
55
50
  <p>
@@ -58,12 +53,12 @@ export const withFillProps = () => {
58
53
  bubblesVirtually
59
54
  as="span"
60
55
  name="age"
61
- fillProps={ { age } }
56
+ fillProps={ { age: 33 } }
62
57
  />
63
58
  </p>
64
59
  <Fill name="name">{ ( fillProps ) => fillProps.name }</Fill>
65
60
  <Fill name="age">{ ( fillProps ) => fillProps.age }</Fill>
66
- </Provider>
61
+ </SlotFillProvider>
67
62
  );
68
63
  };
69
64
 
@@ -74,7 +69,7 @@ export const withContext = () => {
74
69
  return <Fill name={ name }>{ value }</Fill>;
75
70
  };
76
71
  return (
77
- <Provider>
72
+ <SlotFillProvider>
78
73
  <h2>Profile</h2>
79
74
  <p>
80
75
  Name: <Slot bubblesVirtually as="span" name="name" />
@@ -88,6 +83,6 @@ export const withContext = () => {
88
83
  <Context.Provider value={ 33 }>
89
84
  <ContextFill name="age" />
90
85
  </Context.Provider>
91
- </Provider>
86
+ </SlotFillProvider>
92
87
  );
93
88
  };
package/src/style.scss CHANGED
@@ -44,7 +44,7 @@
44
44
  @import "./tab-panel/style.scss";
45
45
  @import "./text-control/style.scss";
46
46
  @import "./tip/style.scss";
47
- @import "./toolbar/style.scss";
48
- @import "./toolbar-button/style.scss";
49
- @import "./toolbar-group/style.scss";
47
+ @import "./toolbar/toolbar/style.scss";
48
+ @import "./toolbar/toolbar-button/style.scss";
49
+ @import "./toolbar/toolbar-group/style.scss";
50
50
  @import "./tooltip/style.scss";
@@ -121,6 +121,7 @@ An array of objects containing the following properties:
121
121
  - `title`:`(string)` Defines the translated text for the tab.
122
122
  - `className`:`(string)` Optional. Defines the class to put on the tab.
123
123
  - `icon`:`(ReactNode)` Optional. When set, displays the icon in place of the tab title. The title is then rendered as an aria-label and tooltip.
124
+ - `disabled`:`(boolean)` Optional. Determines if the tab should be disabled or selectable.
124
125
 
125
126
  > > **Note:** Other fields may be added to the object and accessed from the child function if desired.
126
127
 
@@ -2,7 +2,6 @@
2
2
  * External dependencies
3
3
  */
4
4
  import classnames from 'classnames';
5
- import { find } from 'lodash';
6
5
 
7
6
  /**
8
7
  * WordPress dependencies
@@ -20,7 +19,6 @@ import type { WordPressComponentProps } from '../ui/context';
20
19
 
21
20
  const TabButton = ( {
22
21
  tabId,
23
- onClick,
24
22
  children,
25
23
  selected,
26
24
  ...rest
@@ -30,7 +28,7 @@ const TabButton = ( {
30
28
  tabIndex={ selected ? null : -1 }
31
29
  aria-selected={ selected }
32
30
  id={ tabId }
33
- onClick={ onClick }
31
+ __experimentalIsFocusable
34
32
  { ...rest }
35
33
  >
36
34
  { children }
@@ -102,14 +100,28 @@ export function TabPanel( {
102
100
  ) => {
103
101
  child.click();
104
102
  };
105
- const selectedTab = find( tabs, { name: selected } );
103
+ const selectedTab = tabs.find( ( { name } ) => name === selected );
106
104
  const selectedId = `${ instanceId }-${ selectedTab?.name ?? 'none' }`;
107
105
 
108
106
  useEffect( () => {
109
- if ( ! selectedTab?.name && tabs.length > 0 ) {
110
- handleTabSelection( initialTabName || tabs[ 0 ].name );
107
+ const firstEnabledTab = tabs.find( ( tab ) => ! tab.disabled );
108
+ const initialTab = tabs.find( ( tab ) => tab.name === initialTabName );
109
+ if ( ! selectedTab?.name && firstEnabledTab ) {
110
+ handleTabSelection(
111
+ initialTab && ! initialTab.disabled
112
+ ? initialTab.name
113
+ : firstEnabledTab.name
114
+ );
115
+ } else if ( selectedTab?.disabled && firstEnabledTab ) {
116
+ handleTabSelection( firstEnabledTab.name );
111
117
  }
112
- }, [ tabs, selectedTab?.name, initialTabName, handleTabSelection ] );
118
+ }, [
119
+ tabs,
120
+ selectedTab?.name,
121
+ selectedTab?.disabled,
122
+ initialTabName,
123
+ handleTabSelection,
124
+ ] );
113
125
 
114
126
  return (
115
127
  <div className={ className }>
@@ -135,6 +147,7 @@ export function TabPanel( {
135
147
  selected={ tab.name === selected }
136
148
  key={ tab.name }
137
149
  onClick={ () => handleTabSelection( tab.name ) }
150
+ disabled={ tab.disabled }
138
151
  label={ tab.icon && tab.title }
139
152
  icon={ tab.icon }
140
153
  showTooltip={ !! tab.icon }
@@ -35,3 +35,23 @@ Default.args = {
35
35
  },
36
36
  ],
37
37
  };
38
+
39
+ export const DisabledTab = Template.bind( {} );
40
+ DisabledTab.args = {
41
+ children: ( tab ) => <p>Selected tab: { tab.title }</p>,
42
+ tabs: [
43
+ {
44
+ name: 'tab1',
45
+ title: 'Tab 1',
46
+ disabled: true,
47
+ },
48
+ {
49
+ name: 'tab2',
50
+ title: 'Tab 2',
51
+ },
52
+ {
53
+ name: 'tab3',
54
+ title: 'Tab 3',
55
+ },
56
+ ],
57
+ };
@@ -9,6 +9,8 @@ import userEvent from '@testing-library/user-event';
9
9
  */
10
10
  import TabPanel from '..';
11
11
 
12
+ jest.useFakeTimers();
13
+
12
14
  const setupUser = () =>
13
15
  userEvent.setup( {
14
16
  advanceTimers: jest.advanceTimersByTime,
@@ -160,6 +162,95 @@ describe( 'TabPanel', () => {
160
162
  expect( mockOnSelect ).toHaveBeenLastCalledWith( 'beta' );
161
163
  } );
162
164
 
165
+ it( 'should disable the tab when `disabled` is true', async () => {
166
+ const user = setupUser();
167
+ const mockOnSelect = jest.fn();
168
+
169
+ render(
170
+ <TabPanel
171
+ tabs={ [
172
+ ...TABS,
173
+ {
174
+ name: 'delta',
175
+ title: 'Delta',
176
+ className: 'delta-class',
177
+ disabled: true,
178
+ },
179
+ ] }
180
+ children={ () => undefined }
181
+ onSelect={ mockOnSelect }
182
+ />
183
+ );
184
+
185
+ expect( screen.getByRole( 'tab', { name: 'Delta' } ) ).toHaveAttribute(
186
+ 'aria-disabled',
187
+ 'true'
188
+ );
189
+
190
+ // onSelect gets called on the initial render.
191
+ expect( mockOnSelect ).toHaveBeenCalledTimes( 1 );
192
+
193
+ // onSelect should not be called since the disabled tab is highlighted, but not selected.
194
+ await user.keyboard( '[ArrowLeft]' );
195
+ expect( mockOnSelect ).toHaveBeenCalledTimes( 1 );
196
+ } );
197
+
198
+ it( 'should select the first enabled tab when the inital tab is disabled', () => {
199
+ const mockOnSelect = jest.fn();
200
+
201
+ render(
202
+ <TabPanel
203
+ tabs={ [
204
+ {
205
+ name: 'alpha',
206
+ title: 'Alpha',
207
+ className: 'alpha-class',
208
+ disabled: true,
209
+ },
210
+ {
211
+ name: 'beta',
212
+ title: 'Beta',
213
+ className: 'beta-class',
214
+ },
215
+ ] }
216
+ initialTabName="alpha"
217
+ children={ () => undefined }
218
+ onSelect={ mockOnSelect }
219
+ />
220
+ );
221
+
222
+ expect( getSelectedTab() ).toHaveTextContent( 'Beta' );
223
+ } );
224
+
225
+ it( 'should select the first enabled tab when the currently selected becomes disabled', () => {
226
+ const mockOnSelect = jest.fn();
227
+
228
+ const { rerender } = render(
229
+ <TabPanel
230
+ tabs={ TABS }
231
+ children={ () => undefined }
232
+ onSelect={ mockOnSelect }
233
+ />
234
+ );
235
+
236
+ expect( getSelectedTab() ).toHaveTextContent( 'Alpha' );
237
+
238
+ rerender(
239
+ <TabPanel
240
+ tabs={ TABS.map( ( tab ) => {
241
+ if ( tab.name === 'alpha' ) {
242
+ return { ...tab, disabled: true };
243
+ }
244
+ return tab;
245
+ } ) }
246
+ children={ () => undefined }
247
+ onSelect={ mockOnSelect }
248
+ />
249
+ );
250
+
251
+ expect( getSelectedTab() ).toHaveTextContent( 'Beta' );
252
+ } );
253
+
163
254
  describe( 'fallbacks when new tab list invalidates current selection', () => {
164
255
  it( 'should select `initialTabName` if defined', async () => {
165
256
  const user = setupUser();
@@ -8,7 +8,7 @@ import type { ReactNode } from 'react';
8
8
  */
9
9
  import type { IconType } from '../icon';
10
10
 
11
- type Tab = {
11
+ type Tab< IconProps = unknown > = {
12
12
  /**
13
13
  * The key of the tab.
14
14
  */
@@ -21,18 +21,24 @@ type Tab = {
21
21
  * The class name to apply to the tab button.
22
22
  */
23
23
  className?: string;
24
+ /**
25
+ * The icon used for the tab button.
26
+ */
27
+ icon?: IconType< IconProps >;
28
+ /**
29
+ * Determines if the tab button should be disabled.
30
+ */
31
+ disabled?: boolean;
24
32
  } & Record< any, any >;
25
33
 
26
34
  export type TabButtonProps< IconProps = unknown > = {
27
35
  children: ReactNode;
28
- className?: string;
29
- icon?: IconType< IconProps >;
30
36
  label?: string;
31
37
  onClick: ( event: MouseEvent ) => void;
32
38
  selected: boolean;
33
39
  showTooltip?: boolean;
34
40
  tabId: string;
35
- };
41
+ } & Pick< Tab< IconProps >, 'className' | 'icon' | 'disabled' >;
36
42
 
37
43
  export type TabPanelProps = {
38
44
  /**
@@ -11,6 +11,7 @@ import TextHighlight from '..';
11
11
  const getMarks = ( container: Element ) =>
12
12
  // Use querySelectorAll because the `mark` role is not officially supported
13
13
  // yet. This should be changed to `getByRole` when it is.
14
+ // eslint-disable-next-line testing-library/no-node-access
14
15
  Array.from( container.querySelectorAll( 'mark' ) );
15
16
 
16
17
  const defaultText =
@@ -18,6 +18,8 @@ import {
18
18
  ToggleGroupControlOptionIcon,
19
19
  } from '../index';
20
20
 
21
+ jest.useFakeTimers();
22
+
21
23
  function getWrappingPopoverElement( element: HTMLElement ) {
22
24
  return element.closest( '.components-popover' );
23
25
  }