@wordpress/components 40.0.0 → 40.1.1-next.v.202609031004.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 (291) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/build/border-box-control/border-box-control/component.cjs +37 -5
  3. package/build/border-box-control/border-box-control/component.cjs.map +3 -3
  4. package/build/border-box-control/border-box-control/hook.cjs +24 -3
  5. package/build/border-box-control/border-box-control/hook.cjs.map +3 -3
  6. package/build/border-box-control/border-box-control-linked-button/hook.cjs +2 -2
  7. package/build/border-box-control/border-box-control-linked-button/hook.cjs.map +2 -2
  8. package/build/border-box-control/border-box-control-split-controls/hook.cjs +2 -2
  9. package/build/border-box-control/border-box-control-split-controls/hook.cjs.map +2 -2
  10. package/build/border-box-control/border-box-control-visualizer/hook.cjs +2 -2
  11. package/build/border-box-control/border-box-control-visualizer/hook.cjs.map +2 -2
  12. package/build/color-palette/index.cjs +1 -1
  13. package/build/color-palette/index.cjs.map +2 -2
  14. package/build/context/context-system-provider.cjs +2 -5
  15. package/build/context/context-system-provider.cjs.map +3 -3
  16. package/build/context/use-context-system.cjs +7 -2
  17. package/build/context/use-context-system.cjs.map +2 -2
  18. package/build/icon/index.cjs +30 -12
  19. package/build/icon/index.cjs.map +2 -2
  20. package/build/item-group/item/hook.cjs +1 -1
  21. package/build/item-group/item/hook.cjs.map +2 -2
  22. package/build/item-group/item-group/hook.cjs +1 -1
  23. package/build/item-group/item-group/hook.cjs.map +2 -2
  24. package/build/resizable-box/index.cjs.map +1 -1
  25. package/build/snackbar/index.cjs +8 -5
  26. package/build/snackbar/index.cjs.map +2 -2
  27. package/build/tools-panel/tools-panel/hook.cjs +102 -106
  28. package/build/tools-panel/tools-panel/hook.cjs.map +2 -2
  29. package/build/tools-panel/tools-panel-item/hook.cjs +33 -33
  30. package/build/tools-panel/tools-panel-item/hook.cjs.map +2 -2
  31. package/build-module/border-box-control/border-box-control/component.mjs +38 -6
  32. package/build-module/border-box-control/border-box-control/component.mjs.map +2 -2
  33. package/build-module/border-box-control/border-box-control/hook.mjs +14 -3
  34. package/build-module/border-box-control/border-box-control/hook.mjs.map +2 -2
  35. package/build-module/border-box-control/border-box-control-linked-button/hook.mjs +2 -2
  36. package/build-module/border-box-control/border-box-control-linked-button/hook.mjs.map +2 -2
  37. package/build-module/border-box-control/border-box-control-split-controls/hook.mjs +2 -2
  38. package/build-module/border-box-control/border-box-control-split-controls/hook.mjs.map +2 -2
  39. package/build-module/border-box-control/border-box-control-visualizer/hook.mjs +2 -2
  40. package/build-module/border-box-control/border-box-control-visualizer/hook.mjs.map +2 -2
  41. package/build-module/color-palette/index.mjs +1 -1
  42. package/build-module/color-palette/index.mjs.map +2 -2
  43. package/build-module/context/context-system-provider.mjs +2 -5
  44. package/build-module/context/context-system-provider.mjs.map +3 -3
  45. package/build-module/context/use-context-system.mjs +7 -2
  46. package/build-module/context/use-context-system.mjs.map +2 -2
  47. package/build-module/icon/index.mjs +30 -12
  48. package/build-module/icon/index.mjs.map +2 -2
  49. package/build-module/item-group/item/hook.mjs +1 -1
  50. package/build-module/item-group/item/hook.mjs.map +2 -2
  51. package/build-module/item-group/item-group/hook.mjs +1 -1
  52. package/build-module/item-group/item-group/hook.mjs.map +2 -2
  53. package/build-module/resizable-box/index.mjs.map +1 -1
  54. package/build-module/snackbar/index.mjs +8 -5
  55. package/build-module/snackbar/index.mjs.map +2 -2
  56. package/build-module/tools-panel/tools-panel/hook.mjs +103 -107
  57. package/build-module/tools-panel/tools-panel/hook.mjs.map +2 -2
  58. package/build-module/tools-panel/tools-panel-item/hook.mjs +35 -35
  59. package/build-module/tools-panel/tools-panel-item/hook.mjs.map +2 -2
  60. package/build-style/style-rtl.css +7 -35
  61. package/build-style/style.css +7 -35
  62. package/build-types/border-box-control/border-box-control/component.d.ts +4 -0
  63. package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
  64. package/build-types/border-box-control/border-box-control/hook.d.ts +4 -2
  65. package/build-types/border-box-control/border-box-control/hook.d.ts.map +1 -1
  66. package/build-types/border-box-control/types.d.ts +6 -2
  67. package/build-types/border-box-control/types.d.ts.map +1 -1
  68. package/build-types/composite/types.d.ts +1 -1
  69. package/build-types/context/context-system-provider.d.ts +8 -6
  70. package/build-types/context/context-system-provider.d.ts.map +1 -1
  71. package/build-types/context/use-context-system.d.ts.map +1 -1
  72. package/build-types/icon/index.d.ts.map +1 -1
  73. package/build-types/popover/types.d.ts +6 -2
  74. package/build-types/popover/types.d.ts.map +1 -1
  75. package/build-types/snackbar/index.d.ts.map +1 -1
  76. package/build-types/tools-panel/tools-panel/hook.d.ts +4 -4
  77. package/build-types/tools-panel/tools-panel/hook.d.ts.map +1 -1
  78. package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
  79. package/build-types/tools-panel/types.d.ts +52 -9
  80. package/build-types/tools-panel/types.d.ts.map +1 -1
  81. package/package.json +26 -25
  82. package/src/angle-picker-control/style.module.scss +1 -1
  83. package/src/autocomplete/test/get-autocomplete-match.ts +2 -1
  84. package/src/base-control/stories/index.story.tsx +2 -2
  85. package/src/border-box-control/border-box-control/README.md +5 -3
  86. package/src/border-box-control/border-box-control/component.tsx +83 -15
  87. package/src/border-box-control/border-box-control/hook.ts +19 -1
  88. package/src/border-box-control/stories/index.story.tsx +10 -0
  89. package/src/border-box-control/style.module.scss +34 -3
  90. package/src/border-box-control/test/{index.tsx → index.jsdom.test.tsx} +133 -0
  91. package/src/border-box-control/test/utils.ts +11 -0
  92. package/src/border-box-control/types.ts +6 -2
  93. package/src/border-control/test/{index.js → index.jsdom.test.tsx} +20 -13
  94. package/src/checkbox-control/style.scss +2 -2
  95. package/src/checkbox-control/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +8 -5
  96. package/src/color-palette/index.tsx +1 -1
  97. package/src/composite/README.md +1 -1
  98. package/src/composite/types.ts +1 -1
  99. package/src/context/{context-system-provider.js → context-system-provider.tsx} +19 -5
  100. package/src/context/stories/{ComponentsProvider.stories.jsx → ComponentsProvider.stories.tsx} +2 -2
  101. package/src/context/test/__snapshots__/{context-system-provider.js.snap → context-system-provider.jsdom.test.tsx.snap} +3 -3
  102. package/src/context/test/context-connect.tsx +1 -2
  103. package/src/context/test/{context-system-provider.js → context-system-provider.jsdom.test.tsx} +81 -43
  104. package/src/context/test/wordpress-component.tsx +1 -2
  105. package/src/context/use-context-system.js +13 -4
  106. package/src/custom-gradient-picker/test/serializer.ts +1 -0
  107. package/src/date-time/test/utils.test.ts +9 -0
  108. package/src/draggable/style.module.scss +1 -1
  109. package/src/dropdown/style.module.scss +2 -2
  110. package/src/font-size-picker/test/utils.ts +1 -0
  111. package/src/icon/index.tsx +28 -12
  112. package/src/icon/test/{index.tsx → index.jsdom.test.tsx} +66 -0
  113. package/src/input-control/test/{index.js → index.jsdom.test.tsx} +16 -10
  114. package/src/item-group/style.module.scss +1 -2
  115. package/src/navigator/test/router.ts +1 -0
  116. package/src/notice/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +5 -2
  117. package/src/popover/README.md +2 -2
  118. package/src/popover/test/{index.tsx → index.jsdom.test.tsx} +23 -0
  119. package/src/popover/types.ts +9 -3
  120. package/src/query-controls/test/terms.ts +1 -0
  121. package/src/resizable-box/index.tsx +1 -1
  122. package/src/slot-fill/test/{index.js → index.jsdom.test.tsx} +3 -3
  123. package/src/slot-fill/test/{slot.js → slot.jsdom.test.tsx} +17 -9
  124. package/src/snackbar/index.tsx +10 -6
  125. package/src/snackbar/test/{index.tsx → index.jsdom.test.tsx} +28 -2
  126. package/src/snackbar/test/list.jsdom.test.tsx +99 -0
  127. package/src/surface/style.module.scss +2 -2
  128. package/src/textarea-control/style.module.scss +1 -1
  129. package/src/tip/style.scss +1 -1
  130. package/src/toggle-group-control/toggle-group-control/style.module.scss +1 -1
  131. package/src/tools-panel/test/{index.tsx → index.jsdom.test.tsx} +528 -9
  132. package/src/tools-panel/tools-panel/hook.ts +195 -180
  133. package/src/tools-panel/tools-panel-item/README.md +42 -1
  134. package/src/tools-panel/tools-panel-item/hook.ts +97 -69
  135. package/src/tools-panel/types.ts +54 -9
  136. package/src/truncate/style.module.scss +0 -1
  137. package/src/unit-control/test/utils.ts +1 -0
  138. package/src/utils/hooks/test/{use-controlled-state.js → use-controlled-state.jsdom.test.tsx} +17 -3
  139. package/src/utils/hooks/test/{use-controlled-value.js → use-controlled-value.jsdom.test.tsx} +3 -1
  140. package/src/utils/hooks/test/{use-cx.js → use-cx.jsdom.test.tsx} +3 -1
  141. package/src/utils/test/colors.js +1 -0
  142. package/src/utils/test/{get-node-text.js → get-node-text.tsx} +1 -0
  143. package/src/utils/test/math.js +1 -0
  144. package/src/utils/test/rtl.js +1 -0
  145. package/src/utils/test/space.js +1 -0
  146. package/src/utils/test/strings.js +1 -0
  147. package/src/utils/test/unit-values.js +1 -0
  148. package/src/view/test/{index.js → index.jsdom.test.tsx} +5 -1
  149. package/src/snackbar/test/list.tsx +0 -39
  150. /package/src/alignment-matrix-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  151. /package/src/autocomplete/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  152. /package/src/badge/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  153. /package/src/base-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  154. /package/src/box-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  155. /package/src/button/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  156. /package/src/card/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  157. /package/src/card/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  158. /package/src/checkbox-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  159. /package/src/circular-option-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  160. /package/src/color-indicator/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  161. /package/src/color-indicator/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  162. /package/src/color-palette/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  163. /package/src/color-palette/test/{utils.ts → utils.jsdom.test.ts} +0 -0
  164. /package/src/color-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  165. /package/src/combobox-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  166. /package/src/composite/legacy/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  167. /package/src/composite/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  168. /package/src/confirm-dialog/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  169. /package/src/content-editable-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  170. /package/src/custom-gradient-picker/gradient-bar/test/{utils.ts → utils.jsdom.test.ts} +0 -0
  171. /package/src/custom-gradient-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  172. /package/src/custom-select-control/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  173. /package/src/custom-select-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  174. /package/src/custom-select-control-v2/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  175. /package/src/date-time/date-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  176. /package/src/date-time/date-picker/test/{use-lilius.ts → use-lilius.jsdom.test.ts} +0 -0
  177. /package/src/date-time/date-time/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  178. /package/src/date-time/time-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  179. /package/src/date-time/time-picker/time-input/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  180. /package/src/disabled/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  181. /package/src/divider/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  182. /package/src/dropdown/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  183. /package/src/dropdown-menu/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  184. /package/src/duotone-picker/test/{custom-duotone-bar.tsx → custom-duotone-bar.jsdom.test.tsx} +0 -0
  185. /package/src/duotone-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  186. /package/src/elevation/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  187. /package/src/elevation/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  188. /package/src/external-link/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  189. /package/src/flex/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  190. /package/src/flex/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  191. /package/src/focal-point-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  192. /package/src/focal-point-picker/test/{media.tsx → media.jsdom.test.tsx} +0 -0
  193. /package/src/font-size-picker/test/{font-size-picker-select.tsx → font-size-picker-select.jsdom.test.tsx} +0 -0
  194. /package/src/font-size-picker/test/{font-size-picker-toggle-group.tsx → font-size-picker-toggle-group.jsdom.test.tsx} +0 -0
  195. /package/src/font-size-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  196. /package/src/form-file-upload/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  197. /package/src/form-toggle/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  198. /package/src/form-toggle/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  199. /package/src/form-token-field/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  200. /package/src/gradient-picker/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  201. /package/src/grid/test/{grid.tsx → grid.jsdom.test.tsx} +0 -0
  202. /package/src/guide/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  203. /package/src/h-stack/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  204. /package/src/h-stack/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  205. /package/src/heading/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  206. /package/src/heading/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  207. /package/src/higher-order/with-fallback-styles/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  208. /package/src/higher-order/with-filters/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  209. /package/src/higher-order/with-filters/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  210. /package/src/higher-order/with-focus-outside/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  211. /package/src/higher-order/with-focus-return/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  212. /package/src/higher-order/with-notices/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  213. /package/src/higher-order/with-spoken-messages/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  214. /package/src/input-control/test/__snapshots__/{index.js.snap → index.jsdom.test.tsx.snap} +0 -0
  215. /package/src/isolated-event-container/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  216. /package/src/item-group/test/__snapshots__/{index.js.snap → index.jsdom.test.tsx.snap} +0 -0
  217. /package/src/item-group/test/{index.js → index.jsdom.test.tsx} +0 -0
  218. /package/src/keyboard-shortcuts/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  219. /package/src/menu/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  220. /package/src/menu-group/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  221. /package/src/menu-item/test/__snapshots__/{index.js.snap → index.jsdom.test.tsx.snap} +0 -0
  222. /package/src/menu-item/test/{index.js → index.jsdom.test.tsx} +0 -0
  223. /package/src/modal/test/{aria-helper.ts → aria-helper.jsdom.test.ts} +0 -0
  224. /package/src/modal/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  225. /package/src/navigable-container/test/{navigable-menu.tsx → navigable-menu.jsdom.test.tsx} +0 -0
  226. /package/src/navigable-container/test/{tababble-container.tsx → tababble-container.jsdom.test.tsx} +0 -0
  227. /package/src/navigator/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  228. /package/src/notice/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  229. /package/src/notice/test/{list.tsx → list.jsdom.test.tsx} +0 -0
  230. /package/src/number-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  231. /package/src/palette-edit/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  232. /package/src/panel/test/__snapshots__/{body.tsx.snap → body.jsdom.test.tsx.snap} +0 -0
  233. /package/src/panel/test/__snapshots__/{header.tsx.snap → header.jsdom.test.tsx.snap} +0 -0
  234. /package/src/panel/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  235. /package/src/panel/test/__snapshots__/{row.tsx.snap → row.jsdom.test.tsx.snap} +0 -0
  236. /package/src/panel/test/{body.tsx → body.jsdom.test.tsx} +0 -0
  237. /package/src/panel/test/{header.tsx → header.jsdom.test.tsx} +0 -0
  238. /package/src/panel/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  239. /package/src/panel/test/{row.tsx → row.jsdom.test.tsx} +0 -0
  240. /package/src/placeholder/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  241. /package/src/progress-bar/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  242. /package/src/radio-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  243. /package/src/range-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  244. /package/src/resizable-box/resize-tooltip/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  245. /package/src/resizable-box/resize-tooltip/test/{label.tsx → label.jsdom.test.tsx} +0 -0
  246. /package/src/sandbox/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  247. /package/src/scroll-lock/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  248. /package/src/scrollable/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  249. /package/src/search-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  250. /package/src/select-control/test/__snapshots__/{select-control.tsx.snap → select-control.jsdom.test.tsx.snap} +0 -0
  251. /package/src/select-control/test/{select-control.tsx → select-control.jsdom.test.tsx} +0 -0
  252. /package/src/shortcut/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  253. /package/src/shortcut/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  254. /package/src/slot-fill/test/__snapshots__/{slot.js.snap → slot.jsdom.test.tsx.snap} +0 -0
  255. /package/src/spacer/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  256. /package/src/spacer/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  257. /package/src/style-provider/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  258. /package/src/surface/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  259. /package/src/tab-panel/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  260. /package/src/tabs/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  261. /package/src/text/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  262. /package/src/text/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  263. /package/src/text-control/test/{text-control.tsx → text-control.jsdom.test.tsx} +0 -0
  264. /package/src/text-highlight/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  265. /package/src/toggle-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  266. /package/src/toggle-group-control/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  267. /package/src/toggle-group-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  268. /package/src/toolbar/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  269. /package/src/toolbar/test/{toolbar-group.tsx → toolbar-group.jsdom.test.tsx} +0 -0
  270. /package/src/tooltip/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  271. /package/src/tree-grid/test/__snapshots__/{cell.tsx.snap → cell.jsdom.test.tsx.snap} +0 -0
  272. /package/src/tree-grid/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  273. /package/src/tree-grid/test/__snapshots__/{roving-tab-index-item.tsx.snap → roving-tab-index-item.jsdom.test.tsx.snap} +0 -0
  274. /package/src/tree-grid/test/__snapshots__/{roving-tab-index.tsx.snap → roving-tab-index.jsdom.test.tsx.snap} +0 -0
  275. /package/src/tree-grid/test/__snapshots__/{row.tsx.snap → row.jsdom.test.tsx.snap} +0 -0
  276. /package/src/tree-grid/test/{cell.tsx → cell.jsdom.test.tsx} +0 -0
  277. /package/src/tree-grid/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  278. /package/src/tree-grid/test/{roving-tab-index-item.tsx → roving-tab-index-item.jsdom.test.tsx} +0 -0
  279. /package/src/tree-grid/test/{roving-tab-index.tsx → roving-tab-index.jsdom.test.tsx} +0 -0
  280. /package/src/tree-grid/test/{row.tsx → row.jsdom.test.tsx} +0 -0
  281. /package/src/truncate/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  282. /package/src/unit-control/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  283. /package/src/utils/test/{polymorphic-element.tsx → polymorphic-element.jsdom.test.tsx} +0 -0
  284. /package/src/v-stack/test/__snapshots__/{index.tsx.snap → index.jsdom.test.tsx.snap} +0 -0
  285. /package/src/v-stack/test/{index.tsx → index.jsdom.test.tsx} +0 -0
  286. /package/src/validated-form-controls/test/{content-editable-control.tsx → content-editable-control.jsdom.test.tsx} +0 -0
  287. /package/src/validated-form-controls/test/{custom-select-control.tsx → custom-select-control.jsdom.test.tsx} +0 -0
  288. /package/src/validated-form-controls/test/{input-control.tsx → input-control.jsdom.test.tsx} +0 -0
  289. /package/src/validated-form-controls/test/{range-control.tsx → range-control.jsdom.test.tsx} +0 -0
  290. /package/src/validated-form-controls/test/{textarea-control.tsx → textarea-control.jsdom.test.tsx} +0 -0
  291. /package/src/view/test/__snapshots__/{index.js.snap → index.jsdom.test.tsx.snap} +0 -0
@@ -1,3 +1,4 @@
1
+ import { useState } from '@wordpress/element';
1
2
  import { render, screen, within } from '@testing-library/react';
2
3
  import userEvent from '@testing-library/user-event';
3
4
  import { ToolsPanel, ToolsPanelContext, ToolsPanelItem } from '../';
@@ -38,6 +39,7 @@ const controlProps = {
38
39
  controlValue = undefined;
39
40
  } ),
40
41
  onSelect: jest.fn(),
42
+ onShownChange: jest.fn(),
41
43
  };
42
44
 
43
45
  // Default props without a value for an alternate control to be rendered within
@@ -50,6 +52,7 @@ const altControlProps = {
50
52
  label: 'Alt',
51
53
  onDeselect: jest.fn(),
52
54
  onSelect: jest.fn(),
55
+ onShownChange: jest.fn(),
53
56
  };
54
57
 
55
58
  // Default props for wrapped or grouped panel items.
@@ -488,6 +491,156 @@ describe( 'ToolsPanel', () => {
488
491
  expect( controlRerendered ).toBeInTheDocument();
489
492
  } );
490
493
 
494
+ it( 'should not render optional item without a value by default', () => {
495
+ render(
496
+ <ToolsPanel { ...defaultProps }>
497
+ <ToolsPanelItem { ...altControlProps }>
498
+ <div>Optional control</div>
499
+ </ToolsPanelItem>
500
+ </ToolsPanel>
501
+ );
502
+
503
+ expect(
504
+ screen.queryByText( 'Optional control' )
505
+ ).not.toBeInTheDocument();
506
+ } );
507
+
508
+ it( 'should render optional item on first render when defaultShown is true', () => {
509
+ render(
510
+ <ToolsPanel { ...defaultProps }>
511
+ <ToolsPanelItem { ...altControlProps } defaultShown>
512
+ <div>Optional control</div>
513
+ </ToolsPanelItem>
514
+ </ToolsPanel>
515
+ );
516
+
517
+ expect(
518
+ screen.getByText( 'Optional control' )
519
+ ).toBeInTheDocument();
520
+ } );
521
+
522
+ it( 'should render optional item with a value even when defaultShown is false', () => {
523
+ altControlValue = true;
524
+
525
+ render(
526
+ <ToolsPanel { ...defaultProps }>
527
+ <ToolsPanelItem
528
+ { ...altControlProps }
529
+ defaultShown={ false }
530
+ >
531
+ <div>Optional control</div>
532
+ </ToolsPanelItem>
533
+ </ToolsPanel>
534
+ );
535
+
536
+ expect(
537
+ screen.getByText( 'Optional control' )
538
+ ).toBeInTheDocument();
539
+ } );
540
+
541
+ // `defaultShown` only seeds the item's initial visibility. A change
542
+ // after mount must leave the item as it is, and must not be reported
543
+ // as though the user had used the menu.
544
+ describe( 'changing defaultShown after mount', () => {
545
+ const onDeselect = jest.fn();
546
+ const onSelect = jest.fn();
547
+ const onShownChange = jest.fn();
548
+
549
+ const ToolsPanelOptional = ( {
550
+ defaultShown,
551
+ }: {
552
+ defaultShown: boolean;
553
+ } ) => (
554
+ <ToolsPanel { ...defaultProps }>
555
+ <ToolsPanelItem
556
+ defaultShown={ defaultShown }
557
+ hasValue={ () => false }
558
+ label="Alt"
559
+ onDeselect={ onDeselect }
560
+ onSelect={ onSelect }
561
+ onShownChange={ onShownChange }
562
+ >
563
+ <div>Optional control</div>
564
+ </ToolsPanelItem>
565
+ </ToolsPanel>
566
+ );
567
+
568
+ beforeEach( () => {
569
+ jest.clearAllMocks();
570
+ } );
571
+
572
+ it( 'should keep a hidden item hidden when it changes to true', () => {
573
+ const { rerender } = render(
574
+ <ToolsPanelOptional defaultShown={ false } />
575
+ );
576
+
577
+ rerender( <ToolsPanelOptional defaultShown /> );
578
+
579
+ expect(
580
+ screen.queryByText( 'Optional control' )
581
+ ).not.toBeInTheDocument();
582
+ expect( onShownChange ).not.toHaveBeenCalled();
583
+ expect( onSelect ).not.toHaveBeenCalled();
584
+ expect( onDeselect ).not.toHaveBeenCalled();
585
+ } );
586
+
587
+ it( 'should keep a shown item visible when it changes to false', () => {
588
+ const { rerender } = render(
589
+ <ToolsPanelOptional defaultShown />
590
+ );
591
+
592
+ rerender( <ToolsPanelOptional defaultShown={ false } /> );
593
+
594
+ expect(
595
+ screen.getByText( 'Optional control' )
596
+ ).toBeInTheDocument();
597
+ expect( onShownChange ).not.toHaveBeenCalled();
598
+ expect( onSelect ).not.toHaveBeenCalled();
599
+ expect( onDeselect ).not.toHaveBeenCalled();
600
+ } );
601
+ } );
602
+
603
+ it( 'should keep an item the user hid hidden when another item registers', async () => {
604
+ // Registering an item regenerates the panel's menu state. An item
605
+ // the user hid is stored as `false`, which must be preserved
606
+ // rather than treated as unregistered and reseeded from
607
+ // `defaultShown`.
608
+ const TestPanel = ( { showExtra }: { showExtra: boolean } ) => (
609
+ <ToolsPanel { ...defaultProps }>
610
+ <ToolsPanelItem { ...altControlProps } defaultShown>
611
+ <div>Optional control</div>
612
+ </ToolsPanelItem>
613
+ { showExtra && (
614
+ <ToolsPanelItem
615
+ hasValue={ () => false }
616
+ label="Extra"
617
+ onDeselect={ noop }
618
+ onSelect={ noop }
619
+ >
620
+ <div>Extra control</div>
621
+ </ToolsPanelItem>
622
+ ) }
623
+ </ToolsPanel>
624
+ );
625
+
626
+ const { rerender } = render( <TestPanel showExtra={ false } /> );
627
+ expect(
628
+ screen.getByText( 'Optional control' )
629
+ ).toBeInTheDocument();
630
+
631
+ await openDropdownMenu();
632
+ await selectMenuItem( altControlProps.label );
633
+ expect(
634
+ screen.queryByText( 'Optional control' )
635
+ ).not.toBeInTheDocument();
636
+
637
+ rerender( <TestPanel showExtra /> );
638
+
639
+ expect(
640
+ screen.queryByText( 'Optional control' )
641
+ ).not.toBeInTheDocument();
642
+ } );
643
+
491
644
  it( 'should continue to render shown by default item after it is toggled off via menu item', async () => {
492
645
  render(
493
646
  <ToolsPanel { ...defaultProps }>
@@ -734,7 +887,8 @@ describe( 'ToolsPanel', () => {
734
887
  expect( context.registerPanelItem ).toHaveBeenCalledTimes( 1 );
735
888
  // deregisterPanelItem is called, given that we have switched panels.
736
889
  expect( context.deregisterPanelItem ).toHaveBeenCalledWith(
737
- altControlProps.label
890
+ altControlProps.label,
891
+ expect.objectContaining( { label: altControlProps.label } )
738
892
  );
739
893
 
740
894
  // Simulate switching back to the original panelId, e.g. by selecting
@@ -757,6 +911,72 @@ describe( 'ToolsPanel', () => {
757
911
  expect( context.deregisterPanelItem ).toHaveBeenCalledTimes( 1 );
758
912
  } );
759
913
 
914
+ it( 'should register with the latest defaultShown when panelId changes', () => {
915
+ // A consumer that persists the user's choice feeds it back in
916
+ // through `defaultShown`. A change to that prop must not
917
+ // re-register the item on its own, but a re-registration caused by
918
+ // something else has to seed from the saved preference rather than
919
+ // the value the item mounted with.
920
+ const context: ToolsPanelContextType = {
921
+ ...panelContext,
922
+ registerPanelItem: jest.fn(),
923
+ deregisterPanelItem: jest.fn(),
924
+ };
925
+ const TestPanel = ( {
926
+ defaultShown,
927
+ }: {
928
+ defaultShown: boolean;
929
+ } ) => (
930
+ <ToolsPanelContext.Provider value={ context }>
931
+ <ToolsPanelItem
932
+ { ...altControlProps }
933
+ defaultShown={ defaultShown }
934
+ panelId="1234"
935
+ >
936
+ <div>Item</div>
937
+ </ToolsPanelItem>
938
+ </ToolsPanelContext.Provider>
939
+ );
940
+
941
+ const { rerender } = render( <TestPanel defaultShown={ false } /> );
942
+
943
+ expect( context.registerPanelItem ).toHaveBeenCalledWith(
944
+ expect.objectContaining( { defaultShown: false } )
945
+ );
946
+
947
+ // Let registration settle, so that any further calls can only
948
+ // have been caused by the changes made below.
949
+ rerender( <TestPanel defaultShown={ false } /> );
950
+ const settledCalls = ( context.registerPanelItem as jest.Mock ).mock
951
+ .calls.length;
952
+
953
+ // The user shows the item and the consumer saves that preference.
954
+ // The updated prop alone must not re-register the item, which
955
+ // would discard the visibility the user chose.
956
+ rerender( <TestPanel defaultShown /> );
957
+
958
+ expect( context.registerPanelItem ).toHaveBeenCalledTimes(
959
+ settledCalls
960
+ );
961
+
962
+ // Simulate switching block selection away and back again, which
963
+ // deregisters and re-registers the item.
964
+ context.panelId = '4321';
965
+ rerender( <TestPanel defaultShown /> );
966
+ context.panelId = '1234';
967
+ rerender( <TestPanel defaultShown /> );
968
+
969
+ expect( context.deregisterPanelItem ).toHaveBeenCalledWith(
970
+ altControlProps.label,
971
+ expect.objectContaining( { label: altControlProps.label } )
972
+ );
973
+ // The item registers again with the saved preference rather than
974
+ // the value it mounted with.
975
+ expect( context.registerPanelItem ).toHaveBeenLastCalledWith(
976
+ expect.objectContaining( { defaultShown: true } )
977
+ );
978
+ } );
979
+
760
980
  it( 'should register items when ToolsPanel panelId is null', () => {
761
981
  // This test simulates when a panel spans multiple block selections.
762
982
  // Multi-selection means a panel can't have a single id to match
@@ -802,23 +1022,24 @@ describe( 'ToolsPanel', () => {
802
1022
  expect( context.deregisterPanelItem ).not.toHaveBeenCalled();
803
1023
 
804
1024
  // Simulate another multi-selection where the panelId is `null`.
805
- // Item should re-register itself after it deregistered as the
806
- // multi-selection occurred.
1025
+ // Still matches the panel, so the registration stands rather than
1026
+ // churning through a deregister/register pair.
807
1027
  context.panelId = null;
808
1028
  rerender( <TestPanel /> );
809
- expect( context.registerPanelItem ).toHaveBeenCalledTimes( 2 );
810
- expect( context.deregisterPanelItem ).toHaveBeenCalledTimes( 1 );
1029
+ expect( context.registerPanelItem ).toHaveBeenCalledTimes( 1 );
1030
+ expect( context.deregisterPanelItem ).not.toHaveBeenCalled();
811
1031
 
812
1032
  // Simulate a change in panel e.g. back to a single block selection
813
1033
  // Where the item's panelId is not a match.
814
1034
  context.panelId = '4321';
815
1035
  rerender( <TestPanel /> );
816
1036
 
817
- // As the item no longer matches the panelId it should not have
818
- // registered again but instead deregistered.
1037
+ // No longer matches, so it has already deregistered. Unmounting
1038
+ // must not deregister again.
1039
+ expect( context.deregisterPanelItem ).toHaveBeenCalledTimes( 1 );
819
1040
  unmount();
820
- expect( context.registerPanelItem ).toHaveBeenCalledTimes( 2 );
821
- expect( context.deregisterPanelItem ).toHaveBeenCalledTimes( 2 );
1041
+ expect( context.registerPanelItem ).toHaveBeenCalledTimes( 1 );
1042
+ expect( context.deregisterPanelItem ).toHaveBeenCalledTimes( 1 );
822
1043
  } );
823
1044
  } );
824
1045
 
@@ -878,6 +1099,126 @@ describe( 'ToolsPanel', () => {
878
1099
  } );
879
1100
  } );
880
1101
 
1102
+ describe( 'shown change callback', () => {
1103
+ beforeEach( () => {
1104
+ jest.clearAllMocks();
1105
+ } );
1106
+
1107
+ it( 'should call onShownChange with true when an optional item is shown via the menu', async () => {
1108
+ renderPanel();
1109
+
1110
+ await openDropdownMenu();
1111
+ await selectMenuItem( altControlProps.label );
1112
+
1113
+ expect( altControlProps.onShownChange ).toHaveBeenCalledTimes( 1 );
1114
+ expect( altControlProps.onShownChange ).toHaveBeenCalledWith(
1115
+ true
1116
+ );
1117
+ } );
1118
+
1119
+ it( 'should call onShownChange with false when an optional item without a value is hidden via the menu', async () => {
1120
+ renderPanel();
1121
+
1122
+ await openDropdownMenu();
1123
+ await selectMenuItem( altControlProps.label );
1124
+ await selectMenuItem( altControlProps.label );
1125
+
1126
+ expect( altControlProps.onShownChange ).toHaveBeenCalledTimes( 2 );
1127
+ expect( altControlProps.onShownChange ).toHaveBeenLastCalledWith(
1128
+ false
1129
+ );
1130
+ // The item never had a value, so there was nothing to reset.
1131
+ expect( altControlProps.onDeselect ).not.toHaveBeenCalled();
1132
+ } );
1133
+
1134
+ it( 'should call both onShownChange and onDeselect when an optional item with a value is hidden via the menu', async () => {
1135
+ renderPanel();
1136
+
1137
+ await openDropdownMenu();
1138
+ await selectMenuItem( controlProps.label );
1139
+
1140
+ expect( controlProps.onShownChange ).toHaveBeenCalledTimes( 1 );
1141
+ expect( controlProps.onShownChange ).toHaveBeenCalledWith( false );
1142
+ expect( controlProps.onDeselect ).toHaveBeenCalledTimes( 1 );
1143
+ } );
1144
+
1145
+ it( 'should not call onShownChange for default items', async () => {
1146
+ render(
1147
+ <ToolsPanel { ...defaultProps }>
1148
+ <ToolsPanelItem { ...controlProps } isShownByDefault>
1149
+ <div>Example control</div>
1150
+ </ToolsPanelItem>
1151
+ </ToolsPanel>
1152
+ );
1153
+
1154
+ await openDropdownMenu();
1155
+ await selectMenuItem( controlProps.label );
1156
+
1157
+ // Default items stay visible when toggled off; the action resets
1158
+ // them rather than hiding them.
1159
+ expect( controlProps.onDeselect ).toHaveBeenCalledTimes( 1 );
1160
+ expect( controlProps.onShownChange ).not.toHaveBeenCalled();
1161
+ } );
1162
+
1163
+ it( 'should not call onShownChange when items are hidden by Reset all', async () => {
1164
+ renderPanel();
1165
+
1166
+ await openDropdownMenu();
1167
+ await selectMenuItem( 'Reset all' );
1168
+
1169
+ expect( controlProps.onShownChange ).not.toHaveBeenCalled();
1170
+ expect( altControlProps.onShownChange ).not.toHaveBeenCalled();
1171
+ } );
1172
+
1173
+ it( 'should not call onShownChange when the value changes programmatically', () => {
1174
+ const onShownChange = jest.fn();
1175
+ const ToolsPanelOptional = ( { value }: { value?: number } ) => (
1176
+ <ToolsPanel { ...defaultProps } panelId="1234">
1177
+ <ToolsPanelItem
1178
+ hasValue={ () => !! value }
1179
+ label="Alt"
1180
+ onShownChange={ onShownChange }
1181
+ panelId="1234"
1182
+ >
1183
+ <div>Optional control</div>
1184
+ </ToolsPanelItem>
1185
+ </ToolsPanel>
1186
+ );
1187
+
1188
+ const { rerender } = render( <ToolsPanelOptional /> );
1189
+ expect(
1190
+ screen.queryByText( 'Optional control' )
1191
+ ).not.toBeInTheDocument();
1192
+
1193
+ // Gaining a value shows the item, but that is not a menu action.
1194
+ rerender( <ToolsPanelOptional value={ 100 } /> );
1195
+ expect(
1196
+ screen.getByText( 'Optional control' )
1197
+ ).toBeInTheDocument();
1198
+
1199
+ // Losing it again is not a menu action either.
1200
+ rerender( <ToolsPanelOptional /> );
1201
+
1202
+ expect( onShownChange ).not.toHaveBeenCalled();
1203
+ } );
1204
+
1205
+ it( 'should not call any callback when an item is mounted with defaultShown', () => {
1206
+ render(
1207
+ <ToolsPanel { ...defaultProps }>
1208
+ <ToolsPanelItem { ...altControlProps } defaultShown>
1209
+ <div>Alt control</div>
1210
+ </ToolsPanelItem>
1211
+ </ToolsPanel>
1212
+ );
1213
+
1214
+ // Registering an item as shown is not a menu action, so none of
1215
+ // the item's callbacks should fire.
1216
+ expect( screen.getByText( 'Alt control' ) ).toBeInTheDocument();
1217
+ expect( altControlProps.onShownChange ).not.toHaveBeenCalled();
1218
+ expect( altControlProps.onSelect ).not.toHaveBeenCalled();
1219
+ } );
1220
+ } );
1221
+
881
1222
  describe( 'grouped panel items within custom components', () => {
882
1223
  it( 'should render grouped items correctly', () => {
883
1224
  renderGroupedItemsInPanel();
@@ -1153,6 +1494,103 @@ describe( 'ToolsPanel', () => {
1153
1494
  expect( altControlProps.onDeselect ).not.toHaveBeenCalled();
1154
1495
  } );
1155
1496
 
1497
+ it( 'should not contain menu items for an item belonging to another panel', async () => {
1498
+ // A fill can mount after the panel it is rendered into has already
1499
+ // settled. An item whose `panelId` doesn't match must stay out of
1500
+ // that panel's menu entirely, including out of the value flagging
1501
+ // that populates it.
1502
+ const Panel = ( { withForeign }: { withForeign: boolean } ) => (
1503
+ <ToolsPanel { ...defaultProps } panelId="1234">
1504
+ <ToolsPanelItem
1505
+ label="Mine"
1506
+ panelId="1234"
1507
+ isShownByDefault
1508
+ hasValue={ () => false }
1509
+ >
1510
+ <div>My control</div>
1511
+ </ToolsPanelItem>
1512
+ { withForeign && (
1513
+ <ToolsPanelItem
1514
+ label="Foreign"
1515
+ panelId="9999"
1516
+ hasValue={ () => true }
1517
+ >
1518
+ <div>Foreign control</div>
1519
+ </ToolsPanelItem>
1520
+ ) }
1521
+ </ToolsPanel>
1522
+ );
1523
+
1524
+ // Let the panel settle with only its own item registered, then
1525
+ // bring in an item that belongs to a different panel.
1526
+ const { rerender } = render( <Panel withForeign={ false } /> );
1527
+ rerender( <Panel withForeign /> );
1528
+
1529
+ await openDropdownMenu();
1530
+
1531
+ expect(
1532
+ screen.queryByRole( 'menuitemcheckbox', { name: /Foreign/i } )
1533
+ ).not.toBeInTheDocument();
1534
+ } );
1535
+
1536
+ it( "should not let a replacement item inherit the outgoing one's state", async () => {
1537
+ // Two blocks can each contribute a control of the same name. When
1538
+ // selection moves between them, the incoming item starts from its
1539
+ // own value rather than the visibility the user chose for the one
1540
+ // it replaced.
1541
+ const SameLabelInTwoPanels = ( {
1542
+ panelId,
1543
+ }: Pick<
1544
+ React.ComponentProps< typeof ToolsPanelItem >,
1545
+ 'panelId'
1546
+ > ) => (
1547
+ <SlotFillProvider>
1548
+ <ToolsPanelItems>
1549
+ <ToolsPanelItem
1550
+ label="Shared"
1551
+ panelId="1234"
1552
+ hasValue={ () => false }
1553
+ >
1554
+ <div>Item 1</div>
1555
+ </ToolsPanelItem>
1556
+ </ToolsPanelItems>
1557
+ <ToolsPanelItems>
1558
+ <ToolsPanelItem
1559
+ label="Shared"
1560
+ panelId="9999"
1561
+ hasValue={ () => false }
1562
+ >
1563
+ <div>Item 2</div>
1564
+ </ToolsPanelItem>
1565
+ </ToolsPanelItems>
1566
+ <ToolsPanel { ...defaultProps } panelId={ panelId }>
1567
+ <Slot />
1568
+ </ToolsPanel>
1569
+ </SlotFillProvider>
1570
+ );
1571
+
1572
+ const { rerender } = render(
1573
+ <SameLabelInTwoPanels panelId="1234" />
1574
+ );
1575
+
1576
+ // Show the first block's control.
1577
+ await openDropdownMenu();
1578
+ await selectMenuItem( 'Shared' );
1579
+ expect( screen.getByText( 'Item 1' ) ).toBeInTheDocument();
1580
+
1581
+ // Move to the other block. Its control has no value and was never
1582
+ // shown, so it stays hidden.
1583
+ // The menu stays open across the rerender.
1584
+ rerender( <SameLabelInTwoPanels panelId="9999" /> );
1585
+
1586
+ expect(
1587
+ await screen.findByRole( 'menuitemcheckbox', {
1588
+ name: 'Show Shared',
1589
+ } )
1590
+ ).toBeInTheDocument();
1591
+ expect( screen.queryByText( 'Item 2' ) ).not.toBeInTheDocument();
1592
+ } );
1593
+
1156
1594
  it( 'should not contain orphaned menu items when panelId changes', async () => {
1157
1595
  // As fills and the panel can update independently this aims to
1158
1596
  // test that no orphaned items appear registered in the panel menu.
@@ -1291,6 +1729,45 @@ describe( 'ToolsPanel', () => {
1291
1729
  expect( optionsDisplayedIcon ).not.toHaveAccessibleDescription();
1292
1730
  } );
1293
1731
 
1732
+ it( 'should pass reset all filters that see the latest props', async () => {
1733
+ let received: unknown[] = [];
1734
+ const ChangingFilter = () => {
1735
+ const [ count, setCount ] = useState( 1 );
1736
+ return (
1737
+ <ToolsPanel
1738
+ label="Panel header"
1739
+ resetAll={ ( filters ) => {
1740
+ received = ( filters ?? [] ).map( ( filter ) =>
1741
+ filter()
1742
+ );
1743
+ } }
1744
+ >
1745
+ <ToolsPanelItem
1746
+ label="Filtered"
1747
+ isShownByDefault
1748
+ hasValue={ () => true }
1749
+ resetAllFilter={ () => count }
1750
+ >
1751
+ <button onClick={ () => setCount( 2 ) }>
1752
+ bump
1753
+ </button>
1754
+ </ToolsPanelItem>
1755
+ </ToolsPanel>
1756
+ );
1757
+ };
1758
+
1759
+ const user = userEvent.setup();
1760
+ render( <ChangingFilter /> );
1761
+
1762
+ // The panelId never changes, which is where a filter frozen at
1763
+ // registration goes stale.
1764
+ await user.click( screen.getByText( 'bump' ) );
1765
+ await openDropdownMenu();
1766
+ await selectMenuItem( 'Reset all' );
1767
+
1768
+ expect( received ).toEqual( [ 2 ] );
1769
+ } );
1770
+
1294
1771
  it( 'should not call reset all for different panelIds', async () => {
1295
1772
  const resetItem = jest.fn();
1296
1773
  const resetItemB = jest.fn();
@@ -1383,6 +1860,48 @@ describe( 'ToolsPanel', () => {
1383
1860
  } );
1384
1861
  } );
1385
1862
 
1863
+ describe( 'reset all with values the reset leaves in place', () => {
1864
+ it( 'should keep a default control resettable when its value survives', async () => {
1865
+ // The value arrives after mount, like block library controls whose
1866
+ // `hasValue` closes over an attribute: false at mount, true once
1867
+ // edited. A value read back from registration time misses it.
1868
+ const GainsAValue = () => {
1869
+ const [ hasVal, setHasVal ] = useState( false );
1870
+ return (
1871
+ <ToolsPanel label="Panel header" resetAll={ () => {} }>
1872
+ <ToolsPanelItem
1873
+ label="Survivor"
1874
+ isShownByDefault
1875
+ hasValue={ () => hasVal }
1876
+ >
1877
+ <button onClick={ () => setHasVal( true ) }>
1878
+ set a value
1879
+ </button>
1880
+ </ToolsPanelItem>
1881
+ </ToolsPanel>
1882
+ );
1883
+ };
1884
+
1885
+ const user = userEvent.setup();
1886
+ render( <GainsAValue /> );
1887
+
1888
+ await user.click( screen.getByText( 'set a value' ) );
1889
+ await openDropdownMenu();
1890
+ await selectMenuItem( 'Reset all' );
1891
+
1892
+ // `resetAll` clears nothing here, so the value is still set and
1893
+ // must stay resettable from both menu entries.
1894
+ expect(
1895
+ await screen.findByRole( 'menuitem', { name: 'Reset all' } )
1896
+ ).toHaveAttribute( 'aria-disabled', 'false' );
1897
+ expect(
1898
+ await screen.findByRole( 'menuitem', {
1899
+ name: 'Reset Survivor',
1900
+ } )
1901
+ ).toBeInTheDocument();
1902
+ } );
1903
+ } );
1904
+
1386
1905
  describe( 'first and last panel items', () => {
1387
1906
  it( 'should apply first/last classes to appropriate items', () => {
1388
1907
  render(