@wordpress/components 23.2.0 → 23.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 (377) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/CONTRIBUTING.md +1 -1
  3. package/build/alignment-matrix-control/utils.js +2 -2
  4. package/build/alignment-matrix-control/utils.js.map +1 -1
  5. package/build/autocomplete/autocompleter-ui.js +1 -3
  6. package/build/autocomplete/autocompleter-ui.js.map +1 -1
  7. package/build/border-box-control/border-box-control-linked-button/component.js.map +1 -1
  8. package/build/border-box-control/border-box-control-linked-button/hook.js.map +1 -1
  9. package/build/border-control/border-control-dropdown/component.js +8 -4
  10. package/build/border-control/border-control-dropdown/component.js.map +1 -1
  11. package/build/button/deprecated.js +8 -6
  12. package/build/button/deprecated.js.map +1 -1
  13. package/build/button/index.js +52 -23
  14. package/build/button/index.js.map +1 -1
  15. package/build/button/types.js +6 -0
  16. package/build/button/types.js.map +1 -0
  17. package/build/color-list-picker/index.js.map +1 -1
  18. package/build/color-list-picker/types.js +6 -0
  19. package/build/color-list-picker/types.js.map +1 -0
  20. package/build/color-palette/index.js +9 -61
  21. package/build/color-palette/index.js.map +1 -1
  22. package/build/color-palette/index.native.js +24 -9
  23. package/build/color-palette/index.native.js.map +1 -1
  24. package/build/color-palette/utils.js +103 -0
  25. package/build/color-palette/utils.js.map +1 -0
  26. package/build/custom-gradient-picker/gradient-bar/utils.js +1 -1
  27. package/build/custom-gradient-picker/gradient-bar/utils.js.map +1 -1
  28. package/build/date-time/date/index.js.map +1 -1
  29. package/build/dropdown/index.js +20 -8
  30. package/build/dropdown/index.js.map +1 -1
  31. package/build/form-token-field/token.js +1 -1
  32. package/build/form-token-field/token.js.map +1 -1
  33. package/build/gradient-picker/index.js +9 -1
  34. package/build/gradient-picker/index.js.map +1 -1
  35. package/build/h-stack/component.js +0 -1
  36. package/build/h-stack/component.js.map +1 -1
  37. package/build/input-control/input-field.js +4 -2
  38. package/build/input-control/input-field.js.map +1 -1
  39. package/build/keyboard-shortcuts/index.js +44 -16
  40. package/build/keyboard-shortcuts/index.js.map +1 -1
  41. package/build/keyboard-shortcuts/types.js +6 -0
  42. package/build/keyboard-shortcuts/types.js.map +1 -0
  43. package/build/modal/index.js +1 -1
  44. package/build/modal/index.js.map +1 -1
  45. package/build/notice/index.js +16 -18
  46. package/build/notice/index.js.map +1 -1
  47. package/build/notice/list.js +23 -8
  48. package/build/notice/list.js.map +1 -1
  49. package/build/notice/types.js +6 -0
  50. package/build/notice/types.js.map +1 -0
  51. package/build/number-control/index.js +1 -1
  52. package/build/number-control/index.js.map +1 -1
  53. package/build/query-controls/author-select.js +7 -3
  54. package/build/query-controls/author-select.js.map +1 -1
  55. package/build/query-controls/category-select.js +7 -3
  56. package/build/query-controls/category-select.js.map +1 -1
  57. package/build/query-controls/index.js +68 -20
  58. package/build/query-controls/index.js.map +1 -1
  59. package/build/query-controls/terms.js +4 -3
  60. package/build/query-controls/terms.js.map +1 -1
  61. package/build/query-controls/types.js +6 -0
  62. package/build/query-controls/types.js.map +1 -0
  63. package/build/slot-fill/bubbles-virtually/fill.js +1 -0
  64. package/build/slot-fill/bubbles-virtually/fill.js.map +1 -1
  65. package/build/slot-fill/slot.js +1 -0
  66. package/build/slot-fill/slot.js.map +1 -1
  67. package/build/slot-fill/use-slot.js +1 -11
  68. package/build/slot-fill/use-slot.js.map +1 -1
  69. package/build/snackbar/index.js.map +1 -1
  70. package/build/snackbar/list.js.map +1 -1
  71. package/build/tab-panel/index.js +36 -8
  72. package/build/tab-panel/index.js.map +1 -1
  73. package/build/tree-grid/index.js +1 -1
  74. package/build/tree-grid/index.js.map +1 -1
  75. package/build/tree-select/index.js +2 -6
  76. package/build/tree-select/index.js.map +1 -1
  77. package/build-module/alignment-matrix-control/utils.js +2 -2
  78. package/build-module/alignment-matrix-control/utils.js.map +1 -1
  79. package/build-module/autocomplete/autocompleter-ui.js +1 -2
  80. package/build-module/autocomplete/autocompleter-ui.js.map +1 -1
  81. package/build-module/border-box-control/border-box-control-linked-button/component.js.map +1 -1
  82. package/build-module/border-box-control/border-box-control-linked-button/hook.js.map +1 -1
  83. package/build-module/border-control/border-control-dropdown/component.js +7 -4
  84. package/build-module/border-control/border-control-dropdown/component.js.map +1 -1
  85. package/build-module/button/deprecated.js +8 -5
  86. package/build-module/button/deprecated.js.map +1 -1
  87. package/build-module/button/index.js +51 -22
  88. package/build-module/button/index.js.map +1 -1
  89. package/build-module/button/types.js +2 -0
  90. package/build-module/button/types.js.map +1 -0
  91. package/build-module/color-list-picker/index.js.map +1 -1
  92. package/build-module/color-list-picker/types.js +2 -0
  93. package/build-module/color-list-picker/types.js.map +1 -0
  94. package/build-module/color-palette/index.js +7 -54
  95. package/build-module/color-palette/index.js.map +1 -1
  96. package/build-module/color-palette/index.native.js +24 -8
  97. package/build-module/color-palette/index.native.js.map +1 -1
  98. package/build-module/color-palette/utils.js +79 -0
  99. package/build-module/color-palette/utils.js.map +1 -0
  100. package/build-module/custom-gradient-picker/gradient-bar/utils.js +1 -1
  101. package/build-module/custom-gradient-picker/gradient-bar/utils.js.map +1 -1
  102. package/build-module/date-time/date/index.js +1 -1
  103. package/build-module/date-time/date/index.js.map +1 -1
  104. package/build-module/dropdown/index.js +19 -8
  105. package/build-module/dropdown/index.js.map +1 -1
  106. package/build-module/form-token-field/token.js +1 -1
  107. package/build-module/form-token-field/token.js.map +1 -1
  108. package/build-module/gradient-picker/index.js +9 -2
  109. package/build-module/gradient-picker/index.js.map +1 -1
  110. package/build-module/h-stack/component.js +0 -1
  111. package/build-module/h-stack/component.js.map +1 -1
  112. package/build-module/input-control/input-field.js +4 -2
  113. package/build-module/input-control/input-field.js.map +1 -1
  114. package/build-module/keyboard-shortcuts/index.js +48 -16
  115. package/build-module/keyboard-shortcuts/index.js.map +1 -1
  116. package/build-module/keyboard-shortcuts/types.js +2 -0
  117. package/build-module/keyboard-shortcuts/types.js.map +1 -0
  118. package/build-module/modal/index.js +1 -1
  119. package/build-module/modal/index.js.map +1 -1
  120. package/build-module/notice/index.js +14 -15
  121. package/build-module/notice/index.js.map +1 -1
  122. package/build-module/notice/list.js +23 -8
  123. package/build-module/notice/list.js.map +1 -1
  124. package/build-module/notice/types.js +2 -0
  125. package/build-module/notice/types.js.map +1 -0
  126. package/build-module/number-control/index.js +1 -1
  127. package/build-module/number-control/index.js.map +1 -1
  128. package/build-module/query-controls/author-select.js +7 -3
  129. package/build-module/query-controls/author-select.js.map +1 -1
  130. package/build-module/query-controls/category-select.js +8 -4
  131. package/build-module/query-controls/category-select.js.map +1 -1
  132. package/build-module/query-controls/index.js +64 -20
  133. package/build-module/query-controls/index.js.map +1 -1
  134. package/build-module/query-controls/terms.js +8 -4
  135. package/build-module/query-controls/terms.js.map +1 -1
  136. package/build-module/query-controls/types.js +2 -0
  137. package/build-module/query-controls/types.js.map +1 -0
  138. package/build-module/slot-fill/bubbles-virtually/fill.js +1 -0
  139. package/build-module/slot-fill/bubbles-virtually/fill.js.map +1 -1
  140. package/build-module/slot-fill/slot.js +1 -0
  141. package/build-module/slot-fill/slot.js.map +1 -1
  142. package/build-module/slot-fill/use-slot.js +2 -12
  143. package/build-module/slot-fill/use-slot.js.map +1 -1
  144. package/build-module/snackbar/index.js.map +1 -1
  145. package/build-module/snackbar/list.js.map +1 -1
  146. package/build-module/tab-panel/index.js +36 -8
  147. package/build-module/tab-panel/index.js.map +1 -1
  148. package/build-module/tree-grid/index.js +1 -1
  149. package/build-module/tree-grid/index.js.map +1 -1
  150. package/build-module/tree-select/index.js +2 -6
  151. package/build-module/tree-select/index.js.map +1 -1
  152. package/build-style/style-rtl.css +5 -0
  153. package/build-style/style.css +5 -0
  154. package/build-types/border-box-control/border-box-control/hook.d.ts +1 -1
  155. package/build-types/border-box-control/border-box-control-linked-button/component.d.ts +1 -1
  156. package/build-types/border-box-control/border-box-control-linked-button/hook.d.ts +171 -160
  157. package/build-types/border-box-control/border-box-control-linked-button/hook.d.ts.map +1 -1
  158. package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts +1 -1
  159. package/build-types/border-control/border-control/hook.d.ts +1 -1
  160. package/build-types/border-control/border-control-dropdown/component.d.ts.map +1 -1
  161. package/build-types/border-control/border-control-dropdown/hook.d.ts +1 -1
  162. package/build-types/button/deprecated.d.ts +143 -7
  163. package/build-types/button/deprecated.d.ts.map +1 -1
  164. package/build-types/button/index.d.ts +20 -3
  165. package/build-types/button/index.d.ts.map +1 -1
  166. package/build-types/button/stories/index.d.ts +20 -0
  167. package/build-types/button/stories/index.d.ts.map +1 -0
  168. package/build-types/button/test/index.d.ts +2 -0
  169. package/build-types/button/test/index.d.ts.map +1 -0
  170. package/build-types/button/types.d.ts +134 -0
  171. package/build-types/button/types.d.ts.map +1 -0
  172. package/build-types/color-list-picker/index.d.ts +5 -0
  173. package/build-types/color-list-picker/index.d.ts.map +1 -0
  174. package/build-types/color-list-picker/types.d.ts +42 -0
  175. package/build-types/color-list-picker/types.d.ts.map +1 -0
  176. package/build-types/color-palette/index.d.ts +2 -4
  177. package/build-types/color-palette/index.d.ts.map +1 -1
  178. package/build-types/color-palette/stories/index.d.ts +2 -2
  179. package/build-types/color-palette/styles.d.ts +1 -1
  180. package/build-types/color-palette/types.d.ts +1 -1
  181. package/build-types/color-palette/types.d.ts.map +1 -1
  182. package/build-types/color-palette/utils.d.ts +14 -0
  183. package/build-types/color-palette/utils.d.ts.map +1 -0
  184. package/build-types/color-picker/styles.d.ts +2 -2
  185. package/build-types/date-time/date/index.d.ts.map +1 -1
  186. package/build-types/date-time/date/styles.d.ts +3 -3
  187. package/build-types/dropdown/index.d.ts +4 -4
  188. package/build-types/dropdown/index.d.ts.map +1 -1
  189. package/build-types/dropdown/stories/index.d.ts.map +1 -1
  190. package/build-types/dropdown/types.d.ts +9 -10
  191. package/build-types/dropdown/types.d.ts.map +1 -1
  192. package/build-types/font-size-picker/styles.d.ts +2 -2
  193. package/build-types/h-stack/component.d.ts +0 -1
  194. package/build-types/h-stack/component.d.ts.map +1 -1
  195. package/build-types/input-control/input-field.d.ts.map +1 -1
  196. package/build-types/keyboard-shortcuts/index.d.ts +38 -0
  197. package/build-types/keyboard-shortcuts/index.d.ts.map +1 -0
  198. package/build-types/keyboard-shortcuts/stories/index.d.ts +12 -0
  199. package/build-types/keyboard-shortcuts/stories/index.d.ts.map +1 -0
  200. package/build-types/keyboard-shortcuts/test/index.d.ts +2 -0
  201. package/build-types/keyboard-shortcuts/test/index.d.ts.map +1 -0
  202. package/build-types/keyboard-shortcuts/types.d.ts +48 -0
  203. package/build-types/keyboard-shortcuts/types.d.ts.map +1 -0
  204. package/build-types/modal/index.d.ts.map +1 -1
  205. package/build-types/navigator/navigator-back-button/component.d.ts +1 -1
  206. package/build-types/navigator/navigator-back-button/hook.d.ts +2 -2
  207. package/build-types/navigator/navigator-button/component.d.ts +1 -1
  208. package/build-types/navigator/navigator-button/hook.d.ts +2 -2
  209. package/build-types/notice/index.d.ts +16 -0
  210. package/build-types/notice/index.d.ts.map +1 -0
  211. package/build-types/notice/list.d.ts +32 -0
  212. package/build-types/notice/list.d.ts.map +1 -0
  213. package/build-types/notice/stories/index.d.ts +17 -0
  214. package/build-types/notice/stories/index.d.ts.map +1 -0
  215. package/build-types/notice/test/index.d.ts +2 -0
  216. package/build-types/notice/test/index.d.ts.map +1 -0
  217. package/build-types/notice/test/list.d.ts +2 -0
  218. package/build-types/notice/test/list.d.ts.map +1 -0
  219. package/build-types/notice/types.d.ts +128 -0
  220. package/build-types/notice/types.d.ts.map +1 -0
  221. package/build-types/number-control/styles/number-control-styles.d.ts +2 -2
  222. package/build-types/number-control/styles/number-control-styles.d.ts.map +1 -1
  223. package/build-types/placeholder/stories/index.d.ts.map +1 -1
  224. package/build-types/query-controls/author-select.d.ts +4 -0
  225. package/build-types/query-controls/author-select.d.ts.map +1 -0
  226. package/build-types/query-controls/category-select.d.ts +4 -0
  227. package/build-types/query-controls/category-select.d.ts.map +1 -0
  228. package/build-types/query-controls/index.d.ts +30 -0
  229. package/build-types/query-controls/index.d.ts.map +1 -0
  230. package/build-types/query-controls/stories/index.d.ts +13 -0
  231. package/build-types/query-controls/stories/index.d.ts.map +1 -0
  232. package/build-types/query-controls/terms.d.ts +13 -0
  233. package/build-types/query-controls/terms.d.ts.map +1 -0
  234. package/build-types/query-controls/test/terms.d.ts +2 -0
  235. package/build-types/query-controls/test/terms.d.ts.map +1 -0
  236. package/build-types/query-controls/types.d.ts +131 -0
  237. package/build-types/query-controls/types.d.ts.map +1 -0
  238. package/build-types/range-control/index.d.ts +1 -1
  239. package/build-types/slot-fill/bubbles-virtually/fill.d.ts.map +1 -1
  240. package/build-types/slot-fill/use-slot.d.ts.map +1 -1
  241. package/build-types/snackbar/index.d.ts +9 -2
  242. package/build-types/snackbar/index.d.ts.map +1 -1
  243. package/build-types/snackbar/list.d.ts.map +1 -1
  244. package/build-types/snackbar/types.d.ts +15 -88
  245. package/build-types/snackbar/types.d.ts.map +1 -1
  246. package/build-types/tab-panel/index.d.ts.map +1 -1
  247. package/build-types/tab-panel/types.d.ts +1 -1
  248. package/build-types/tab-panel/types.d.ts.map +1 -1
  249. package/build-types/toggle-group-control/stories/index.d.ts.map +1 -1
  250. package/build-types/tree-select/index.d.ts.map +1 -1
  251. package/build-types/ui/form-group/form-group.d.ts +2 -2
  252. package/package.json +18 -17
  253. package/src/alignment-matrix-control/utils.tsx +2 -2
  254. package/src/autocomplete/autocompleter-ui.js +1 -2
  255. package/src/autocomplete/test/index.js +1 -5
  256. package/src/border-box-control/border-box-control-linked-button/component.tsx +1 -1
  257. package/src/border-box-control/border-box-control-linked-button/hook.ts +1 -1
  258. package/src/border-control/border-control-dropdown/component.tsx +9 -8
  259. package/src/box-control/test/index.js +11 -35
  260. package/src/button/README.md +49 -55
  261. package/src/button/{deprecated.js → deprecated.tsx} +19 -4
  262. package/src/button/{index.js → index.tsx} +95 -34
  263. package/src/button/stories/index.tsx +106 -0
  264. package/src/button/style.scss +3 -2
  265. package/src/button/test/{index.js → index.tsx} +30 -7
  266. package/src/button/types.ts +138 -0
  267. package/src/checkbox-control/test/index.tsx +1 -5
  268. package/src/color-list-picker/{index.js → index.tsx} +3 -2
  269. package/src/color-list-picker/types.ts +46 -0
  270. package/src/color-palette/README.md +1 -1
  271. package/src/color-palette/index.native.js +11 -4
  272. package/src/color-palette/index.tsx +11 -67
  273. package/src/color-palette/test/index.tsx +4 -14
  274. package/src/color-palette/test/utils.ts +1 -1
  275. package/src/color-palette/types.ts +1 -1
  276. package/src/color-palette/utils.ts +98 -0
  277. package/src/color-picker/test/index.js +6 -15
  278. package/src/combobox-control/test/index.js +1 -6
  279. package/src/confirm-dialog/test/index.js +9 -29
  280. package/src/custom-gradient-picker/gradient-bar/utils.js +1 -1
  281. package/src/date-time/date/index.tsx +2 -1
  282. package/src/date-time/date/test/index.tsx +2 -8
  283. package/src/date-time/time/test/index.tsx +9 -29
  284. package/src/dimension-control/test/index.test.js +2 -8
  285. package/src/disabled/test/index.tsx +1 -5
  286. package/src/draggable/test/index.native.js +4 -4
  287. package/src/dropdown/README.md +1 -8
  288. package/src/dropdown/index.tsx +17 -6
  289. package/src/dropdown/stories/index.tsx +3 -3
  290. package/src/dropdown/test/index.tsx +2 -8
  291. package/src/dropdown/types.ts +9 -10
  292. package/src/dropdown-menu/README.md +1 -1
  293. package/src/dropdown-menu/stories/index.js +96 -27
  294. package/src/dropdown-menu/test/index.js +2 -8
  295. package/src/external-link/test/index.tsx +1 -6
  296. package/src/focal-point-picker/test/index.js +3 -11
  297. package/src/font-size-picker/test/index.tsx +14 -44
  298. package/src/form-file-upload/test/index.tsx +2 -17
  299. package/src/form-toggle/test/index.tsx +1 -5
  300. package/src/form-token-field/test/index.tsx +80 -163
  301. package/src/form-token-field/token.tsx +1 -1
  302. package/src/gradient-picker/index.js +15 -4
  303. package/src/guide/test/index.js +5 -17
  304. package/src/h-stack/component.tsx +0 -1
  305. package/src/higher-order/with-filters/test/index.js +24 -24
  306. package/src/higher-order/with-focus-outside/test/index.js +11 -25
  307. package/src/higher-order/with-focus-return/test/index.js +1 -5
  308. package/src/input-control/input-field.tsx +3 -1
  309. package/src/input-control/test/index.js +1 -6
  310. package/src/isolated-event-container/test/index.js +2 -8
  311. package/src/keyboard-shortcuts/README.md +1 -1
  312. package/src/keyboard-shortcuts/index.tsx +93 -0
  313. package/src/keyboard-shortcuts/stories/index.tsx +60 -0
  314. package/src/keyboard-shortcuts/test/{index.js → index.tsx} +16 -6
  315. package/src/keyboard-shortcuts/types.ts +51 -0
  316. package/src/modal/index.tsx +1 -2
  317. package/src/navigable-container/test/navigable-menu.js +5 -17
  318. package/src/navigable-container/test/tababble-container.js +3 -11
  319. package/src/navigation/test/index.js +3 -11
  320. package/src/navigator/test/index.tsx +6 -20
  321. package/src/notice/README.md +89 -42
  322. package/src/notice/{index.js → index.tsx} +28 -20
  323. package/src/notice/list.tsx +72 -0
  324. package/src/notice/stories/index.tsx +119 -0
  325. package/src/notice/test/__snapshots__/{index.js.snap → index.tsx.snap} +0 -0
  326. package/src/notice/test/{index.js → index.tsx} +7 -4
  327. package/src/notice/test/{list.js → list.tsx} +0 -0
  328. package/src/notice/types.ts +136 -0
  329. package/src/number-control/index.tsx +1 -1
  330. package/src/number-control/test/index.tsx +28 -86
  331. package/src/panel/test/body.js +2 -8
  332. package/src/placeholder/stories/index.tsx +1 -0
  333. package/src/query-controls/README.md +56 -56
  334. package/src/query-controls/author-select.tsx +37 -0
  335. package/src/query-controls/category-select.tsx +46 -0
  336. package/src/query-controls/index.tsx +192 -0
  337. package/src/query-controls/stories/index.tsx +205 -0
  338. package/src/query-controls/terms.ts +57 -0
  339. package/src/query-controls/test/{terms.js → terms.ts} +36 -20
  340. package/src/query-controls/types.ts +150 -0
  341. package/src/select-control/test/select-control.tsx +1 -6
  342. package/src/slot-fill/bubbles-virtually/fill.js +1 -0
  343. package/src/slot-fill/slot.js +1 -1
  344. package/src/slot-fill/use-slot.js +6 -16
  345. package/src/snackbar/index.tsx +6 -5
  346. package/src/snackbar/list.tsx +4 -2
  347. package/src/snackbar/types.ts +18 -92
  348. package/src/tab-panel/index.tsx +38 -16
  349. package/src/tab-panel/style.scss +8 -0
  350. package/src/tab-panel/test/index.tsx +35 -7
  351. package/src/tab-panel/types.ts +1 -1
  352. package/src/theme/test/index.tsx +4 -4
  353. package/src/toggle-group-control/stories/index.tsx +1 -0
  354. package/src/toggle-group-control/test/index.tsx +7 -23
  355. package/src/toolbar/stories/index.js +75 -72
  356. package/src/tools-panel/stories/index.js +3 -0
  357. package/src/tools-panel/test/index.js +1 -1
  358. package/src/tree-grid/index.js +1 -1
  359. package/src/tree-select/index.tsx +3 -6
  360. package/src/ui/context/test/context-connect.tsx +2 -0
  361. package/src/ui/context/test/wordpress-component.tsx +2 -0
  362. package/src/unit-control/test/index.tsx +21 -74
  363. package/src/utils/hooks/test/use-latest-ref.js +15 -18
  364. package/tsconfig.json +1 -4
  365. package/tsconfig.tsbuildinfo +1 -1
  366. package/build-types/radio-context/index.d.ts +0 -6
  367. package/build-types/radio-context/index.d.ts.map +0 -1
  368. package/src/button/stories/index.js +0 -179
  369. package/src/keyboard-shortcuts/index.js +0 -56
  370. package/src/notice/list.js +0 -48
  371. package/src/notice/stories/index.js +0 -46
  372. package/src/query-controls/author-select.js +0 -23
  373. package/src/query-controls/category-select.js +0 -31
  374. package/src/query-controls/index.js +0 -122
  375. package/src/query-controls/terms.js +0 -40
  376. package/src/toolbar/stories/toolbar-button.js +0 -32
  377. package/src/toolbar/stories/toolbar-group.js +0 -33
@@ -16,8 +16,6 @@ import Navigation from '..';
16
16
  import NavigationItem from '../item';
17
17
  import NavigationMenu from '../menu';
18
18
 
19
- jest.useFakeTimers();
20
-
21
19
  const TestNavigation = ( { activeItem, rootTitle, showBadge } = {} ) => (
22
20
  <Navigation activeItem={ activeItem }>
23
21
  <NavigationMenu title={ rootTitle }>
@@ -192,9 +190,7 @@ describe( 'Navigation', () => {
192
190
  } );
193
191
 
194
192
  it( 'should set an active category on click', async () => {
195
- const user = userEvent.setup( {
196
- advanceTimers: jest.advanceTimersByTime,
197
- } );
193
+ const user = userEvent.setup();
198
194
 
199
195
  render( <TestNavigation /> );
200
196
 
@@ -236,9 +232,7 @@ describe( 'Navigation', () => {
236
232
  } );
237
233
 
238
234
  it( 'should navigate up a level when clicking the back button', async () => {
239
- const user = userEvent.setup( {
240
- advanceTimers: jest.advanceTimersByTime,
241
- } );
235
+ const user = userEvent.setup();
242
236
 
243
237
  render( <TestNavigation rootTitle="Home" /> );
244
238
 
@@ -252,9 +246,7 @@ describe( 'Navigation', () => {
252
246
  } );
253
247
 
254
248
  it( 'should navigate correctly when controlled', async () => {
255
- const user = userEvent.setup( {
256
- advanceTimers: jest.advanceTimersByTime,
257
- } );
249
+ const user = userEvent.setup();
258
250
 
259
251
  render( <TestNavigationControlled /> );
260
252
 
@@ -20,8 +20,6 @@ import {
20
20
  NavigatorBackButton,
21
21
  } from '..';
22
22
 
23
- jest.useFakeTimers();
24
-
25
23
  jest.mock( 'framer-motion', () => {
26
24
  const actual = jest.requireActual( 'framer-motion' );
27
25
  return {
@@ -304,9 +302,7 @@ describe( 'Navigator', () => {
304
302
  it( 'should navigate across screens', async () => {
305
303
  const spy = jest.fn();
306
304
 
307
- const user = userEvent.setup( {
308
- advanceTimers: jest.advanceTimersByTime,
309
- } );
305
+ const user = userEvent.setup();
310
306
 
311
307
  render( <MyNavigation onNavigatorButtonClick={ spy } /> );
312
308
 
@@ -376,9 +372,7 @@ describe( 'Navigator', () => {
376
372
  it( 'should not rended anything if the path does not match any available screen', async () => {
377
373
  const spy = jest.fn();
378
374
 
379
- const user = userEvent.setup( {
380
- advanceTimers: jest.advanceTimersByTime,
381
- } );
375
+ const user = userEvent.setup();
382
376
 
383
377
  render( <MyNavigation onNavigatorButtonClick={ spy } /> );
384
378
 
@@ -402,9 +396,7 @@ describe( 'Navigator', () => {
402
396
  } );
403
397
 
404
398
  it( 'should escape the value of the `path` prop', async () => {
405
- const user = userEvent.setup( {
406
- advanceTimers: jest.advanceTimersByTime,
407
- } );
399
+ const user = userEvent.setup();
408
400
 
409
401
  render( <MyNavigation /> );
410
402
 
@@ -437,9 +429,7 @@ describe( 'Navigator', () => {
437
429
 
438
430
  describe( 'focus management', () => {
439
431
  it( 'should restore focus correctly', async () => {
440
- const user = userEvent.setup( {
441
- advanceTimers: jest.advanceTimersByTime,
442
- } );
432
+ const user = userEvent.setup();
443
433
 
444
434
  render( <MyNavigation /> );
445
435
 
@@ -469,9 +459,7 @@ describe( 'Navigator', () => {
469
459
  } );
470
460
 
471
461
  it( 'should keep focus on an active element inside navigator, while re-rendering', async () => {
472
- const user = userEvent.setup( {
473
- advanceTimers: jest.advanceTimersByTime,
474
- } );
462
+ const user = userEvent.setup();
475
463
 
476
464
  render( <MyNavigation /> );
477
465
 
@@ -489,9 +477,7 @@ describe( 'Navigator', () => {
489
477
  } );
490
478
 
491
479
  it( 'should keep focus on an active element outside navigator, while re-rendering', async () => {
492
- const user = userEvent.setup( {
493
- advanceTimers: jest.advanceTimersByTime,
494
- } );
480
+ const user = userEvent.setup();
495
481
 
496
482
  render( <MyNavigation /> );
497
483
 
@@ -16,62 +16,50 @@ A Notice displays a succinct message. It can also offer the user options, like v
16
16
 
17
17
  Use Notices to communicate things that are important but don’t necessarily require action — a user can keep using the product even if they don’t choose to act on a Notice. They are less interruptive than a Modal.
18
18
 
19
- ### Anatomy
20
-
21
- ![Diagram of a Notice component with numbered labels](https://make.wordpress.org/design/files/2019/03/Notice-Anatomy.png)
22
-
23
- 1. Container (status indicated with color)
24
- 2. Icon (optional)
25
- 3. Message
26
- 4. Dismiss icon (optional)
27
-
28
19
  ### Usage
29
20
 
30
21
  Notices display at the top of the screen, below any toolbars anchored to the top of the page. They’re persistent and non-modal. Since they don’t overlay the content, users can ignore or dismiss them, and choose when to interact with them.
31
22
 
32
- ![](https://make.wordpress.org/design/files/2019/03/Notice-States.png)
33
-
34
23
  Notices are color-coded to indicate the type of message being communicated:
35
24
 
36
- - **Default** notices have **no background**.
37
- - **Informational** notices are **blue** by default.
38
- - If there is a parent `Theme` component with an `accent` color prop, informational notices will take on that color instead.
39
- - **Success** notices are **green.**
40
- - **Warning** notices are **yellow\*\***.\*\*
41
- - **Error** notices are **red.**
25
+ - **Informational** notices are **blue** by default.
26
+ - If there is a parent `Theme` component with an `accent` color prop, informational notices will take on that color instead.
27
+ - **Success** notices are **green.**
28
+ - **Warning** notices are **yellow\*\***.\*\*
29
+ - **Error** notices are **red.**
42
30
 
43
31
  If an icon is included in the Notice, it should be color-coded to match the Notice state.
44
32
 
33
+ ### Do's and Don'ts
34
+ **Do** use a Notice when you want to communicate a message of medium importance.
35
+
45
36
  ![A success Notice for updating a post](https://make.wordpress.org/design/files/2019/03/Notice-Do-1-alt.png)
46
37
 
47
- **Do**
48
- Do use a Notice when you want to communicate a message of medium importance.
38
+ ---
39
+ **Don’t** use a Notice for a message that requires immediate attention and action from the user. Use a Modal for this instead.
49
40
 
50
41
  ![A Notice that requires an immediate action](https://make.wordpress.org/design/files/2019/03/Notice-Dont-1-alt.png)
51
42
 
52
- **Don’t**
53
- Don't use a Notice for a message that requires immediate attention and action from the user. Use a Modal for this instead.
43
+ ---
44
+ **Do** display Notices at the top of the screen, below any toolbars.
54
45
 
55
46
  ![A success Notice for publishing a post](https://make.wordpress.org/design/files/2019/03/Notice-Do-2-alt.png)
56
47
 
57
- **Do**
58
- Do display Notices at the top of the screen, below any toolbars.
48
+ ---
49
+ **Don’t** show Notices on top of toolbars.
59
50
 
60
51
  ![A success Notice on top of the editor toolbar](https://make.wordpress.org/design/files/2019/03/Notice-Dont-2-alt.png)
61
52
 
62
- **Don’t**
63
- Don't show Notices on top of toolbars.
53
+ ---
54
+ **Do** use color to indicate the type of message being communicated.
64
55
 
65
56
  ![An error Notice using red](https://make.wordpress.org/design/files/2019/03/Notice-Do-3-alt.png)
66
57
 
67
- **Do**
68
- Do use color to indicate the type of message being communicated.
58
+ ---
59
+ **Don’t** apply any colors other than those for Warnings, Success, or Errors.
69
60
 
70
61
  ![An error Notice using purple](https://make.wordpress.org/design/files/2019/03/Notice-Dont-3-alt.png)
71
62
 
72
- **Don’t**
73
- Don't apply any colors other than those for Warnings, Success, or Errors.
74
-
75
63
  ## Development guidelines
76
64
 
77
65
  ### Usage
@@ -79,6 +67,8 @@ Don't apply any colors other than those for Warnings, Success, or Errors.
79
67
  To display a plain notice, pass `Notice` a string:
80
68
 
81
69
  ```jsx
70
+ import { Notice } from `@wordpress/components`;
71
+
82
72
  const MyNotice = () => (
83
73
  <Notice status="error">An unknown error occurred.</Notice>
84
74
  );
@@ -87,6 +77,8 @@ const MyNotice = () => (
87
77
  For more complex markup, you can pass any JSX element:
88
78
 
89
79
  ```jsx
80
+ import { Notice } from `@wordpress/components`;
81
+
90
82
  const MyNotice = () => (
91
83
  <Notice status="error">
92
84
  <p>
@@ -96,21 +88,76 @@ const MyNotice = () => (
96
88
  );
97
89
  ```
98
90
 
99
- #### Props
91
+ ### Props
100
92
 
101
93
  The following props are used to control the behavior of the component.
102
94
 
103
- - `children`: (string) The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.
104
- - `spokenMessage`: (string) Used to provide a custom spoken message in place of the `children` default.
105
- - `status`: (string) can be `warning` (yellow), `success` (green), `error` (red), or `info`. Defaults to `info`.
106
- - `onRemove`: function called when dismissing the notice
107
- - `politeness`: (string) A politeness level for the notice's spoken message. Should be provided as one of the valid options for [an `aria-live` attribute value](https://www.w3.org/TR/wai-aria-1.1/#aria-live). If not provided, a sensible default is used based on the notice status. Note that this value should be considered a suggestion; assistive technologies may override it based on internal heuristics.
108
- - A value of `'assertive'` is to be used for important, and usually time-sensitive, information. It will interrupt anything else the screen reader is announcing in that moment.
109
- - A value of `'polite'` is to be used for advisory information. It should not interrupt what the screen reader is announcing in that moment (the "speech queue") or interrupt the current task.
110
- - `isDismissible`: (boolean) defaults to true, whether the notice should be dismissible or not
111
- - `onDismiss` : callback function which is executed when the notice is dismissed. It is distinct from onRemove, which _looks_ like a callback but is actually the function to call to remove the notice from the UI.
112
- - `actions`: (array) an array of action objects. Each member object should contain a `label` and either a `url` link string or `onClick` callback function. A `className` property can be used to add custom classes to the button styles. The default appearance of the button is inferred based on whether `url` or `onClick` are provided, rendering the button as a link if appropriate. A `noDefaultClasses` property value of `true` will remove all default styling. You can denote a primary button action for a notice by passing the `variant` property with a value of `primary`.
95
+ #### `children`: `ReactNode`
96
+
97
+ The displayed message of a notice. Also used as the spoken message for assistive technology, unless `spokenMessage` is provided as an alternative message.
98
+
99
+ - Required: Yes
100
+
101
+ #### `spokenMessage`: `ReactNode`
102
+
103
+ Used to provide a custom spoken message in place of the `children` default.
104
+
105
+ - Required: No
106
+ - Default: `children`
107
+
108
+ #### `status`: `'warning' | 'success' | 'error' | 'info'`
109
+
110
+ Determines the color of the notice: `warning` (yellow), `success` (green), `error` (red), or `'info'`. By default `'info'` will be blue, but if there is a parent Theme component with an accent color prop, the notice will take on that color instead.
111
+
112
+ - Required: No
113
+ - Default: `info`
114
+
115
+ #### `onRemove`: `() => void`
116
+
117
+ A function called to dismiss/remove the notice.
118
+
119
+ - Required: No
120
+ - Default: `noop`
121
+
122
+ #### `politeness`: `'polite' | 'assertive'`
123
+
124
+ A politeness level for the notice's spoken message. Should be provided as one of the valid options for [an `aria-live` attribute value](https://www.w3.org/TR/wai-aria-1.1/#aria-live).
125
+
126
+ - A value of `'assertive'` is to be used for important, and usually time-sensitive, information. It will interrupt anything else the screen reader is announcing in that moment.
127
+ - A value of `'polite'` is to be used for advisory information. It should not interrupt what the screen reader is announcing in that moment (the "speech queue") or interrupt the current task.
128
+
129
+ Note that this value should be considered a suggestion; assistive technologies may override it based on internal heuristics.
130
+
131
+ - Required: No
132
+ - Default: `'assertive'` or `'polite'`, based on the notice status.
133
+
134
+ #### `isDismissible`: `boolean`
135
+
136
+ Whether the notice should be dismissible or not
137
+
138
+ - Required: No
139
+ - Default: `true`
140
+
141
+ #### `onDismiss` : `() => void`
142
+
143
+ A deprecated alternative to `onRemove`. This prop is kept for compatibilty reasons but should be avoided.
144
+
145
+ - Requiered: No
146
+ - Default: `noop`
147
+
148
+ #### `actions`: `Array<NoticeAction>`.
149
+
150
+ An array of notice actions. Each member object should contain:
151
+
152
+ - `label`: `string` containing the text of the button/link
153
+ - `url`: `string` OR `onClick`: `( event: SyntheticEvent ) => void` to specify what the action does.
154
+ - `className`: `string` (optional) to add custom classes to the button styles.
155
+ - `noDefaultClasses`: `boolean` (optional) A value of `true` will remove all default styling.
156
+ - `variant`: `'primary' | 'secondary' | 'link'` (optional) You can denote a primary button action for a notice by passing a value of `primary`.
157
+
158
+ The default appearance of an action button is inferred based on whether `url` or `onClick` are provided, rendering the button as a link if appropriate. If both props are provided, `url` takes precedence, and the action button will render as an anchor tag.
113
159
 
114
160
  ## Related components
115
161
 
116
- - To create a more prominent message that requires action, use a Modal.
162
+ - To create a more prominent message that requires action, use a Modal.
163
+ - For low priority, non-interruptive messsages, use Snackbar.
@@ -14,20 +14,21 @@ import { close } from '@wordpress/icons';
14
14
  /**
15
15
  * Internal dependencies
16
16
  */
17
- import { Button } from '../';
18
-
19
- /** @typedef {import('@wordpress/element').WPElement} WPElement */
17
+ import Button from '../button';
18
+ import type { NoticeAction, NoticeProps } from './types';
19
+ import type { SyntheticEvent } from 'react';
20
+ import type { DeprecatedButtonProps } from '../button/types';
20
21
 
21
22
  const noop = () => {};
22
23
 
23
24
  /**
24
25
  * Custom hook which announces the message with the given politeness, if a
25
26
  * valid message is provided.
26
- *
27
- * @param {string|WPElement} [message] Message to announce.
28
- * @param {'polite'|'assertive'} politeness Politeness to announce.
29
27
  */
30
- function useSpokenMessage( message, politeness ) {
28
+ function useSpokenMessage(
29
+ message: NoticeProps[ 'spokenMessage' ],
30
+ politeness: NoticeProps[ 'politeness' ]
31
+ ) {
31
32
  const spokenMessage =
32
33
  typeof message === 'string' ? message : renderToString( message );
33
34
 
@@ -38,15 +39,7 @@ function useSpokenMessage( message, politeness ) {
38
39
  }, [ spokenMessage, politeness ] );
39
40
  }
40
41
 
41
- /**
42
- * Given a notice status, returns an assumed default politeness for the status.
43
- * Defaults to 'assertive'.
44
- *
45
- * @param {string} [status] Notice status.
46
- *
47
- * @return {'polite'|'assertive'} Notice politeness.
48
- */
49
- function getDefaultPoliteness( status ) {
42
+ function getDefaultPoliteness( status: NoticeProps[ 'status' ] ) {
50
43
  switch ( status ) {
51
44
  case 'success':
52
45
  case 'warning':
@@ -59,6 +52,17 @@ function getDefaultPoliteness( status ) {
59
52
  }
60
53
  }
61
54
 
55
+ /**
56
+ * `Notice` is a component used to communicate feedback to the user.
57
+ *
58
+ *```jsx
59
+ * import { Notice } from `@wordpress/components`;
60
+ *
61
+ * const MyNotice = () => (
62
+ * <Notice status="error">An unknown error occurred.</Notice>
63
+ * );
64
+ * ```
65
+ */
62
66
  function Notice( {
63
67
  className,
64
68
  status = 'info',
@@ -73,7 +77,7 @@ function Notice( {
73
77
  // It is distinct from onRemove, which _looks_ like a callback but is
74
78
  // actually the function to call to remove the notice from the UI.
75
79
  onDismiss = noop,
76
- } ) {
80
+ }: NoticeProps ) {
77
81
  useSpokenMessage( spokenMessage, politeness );
78
82
 
79
83
  const classes = classnames(
@@ -85,11 +89,11 @@ function Notice( {
85
89
  }
86
90
  );
87
91
 
88
- if ( __unstableHTML ) {
92
+ if ( __unstableHTML && typeof children === 'string' ) {
89
93
  children = <RawHTML>{ children }</RawHTML>;
90
94
  }
91
95
 
92
- const onDismissNotice = ( event ) => {
96
+ const onDismissNotice = ( event: SyntheticEvent ) => {
93
97
  event?.preventDefault?.();
94
98
  onDismiss();
95
99
  onRemove();
@@ -110,7 +114,11 @@ function Notice( {
110
114
  noDefaultClasses = false,
111
115
  onClick,
112
116
  url,
113
- },
117
+ }: NoticeAction &
118
+ // `isPrimary` is a legacy prop included for
119
+ // backcompat, but `variant` should be used
120
+ // instead.
121
+ Pick< DeprecatedButtonProps, 'isPrimary' >,
114
122
  index
115
123
  ) => {
116
124
  let computedVariant = variant;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import Notice from '.';
10
+ import type { WordPressComponentProps } from '../ui/context';
11
+ import type { NoticeListProps } from './types';
12
+
13
+ const noop = () => {};
14
+
15
+ /**
16
+ * `NoticeList` is a component used to render a collection of notices.
17
+ *
18
+ *```jsx
19
+ * import { Notice, NoticeList } from `@wordpress/components`;
20
+ *
21
+ * const MyNoticeList = () => {
22
+ * const [ notices, setNotices ] = useState( [
23
+ * {
24
+ * id: 'second-notice',
25
+ * content: 'second notice content',
26
+ * },
27
+ * {
28
+ * id: 'fist-notice',
29
+ * content: 'first notice content',
30
+ * },
31
+ * ] );
32
+ *
33
+ * const removeNotice = ( id ) => {
34
+ * setNotices( notices.filter( ( notice ) => notice.id !== id ) );
35
+ * };
36
+ *
37
+ * return <NoticeList notices={ notices } onRemove={ removeNotice } />;
38
+ *};
39
+ *```
40
+ */
41
+ function NoticeList( {
42
+ notices,
43
+ onRemove = noop,
44
+ className,
45
+ children,
46
+ }: WordPressComponentProps< NoticeListProps, 'div', false > ) {
47
+ const removeNotice =
48
+ ( id: NoticeListProps[ 'notices' ][ number ][ 'id' ] ) => () =>
49
+ onRemove( id );
50
+
51
+ className = classnames( 'components-notice-list', className );
52
+
53
+ return (
54
+ <div className={ className }>
55
+ { children }
56
+ { [ ...notices ].reverse().map( ( notice ) => {
57
+ const { content, ...restNotice } = notice;
58
+ return (
59
+ <Notice
60
+ { ...restNotice }
61
+ key={ notice.id }
62
+ onRemove={ removeNotice( notice.id ) }
63
+ >
64
+ { notice.content }
65
+ </Notice>
66
+ );
67
+ } ) }
68
+ </div>
69
+ );
70
+ }
71
+
72
+ export default NoticeList;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { ComponentMeta, ComponentStory } from '@storybook/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useState } from '@wordpress/element';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import Notice from '..';
15
+ import Button from '../../button';
16
+ import NoticeList from '../list';
17
+ import type { NoticeListProps } from '../types';
18
+
19
+ const meta: ComponentMeta< typeof Notice > = {
20
+ title: 'Components/Notice',
21
+ component: Notice,
22
+ subcomponents: { NoticeList },
23
+ parameters: {
24
+ actions: { argTypesRegex: '^on.*' },
25
+ controls: { expanded: true },
26
+ docs: { source: { state: 'open' } },
27
+ },
28
+ };
29
+ export default meta;
30
+
31
+ const Template: ComponentStory< typeof Notice > = ( props ) => {
32
+ return <Notice { ...props } />;
33
+ };
34
+
35
+ export const Default = Template.bind( {} );
36
+ Default.args = {
37
+ children: 'This is a notice.',
38
+ };
39
+
40
+ export const WithCustomSpokenMessage = Template.bind( {} );
41
+ WithCustomSpokenMessage.args = {
42
+ ...Default.args,
43
+ politeness: 'assertive',
44
+ spokenMessage: 'This is a notice with a custom spoken message',
45
+ };
46
+
47
+ export const WithJSXChildren = Template.bind( {} );
48
+ WithJSXChildren.args = {
49
+ ...Default.args,
50
+ children: (
51
+ <>
52
+ <p>
53
+ JSX elements can be helpful
54
+ <strong> if you need to format</strong> the notice output.
55
+ </p>
56
+ <code>
57
+ note: in the interest of consistency, this should not be
58
+ overused!
59
+ </code>
60
+ </>
61
+ ),
62
+ };
63
+
64
+ export const WithActions = Template.bind( {} );
65
+ WithActions.args = {
66
+ ...Default.args,
67
+ actions: [
68
+ {
69
+ label: 'Click me!',
70
+ onClick: () => {},
71
+ variant: 'primary',
72
+ },
73
+ {
74
+ label: 'Or click me instead!',
75
+ onClick: () => {},
76
+ },
77
+ {
78
+ label: 'Or visit a link for more info',
79
+ url: 'https://wordpress.org',
80
+ variant: 'link',
81
+ },
82
+ ],
83
+ };
84
+
85
+ export const NoticeListSubcomponent: ComponentStory<
86
+ typeof NoticeList
87
+ > = () => {
88
+ const exampleNotices = [
89
+ {
90
+ id: 'second-notice',
91
+ content: 'second notice content',
92
+ },
93
+ {
94
+ id: 'first-notice',
95
+ content: 'first notice content',
96
+ },
97
+ ];
98
+ const [ notices, setNotices ] = useState( exampleNotices );
99
+
100
+ const removeNotice = (
101
+ id: NoticeListProps[ 'notices' ][ number ][ 'id' ]
102
+ ) => {
103
+ setNotices( notices.filter( ( notice ) => notice.id !== id ) );
104
+ };
105
+
106
+ const resetNotices = () => {
107
+ setNotices( exampleNotices );
108
+ };
109
+
110
+ return (
111
+ <>
112
+ <NoticeList notices={ notices } onRemove={ removeNotice } />
113
+ <Button variant={ 'primary' } onClick={ resetNotices }>
114
+ Reset Notices
115
+ </Button>
116
+ </>
117
+ );
118
+ };
119
+ NoticeListSubcomponent.storyName = 'NoticeList Subcomponent';
@@ -14,14 +14,15 @@ import { speak } from '@wordpress/a11y';
14
14
  import Notice from '../index';
15
15
 
16
16
  jest.mock( '@wordpress/a11y', () => ( { speak: jest.fn() } ) );
17
+ const mockedSpeak = jest.mocked( speak );
17
18
 
18
- function getNoticeWrapper( container ) {
19
+ function getNoticeWrapper( container: HTMLElement ) {
19
20
  return container.firstChild;
20
21
  }
21
22
 
22
23
  describe( 'Notice', () => {
23
24
  beforeEach( () => {
24
- speak.mockReset();
25
+ mockedSpeak.mockReset();
25
26
  } );
26
27
 
27
28
  it( 'should match snapshot', () => {
@@ -42,7 +43,9 @@ describe( 'Notice', () => {
42
43
  } );
43
44
 
44
45
  it( 'should not have is-dismissible class when isDismissible prop is false', () => {
45
- const { container } = render( <Notice isDismissible={ false } /> );
46
+ const { container } = render(
47
+ <Notice isDismissible={ false }>I cannot be dismissed!</Notice>
48
+ );
46
49
  const wrapper = getNoticeWrapper( container );
47
50
 
48
51
  expect( wrapper ).toHaveClass( 'components-notice' );
@@ -50,7 +53,7 @@ describe( 'Notice', () => {
50
53
  } );
51
54
 
52
55
  it( 'should default to info status', () => {
53
- const { container } = render( <Notice /> );
56
+ const { container } = render( <Notice>FYI</Notice> );
54
57
 
55
58
  expect( getNoticeWrapper( container ) ).toHaveClass( 'is-info' );
56
59
  } );
File without changes