@wordpress/components 25.9.1 → 25.11.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 (369) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/build/alignment-matrix-control/cell.js +8 -5
  3. package/build/alignment-matrix-control/cell.js.map +1 -1
  4. package/build/alignment-matrix-control/index.js +27 -43
  5. package/build/alignment-matrix-control/index.js.map +1 -1
  6. package/build/alignment-matrix-control/utils.js +29 -9
  7. package/build/alignment-matrix-control/utils.js.map +1 -1
  8. package/build/autocomplete/index.js +104 -52
  9. package/build/autocomplete/index.js.map +1 -1
  10. package/build/circular-option-picker/circular-option-picker-option.js +20 -39
  11. package/build/circular-option-picker/circular-option-picker-option.js.map +1 -1
  12. package/build/circular-option-picker/circular-option-picker.js +11 -32
  13. package/build/circular-option-picker/circular-option-picker.js.map +1 -1
  14. package/build/circular-option-picker/types.js.map +1 -1
  15. package/build/color-palette/index.js +7 -2
  16. package/build/color-palette/index.js.map +1 -1
  17. package/build/color-picker/component.js +12 -2
  18. package/build/color-picker/component.js.map +1 -1
  19. package/build/color-picker/picker.js +77 -1
  20. package/build/color-picker/picker.js.map +1 -1
  21. package/build/color-picker/styles.js +8 -8
  22. package/build/color-picker/styles.js.map +1 -1
  23. package/build/color-picker/types.js.map +1 -1
  24. package/build/composite/v2.js +43 -0
  25. package/build/composite/v2.js.map +1 -0
  26. package/build/confirm-dialog/component.js +74 -8
  27. package/build/confirm-dialog/component.js.map +1 -1
  28. package/build/confirm-dialog/types.js.map +1 -1
  29. package/build/custom-gradient-picker/gradient-bar/control-points.js +13 -4
  30. package/build/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
  31. package/build/dropdown-menu-v2-ariakit/index.js +217 -0
  32. package/build/dropdown-menu-v2-ariakit/index.js.map +1 -0
  33. package/build/dropdown-menu-v2-ariakit/styles.js +157 -0
  34. package/build/dropdown-menu-v2-ariakit/styles.js.map +1 -0
  35. package/build/dropdown-menu-v2-ariakit/types.js +6 -0
  36. package/build/dropdown-menu-v2-ariakit/types.js.map +1 -0
  37. package/build/font-size-picker/utils.js +1 -1
  38. package/build/font-size-picker/utils.js.map +1 -1
  39. package/build/input-control/styles/input-control-styles.js +23 -23
  40. package/build/input-control/styles/input-control-styles.js.map +1 -1
  41. package/build/mobile/global-styles-context/utils.native.js +1 -1
  42. package/build/mobile/global-styles-context/utils.native.js.map +1 -1
  43. package/build/modal/index.js +45 -16
  44. package/build/modal/index.js.map +1 -1
  45. package/build/palette-edit/index.js +4 -0
  46. package/build/palette-edit/index.js.map +1 -1
  47. package/build/popover/index.js +34 -6
  48. package/build/popover/index.js.map +1 -1
  49. package/build/private-apis.js +18 -2
  50. package/build/private-apis.js.map +1 -1
  51. package/build/progress-bar/styles.js +5 -5
  52. package/build/progress-bar/styles.js.map +1 -1
  53. package/build/sandbox/index.js +1 -1
  54. package/build/sandbox/index.js.map +1 -1
  55. package/build/sandbox/index.native.js +1 -1
  56. package/build/sandbox/index.native.js.map +1 -1
  57. package/build/select-control/styles/select-control-styles.js +8 -8
  58. package/build/select-control/styles/select-control-styles.js.map +1 -1
  59. package/build/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
  60. package/build/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
  61. package/build/tabs/context.js +16 -0
  62. package/build/tabs/context.js.map +1 -0
  63. package/build/tabs/index.js +147 -0
  64. package/build/tabs/index.js.map +1 -0
  65. package/build/tabs/styles.js +38 -0
  66. package/build/tabs/styles.js.map +1 -0
  67. package/build/tabs/tab.js +46 -0
  68. package/build/tabs/tab.js.map +1 -0
  69. package/build/tabs/tablist.js +47 -0
  70. package/build/tabs/tablist.js.map +1 -0
  71. package/build/tabs/tabpanel.js +48 -0
  72. package/build/tabs/tabpanel.js.map +1 -0
  73. package/build/tabs/types.js +6 -0
  74. package/build/tabs/types.js.map +1 -0
  75. package/build/text/component.js +7 -6
  76. package/build/text/component.js.map +1 -1
  77. package/build/text/hook.js +6 -15
  78. package/build/text/hook.js.map +1 -1
  79. package/build/text/index.js.map +1 -1
  80. package/build/text/styles.js +7 -7
  81. package/build/text/styles.js.map +1 -1
  82. package/build/text/types.js.map +1 -1
  83. package/build/text/utils.js +17 -33
  84. package/build/text/utils.js.map +1 -1
  85. package/build/toggle-group-control/toggle-group-control-option-base/component.js +1 -0
  86. package/build/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  87. package/build/toolbar/toolbar/index.js +17 -10
  88. package/build/toolbar/toolbar/index.js.map +1 -1
  89. package/build/toolbar/toolbar/types.js.map +1 -1
  90. package/build/tools-panel/tools-panel-item/hook.js +2 -2
  91. package/build/tools-panel/tools-panel-item/hook.js.map +1 -1
  92. package/build/tools-panel/types.js.map +1 -1
  93. package/build/tooltip/index.js +2 -2
  94. package/build/tooltip/index.js.map +1 -1
  95. package/build/unit-control/utils.js +108 -0
  96. package/build/unit-control/utils.js.map +1 -1
  97. package/build/utils/unit-values.js +1 -1
  98. package/build/utils/unit-values.js.map +1 -1
  99. package/build-module/alignment-matrix-control/cell.js +7 -4
  100. package/build-module/alignment-matrix-control/cell.js.map +1 -1
  101. package/build-module/alignment-matrix-control/index.js +27 -43
  102. package/build-module/alignment-matrix-control/index.js.map +1 -1
  103. package/build-module/alignment-matrix-control/utils.js +29 -8
  104. package/build-module/alignment-matrix-control/utils.js.map +1 -1
  105. package/build-module/autocomplete/index.js +104 -52
  106. package/build-module/autocomplete/index.js.map +1 -1
  107. package/build-module/circular-option-picker/circular-option-picker-option.js +20 -39
  108. package/build-module/circular-option-picker/circular-option-picker-option.js.map +1 -1
  109. package/build-module/circular-option-picker/circular-option-picker.js +10 -31
  110. package/build-module/circular-option-picker/circular-option-picker.js.map +1 -1
  111. package/build-module/circular-option-picker/types.js.map +1 -1
  112. package/build-module/color-palette/index.js +7 -2
  113. package/build-module/color-palette/index.js.map +1 -1
  114. package/build-module/color-picker/component.js +13 -3
  115. package/build-module/color-picker/component.js.map +1 -1
  116. package/build-module/color-picker/picker.js +78 -2
  117. package/build-module/color-picker/picker.js.map +1 -1
  118. package/build-module/color-picker/styles.js +8 -8
  119. package/build-module/color-picker/styles.js.map +1 -1
  120. package/build-module/color-picker/types.js.map +1 -1
  121. package/build-module/composite/v2.js +15 -0
  122. package/build-module/composite/v2.js.map +1 -0
  123. package/build-module/confirm-dialog/component.js +72 -7
  124. package/build-module/confirm-dialog/component.js.map +1 -1
  125. package/build-module/confirm-dialog/types.js.map +1 -1
  126. package/build-module/custom-gradient-picker/gradient-bar/control-points.js +13 -4
  127. package/build-module/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
  128. package/build-module/dropdown-menu-v2-ariakit/index.js +199 -0
  129. package/build-module/dropdown-menu-v2-ariakit/index.js.map +1 -0
  130. package/build-module/dropdown-menu-v2-ariakit/styles.js +136 -0
  131. package/build-module/dropdown-menu-v2-ariakit/styles.js.map +1 -0
  132. package/build-module/dropdown-menu-v2-ariakit/types.js +2 -0
  133. package/build-module/dropdown-menu-v2-ariakit/types.js.map +1 -0
  134. package/build-module/font-size-picker/utils.js +1 -1
  135. package/build-module/font-size-picker/utils.js.map +1 -1
  136. package/build-module/input-control/styles/input-control-styles.js +23 -23
  137. package/build-module/input-control/styles/input-control-styles.js.map +1 -1
  138. package/build-module/mobile/global-styles-context/utils.native.js +2 -2
  139. package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
  140. package/build-module/modal/index.js +47 -18
  141. package/build-module/modal/index.js.map +1 -1
  142. package/build-module/palette-edit/index.js +4 -0
  143. package/build-module/palette-edit/index.js.map +1 -1
  144. package/build-module/popover/index.js +34 -6
  145. package/build-module/popover/index.js.map +1 -1
  146. package/build-module/private-apis.js +18 -2
  147. package/build-module/private-apis.js.map +1 -1
  148. package/build-module/progress-bar/styles.js +5 -5
  149. package/build-module/progress-bar/styles.js.map +1 -1
  150. package/build-module/sandbox/index.js +1 -1
  151. package/build-module/sandbox/index.js.map +1 -1
  152. package/build-module/sandbox/index.native.js +1 -1
  153. package/build-module/sandbox/index.native.js.map +1 -1
  154. package/build-module/select-control/styles/select-control-styles.js +8 -8
  155. package/build-module/select-control/styles/select-control-styles.js.map +1 -1
  156. package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
  157. package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
  158. package/build-module/tabs/context.js +12 -0
  159. package/build-module/tabs/context.js.map +1 -0
  160. package/build-module/tabs/index.js +142 -0
  161. package/build-module/tabs/index.js.map +1 -0
  162. package/build-module/tabs/styles.js +36 -0
  163. package/build-module/tabs/styles.js.map +1 -0
  164. package/build-module/tabs/tab.js +43 -0
  165. package/build-module/tabs/tab.js.map +1 -0
  166. package/build-module/tabs/tablist.js +41 -0
  167. package/build-module/tabs/tablist.js.map +1 -0
  168. package/build-module/tabs/tabpanel.js +43 -0
  169. package/build-module/tabs/tabpanel.js.map +1 -0
  170. package/build-module/tabs/types.js +2 -0
  171. package/build-module/tabs/types.js.map +1 -0
  172. package/build-module/text/component.js +6 -6
  173. package/build-module/text/component.js.map +1 -1
  174. package/build-module/text/hook.js +11 -19
  175. package/build-module/text/hook.js.map +1 -1
  176. package/build-module/text/index.js.map +1 -1
  177. package/build-module/text/styles.js +7 -7
  178. package/build-module/text/styles.js.map +1 -1
  179. package/build-module/text/types.js.map +1 -1
  180. package/build-module/text/utils.js +17 -10
  181. package/build-module/text/utils.js.map +1 -1
  182. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js +1 -0
  183. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  184. package/build-module/toolbar/toolbar/index.js +18 -11
  185. package/build-module/toolbar/toolbar/index.js.map +1 -1
  186. package/build-module/toolbar/toolbar/types.js.map +1 -1
  187. package/build-module/tools-panel/tools-panel-item/hook.js +2 -2
  188. package/build-module/tools-panel/tools-panel-item/hook.js.map +1 -1
  189. package/build-module/tools-panel/types.js.map +1 -1
  190. package/build-module/tooltip/index.js +2 -2
  191. package/build-module/tooltip/index.js.map +1 -1
  192. package/build-module/unit-control/utils.js +108 -0
  193. package/build-module/unit-control/utils.js.map +1 -1
  194. package/build-module/utils/unit-values.js +1 -1
  195. package/build-module/utils/unit-values.js.map +1 -1
  196. package/build-style/style-rtl.css +17 -5
  197. package/build-style/style.css +17 -5
  198. package/build-types/alignment-matrix-control/cell.d.ts +1 -1
  199. package/build-types/alignment-matrix-control/cell.d.ts.map +1 -1
  200. package/build-types/alignment-matrix-control/index.d.ts.map +1 -1
  201. package/build-types/alignment-matrix-control/stories/index.story.d.ts.map +1 -1
  202. package/build-types/alignment-matrix-control/utils.d.ts +9 -9
  203. package/build-types/alignment-matrix-control/utils.d.ts.map +1 -1
  204. package/build-types/autocomplete/index.d.ts.map +1 -1
  205. package/build-types/circular-option-picker/circular-option-picker-option.d.ts.map +1 -1
  206. package/build-types/circular-option-picker/circular-option-picker.d.ts.map +1 -1
  207. package/build-types/circular-option-picker/types.d.ts +4 -6
  208. package/build-types/circular-option-picker/types.d.ts.map +1 -1
  209. package/build-types/color-palette/index.d.ts.map +1 -1
  210. package/build-types/color-picker/component.d.ts.map +1 -1
  211. package/build-types/color-picker/picker.d.ts +1 -1
  212. package/build-types/color-picker/picker.d.ts.map +1 -1
  213. package/build-types/color-picker/styles.d.ts.map +1 -1
  214. package/build-types/color-picker/types.d.ts +3 -0
  215. package/build-types/color-picker/types.d.ts.map +1 -1
  216. package/build-types/composite/v2.d.ts +12 -0
  217. package/build-types/composite/v2.d.ts.map +1 -0
  218. package/build-types/confirm-dialog/component.d.ts +70 -29
  219. package/build-types/confirm-dialog/component.d.ts.map +1 -1
  220. package/build-types/confirm-dialog/stories/index.story.d.ts +11 -0
  221. package/build-types/confirm-dialog/stories/index.story.d.ts.map +1 -0
  222. package/build-types/confirm-dialog/test/index.d.ts +2 -0
  223. package/build-types/confirm-dialog/test/index.d.ts.map +1 -0
  224. package/build-types/confirm-dialog/types.d.ts +32 -10
  225. package/build-types/confirm-dialog/types.d.ts.map +1 -1
  226. package/build-types/custom-gradient-picker/gradient-bar/control-points.d.ts.map +1 -1
  227. package/build-types/dropdown-menu-v2-ariakit/index.d.ts +11 -0
  228. package/build-types/dropdown-menu-v2-ariakit/index.d.ts.map +1 -0
  229. package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts +16 -0
  230. package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts.map +1 -0
  231. package/build-types/dropdown-menu-v2-ariakit/styles.d.ts +88 -0
  232. package/build-types/dropdown-menu-v2-ariakit/styles.d.ts.map +1 -0
  233. package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts +2 -0
  234. package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts.map +1 -0
  235. package/build-types/dropdown-menu-v2-ariakit/types.d.ts +174 -0
  236. package/build-types/dropdown-menu-v2-ariakit/types.d.ts.map +1 -0
  237. package/build-types/font-size-picker/utils.d.ts.map +1 -1
  238. package/build-types/heading/stories/index.story.d.ts.map +1 -1
  239. package/build-types/modal/index.d.ts.map +1 -1
  240. package/build-types/palette-edit/index.d.ts.map +1 -1
  241. package/build-types/popover/index.d.ts +1 -1
  242. package/build-types/popover/index.d.ts.map +1 -1
  243. package/build-types/popover/stories/e2e/index.story.d.ts +1 -1
  244. package/build-types/private-apis.d.ts.map +1 -1
  245. package/build-types/progress-bar/styles.d.ts.map +1 -1
  246. package/build-types/sandbox/index.d.ts.map +1 -1
  247. package/build-types/tabs/context.d.ts +8 -0
  248. package/build-types/tabs/context.d.ts.map +1 -0
  249. package/build-types/tabs/index.d.ts +13 -0
  250. package/build-types/tabs/index.d.ts.map +1 -0
  251. package/build-types/tabs/stories/index.story.d.ts +20 -0
  252. package/build-types/tabs/stories/index.story.d.ts.map +1 -0
  253. package/build-types/tabs/styles.d.ts +17 -0
  254. package/build-types/tabs/styles.d.ts.map +1 -0
  255. package/build-types/tabs/tab.d.ts +10 -0
  256. package/build-types/tabs/tab.d.ts.map +1 -0
  257. package/build-types/tabs/tablist.d.ts +7 -0
  258. package/build-types/tabs/tablist.d.ts.map +1 -0
  259. package/build-types/tabs/tabpanel.d.ts +7 -0
  260. package/build-types/tabs/tabpanel.d.ts.map +1 -0
  261. package/build-types/tabs/test/index.d.ts +2 -0
  262. package/build-types/tabs/test/index.d.ts.map +1 -0
  263. package/build-types/tabs/types.d.ts +134 -0
  264. package/build-types/tabs/types.d.ts.map +1 -0
  265. package/build-types/text/component.d.ts +4 -2
  266. package/build-types/text/component.d.ts.map +1 -1
  267. package/build-types/text/hook.d.ts +171 -165
  268. package/build-types/text/hook.d.ts.map +1 -1
  269. package/build-types/text/index.d.ts +2 -2
  270. package/build-types/text/index.d.ts.map +1 -1
  271. package/build-types/text/stories/index.story.d.ts +21 -0
  272. package/build-types/text/stories/index.story.d.ts.map +1 -0
  273. package/build-types/text/styles.d.ts +7 -7
  274. package/build-types/text/styles.d.ts.map +1 -1
  275. package/build-types/text/types.d.ts +1 -1
  276. package/build-types/text/types.d.ts.map +1 -1
  277. package/build-types/text/utils.d.ts +56 -61
  278. package/build-types/text/utils.d.ts.map +1 -1
  279. package/build-types/toggle-group-control/toggle-group-control-option-base/component.d.ts.map +1 -1
  280. package/build-types/toolbar/stories/index.story.d.ts +5 -0
  281. package/build-types/toolbar/stories/index.story.d.ts.map +1 -1
  282. package/build-types/toolbar/toolbar/index.d.ts.map +1 -1
  283. package/build-types/toolbar/toolbar/types.d.ts +10 -0
  284. package/build-types/toolbar/toolbar/types.d.ts.map +1 -1
  285. package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
  286. package/build-types/tools-panel/types.d.ts +2 -0
  287. package/build-types/tools-panel/types.d.ts.map +1 -1
  288. package/build-types/tooltip/index.d.ts.map +1 -1
  289. package/build-types/unit-control/utils.d.ts.map +1 -1
  290. package/package.json +21 -20
  291. package/src/alignment-matrix-control/cell.tsx +6 -2
  292. package/src/alignment-matrix-control/index.tsx +31 -54
  293. package/src/alignment-matrix-control/stories/index.story.tsx +3 -7
  294. package/src/alignment-matrix-control/test/index.tsx +117 -18
  295. package/src/alignment-matrix-control/utils.tsx +33 -9
  296. package/src/autocomplete/index.tsx +136 -77
  297. package/src/button/style.scss +1 -2
  298. package/src/circular-option-picker/circular-option-picker-option.tsx +24 -38
  299. package/src/circular-option-picker/circular-option-picker.tsx +11 -28
  300. package/src/circular-option-picker/types.ts +6 -5
  301. package/src/color-palette/index.tsx +6 -1
  302. package/src/color-picker/component.tsx +25 -3
  303. package/src/color-picker/picker.tsx +96 -2
  304. package/src/color-picker/styles.ts +0 -1
  305. package/src/color-picker/types.ts +3 -0
  306. package/src/composite/v2.ts +22 -0
  307. package/src/confirm-dialog/README.md +1 -1
  308. package/src/confirm-dialog/component.tsx +79 -13
  309. package/src/confirm-dialog/stories/{index.story.js → index.story.tsx} +26 -24
  310. package/src/confirm-dialog/test/{index.js → index.tsx} +3 -3
  311. package/src/confirm-dialog/types.ts +32 -12
  312. package/src/custom-gradient-picker/gradient-bar/control-points.tsx +32 -25
  313. package/src/dimension-control/test/__snapshots__/index.test.js.snap +8 -8
  314. package/src/dropdown-menu-v2-ariakit/README.md +324 -0
  315. package/src/dropdown-menu-v2-ariakit/index.tsx +318 -0
  316. package/src/dropdown-menu-v2-ariakit/stories/index.story.tsx +506 -0
  317. package/src/dropdown-menu-v2-ariakit/styles.ts +297 -0
  318. package/src/dropdown-menu-v2-ariakit/test/index.tsx +1139 -0
  319. package/src/dropdown-menu-v2-ariakit/types.ts +186 -0
  320. package/src/font-size-picker/utils.ts +2 -1
  321. package/src/heading/stories/index.story.tsx +2 -4
  322. package/src/input-control/styles/input-control-styles.tsx +2 -2
  323. package/src/mobile/global-styles-context/utils.native.js +2 -2
  324. package/src/modal/index.tsx +58 -22
  325. package/src/modal/test/index.tsx +29 -0
  326. package/src/notice/style.scss +0 -1
  327. package/src/palette-edit/index.tsx +4 -0
  328. package/src/popover/index.tsx +99 -57
  329. package/src/popover/style.scss +9 -0
  330. package/src/private-apis.ts +31 -1
  331. package/src/progress-bar/styles.ts +19 -4
  332. package/src/sandbox/index.native.js +1 -1
  333. package/src/sandbox/index.tsx +3 -1
  334. package/src/select-control/styles/select-control-styles.ts +2 -2
  335. package/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +1 -1
  336. package/src/tabs/README.md +242 -0
  337. package/src/tabs/context.ts +13 -0
  338. package/src/tabs/index.tsx +167 -0
  339. package/src/tabs/stories/index.story.tsx +352 -0
  340. package/src/tabs/styles.ts +103 -0
  341. package/src/tabs/tab.tsx +39 -0
  342. package/src/tabs/tablist.tsx +40 -0
  343. package/src/tabs/tabpanel.tsx +42 -0
  344. package/src/tabs/test/index.tsx +1133 -0
  345. package/src/tabs/types.ts +142 -0
  346. package/src/text/README.md +2 -2
  347. package/src/text/{component.js → component.tsx} +10 -6
  348. package/src/text/{hook.js → hook.ts} +12 -15
  349. package/src/text/stories/index.story.tsx +80 -0
  350. package/src/text/types.ts +1 -6
  351. package/src/text/{utils.js → utils.ts} +40 -14
  352. package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +16 -0
  353. package/src/toggle-group-control/toggle-group-control-option-base/component.tsx +1 -0
  354. package/src/toolbar/stories/index.story.tsx +15 -0
  355. package/src/toolbar/test/index.tsx +8 -0
  356. package/src/toolbar/toolbar/README.md +9 -0
  357. package/src/toolbar/toolbar/index.tsx +21 -12
  358. package/src/toolbar/toolbar/style.scss +9 -0
  359. package/src/toolbar/toolbar/types.ts +10 -0
  360. package/src/tools-panel/tools-panel/README.md +3 -0
  361. package/src/tools-panel/tools-panel-item/hook.ts +4 -6
  362. package/src/tools-panel/types.ts +2 -0
  363. package/src/tooltip/index.tsx +2 -3
  364. package/src/unit-control/utils.ts +124 -0
  365. package/src/utils/unit-values.ts +1 -1
  366. package/tsconfig.tsbuildinfo +1 -1
  367. package/src/text/stories/index.story.js +0 -53
  368. /package/src/text/{index.js → index.ts} +0 -0
  369. /package/src/text/{styles.js → styles.ts} +0 -0
@@ -22,6 +22,8 @@ import {
22
22
  isCollapsed,
23
23
  getTextContent,
24
24
  } from '@wordpress/rich-text';
25
+ import { speak } from '@wordpress/a11y';
26
+ import { isAppleOS } from '@wordpress/keycodes';
25
27
 
26
28
  /**
27
29
  * Internal dependencies
@@ -39,6 +41,35 @@ import type {
39
41
  WPCompleter,
40
42
  } from './types';
41
43
 
44
+ const getNodeText = ( node: React.ReactNode ): string => {
45
+ if ( node === null ) {
46
+ return '';
47
+ }
48
+
49
+ switch ( typeof node ) {
50
+ case 'string':
51
+ case 'number':
52
+ return node.toString();
53
+ break;
54
+ case 'boolean':
55
+ return '';
56
+ break;
57
+ case 'object': {
58
+ if ( node instanceof Array ) {
59
+ return node.map( getNodeText ).join( '' );
60
+ }
61
+ if ( 'props' in node ) {
62
+ return getNodeText( node.props.children );
63
+ }
64
+ break;
65
+ }
66
+ default:
67
+ return '';
68
+ }
69
+
70
+ return '';
71
+ };
72
+
42
73
  const EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];
43
74
 
44
75
  export function useAutocomplete( {
@@ -163,20 +194,35 @@ export function useAutocomplete( {
163
194
  ) {
164
195
  return;
165
196
  }
197
+
166
198
  switch ( event.key ) {
167
- case 'ArrowUp':
168
- setSelectedIndex(
199
+ case 'ArrowUp': {
200
+ const newIndex =
169
201
  ( selectedIndex === 0
170
202
  ? filteredOptions.length
171
- : selectedIndex ) - 1
172
- );
203
+ : selectedIndex ) - 1;
204
+ setSelectedIndex( newIndex );
205
+ // See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902.
206
+ if ( isAppleOS() ) {
207
+ speak(
208
+ getNodeText( filteredOptions[ newIndex ].label ),
209
+ 'assertive'
210
+ );
211
+ }
173
212
  break;
213
+ }
174
214
 
175
- case 'ArrowDown':
176
- setSelectedIndex(
177
- ( selectedIndex + 1 ) % filteredOptions.length
178
- );
215
+ case 'ArrowDown': {
216
+ const newIndex = ( selectedIndex + 1 ) % filteredOptions.length;
217
+ setSelectedIndex( newIndex );
218
+ if ( isAppleOS() ) {
219
+ speak(
220
+ getNodeText( filteredOptions[ newIndex ].label ),
221
+ 'assertive'
222
+ );
223
+ }
179
224
  break;
225
+ }
180
226
 
181
227
  case 'Escape':
182
228
  setAutocompleter( null );
@@ -218,82 +264,95 @@ export function useAutocomplete( {
218
264
  return;
219
265
  }
220
266
 
221
- const completer = completers?.find(
222
- ( { triggerPrefix, allowContext } ) => {
223
- const index = textContent.lastIndexOf( triggerPrefix );
224
-
225
- if ( index === -1 ) {
226
- return false;
227
- }
228
-
229
- const textWithoutTrigger = textContent.slice(
230
- index + triggerPrefix.length
267
+ // Find the completer with the highest triggerPrefix index in the
268
+ // textContent.
269
+ const completer = completers.reduce< WPCompleter | null >(
270
+ ( lastTrigger, currentCompleter ) => {
271
+ const triggerIndex = textContent.lastIndexOf(
272
+ currentCompleter.triggerPrefix
231
273
  );
274
+ const lastTriggerIndex =
275
+ lastTrigger !== null
276
+ ? textContent.lastIndexOf( lastTrigger.triggerPrefix )
277
+ : -1;
278
+
279
+ return triggerIndex > lastTriggerIndex
280
+ ? currentCompleter
281
+ : lastTrigger;
282
+ },
283
+ null
284
+ );
232
285
 
233
- const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.
234
- // This is a final barrier to prevent the effect from completing with
235
- // an extremely long string, which causes the editor to slow-down
236
- // significantly. This could happen, for example, if `matchingWhileBackspacing`
237
- // is true and one of the "words" end up being too long. If that's the case,
238
- // it will be caught by this guard.
239
- if ( tooDistantFromTrigger ) return false;
240
-
241
- const mismatch = filteredOptions.length === 0;
242
- const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
243
- // We need to allow the effect to run when not backspacing and if there
244
- // was a mismatch. i.e when typing a trigger + the match string or when
245
- // clicking in an existing trigger word on the page. We do that if we
246
- // detect that we have one word from trigger in the current textual context.
247
- //
248
- // Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
249
- // allow the effect to run. It will run until there's a mismatch.
250
- const hasOneTriggerWord = wordsFromTrigger.length === 1;
251
- // This is used to allow the effect to run when backspacing and if
252
- // "touching" a word that "belongs" to a trigger. We consider a "trigger
253
- // word" any word up to the limit of 3 from the trigger character.
254
- // Anything beyond that is ignored if there's a mismatch. This allows
255
- // us to "escape" a mismatch when backspacing, but still imposing some
256
- // sane limits.
257
- //
258
- // Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
259
- // if the user presses backspace here, it will show the completion popup again.
260
- const matchingWhileBackspacing =
261
- backspacing.current &&
262
- textWithoutTrigger.split( /\s/ ).length <= 3;
263
-
264
- if (
265
- mismatch &&
266
- ! ( matchingWhileBackspacing || hasOneTriggerWord )
267
- ) {
268
- return false;
269
- }
270
-
271
- const textAfterSelection = getTextContent(
272
- slice( record, undefined, getTextContent( record ).length )
273
- );
286
+ if ( ! completer ) {
287
+ if ( autocompleter ) reset();
288
+ return;
289
+ }
274
290
 
275
- if (
276
- allowContext &&
277
- ! allowContext(
278
- textContent.slice( 0, index ),
279
- textAfterSelection
280
- )
281
- ) {
282
- return false;
283
- }
291
+ const { allowContext, triggerPrefix } = completer;
292
+ const triggerIndex = textContent.lastIndexOf( triggerPrefix );
293
+ const textWithoutTrigger = textContent.slice(
294
+ triggerIndex + triggerPrefix.length
295
+ );
284
296
 
285
- if (
286
- /^\s/.test( textWithoutTrigger ) ||
287
- /\s\s+$/.test( textWithoutTrigger )
288
- ) {
289
- return false;
290
- }
297
+ const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.
298
+ // This is a final barrier to prevent the effect from completing with
299
+ // an extremely long string, which causes the editor to slow-down
300
+ // significantly. This could happen, for example, if `matchingWhileBackspacing`
301
+ // is true and one of the "words" end up being too long. If that's the case,
302
+ // it will be caught by this guard.
303
+ if ( tooDistantFromTrigger ) return;
304
+
305
+ const mismatch = filteredOptions.length === 0;
306
+ const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
307
+ // We need to allow the effect to run when not backspacing and if there
308
+ // was a mismatch. i.e when typing a trigger + the match string or when
309
+ // clicking in an existing trigger word on the page. We do that if we
310
+ // detect that we have one word from trigger in the current textual context.
311
+ //
312
+ // Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
313
+ // allow the effect to run. It will run until there's a mismatch.
314
+ const hasOneTriggerWord = wordsFromTrigger.length === 1;
315
+ // This is used to allow the effect to run when backspacing and if
316
+ // "touching" a word that "belongs" to a trigger. We consider a "trigger
317
+ // word" any word up to the limit of 3 from the trigger character.
318
+ // Anything beyond that is ignored if there's a mismatch. This allows
319
+ // us to "escape" a mismatch when backspacing, but still imposing some
320
+ // sane limits.
321
+ //
322
+ // Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
323
+ // if the user presses backspace here, it will show the completion popup again.
324
+ const matchingWhileBackspacing =
325
+ backspacing.current && wordsFromTrigger.length <= 3;
326
+
327
+ if ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) {
328
+ if ( autocompleter ) reset();
329
+ return;
330
+ }
291
331
 
292
- return /[\u0000-\uFFFF]*$/.test( textWithoutTrigger );
293
- }
332
+ const textAfterSelection = getTextContent(
333
+ slice( record, undefined, getTextContent( record ).length )
294
334
  );
295
335
 
296
- if ( ! completer ) {
336
+ if (
337
+ allowContext &&
338
+ ! allowContext(
339
+ textContent.slice( 0, triggerIndex ),
340
+ textAfterSelection
341
+ )
342
+ ) {
343
+ if ( autocompleter ) reset();
344
+ return;
345
+ }
346
+
347
+ if (
348
+ /^\s/.test( textWithoutTrigger ) ||
349
+ /\s\s+$/.test( textWithoutTrigger )
350
+ ) {
351
+ if ( autocompleter ) reset();
352
+ return;
353
+ }
354
+
355
+ if ( ! /[\u0000-\uFFFF]*$/.test( textWithoutTrigger ) ) {
297
356
  if ( autocompleter ) reset();
298
357
  return;
299
358
  }
@@ -308,8 +308,7 @@
308
308
  }
309
309
 
310
310
  // Toggled style.
311
- &[aria-pressed="true"],
312
- &[aria-pressed="mixed"] {
311
+ &.is-pressed {
313
312
  color: $components-color-foreground-inverted;
314
313
  background: $components-color-foreground;
315
314
 
@@ -8,7 +8,7 @@ import type { ForwardedRef } from 'react';
8
8
  * WordPress dependencies
9
9
  */
10
10
  import { useInstanceId } from '@wordpress/compose';
11
- import { forwardRef, useContext, useEffect } from '@wordpress/element';
11
+ import { forwardRef, useContext } from '@wordpress/element';
12
12
  import { Icon, check } from '@wordpress/icons';
13
13
 
14
14
  /**
@@ -16,15 +16,9 @@ import { Icon, check } from '@wordpress/icons';
16
16
  */
17
17
  import { CircularOptionPickerContext } from './circular-option-picker-context';
18
18
  import Button from '../button';
19
- import { CompositeItem } from '../composite';
19
+ import { CompositeItem } from '../composite/v2';
20
20
  import Tooltip from '../tooltip';
21
- import type {
22
- OptionProps,
23
- CircularOptionPickerCompositeState,
24
- CircularOptionPickerContextProps,
25
- } from './types';
26
-
27
- const hasSelectedOption = new Map();
21
+ import type { OptionProps, CircularOptionPickerCompositeStore } from './types';
28
22
 
29
23
  function UnforwardedOptionAsButton(
30
24
  props: {
@@ -40,7 +34,7 @@ function UnforwardedOptionAsButton(
40
34
  { ...additionalProps }
41
35
  aria-pressed={ isPressed }
42
36
  ref={ forwardedRef }
43
- ></Button>
37
+ />
44
38
  );
45
39
  }
46
40
 
@@ -51,38 +45,29 @@ function UnforwardedOptionAsOption(
51
45
  id: string;
52
46
  className?: string;
53
47
  isSelected?: boolean;
54
- context: CircularOptionPickerContextProps;
48
+ compositeStore: CircularOptionPickerCompositeStore;
55
49
  },
56
50
  forwardedRef: ForwardedRef< any >
57
51
  ) {
58
- const { id, isSelected, context, ...additionalProps } = props;
59
- const { isComposite, ..._compositeState } = context;
60
- const compositeState =
61
- _compositeState as CircularOptionPickerCompositeState;
62
- const { baseId, currentId, setCurrentId } = compositeState;
52
+ const { id, isSelected, compositeStore, ...additionalProps } = props;
53
+ const activeId = compositeStore.useState( 'activeId' );
63
54
 
64
- useEffect( () => {
65
- // If we call `setCurrentId` here, it doesn't update for other
66
- // Option renders in the same pass. So we have to store our own
67
- // map to make sure that we only set the first selected option.
68
- // We still need to check `currentId` because the control will
69
- // update this as the user moves around, and that state should
70
- // be maintained as the group gains and loses focus.
71
- if ( isSelected && ! currentId && ! hasSelectedOption.get( baseId ) ) {
72
- hasSelectedOption.set( baseId, true );
73
- setCurrentId( id );
74
- }
75
- }, [ baseId, currentId, id, isSelected, setCurrentId ] );
55
+ if ( isSelected && ! activeId ) {
56
+ compositeStore.setActiveId( id );
57
+ }
76
58
 
77
59
  return (
78
60
  <CompositeItem
79
- { ...additionalProps }
80
- { ...compositeState }
81
- as={ Button }
61
+ render={
62
+ <Button
63
+ { ...additionalProps }
64
+ role="option"
65
+ aria-selected={ !! isSelected }
66
+ ref={ forwardedRef }
67
+ />
68
+ }
69
+ store={ compositeStore }
82
70
  id={ id }
83
- role="option"
84
- aria-selected={ !! isSelected }
85
- ref={ forwardedRef }
86
71
  />
87
72
  );
88
73
  }
@@ -96,8 +81,9 @@ export function Option( {
96
81
  tooltipText,
97
82
  ...additionalProps
98
83
  }: OptionProps ) {
99
- const compositeContext = useContext( CircularOptionPickerContext );
100
- const { isComposite, baseId } = compositeContext;
84
+ const { baseId, compositeStore } = useContext(
85
+ CircularOptionPickerContext
86
+ );
101
87
  const id = useInstanceId(
102
88
  Option,
103
89
  baseId || 'components-circular-option-picker__option'
@@ -109,10 +95,10 @@ export function Option( {
109
95
  ...additionalProps,
110
96
  };
111
97
 
112
- const optionControl = isComposite ? (
98
+ const optionControl = compositeStore ? (
113
99
  <OptionAsOption
114
100
  { ...commonProps }
115
- context={ compositeContext }
101
+ compositeStore={ compositeStore }
116
102
  isSelected={ isSelected }
117
103
  />
118
104
  ) : (
@@ -7,14 +7,13 @@ import classnames from 'classnames';
7
7
  * WordPress dependencies
8
8
  */
9
9
  import { useInstanceId } from '@wordpress/compose';
10
- import { useEffect } from '@wordpress/element';
11
10
  import { isRTL } from '@wordpress/i18n';
12
11
 
13
12
  /**
14
13
  * Internal dependencies
15
14
  */
16
15
  import { CircularOptionPickerContext } from './circular-option-picker-context';
17
- import { Composite, useCompositeState } from '../composite';
16
+ import { Composite, useCompositeStore } from '../composite/v2';
18
17
  import type {
19
18
  CircularOptionPickerProps,
20
19
  ListboxCircularOptionPickerProps,
@@ -85,30 +84,15 @@ function ListboxCircularOptionPicker(
85
84
  children,
86
85
  ...additionalProps
87
86
  } = props;
88
- const rtl = isRTL();
89
87
 
90
- const compositeState = useCompositeState( { baseId, loop, rtl } );
91
- const { setBaseId, setLoop, setRTL } = compositeState;
92
-
93
- // These are necessary as `useCompositeState` is sealed after
94
- // the first render, so although unlikely to happen, if a state
95
- // property should change, we need to process it accordingly.
96
-
97
- useEffect( () => {
98
- setBaseId( baseId );
99
- }, [ setBaseId, baseId ] );
100
-
101
- useEffect( () => {
102
- setLoop( loop );
103
- }, [ setLoop, loop ] );
104
-
105
- useEffect( () => {
106
- setRTL( rtl );
107
- }, [ setRTL, rtl ] );
88
+ const compositeStore = useCompositeStore( {
89
+ focusLoop: loop,
90
+ rtl: isRTL(),
91
+ } );
108
92
 
109
93
  const compositeContext = {
110
- isComposite: true,
111
- ...compositeState,
94
+ baseId,
95
+ compositeStore,
112
96
  };
113
97
 
114
98
  return (
@@ -116,7 +100,8 @@ function ListboxCircularOptionPicker(
116
100
  <CircularOptionPickerContext.Provider value={ compositeContext }>
117
101
  <Composite
118
102
  { ...additionalProps }
119
- { ...compositeState }
103
+ id={ baseId }
104
+ store={ compositeStore }
120
105
  role={ 'listbox' }
121
106
  >
122
107
  { options }
@@ -134,10 +119,8 @@ function ButtonsCircularOptionPicker(
134
119
  const { actions, options, children, baseId, ...additionalProps } = props;
135
120
 
136
121
  return (
137
- <div { ...additionalProps }>
138
- <CircularOptionPickerContext.Provider
139
- value={ { isComposite: false, baseId } }
140
- >
122
+ <div { ...additionalProps } id={ baseId }>
123
+ <CircularOptionPickerContext.Provider value={ { baseId } }>
141
124
  { options }
142
125
  { children }
143
126
  { actions }
@@ -14,7 +14,7 @@ import type { Icon } from '@wordpress/icons';
14
14
  import type { ButtonAsButtonProps } from '../button/types';
15
15
  import type { DropdownProps } from '../dropdown/types';
16
16
  import type { WordPressComponentProps } from '../context';
17
- import type { CompositeState } from '../composite';
17
+ import type { CompositeStore } from '../composite/v2';
18
18
 
19
19
  type CommonCircularOptionPickerProps = {
20
20
  /**
@@ -123,7 +123,8 @@ export type OptionProps = Omit<
123
123
  >;
124
124
  };
125
125
 
126
- export type CircularOptionPickerCompositeState = CompositeState;
127
- export type CircularOptionPickerContextProps =
128
- | { isComposite?: false; baseId?: string }
129
- | ( { isComposite: true } & CircularOptionPickerCompositeState );
126
+ export type CircularOptionPickerCompositeStore = CompositeStore;
127
+ export type CircularOptionPickerContextProps = {
128
+ baseId?: string;
129
+ compositeStore?: CircularOptionPickerCompositeStore;
130
+ };
@@ -147,6 +147,10 @@ export function CustomColorPickerDropdown( {
147
147
  const popoverProps = useMemo< DropdownProps[ 'popoverProps' ] >(
148
148
  () => ( {
149
149
  shift: true,
150
+ // Disabling resize as it would otherwise cause the popover to show
151
+ // scrollbars while dragging the color picker's handle close to the
152
+ // popover edge.
153
+ resize: false,
150
154
  ...( isRenderedInSidebar
151
155
  ? {
152
156
  // When in the sidebar: open to the left (stacking),
@@ -299,6 +303,7 @@ function UnforwardedColorPalette(
299
303
  style={ {
300
304
  background: value,
301
305
  } }
306
+ type="button"
302
307
  />
303
308
  <VStack
304
309
  className="components-color-palette__custom-color-text-wrapper"
@@ -307,7 +312,7 @@ function UnforwardedColorPalette(
307
312
  <Truncate className="components-color-palette__custom-color-name">
308
313
  { value
309
314
  ? buttonLabelName
310
- : 'No color selected' }
315
+ : __( 'No color selected' ) }
311
316
  </Truncate>
312
317
  { /*
313
318
  This `Truncate` is always rendered, even if
@@ -10,7 +10,7 @@ import namesPlugin from 'colord/plugins/names';
10
10
  * WordPress dependencies
11
11
  */
12
12
  import { useCallback, useState, useMemo } from '@wordpress/element';
13
- import { useDebounce } from '@wordpress/compose';
13
+ import { useDebounce, useMergeRefs } from '@wordpress/compose';
14
14
  import { __ } from '@wordpress/i18n';
15
15
 
16
16
  /**
@@ -49,8 +49,24 @@ const UnconnectedColorPicker = (
49
49
  onChange,
50
50
  defaultValue = '#fff',
51
51
  copyFormat,
52
+
53
+ // Context
54
+ onPickerDragStart,
55
+ onPickerDragEnd,
52
56
  ...divProps
53
- } = useContextSystem( props, 'ColorPicker' );
57
+ } = useContextSystem<
58
+ ColorPickerProps & {
59
+ onPickerDragStart?: ( event: MouseEvent ) => void;
60
+ onPickerDragEnd?: ( event: MouseEvent ) => void;
61
+ }
62
+ >( props, 'ColorPicker' );
63
+
64
+ const [ containerEl, setContainerEl ] = useState< HTMLElement | null >(
65
+ null
66
+ );
67
+ const containerRef = ( node: HTMLElement | null ) => {
68
+ setContainerEl( node );
69
+ };
54
70
 
55
71
  // Use a safe default value for the color and remove the possibility of `undefined`.
56
72
  const [ color, setColor ] = useControlledValue( {
@@ -77,11 +93,17 @@ const UnconnectedColorPicker = (
77
93
  );
78
94
 
79
95
  return (
80
- <ColorfulWrapper ref={ forwardedRef } { ...divProps }>
96
+ <ColorfulWrapper
97
+ ref={ useMergeRefs( [ containerRef, forwardedRef ] ) }
98
+ { ...divProps }
99
+ >
81
100
  <Picker
101
+ containerEl={ containerEl }
82
102
  onChange={ handleChange }
83
103
  color={ safeColordColor }
84
104
  enableAlpha={ enableAlpha }
105
+ onDragStart={ onPickerDragStart }
106
+ onDragEnd={ onPickerDragEnd }
85
107
  />
86
108
  <AuxiliaryColorArtefactWrapper>
87
109
  <AuxiliaryColorArtefactHStackHeader justify="space-between">
@@ -7,18 +7,112 @@ import { colord } from 'colord';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- import { useMemo } from '@wordpress/element';
10
+ import { useMemo, useEffect, useRef } from '@wordpress/element';
11
11
  /**
12
12
  * Internal dependencies
13
13
  */
14
14
  import type { PickerProps } from './types';
15
15
 
16
- export const Picker = ( { color, enableAlpha, onChange }: PickerProps ) => {
16
+ /**
17
+ * Track the start and the end of drag pointer events related to controlling
18
+ * the picker's saturation / hue / alpha, and fire the corresponding callbacks.
19
+ * This is particularly useful to implement synergies like the one with the
20
+ * `Popover` component, where a pointer events "trap" is rendered while
21
+ * the user is dragging the pointer to avoid potential interference with iframe
22
+ * elements.
23
+ *
24
+ * @param props
25
+ * @param props.containerEl
26
+ * @param props.onDragStart
27
+ * @param props.onDragEnd
28
+ */
29
+ const useOnPickerDrag = ( {
30
+ containerEl,
31
+ onDragStart,
32
+ onDragEnd,
33
+ }: Pick< PickerProps, 'containerEl' | 'onDragStart' | 'onDragEnd' > ) => {
34
+ const isDragging = useRef( false );
35
+ const leftWhileDragging = useRef( false );
36
+ useEffect( () => {
37
+ if ( ! containerEl || ( ! onDragStart && ! onDragEnd ) ) {
38
+ return;
39
+ }
40
+ const interactiveElements = [
41
+ containerEl.querySelector( '.react-colorful__saturation' ),
42
+ containerEl.querySelector( '.react-colorful__hue' ),
43
+ containerEl.querySelector( '.react-colorful__alpha' ),
44
+ ].filter( ( el ) => !! el ) as Element[];
45
+
46
+ if ( interactiveElements.length === 0 ) {
47
+ return;
48
+ }
49
+
50
+ const doc = containerEl.ownerDocument;
51
+
52
+ const onPointerUp: EventListener = ( event ) => {
53
+ isDragging.current = false;
54
+ leftWhileDragging.current = false;
55
+ onDragEnd?.( event as MouseEvent );
56
+ };
57
+
58
+ const onPointerDown: EventListener = ( event ) => {
59
+ isDragging.current = true;
60
+ onDragStart?.( event as MouseEvent );
61
+ };
62
+
63
+ const onPointerLeave: EventListener = () => {
64
+ leftWhileDragging.current = isDragging.current;
65
+ };
66
+
67
+ // Try to detect if the user released the pointer while away from the
68
+ // current window. If the check is successfull, the dragEnd callback will
69
+ // called as soon as the pointer re-enters the window (better late than never)
70
+ const onPointerEnter: EventListener = ( event ) => {
71
+ const noPointerButtonsArePressed =
72
+ ( event as PointerEvent ).buttons === 0;
73
+
74
+ if ( leftWhileDragging.current && noPointerButtonsArePressed ) {
75
+ onPointerUp( event );
76
+ }
77
+ };
78
+
79
+ // The pointerdown event is added on the interactive elements,
80
+ // while the remaining events are added on the document object since
81
+ // the pointer wouldn't necessarily be hovering the initial interactive
82
+ // element at that point.
83
+ interactiveElements.forEach( ( el ) =>
84
+ el.addEventListener( 'pointerdown', onPointerDown )
85
+ );
86
+ doc.addEventListener( 'pointerup', onPointerUp );
87
+ doc.addEventListener( 'pointerenter', onPointerEnter );
88
+ doc.addEventListener( 'pointerleave', onPointerLeave );
89
+
90
+ return () => {
91
+ interactiveElements.forEach( ( el ) =>
92
+ el.removeEventListener( 'pointerdown', onPointerDown )
93
+ );
94
+ doc.removeEventListener( 'pointerup', onPointerUp );
95
+ doc.removeEventListener( 'pointerenter', onPointerEnter );
96
+ doc.removeEventListener( 'pointerleave', onPointerUp );
97
+ };
98
+ }, [ onDragStart, onDragEnd, containerEl ] );
99
+ };
100
+
101
+ export const Picker = ( {
102
+ color,
103
+ enableAlpha,
104
+ onChange,
105
+ onDragStart,
106
+ onDragEnd,
107
+ containerEl,
108
+ }: PickerProps ) => {
17
109
  const Component = enableAlpha
18
110
  ? RgbaStringColorPicker
19
111
  : RgbStringColorPicker;
20
112
  const rgbColor = useMemo( () => color.toRgbString(), [ color ] );
21
113
 
114
+ useOnPickerDrag( { containerEl, onDragStart, onDragEnd } );
115
+
22
116
  return (
23
117
  <Component
24
118
  color={ rgbColor }
@@ -81,7 +81,6 @@ export const ColorfulWrapper = styled.div`
81
81
  align-items: center;
82
82
  width: 216px;
83
83
  height: auto;
84
- overflow: hidden;
85
84
  }
86
85
 
87
86
  .react-colorful__saturation {