@graphprotocol/gds-react 0.1.2 → 0.2.1

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 (433) hide show
  1. package/dist/GDSContext.d.ts +13 -0
  2. package/dist/GDSContext.d.ts.map +1 -0
  3. package/dist/GDSContext.js +4 -0
  4. package/dist/GDSContext.js.map +1 -0
  5. package/dist/GDSProvider.d.ts +13 -19
  6. package/dist/GDSProvider.d.ts.map +1 -1
  7. package/dist/GDSProvider.js +14 -11
  8. package/dist/GDSProvider.js.map +1 -1
  9. package/dist/components/Address.js +2 -2
  10. package/dist/components/Address.meta.d.ts +1 -13
  11. package/dist/components/Address.meta.d.ts.map +1 -1
  12. package/dist/components/Avatar.d.ts.map +1 -1
  13. package/dist/components/Avatar.js +3 -11
  14. package/dist/components/Avatar.js.map +1 -1
  15. package/dist/components/Avatar.meta.d.ts +0 -2
  16. package/dist/components/Avatar.meta.d.ts.map +1 -1
  17. package/dist/components/AvatarGroup.meta.d.ts +8 -2
  18. package/dist/components/AvatarGroup.meta.d.ts.map +1 -1
  19. package/dist/components/Breadcrumbs.meta.d.ts +2 -3
  20. package/dist/components/Breadcrumbs.meta.d.ts.map +1 -1
  21. package/dist/components/Breadcrumbs.meta.js +3 -1
  22. package/dist/components/Breadcrumbs.meta.js.map +1 -1
  23. package/dist/components/Breadcrumbs.parts.d.ts.map +1 -1
  24. package/dist/components/Breadcrumbs.parts.js +13 -21
  25. package/dist/components/Breadcrumbs.parts.js.map +1 -1
  26. package/dist/components/Button.d.ts.map +1 -1
  27. package/dist/components/Button.js +70 -69
  28. package/dist/components/Button.js.map +1 -1
  29. package/dist/components/Button.meta.d.ts +1 -4
  30. package/dist/components/Button.meta.d.ts.map +1 -1
  31. package/dist/components/ButtonGroup.d.ts.map +1 -1
  32. package/dist/components/ButtonGroup.js +1 -5
  33. package/dist/components/ButtonGroup.js.map +1 -1
  34. package/dist/components/ButtonGroup.meta.d.ts +1 -5
  35. package/dist/components/ButtonGroup.meta.d.ts.map +1 -1
  36. package/dist/components/ButtonGroup.meta.js +8 -0
  37. package/dist/components/ButtonGroup.meta.js.map +1 -1
  38. package/dist/components/Card.js +2 -2
  39. package/dist/components/Card.js.map +1 -1
  40. package/dist/components/Card.meta.d.ts +1 -2
  41. package/dist/components/Card.meta.d.ts.map +1 -1
  42. package/dist/components/Card.meta.js +1 -0
  43. package/dist/components/Card.meta.js.map +1 -1
  44. package/dist/components/Checkbox.meta.d.ts +1 -6
  45. package/dist/components/Checkbox.meta.d.ts.map +1 -1
  46. package/dist/components/Checkbox.meta.js +1 -5
  47. package/dist/components/Checkbox.meta.js.map +1 -1
  48. package/dist/components/Chip.meta.d.ts +2 -4
  49. package/dist/components/Chip.meta.d.ts.map +1 -1
  50. package/dist/components/Chip.parts.d.ts.map +1 -1
  51. package/dist/components/Chip.parts.js +1 -9
  52. package/dist/components/Chip.parts.js.map +1 -1
  53. package/dist/components/Cluster.meta.d.ts +8 -2
  54. package/dist/components/Cluster.meta.d.ts.map +1 -1
  55. package/dist/components/CodeBlock.d.ts +1 -1
  56. package/dist/components/CodeBlock.meta.d.ts +2 -4
  57. package/dist/components/CodeBlock.meta.d.ts.map +1 -1
  58. package/dist/components/CodeBlock.parts.d.ts +6 -7
  59. package/dist/components/CodeBlock.parts.d.ts.map +1 -1
  60. package/dist/components/CodeBlock.parts.js +28 -10
  61. package/dist/components/CodeBlock.parts.js.map +1 -1
  62. package/dist/components/CodeInline.js +3 -3
  63. package/dist/components/CodeInline.meta.d.ts +1 -1
  64. package/dist/components/CodeInline.meta.d.ts.map +1 -1
  65. package/dist/components/CopyButton.d.ts +1 -1
  66. package/dist/components/CopyButton.d.ts.map +1 -1
  67. package/dist/components/CopyButton.js +46 -21
  68. package/dist/components/CopyButton.js.map +1 -1
  69. package/dist/components/CopyButton.meta.d.ts +1 -12
  70. package/dist/components/CopyButton.meta.d.ts.map +1 -1
  71. package/dist/components/CopyButton.meta.js +1 -6
  72. package/dist/components/CopyButton.meta.js.map +1 -1
  73. package/dist/components/CurrencyInput.meta.d.ts +1 -6
  74. package/dist/components/CurrencyInput.meta.d.ts.map +1 -1
  75. package/dist/components/CurrencyInput.meta.js +1 -5
  76. package/dist/components/CurrencyInput.meta.js.map +1 -1
  77. package/dist/components/DescriptionList.meta.d.ts +2 -5
  78. package/dist/components/DescriptionList.meta.d.ts.map +1 -1
  79. package/dist/components/DescriptionList.parts.d.ts +3 -0
  80. package/dist/components/DescriptionList.parts.d.ts.map +1 -1
  81. package/dist/components/DescriptionList.parts.js +1 -0
  82. package/dist/components/DescriptionList.parts.js.map +1 -1
  83. package/dist/components/Divider.meta.d.ts +1 -3
  84. package/dist/components/Divider.meta.d.ts.map +1 -1
  85. package/dist/components/Icon.js +4 -4
  86. package/dist/components/Icon.js.map +1 -1
  87. package/dist/components/Icon.meta.d.ts +0 -2
  88. package/dist/components/Icon.meta.d.ts.map +1 -1
  89. package/dist/components/Icon.meta.js +1 -0
  90. package/dist/components/Icon.meta.js.map +1 -1
  91. package/dist/components/Input.d.ts +5 -4
  92. package/dist/components/Input.d.ts.map +1 -1
  93. package/dist/components/Input.js +3 -2
  94. package/dist/components/Input.js.map +1 -1
  95. package/dist/components/Input.meta.d.ts +1 -6
  96. package/dist/components/Input.meta.d.ts.map +1 -1
  97. package/dist/components/Input.meta.js +1 -5
  98. package/dist/components/Input.meta.js.map +1 -1
  99. package/dist/components/Keyboard.js +1 -1
  100. package/dist/components/Keyboard.meta.d.ts +0 -1
  101. package/dist/components/Keyboard.meta.d.ts.map +1 -1
  102. package/dist/components/Label.meta.d.ts +1 -3
  103. package/dist/components/Label.meta.d.ts.map +1 -1
  104. package/dist/components/Link.d.ts +1 -1
  105. package/dist/components/Link.d.ts.map +1 -1
  106. package/dist/components/Link.js +3 -4
  107. package/dist/components/Link.js.map +1 -1
  108. package/dist/components/Link.meta.d.ts +1 -2
  109. package/dist/components/Link.meta.d.ts.map +1 -1
  110. package/dist/components/Link.meta.js +1 -0
  111. package/dist/components/Link.meta.js.map +1 -1
  112. package/dist/components/Menu.meta.d.ts +31 -2
  113. package/dist/components/Menu.meta.d.ts.map +1 -1
  114. package/dist/components/Menu.meta.js +39 -1
  115. package/dist/components/Menu.meta.js.map +1 -1
  116. package/dist/components/Menu.parts.d.ts +22 -32
  117. package/dist/components/Menu.parts.d.ts.map +1 -1
  118. package/dist/components/Menu.parts.js +286 -300
  119. package/dist/components/Menu.parts.js.map +1 -1
  120. package/dist/components/Modal.d.ts +1 -1
  121. package/dist/components/Modal.meta.d.ts +1 -3
  122. package/dist/components/Modal.meta.d.ts.map +1 -1
  123. package/dist/components/Modal.meta.js +1 -1
  124. package/dist/components/Modal.meta.js.map +1 -1
  125. package/dist/components/Modal.parts.d.ts +14 -15
  126. package/dist/components/Modal.parts.d.ts.map +1 -1
  127. package/dist/components/Modal.parts.js +20 -20
  128. package/dist/components/Modal.parts.js.map +1 -1
  129. package/dist/components/OTCInput.js +1 -1
  130. package/dist/components/OTCInput.meta.d.ts +1 -6
  131. package/dist/components/OTCInput.meta.d.ts.map +1 -1
  132. package/dist/components/OTCInput.meta.js +1 -5
  133. package/dist/components/OTCInput.meta.js.map +1 -1
  134. package/dist/components/Pane.d.ts +9 -0
  135. package/dist/components/Pane.d.ts.map +1 -0
  136. package/dist/components/Pane.js +8 -0
  137. package/dist/components/Pane.js.map +1 -0
  138. package/dist/components/Pane.meta.d.ts +20 -0
  139. package/dist/components/Pane.meta.d.ts.map +1 -0
  140. package/dist/components/Pane.meta.js +30 -0
  141. package/dist/components/Pane.meta.js.map +1 -0
  142. package/dist/components/Pane.parts.d.ts +77 -0
  143. package/dist/components/Pane.parts.d.ts.map +1 -0
  144. package/dist/components/Pane.parts.js +412 -0
  145. package/dist/components/Pane.parts.js.map +1 -0
  146. package/dist/components/Radio.meta.d.ts +1 -6
  147. package/dist/components/Radio.meta.d.ts.map +1 -1
  148. package/dist/components/Radio.meta.js +1 -5
  149. package/dist/components/Radio.meta.js.map +1 -1
  150. package/dist/components/Search.js +1 -1
  151. package/dist/components/Search.meta.d.ts +1 -3
  152. package/dist/components/Search.meta.d.ts.map +1 -1
  153. package/dist/components/SegmentedControl.meta.d.ts +2 -3
  154. package/dist/components/SegmentedControl.meta.d.ts.map +1 -1
  155. package/dist/components/SegmentedControl.meta.js +3 -1
  156. package/dist/components/SegmentedControl.meta.js.map +1 -1
  157. package/dist/components/SegmentedControl.parts.d.ts.map +1 -1
  158. package/dist/components/SegmentedControl.parts.js +4 -9
  159. package/dist/components/SegmentedControl.parts.js.map +1 -1
  160. package/dist/components/Status.meta.d.ts +0 -2
  161. package/dist/components/Status.meta.d.ts.map +1 -1
  162. package/dist/components/Stepper.meta.d.ts +1 -2
  163. package/dist/components/Stepper.meta.d.ts.map +1 -1
  164. package/dist/components/Stepper.meta.js +1 -0
  165. package/dist/components/Stepper.meta.js.map +1 -1
  166. package/dist/components/Stepper.parts.d.ts.map +1 -1
  167. package/dist/components/Stepper.parts.js +1 -1
  168. package/dist/components/Stepper.parts.js.map +1 -1
  169. package/dist/components/Switch.meta.d.ts +1 -6
  170. package/dist/components/Switch.meta.d.ts.map +1 -1
  171. package/dist/components/Switch.meta.js +1 -5
  172. package/dist/components/Switch.meta.js.map +1 -1
  173. package/dist/components/TabSet.meta.d.ts +2 -5
  174. package/dist/components/TabSet.meta.d.ts.map +1 -1
  175. package/dist/components/TabSet.meta.js +3 -1
  176. package/dist/components/TabSet.meta.js.map +1 -1
  177. package/dist/components/Tag.meta.d.ts +0 -2
  178. package/dist/components/Tag.meta.d.ts.map +1 -1
  179. package/dist/components/TextArea.meta.d.ts +1 -6
  180. package/dist/components/TextArea.meta.d.ts.map +1 -1
  181. package/dist/components/TextArea.meta.js +1 -5
  182. package/dist/components/TextArea.meta.js.map +1 -1
  183. package/dist/components/ToggleButton.js +2 -2
  184. package/dist/components/ToggleButton.js.map +1 -1
  185. package/dist/components/ToggleButton.meta.d.ts +1 -12
  186. package/dist/components/ToggleButton.meta.d.ts.map +1 -1
  187. package/dist/components/ToggleButton.meta.js +1 -6
  188. package/dist/components/ToggleButton.meta.js.map +1 -1
  189. package/dist/components/Tooltip.d.ts +2 -2
  190. package/dist/components/Tooltip.d.ts.map +1 -1
  191. package/dist/components/Tooltip.js +2 -2
  192. package/dist/components/Tooltip.js.map +1 -1
  193. package/dist/components/Tooltip.meta.d.ts +12 -7
  194. package/dist/components/Tooltip.meta.d.ts.map +1 -1
  195. package/dist/components/Tooltip.meta.js +13 -2
  196. package/dist/components/Tooltip.meta.js.map +1 -1
  197. package/dist/components/Tooltip.parts.d.ts +31 -22
  198. package/dist/components/Tooltip.parts.d.ts.map +1 -1
  199. package/dist/components/Tooltip.parts.js +127 -98
  200. package/dist/components/Tooltip.parts.js.map +1 -1
  201. package/dist/components/base/Addon.meta.d.ts +1 -1
  202. package/dist/components/base/Addon.meta.d.ts.map +1 -1
  203. package/dist/components/base/Addon.meta.js +3 -1
  204. package/dist/components/base/Addon.meta.js.map +1 -1
  205. package/dist/components/base/ButtonOrLink.d.ts +2 -2
  206. package/dist/components/base/ButtonOrLink.d.ts.map +1 -1
  207. package/dist/components/base/ButtonOrLink.parts.d.ts +14 -6
  208. package/dist/components/base/ButtonOrLink.parts.d.ts.map +1 -1
  209. package/dist/components/base/ButtonOrLink.parts.js +54 -65
  210. package/dist/components/base/ButtonOrLink.parts.js.map +1 -1
  211. package/dist/components/base/Checkable.meta.d.ts +1 -2
  212. package/dist/components/base/Checkable.meta.d.ts.map +1 -1
  213. package/dist/components/base/Checkable.parts.d.ts +6 -6
  214. package/dist/components/base/Checkable.parts.d.ts.map +1 -1
  215. package/dist/components/base/Checkable.parts.js +2 -2
  216. package/dist/components/base/Checkable.parts.js.map +1 -1
  217. package/dist/components/base/Field.meta.d.ts +1 -2
  218. package/dist/components/base/Field.meta.d.ts.map +1 -1
  219. package/dist/components/base/Field.parts.d.ts +5 -4
  220. package/dist/components/base/Field.parts.d.ts.map +1 -1
  221. package/dist/components/base/Field.parts.js +1 -1
  222. package/dist/components/base/Field.parts.js.map +1 -1
  223. package/dist/components/base/MaybeButtonOrLink.d.ts +20 -3
  224. package/dist/components/base/MaybeButtonOrLink.d.ts.map +1 -1
  225. package/dist/components/base/MaybeButtonOrLink.js +5 -3
  226. package/dist/components/base/MaybeButtonOrLink.js.map +1 -1
  227. package/dist/components/base/Portal.d.ts +1 -1
  228. package/dist/components/base/Portal.d.ts.map +1 -1
  229. package/dist/components/base/Portal.js +3 -6
  230. package/dist/components/base/Portal.js.map +1 -1
  231. package/dist/components/base/Presence.d.ts +157 -0
  232. package/dist/components/base/Presence.d.ts.map +1 -0
  233. package/dist/components/base/Presence.js +808 -0
  234. package/dist/components/base/Presence.js.map +1 -0
  235. package/dist/components/base/Render.d.ts +21 -6
  236. package/dist/components/base/Render.d.ts.map +1 -1
  237. package/dist/components/base/Render.js +3 -2
  238. package/dist/components/base/Render.js.map +1 -1
  239. package/dist/components/base/Transition.js +2 -2
  240. package/dist/components/base/Transition.meta.d.ts +1 -1
  241. package/dist/components/base/Transition.meta.d.ts.map +1 -1
  242. package/dist/components/base/Transition.meta.js +1 -0
  243. package/dist/components/base/Transition.meta.js.map +1 -1
  244. package/dist/components/base/index.d.ts +2 -2
  245. package/dist/components/base/index.d.ts.map +1 -1
  246. package/dist/components/base/index.js +2 -2
  247. package/dist/components/base/index.js.map +1 -1
  248. package/dist/components/index.d.ts +3 -1
  249. package/dist/components/index.d.ts.map +1 -1
  250. package/dist/components/index.js +3 -1
  251. package/dist/components/index.js.map +1 -1
  252. package/dist/hooks/index.d.ts +1 -0
  253. package/dist/hooks/index.d.ts.map +1 -1
  254. package/dist/hooks/index.js +1 -0
  255. package/dist/hooks/index.js.map +1 -1
  256. package/dist/hooks/useCSSProp.d.ts.map +1 -1
  257. package/dist/hooks/useCSSProp.js +7 -7
  258. package/dist/hooks/useCSSProp.js.map +1 -1
  259. package/dist/hooks/useCSSProps.d.ts +11 -13
  260. package/dist/hooks/useCSSProps.d.ts.map +1 -1
  261. package/dist/hooks/useCSSProps.js +11 -19
  262. package/dist/hooks/useCSSProps.js.map +1 -1
  263. package/dist/hooks/useCSSPropsPolyfill.d.ts +1 -1
  264. package/dist/hooks/useCSSPropsPolyfill.d.ts.map +1 -1
  265. package/dist/hooks/useCSSPropsPolyfill.js +12 -20
  266. package/dist/hooks/useCSSPropsPolyfill.js.map +1 -1
  267. package/dist/hooks/useCSSState.d.ts.map +1 -1
  268. package/dist/hooks/useCSSState.js +7 -3
  269. package/dist/hooks/useCSSState.js.map +1 -1
  270. package/dist/hooks/useControlled.d.ts.map +1 -1
  271. package/dist/hooks/useControlled.js +6 -4
  272. package/dist/hooks/useControlled.js.map +1 -1
  273. package/dist/hooks/useEffectWithRefDeps.d.ts +2 -2
  274. package/dist/hooks/useEffectWithRefDeps.d.ts.map +1 -1
  275. package/dist/hooks/useEffectWithRefDeps.js +1 -1
  276. package/dist/hooks/useEffectWithRefDeps.js.map +1 -1
  277. package/dist/hooks/useFirstRender.d.ts +14 -0
  278. package/dist/hooks/useFirstRender.d.ts.map +1 -0
  279. package/dist/hooks/useFirstRender.js +20 -0
  280. package/dist/hooks/useFirstRender.js.map +1 -0
  281. package/dist/hooks/useGDS.d.ts +1 -1
  282. package/dist/hooks/useGDS.js +1 -1
  283. package/dist/hooks/useGDS.js.map +1 -1
  284. package/dist/hooks/usePrevious.d.ts +6 -4
  285. package/dist/hooks/usePrevious.d.ts.map +1 -1
  286. package/dist/hooks/usePrevious.js +6 -4
  287. package/dist/hooks/usePrevious.js.map +1 -1
  288. package/dist/hooks/useRefWithInit.d.ts +2 -2
  289. package/dist/hooks/useRefWithInit.d.ts.map +1 -1
  290. package/dist/hooks/useRefWithInit.js.map +1 -1
  291. package/dist/hooks/useStyleObserver.d.ts +2 -2
  292. package/dist/hooks/useStyleObserver.d.ts.map +1 -1
  293. package/dist/hooks/useStyleObserver.js +1 -1
  294. package/dist/hooks/useStyleObserver.js.map +1 -1
  295. package/dist/icons/CalendarDynamicIcon.d.ts +8 -5
  296. package/dist/icons/CalendarDynamicIcon.d.ts.map +1 -1
  297. package/dist/icons/CalendarDynamicIcon.js +5 -2
  298. package/dist/icons/CalendarDynamicIcon.js.map +1 -1
  299. package/dist/icons/CopyInteractiveIcon.d.ts +5 -4
  300. package/dist/icons/CopyInteractiveIcon.d.ts.map +1 -1
  301. package/dist/icons/CopyInteractiveIcon.js +2 -2
  302. package/dist/icons/CopyInteractiveIcon.js.map +1 -1
  303. package/dist/icons/SidebarLeftInteractiveIcon.d.ts +4 -3
  304. package/dist/icons/SidebarLeftInteractiveIcon.d.ts.map +1 -1
  305. package/dist/icons/SidebarLeftInteractiveIcon.js +2 -2
  306. package/dist/icons/SidebarLeftInteractiveIcon.js.map +1 -1
  307. package/dist/icons/SidebarRightInteractiveIcon.d.ts +4 -3
  308. package/dist/icons/SidebarRightInteractiveIcon.d.ts.map +1 -1
  309. package/dist/icons/SidebarRightInteractiveIcon.js +2 -2
  310. package/dist/icons/SidebarRightInteractiveIcon.js.map +1 -1
  311. package/dist/tailwind-plugin.d.ts.map +1 -1
  312. package/dist/tailwind-plugin.js +8 -5
  313. package/dist/tailwind-plugin.js.map +1 -1
  314. package/dist/utils/InlineCounter.d.ts +3 -0
  315. package/dist/utils/InlineCounter.d.ts.map +1 -0
  316. package/dist/utils/InlineCounter.js +7 -0
  317. package/dist/utils/InlineCounter.js.map +1 -0
  318. package/dist/utils/RenderCount.d.ts +3 -0
  319. package/dist/utils/RenderCount.d.ts.map +1 -0
  320. package/dist/utils/RenderCount.js +7 -0
  321. package/dist/utils/RenderCount.js.map +1 -0
  322. package/dist/utils/cn.d.ts +3 -1
  323. package/dist/utils/cn.d.ts.map +1 -1
  324. package/dist/utils/cn.js +3 -1
  325. package/dist/utils/cn.js.map +1 -1
  326. package/dist/utils/getCSSPropsAttributes.d.ts +10 -3
  327. package/dist/utils/getCSSPropsAttributes.d.ts.map +1 -1
  328. package/dist/utils/getCSSPropsAttributes.js +4 -5
  329. package/dist/utils/getCSSPropsAttributes.js.map +1 -1
  330. package/dist/utils/index.d.ts +2 -0
  331. package/dist/utils/index.d.ts.map +1 -1
  332. package/dist/utils/index.js +2 -0
  333. package/dist/utils/index.js.map +1 -1
  334. package/dist/utils/splitProps.d.ts +1 -4
  335. package/dist/utils/splitProps.d.ts.map +1 -1
  336. package/dist/utils/splitProps.js +2 -7
  337. package/dist/utils/splitProps.js.map +1 -1
  338. package/dist/utils/trimReactNode.d.ts +10 -8
  339. package/dist/utils/trimReactNode.d.ts.map +1 -1
  340. package/dist/utils/trimReactNode.js +10 -8
  341. package/dist/utils/trimReactNode.js.map +1 -1
  342. package/package.json +21 -21
  343. package/src/GDSContext.ts +16 -0
  344. package/src/GDSProvider.tsx +31 -40
  345. package/src/components/Address.tsx +2 -2
  346. package/src/components/Avatar.tsx +8 -12
  347. package/src/components/Breadcrumbs.meta.ts +3 -1
  348. package/src/components/Breadcrumbs.parts.tsx +16 -28
  349. package/src/components/Button.tsx +114 -104
  350. package/src/components/ButtonGroup.meta.ts +8 -0
  351. package/src/components/ButtonGroup.tsx +1 -5
  352. package/src/components/Card.meta.ts +1 -0
  353. package/src/components/Card.tsx +2 -2
  354. package/src/components/Checkbox.meta.ts +1 -5
  355. package/src/components/Chip.parts.tsx +1 -11
  356. package/src/components/CodeBlock.parts.tsx +75 -50
  357. package/src/components/CodeInline.tsx +3 -3
  358. package/src/components/CopyButton.meta.ts +1 -6
  359. package/src/components/CopyButton.tsx +50 -27
  360. package/src/components/CurrencyInput.meta.ts +1 -5
  361. package/src/components/DescriptionList.parts.tsx +1 -0
  362. package/src/components/Icon.meta.ts +1 -0
  363. package/src/components/Icon.tsx +4 -4
  364. package/src/components/Input.meta.ts +1 -5
  365. package/src/components/Input.tsx +6 -7
  366. package/src/components/Keyboard.tsx +1 -1
  367. package/src/components/Link.meta.ts +1 -0
  368. package/src/components/Link.tsx +4 -5
  369. package/src/components/Menu.meta.ts +39 -1
  370. package/src/components/Menu.parts.tsx +554 -547
  371. package/src/components/Modal.meta.ts +1 -1
  372. package/src/components/Modal.parts.tsx +40 -46
  373. package/src/components/OTCInput.meta.ts +1 -5
  374. package/src/components/OTCInput.tsx +1 -1
  375. package/src/components/Pane.meta.ts +31 -0
  376. package/src/components/Pane.parts.tsx +713 -0
  377. package/src/components/Pane.tsx +17 -0
  378. package/src/components/Radio.meta.ts +1 -5
  379. package/src/components/Search.tsx +1 -1
  380. package/src/components/SegmentedControl.meta.ts +3 -1
  381. package/src/components/SegmentedControl.parts.tsx +7 -10
  382. package/src/components/Stepper.meta.ts +1 -0
  383. package/src/components/Stepper.parts.tsx +3 -1
  384. package/src/components/Switch.meta.ts +1 -5
  385. package/src/components/TabSet.meta.ts +3 -1
  386. package/src/components/TextArea.meta.ts +1 -5
  387. package/src/components/ToggleButton.meta.ts +1 -6
  388. package/src/components/ToggleButton.tsx +1 -1
  389. package/src/components/Tooltip.meta.ts +13 -2
  390. package/src/components/Tooltip.parts.tsx +241 -169
  391. package/src/components/Tooltip.tsx +2 -2
  392. package/src/components/base/Addon.meta.ts +3 -1
  393. package/src/components/base/ButtonOrLink.parts.tsx +118 -97
  394. package/src/components/base/ButtonOrLink.tsx +1 -0
  395. package/src/components/base/Checkable.parts.tsx +6 -13
  396. package/src/components/base/Field.parts.tsx +5 -5
  397. package/src/components/base/MaybeButtonOrLink.tsx +26 -5
  398. package/src/components/base/Portal.tsx +5 -7
  399. package/src/components/base/Presence.tsx +1375 -0
  400. package/src/components/base/Render.tsx +37 -15
  401. package/src/components/base/Transition.meta.ts +1 -0
  402. package/src/components/base/Transition.tsx +2 -2
  403. package/src/components/base/index.ts +9 -2
  404. package/src/components/index.ts +11 -2
  405. package/src/hooks/index.ts +1 -0
  406. package/src/hooks/useCSSProp.ts +7 -9
  407. package/src/hooks/useCSSProps.ts +13 -22
  408. package/src/hooks/useCSSPropsPolyfill.ts +15 -23
  409. package/src/hooks/useCSSState.ts +11 -6
  410. package/src/hooks/useControlled.ts +16 -8
  411. package/src/hooks/useEffectWithRefDeps.ts +2 -2
  412. package/src/hooks/useFirstRender.ts +36 -0
  413. package/src/hooks/useGDS.ts +1 -1
  414. package/src/hooks/usePrevious.ts +6 -4
  415. package/src/hooks/useRefWithInit.ts +2 -2
  416. package/src/hooks/useStyleObserver.ts +6 -2
  417. package/src/icons/CalendarDynamicIcon.tsx +16 -6
  418. package/src/icons/CopyInteractiveIcon.tsx +10 -5
  419. package/src/icons/SidebarLeftInteractiveIcon.tsx +9 -5
  420. package/src/icons/SidebarRightInteractiveIcon.tsx +9 -5
  421. package/src/tailwind-plugin.ts +8 -5
  422. package/src/utils/InlineCounter.tsx +17 -0
  423. package/src/utils/RenderCount.tsx +7 -0
  424. package/src/utils/cn.ts +3 -1
  425. package/src/utils/getCSSPropsAttributes.ts +13 -8
  426. package/src/utils/index.ts +2 -0
  427. package/src/utils/splitProps.ts +9 -9
  428. package/src/utils/trimReactNode.tsx +10 -8
  429. package/dist/components/base/ButtonOrLink.meta.d.ts +0 -2
  430. package/dist/components/base/ButtonOrLink.meta.d.ts.map +0 -1
  431. package/dist/components/base/ButtonOrLink.meta.js +0 -6
  432. package/dist/components/base/ButtonOrLink.meta.js.map +0 -1
  433. package/src/components/base/ButtonOrLink.meta.ts +0 -6
@@ -1,219 +1,222 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { createContext, isValidElement, useContext, useRef, } from 'react';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createContext, useContext, useRef } from 'react';
4
4
  import { Menu } from '@base-ui/react/menu';
5
5
  import { useMergedRefs } from '@base-ui/utils/useMergedRefs';
6
6
  import { twToPx } from '@graphprotocol/gds-css';
7
7
  import { ArrowRightInteractiveIcon, ArrowUpRightInteractiveIcon, CaretRightIcon, CheckIcon, LoadingIcon, MagnifyingGlassIcon, XIcon, } from '@graphprotocol/gds-react/icons';
8
- import { useAutoValue, useControlled, useCSSState, useGDS } from "../hooks/index.js";
9
- import { cn } from "../utils/index.js";
8
+ import { useAutoValue, useControlled, useCSSPropsPolyfill, useCSSState, useGDS, } from "../hooks/index.js";
9
+ import { cn, getCSSPropsAttributes, splitProps } from "../utils/index.js";
10
10
  import { renderAddon } from "./base/Addon.js";
11
11
  import { ButtonOrLink } from "./base/ButtonOrLink.js";
12
12
  import { Render } from "./base/Render.js";
13
13
  import { Button } from "./Button.js";
14
14
  import { Checkbox } from "./Checkbox.js";
15
+ import { MenuMeta } from './Menu.meta.js';
15
16
  const MenuTriggerContext = createContext(false);
16
- export function MenuRoot({ ref: passedRef, open: controlledOpen, defaultOpen, onOpenChange, trigger, position: passedPosition = {}, header, footer, label, type, value, defaultValue, onChange, className, children, ...props }) {
17
- useGDS();
18
- const popupRef = useRef(null);
19
- const popupPassedRef = useMergedRefs(popupRef, passedRef);
20
- const isNested = useContext(MenuItemsContext) !== null;
21
- const Root = isNested ? Menu.SubmenuRoot : Menu.Root;
22
- const Trigger = isNested ? Menu.SubmenuTrigger : Menu.Trigger;
23
- const triggerIsElement = isValidElement(trigger);
24
- const [open, setOpen] = useControlled(controlledOpen, defaultOpen ?? false, onOpenChange);
25
- const defaultPosition = {
26
- align: 'start',
27
- alignOffset: 0,
28
- side: 'bottom',
29
- gap: 1,
30
- matchWidth: false,
31
- matchHeight: false,
32
- openOnHover: false,
33
- };
34
- const defaultNestedPosition = {
35
- ...defaultPosition,
36
- alignOffset: passedPosition &&
37
- (passedPosition.side === 'top' ||
38
- passedPosition.side === 'bottom' ||
39
- passedPosition.align === 'center')
40
- ? 0
41
- : -2,
42
- side: 'inline-end',
43
- gap: passedPosition && (passedPosition.side === 'top' || passedPosition.side === 'bottom') ? 0 : 3,
44
- openOnHover: true,
45
- };
46
- const position = isNested
47
- ? passedPosition === false
48
- ? defaultPosition
49
- : { ...defaultNestedPosition, ...passedPosition }
50
- : passedPosition === false
51
- ? false
52
- : {
53
- ...defaultPosition,
54
- ...passedPosition,
17
+ export function MenuRoot({ ref: passedRef, trigger, triggerMode, side, gap, align, alignOffset, matchTriggerWidth, matchTriggerHeight, open: controlledOpen, defaultOpen, onOpenChange, header, footer, label, type, value, defaultValue, onChange, className, style, children, ...props }) {
18
+ const { dirProps } = useGDS();
19
+ const { rootProps, nestedProps } = splitProps(props);
20
+ const portalRef = useRef(null);
21
+ const [cssPropsPolyfillRef, cssPropsPolyfillAttributes, cssProps] = useCSSPropsPolyfill(MenuMeta, {
22
+ side,
23
+ align,
24
+ matchTriggerWidth,
25
+ matchTriggerHeight,
26
+ }, {
27
+ returnPropValues: { side, gap, align, alignOffset, matchTriggerWidth, matchTriggerHeight },
28
+ });
29
+ const isSubmenu = useContext(MenuGroupContext) !== null;
30
+ const MenuRoot = isSubmenu ? Menu.SubmenuRoot : Menu.Root;
31
+ const hasTrigger = trigger !== undefined;
32
+ const triggerElement = (() => {
33
+ if (!hasTrigger)
34
+ return null;
35
+ const renderTrigger = typeof trigger !== 'function'
36
+ ? trigger
37
+ : (renderProps) => {
38
+ // Don't pass event handlers and other potentially too specific props (e.g. `type`)
39
+ const filteredRenderProps = Object.fromEntries(Object.entries(renderProps).filter(([prop]) => prop === 'ref' ||
40
+ prop === 'id' ||
41
+ prop === 'className' ||
42
+ prop.startsWith('aria-') ||
43
+ prop.startsWith('data-')));
44
+ return trigger(filteredRenderProps, {
45
+ open,
46
+ setOpen,
47
+ openMenu: () => setOpen(true),
48
+ });
55
49
  };
56
- const simulateKeyPress = (element, key, keyCode) => {
57
- window.setTimeout(() => {
58
- const newEvent = new KeyboardEvent('keydown', {
59
- key,
60
- code: key,
61
- keyCode,
62
- which: keyCode,
63
- bubbles: true,
64
- cancelable: true,
65
- });
66
- element.dispatchEvent(newEvent);
67
- }, 0);
68
- };
69
- return (_jsxs(Root, { open: open, onOpenChange: (newOpen, eventDetails) => {
70
- // Don't let a non-positioned menu close automatically when interacting outside of it, since it's not modal
71
- if (!newOpen &&
72
- !position &&
73
- (eventDetails.reason === 'trigger-focus' ||
74
- eventDetails.reason === 'trigger-hover' ||
75
- eventDetails.reason === 'outside-press')) {
76
- return;
77
- }
78
- setOpen(newOpen);
79
- }, modal: !isNested ? position !== false : undefined,
80
- /**
81
- * This seems to be the only way to disable a `Menu.SubmenuTrigger` (see
82
- * https://github.com/mui/base-ui/issues/1976#issuecomment-2914529452).
83
- */
84
- disabled: triggerIsElement ? Boolean(trigger.props.disabled) : undefined, closeParentOnEsc: true, children: [_jsx(MenuTriggerContext.Provider, { value: true, children: _jsx(Trigger, { nativeButton: isNested ? false : triggerIsElement, openOnHover: position && position.openOnHover !== false, delay: position && typeof position.openOnHover === 'number' ? position.openOnHover : 100, "data-open-on-hover": Boolean(position && position.openOnHover) || undefined, className: `
50
+ if (isSubmenu) {
51
+ return _jsx(Render, { render: renderTrigger });
52
+ }
53
+ else {
54
+ return (_jsx(Menu.Trigger, { nativeButton: true, openOnHover: triggerMode === 'hover', "data-open-on-hover": triggerMode === 'hover' || undefined, className: `
85
55
  u:i:open:data-open-on-hover:state-hover
86
56
  u:iii:open:not-data-open-on-hover:state-active
87
- `, render: typeof trigger === 'function'
88
- ? (renderProps) => {
89
- // Don't pass event handlers and other potentially too specific props (e.g. `type`)
90
- const filteredRenderProps = Object.fromEntries(Object.entries(renderProps).filter(([prop]) => prop === 'ref' ||
91
- prop === 'id' ||
92
- prop.startsWith('aria-') ||
93
- prop.startsWith('data-')));
94
- return trigger(filteredRenderProps, {
95
- open,
96
- setOpen,
97
- openMenu: () => setOpen(true),
98
- });
99
- }
100
- : // oxlint-disable-next-line no-explicit-any
101
- trigger }) }), _jsx(MaybePortal, { position: position, "data-positioned": position !== false || undefined, "data-match-width": position ? position.matchWidth || undefined : undefined, "data-match-height": position ? position.matchHeight || undefined : undefined, className: cn(`gds-menu root-flex
102
- [--available-height-but-not-too-small:max(var(--available-height),--spacing(16))]
103
- has-nested/menu-footer:[--available-height-but-not-too-small:max(var(--available-height),--spacing(32))]
104
- has-nested/menu-header:[--available-height-but-not-too-small:max(var(--available-height),--spacing(32))]
105
- u:w-max
106
- u:max-w-full
107
- u:rounded-12
108
- u:data-positioned:max-h-(--available-height-but-not-too-small)
109
- u:data-positioned:max-w-(--available-width)
110
- u:i:data-[match-height=at-least]:min-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
111
- u:i:data-[match-height=at-most]:max-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
112
- u:i:data-[match-height=true]:h-(--anchor-height)
113
- u:i:data-[match-width=at-least]:min-w-[min(var(--anchor-width),var(--available-width))]
114
- u:i:data-[match-width=at-most]:max-w-[min(var(--anchor-width),var(--available-width))]
115
- u:i:data-[match-width=true]:w-(--anchor-width)`, className), children: _jsxs(Menu.Popup, { ref: popupPassedRef, className: `
116
- flex grow origin-(--transform-origin) flex-col overflow-clip rounded-inherit bg-muted outline-0 transition
117
- data-ending-style:scale-95
118
- data-ending-style:opacity-0
119
- data-starting-style:scale-95
120
- data-starting-style:opacity-0
121
- `, ...props, onKeyDown: (event) => {
122
- props.onKeyDown?.(event);
123
- /**
124
- * Ensure Shift + Tab doesn't close the menu if there is a previous focusable element
125
- * that is not a menu item (or if the previous focusable element is a menu item while
126
- * the element that is currently focused is not).
127
- */
128
- if (event.key === 'Tab' && event.shiftKey) {
129
- const focusableElements = [
130
- ...event.currentTarget.querySelectorAll(`
131
- a[href],
132
- button:enabled,
133
- input:enabled,
134
- select:enabled,
135
- textarea:enabled,
136
- summary,
137
- [tabindex]:not([tabindex="-1"]),
138
- [contenteditable="true"]
139
- `),
140
- ];
141
- const previousElement = focusableElements.reverse().find((element) => {
142
- return (element.compareDocumentPosition(document.activeElement) &
143
- Node.DOCUMENT_POSITION_FOLLOWING);
144
- });
145
- const activeElementIsMenuItem = document.activeElement?.classList.contains('gds-menu-item');
146
- const previousElementIsMenuItem = previousElement?.classList.contains('gds-menu-item');
147
- if ((previousElement && !previousElementIsMenuItem) ||
148
- (!activeElementIsMenuItem && previousElementIsMenuItem)) {
149
- event.preventBaseUIHandler();
150
- return;
151
- }
152
- }
153
- // If there is a search input in the menu...
154
- const searchInput = event.currentTarget.querySelector('input[type="search"]');
155
- if (searchInput instanceof HTMLInputElement) {
156
- // If the user typed some text, ensure it goes in the input instead of Base UI focusing the item that matches
157
- if ((event.key.length === 1 && event.key !== ' ') ||
158
- event.key === 'Backspace' ||
159
- event.key === 'ArrowLeft' ||
160
- event.key === 'ArrowRight') {
161
- event.preventBaseUIHandler();
162
- searchInput.focus();
163
- }
164
- else {
165
- const searchInputIsFocused = document.activeElement === searchInput;
166
- const menuItems = [
167
- ...event.currentTarget.querySelectorAll('.gds-menu-item'),
168
- ];
169
- const highlightedMenuItem = menuItems.find((item) => item.matches('[data-highlighted]'));
57
+ `, render: renderTrigger }));
58
+ }
59
+ })();
60
+ const [open, setOpen] = useControlled(controlledOpen ?? (!hasTrigger ? true : undefined), defaultOpen ?? false, onOpenChange);
61
+ const initialOpen = useRef(open);
62
+ if (!open) {
63
+ initialOpen.current = false;
64
+ }
65
+ return (_jsx("div", { ref: cssPropsPolyfillRef, "data-is-submenu": isSubmenu || undefined, "data-has-trigger": hasTrigger || undefined, className: cn(`gds-menu root-contents [anchor-scope:all]
66
+ not-data-has-trigger:**:data-base-ui-focus-guard:hidden
67
+ u:rounded-12
68
+ u:data-is-submenu:default-align-offset-[-2]
69
+ u:data-is-submenu:default-gap-3
70
+ u:data-is-submenu:default-side-end`,
71
+ // Very imperfect workaround for https://bugs.webkit.org/show_bug.cgi?id=301871
72
+ `safari:root-block
73
+ i:safari:not-data-is-submenu:size-max`, className), ...getCSSPropsAttributes(MenuMeta, { side, gap, align, alignOffset, matchTriggerWidth, matchTriggerHeight }, style), ...cssPropsPolyfillAttributes, ...rootProps, children: _jsxs(MenuRoot, { open: open, onOpenChange: (newOpen) => {
74
+ // A menu with no trigger can still be opened/closed by the consumer, but it should not send events
75
+ if (hasTrigger)
76
+ setOpen(newOpen);
77
+ }, modal: !isSubmenu ? hasTrigger : undefined, closeParentOnEsc: true, children: [_jsx(MenuTriggerContext.Provider, { value: true, children: triggerElement ?? (
78
+ /**
79
+ * Base UI doesn't explicitly support menus with no `Menu.Trigger`, `Menu.Portal`, or
80
+ * `Menu.Positioner`, so we work around it. We render an invisible trigger to satisfy
81
+ * focus and keyboard expectations (note that it is visible when focused, as an
82
+ * outline). Then, to ensure the menu is rendered inline and not anchored to that
83
+ * trigger, we customize the portal container to be a sibling element (with `contents
84
+ * *:contents` so it's a transparent wrapper), and we apply positioning styles only when
85
+ * a trigger is provided (see `Menu.Positioner`'s `render` prop below). Finally, to
86
+ * prevent focus-trapping behavior that assumes a floating menu, we disable `modal` and
87
+ * hide Base UI’s focus guards with CSS (see root styles above).
88
+ */
89
+ _jsxs(_Fragment, { children: [_jsx(Menu.Trigger, { "aria-label": props['aria-label'] ||
90
+ (label && typeof label === 'string' ? label : undefined) ||
91
+ 'Menu', className: `
92
+ pointer-events-none absolute inset-[anchor(inside)] rounded-inherit [position-anchor:--gds-menu]
93
+ not-open:hidden
94
+ ` }), _jsx("div", { ref: portalRef, className: "contents *:contents" })] })) }), _jsx(Menu.Portal, { container: !hasTrigger
95
+ ? portalRef
96
+ : /**
97
+ * Specifying `document.body` because while it is the default for top-level menus, a submenu
98
+ * defaults to using the same portal as its parent, which is not desirable when the parent is
99
+ * rendered inline (it can cause the submenu to appear behind other elements).
100
+ */
101
+ document?.body, children: _jsx(Menu.Positioner, { side: cssProps.side === 'start'
102
+ ? 'inline-start'
103
+ : cssProps.side === 'end'
104
+ ? 'inline-end'
105
+ : cssProps.side, sideOffset: twToPx(cssProps.gap), align: cssProps.align, alignOffset: twToPx(cssProps.alignOffset), collisionPadding: 8, collisionAvoidance: {
106
+ side: 'flip',
107
+ align: 'flip',
108
+ fallbackAxisSide: cssProps.side === 'start' || cssProps.side === 'end' ? 'end' : 'none',
109
+ }, "data-has-trigger": hasTrigger || undefined, "data-match-trigger-width": cssProps.matchTriggerWidth || undefined, "data-match-trigger-height": cssProps.matchTriggerHeight || undefined, className: cn(`root-flex
110
+ [--available-height-but-not-too-small:max(var(--available-height),--spacing(16))]
111
+ [anchor-name:--gds-menu]
112
+ has-nested/menu-footer:[--available-height-but-not-too-small:max(var(--available-height),--spacing(32))]
113
+ has-nested/menu-header:[--available-height-but-not-too-small:max(var(--available-height),--spacing(32))]
114
+ u:w-max
115
+ u:max-w-full
116
+ u:rounded-12
117
+ u:data-has-trigger:max-h-(--available-height-but-not-too-small)
118
+ u:data-has-trigger:max-w-(--available-width)
119
+ u:i:data-[match-trigger-height=at-least]:min-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
120
+ u:i:data-[match-trigger-height=at-most]:max-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
121
+ u:i:data-[match-trigger-height=true]:h-(--anchor-height)
122
+ u:i:data-[match-trigger-width=at-least]:min-w-[min(var(--anchor-width),var(--available-width))]
123
+ u:i:data-[match-trigger-width=at-most]:max-w-[min(var(--anchor-width),var(--available-width))]
124
+ u:i:data-[match-trigger-width=true]:w-(--anchor-width)`, className), ...dirProps, render: (renderProps) => (_jsx("div", { ...renderProps, style: hasTrigger ? renderProps.style : undefined })), children: _jsxs(Menu.Popup, { ref: passedRef, "data-initial-open": initialOpen.current || undefined, className: `
125
+ flex grow origin-(--transform-origin) flex-col overflow-clip rounded-inherit bg-muted outline-0 transition
126
+ data-ending-style:scale-95
127
+ data-ending-style:opacity-0
128
+ data-starting-style:not-data-initial-open:scale-95
129
+ data-starting-style:not-data-initial-open:opacity-0
130
+ `, ...nestedProps, onKeyDown: (event) => {
131
+ nestedProps.onKeyDown?.(event);
170
132
  /**
171
- * If the user pressed the down arrow while the search input is focused and there is
172
- * a single menu item in the results, move the focus to it because it may already be
173
- * highlighted, which would prevent Base UI from focusing it.
133
+ * Ensure Shift + Tab doesn't close the menu if there is a previous focusable
134
+ * element that is not a menu item (or if the previous focusable element is a menu
135
+ * item while the element that is currently focused is not).
174
136
  */
175
- if (event.key === 'ArrowDown' && searchInputIsFocused && menuItems.length === 1) {
176
- event.preventBaseUIHandler();
177
- menuItems[0].focus();
178
- }
179
- // Inversely, if the user pressed the up arrow and the focus is on the only menu item, move it back to the search input
180
- else if (event.key === 'ArrowUp' &&
181
- menuItems.length === 1 &&
182
- document.activeElement === menuItems[0]) {
183
- event.preventDefault();
184
- searchInput.focus();
137
+ if (event.key === 'Tab' && event.shiftKey) {
138
+ const focusableElements = [
139
+ ...event.currentTarget.querySelectorAll(`
140
+ a[href],
141
+ button:enabled,
142
+ input:enabled,
143
+ select:enabled,
144
+ textarea:enabled,
145
+ summary,
146
+ [tabindex]:not([tabindex="-1"]),
147
+ [contenteditable="true"]
148
+ `),
149
+ ];
150
+ const previousElement = focusableElements.reverse().find((element) => {
151
+ return (element.compareDocumentPosition(document.activeElement) &
152
+ Node.DOCUMENT_POSITION_FOLLOWING);
153
+ });
154
+ const activeElementIsMenuItem = document.activeElement?.classList.contains('gds-menu-item');
155
+ const previousElementIsMenuItem = previousElement?.classList.contains('gds-menu-item');
156
+ if ((previousElement && !previousElementIsMenuItem) ||
157
+ (!activeElementIsMenuItem && previousElementIsMenuItem)) {
158
+ event.preventBaseUIHandler();
159
+ return;
160
+ }
185
161
  }
186
- // If the user pressed Enter while the search input is focused and a menu item is highlighted, select it
187
- else if (event.key === 'Enter' && searchInputIsFocused && highlightedMenuItem) {
188
- highlightedMenuItem.focus();
189
- simulateKeyPress(highlightedMenuItem, 'Enter', 13);
162
+ // If there is a search input in the menu...
163
+ const searchInput = event.currentTarget.querySelector('input[type="search"]');
164
+ if (searchInput instanceof HTMLInputElement) {
165
+ // If the user typed some text, ensure it goes in the input instead of Base UI focusing the item that matches
166
+ if ((event.key.length === 1 && event.key !== ' ') ||
167
+ event.key === 'Backspace' ||
168
+ event.key === 'ArrowLeft' ||
169
+ event.key === 'ArrowRight') {
170
+ event.preventBaseUIHandler();
171
+ searchInput.focus();
172
+ }
173
+ else {
174
+ const searchInputIsFocused = document.activeElement === searchInput;
175
+ const menuItems = [
176
+ ...event.currentTarget.querySelectorAll('.gds-menu-item'),
177
+ ];
178
+ const highlightedMenuItem = menuItems.find((item) => item.matches('[data-highlighted]'));
179
+ /**
180
+ * If the user pressed the down arrow while the search input is focused and
181
+ * there is a single menu item in the results, move the focus to it because it
182
+ * may already be highlighted, which would prevent Base UI from focusing it.
183
+ */
184
+ if (event.key === 'ArrowDown' &&
185
+ searchInputIsFocused &&
186
+ menuItems.length === 1) {
187
+ event.preventBaseUIHandler();
188
+ menuItems[0].focus();
189
+ }
190
+ // Inversely, if the user pressed the up arrow and the focus is on the only menu item, move it back to the search input
191
+ else if (event.key === 'ArrowUp' &&
192
+ menuItems.length === 1 &&
193
+ document.activeElement === menuItems[0]) {
194
+ event.preventDefault();
195
+ searchInput.focus();
196
+ }
197
+ // If the user pressed Enter while the search input is focused and a menu item is highlighted, select it
198
+ else if (event.key === 'Enter' && searchInputIsFocused && highlightedMenuItem) {
199
+ highlightedMenuItem.focus();
200
+ window.setTimeout(() => {
201
+ highlightedMenuItem.dispatchEvent(new KeyboardEvent('keydown', {
202
+ key: 'Enter',
203
+ code: 'Enter',
204
+ keyCode: 13,
205
+ which: 13,
206
+ bubbles: true,
207
+ cancelable: true,
208
+ }));
209
+ }, 0);
210
+ }
211
+ }
190
212
  }
191
- }
192
- }
193
- }, children: [_jsx("div", { className: "w-58" }), header ? (_jsx("div", { className: "nested/menu-header u:shrink-0 u:border-b u:border-muted u:p-4", children: header })) : null, _jsx("div", { className: "scrollbar-thin grow scroll-p-8 overflow-x-clip overflow-y-auto gradient-mask-y", children: _jsx("div", { className: "overflow-clip p-2", children: _jsx(MenuItemsContext.Provider, { value: { position }, children: _jsxs(MenuGroupContext.Provider, { value: null, children: [label !== undefined || type !== undefined ? (type === 'radio' ? (_jsx(MenuGroup, { label: label, type: type, value: value, defaultValue: defaultValue, onChange: onChange, children: children })) : (_jsx(MenuGroup, { label: label, type: type, children: children }))) : (children), _jsx("div", { className: "mt-[calc(-2*(--spacing(2))-1px)] not-preceded-by-peer/menu-group:hidden" })] }) }) }) }), footer ? (_jsx("div", { className: "nested/menu-footer u:shrink-0 u:border-t u:border-muted u:p-4", children: footer })) : null, _jsx("div", { className: "pointer-events-none absolute inset-0 rounded-inherit border border-muted" })] }) })] }));
213
+ }, children: [_jsx("div", { className: "w-58" }), header ? (_jsx("div", { className: "nested/menu-header u:shrink-0 u:border-b u:border-muted u:p-4", children: header })) : null, _jsx("div", { className: "scrollbar-thin grow scroll-p-8 overflow-x-clip overflow-y-auto gradient-mask-y", children: _jsx("div", { className: "overflow-clip p-2", children: _jsxs(MenuGroupContext.Provider, { value: "root", children: [label !== undefined || type !== undefined ? (type === 'radio' ? (_jsx(MenuGroup, { label: label, type: type, value: value, defaultValue: defaultValue, onChange: onChange, children: children })) : (_jsx(MenuGroup, { label: label, type: type, children: children }))) : (children), _jsx("div", { className: "mt-[calc(-2*(--spacing(2))-1px)] not-preceded-by-peer/menu-group:hidden" })] }) }) }), footer ? (_jsx("div", { className: "nested/menu-footer u:shrink-0 u:border-t u:border-muted u:p-4", children: footer })) : null, _jsx("div", { className: "pointer-events-none absolute inset-0 rounded-inherit border border-muted" })] }) }) })] }, `${hasTrigger}-${triggerMode}`) }));
194
214
  }
195
215
  MenuRoot.displayName = 'Menu';
196
- const MenuItemsContext = createContext(null);
197
- const MaybePortal = ({ position, ...props }) => {
198
- const containerRef = useRef(null);
199
- const { dirProps } = useGDS();
200
- return (_jsxs(_Fragment, { children: [!position ? _jsx("div", { ref: containerRef, className: "contents *:contents" }) : null, _jsx(Menu.Portal, { container: !position
201
- ? containerRef
202
- : /**
203
- * Specifying `document.body` because while it is the default for top-level menus, a nested menu
204
- * defaults to using the same portal as its parent, which is not desirable when the parent is not
205
- * positioned (it can cause the nested menu to appear behind other elements).
206
- */
207
- document?.body, children: _jsx(Menu.Positioner, { align: position ? position.align : 'start', alignOffset: position ? twToPx(position.alignOffset) : 0, side: position ? position.side : 'bottom', sideOffset: position ? twToPx(position.gap) : 0, collisionPadding: 8, ...dirProps, render: ({ style, ...otherPositionerProps }) => {
208
- const allowedPositionerProps = position
209
- ? { style, ...otherPositionerProps }
210
- : otherPositionerProps;
211
- return _jsx("div", { ...allowedPositionerProps, ...props });
212
- } }) })] }));
213
- };
214
216
  const MenuGroupContext = createContext(null);
215
217
  export function MenuGroup({ label, type = 'plain', value, defaultValue, onChange, className, style, children, ...props }) {
216
- const isNested = useContext(MenuGroupContext) !== null;
218
+ const groupContext = useContext(MenuGroupContext);
219
+ const isNested = groupContext !== null && groupContext !== 'root';
217
220
  if (isNested) {
218
221
  throw new Error(`[Menu] Groups cannot be nested, make sure you're not using \`Menu.Group\` in a \`Menu\` with a \`label\` and/or \`type\` prop (implicit group)`);
219
222
  }
@@ -235,112 +238,95 @@ export function MenuItem({ ref: passedRef, type: passedType, addonBefore: passed
235
238
  const hasAncestorMenuTrigger = useContext(MenuTriggerContext) !== false;
236
239
  const type = hasAncestorMenuTrigger
237
240
  ? 'submenu-trigger'
238
- : (passedType ?? groupContext?.type ?? 'plain');
239
- const Element = (() => {
240
- switch (type) {
241
- case 'plain':
242
- return Menu.Item;
243
- case 'checkbox':
244
- return CheckboxItem;
245
- case 'radio':
246
- return Menu.RadioItem;
247
- case 'submenu-trigger':
248
- return Render;
241
+ : (passedType ??
242
+ (groupContext !== null && groupContext !== 'root' ? groupContext.type : undefined) ??
243
+ 'plain');
244
+ const renderItem = (renderProps) => {
245
+ let addonBefore = passedAddonBefore;
246
+ let addonInside = undefined;
247
+ let addonAfter = passedAddonAfter;
248
+ if (type === 'checkbox') {
249
+ if (addonBefore)
250
+ addonInside = addonBefore;
251
+ addonBefore = (_jsx(Checkbox, { inert: true, "aria-label": "" // Prevent console warning about missing label
252
+ , className: `
253
+ @state-checked/menu-item:state-checked
254
+ @state-indeterminate/menu-item:state-indeterminate
255
+ @state-hover/menu-item:state-hover
256
+ @state-active/menu-item:state-active
257
+ @state-disabled/menu-item:state-idle
258
+ @state-disabled/menu-item:@state-checked/menu-item:state-disabled
259
+ ` }));
249
260
  }
250
- })();
251
- const elementProps = (() => {
252
- switch (type) {
253
- case 'plain':
254
- return { disabled };
255
- case 'checkbox':
256
- return {
257
- disabled,
258
- checked,
259
- defaultChecked,
260
- onCheckedChange: onChange,
261
- closeOnClick: false,
262
- };
263
- case 'radio':
264
- return {
265
- value: passedValue !== undefined ? passedValue : autoValue,
266
- disabled,
267
- closeOnClick: true,
268
- };
269
- case 'submenu-trigger':
270
- return {};
261
+ if (type === 'radio') {
262
+ if (addonBefore)
263
+ addonInside = addonBefore;
264
+ addonBefore = _jsx(CheckIcon, { alt: "", className: "@state-unchecked/menu-item:invisible" });
271
265
  }
272
- })();
273
- return (_jsx(Element, { ref: stateElementPassedRef, ...state.polyfillAttributes, ...elementProps, ...props, onKeyDown: (event) => {
274
- props.onKeyDown?.(event);
275
- /**
276
- * Allow Space to activate menu items that are links. TODO: This may not be needed in the
277
- * future (see https://github.com/mui/base-ui/issues/1746).
278
- */
279
- if ('preventBaseUIHandler' in event &&
280
- !event.baseUIHandlerPrevented &&
281
- event.key === ' ' &&
282
- href !== undefined) {
283
- event.preventBaseUIHandler();
284
- elementRef.current?.click();
285
- }
286
- }, render: (renderProps) => {
287
- let addonBefore = passedAddonBefore;
288
- let addonInside = undefined;
289
- let addonAfter = passedAddonAfter;
290
- if (type === 'checkbox') {
291
- if (addonBefore)
292
- addonInside = addonBefore;
293
- addonBefore = (_jsx(Checkbox, { inert: true, "aria-label": "" // Prevent console warning about missing label
294
- , className: `
295
- @state-checked/menu-item:state-checked
296
- @state-indeterminate/menu-item:state-indeterminate
297
- @state-hover/menu-item:state-hover
298
- @state-active/menu-item:state-active
299
- @state-disabled/menu-item:state-idle
300
- @state-disabled/menu-item:@state-checked/menu-item:state-disabled
301
- ` }));
302
- }
303
- if (type === 'radio') {
304
- if (addonBefore)
305
- addonInside = addonBefore;
306
- addonBefore = _jsx(CheckIcon, { alt: "", className: "@state-unchecked/menu-item:invisible" });
307
- }
308
- if (loading) {
309
- addonAfter = _jsx(LoadingIcon, {});
310
- }
311
- if (type === 'submenu-trigger' && addonAfter === undefined) {
312
- addonAfter = _jsx(CaretRightIcon, { alt: "" });
313
- }
314
- if (href !== undefined && addonAfter === undefined) {
315
- addonAfter = (_jsx(ButtonOrLink.Consumer, { render: (buttonOrLinkState) => buttonOrLinkState?.target === '_blank' ? (_jsx(ArrowUpRightInteractiveIcon, { hiddenByDefault: true })) : (_jsx(ArrowRightInteractiveIcon, { hiddenByDefault: true })) }));
316
- }
317
- return (_jsxs(Render, { "data-type": type, "data-variant": variant, className: cn(
318
- // TODO: Replace `active:` with `data-pressed:` when https://github.com/mui/base-ui/issues/1726 is added, to style Space presses as well
319
- `gds-menu-item root-flex w-full items-center outline-0 select-none u:rounded-6 u:p-2 u:text-16 u:text-default
320
- u:state-idle
321
- u:checked:state-checked
322
- u:indeterminate:state-indeterminate
323
- u:disabled:pointer-events-none
324
- u:disabled:state-disabled
325
- u:data-highlighted:state-hover
326
- u:data-[variant=danger]:text-status-error-default
327
- u:ii:active:state-active
328
- u:ii:data-[type=submenu-trigger]:not-[a]:cursor-default
329
- u:ii:data-[type=submenu-trigger]:not-[a]:active:state-hover
330
- ${ /* Disabled styles */''}
331
- u:*:transition-opacity
332
- u:disabled:*:opacity-disabled
333
- u:disabled:*:grayscale`, className), ...renderProps, render: href !== undefined ? (_jsx(ButtonOrLink, { href: href, target: target, disabled: disabled })) : (_jsx("div", {})), children: [_jsx("span", { className: `
334
- absolute inset-0 rounded-inherit opacity-100 filter-none transition
335
- @state-hover/menu-item:bg-elevated
336
- @state-active/menu-item:bg-default
337
- @state-active/menu-item:transition-none
338
- ` }), addonBefore ? (_jsx(MenuItemAddon, { className: `
339
- me-2
340
- has-checkbox:@state-checked/menu-item:opacity-100
341
- has-checkbox:@state-checked/menu-item:filter-none
342
- `, children: renderAddon(addonBefore) })) : null, addonInside ? (_jsx(MenuItemAddon, { className: "me-1", children: renderAddon(addonInside) })) : null, _jsx("span", { className: "grow truncate pe-1", children: children || _jsx(_Fragment, { children: "\u00A0" }) }), addonAfter ? (_jsx(MenuItemAddon, { className: "ms-2", children: renderAddon(addonAfter) })) : null] }));
343
- } }));
266
+ if (loading) {
267
+ addonAfter = _jsx(LoadingIcon, {});
268
+ }
269
+ if (type === 'submenu-trigger' && addonAfter === undefined) {
270
+ addonAfter = _jsx(CaretRightIcon, { alt: "" });
271
+ }
272
+ if (href !== undefined && addonAfter === undefined) {
273
+ addonAfter = (_jsx(ButtonOrLink.Consumer, { render: (buttonOrLinkState) => buttonOrLinkState?.target === '_blank' ? (_jsx(ArrowUpRightInteractiveIcon, { hiddenByDefault: true })) : (_jsx(ArrowRightInteractiveIcon, { hiddenByDefault: true })) }));
274
+ }
275
+ return (_jsxs(Render, { render: _jsx(ButtonOrLink, { href: href, target: target }), "data-type": type, "data-variant": variant, className: cn(`gds-menu-item root-flex w-full items-center outline-0 select-none u:rounded-6 u:p-2 u:text-16
276
+ u:state-idle
277
+ u:checked:state-checked
278
+ u:indeterminate:state-indeterminate
279
+ u:disabled:pointer-events-none
280
+ u:disabled:state-disabled
281
+ u:data-highlighted:state-hover
282
+ u:data-[variant=danger]:text-status-error-default
283
+ u:ii:not-disabled:active:state-active
284
+ u:ii:data-[type=submenu-trigger]:not-[a]:cursor-default
285
+ u:ii:data-[type=submenu-trigger]:not-[a]:active:state-hover
286
+ ${ /* Disabled styles */''}
287
+ u:*:transition-opacity
288
+ u:disabled:*:opacity-disabled
289
+ u:disabled:*:grayscale`, className), ...renderProps, children: [_jsx("span", { className: `
290
+ absolute inset-0 rounded-inherit opacity-100 filter-none transition
291
+ @state-hover/menu-item:bg-elevated
292
+ @state-active/menu-item:bg-default
293
+ @state-active/menu-item:transition-none
294
+ ` }), addonBefore ? (_jsx(MenuItemAddon, { className: `
295
+ me-2
296
+ has-checkbox:@state-checked/menu-item:opacity-100
297
+ has-checkbox:@state-checked/menu-item:filter-none
298
+ `, children: renderAddon(addonBefore) })) : null, addonInside ? (_jsx(MenuItemAddon, { className: "me-1", children: renderAddon(addonInside) })) : null, _jsx("span", { className: "grow truncate pe-1", children: children || _jsx(_Fragment, { children: "\u00A0" }) }), addonAfter ? (_jsx(MenuItemAddon, { className: "ms-2", children: renderAddon(addonAfter) })) : null] }));
299
+ };
300
+ // Filter out undefined values to satisfy Base UI's `exactOptionalPropertyTypes`
301
+ // TODO: Remove when https://github.com/mui/base-ui/pull/3302 is released
302
+ const definedProps = Object.fromEntries(Object.entries(props).filter(([, value]) => value !== undefined));
303
+ const baseProps = {
304
+ ref: stateElementPassedRef,
305
+ ...state.polyfillAttributes,
306
+ ...definedProps,
307
+ };
308
+ if (type === 'submenu-trigger') {
309
+ return _jsx(Menu.SubmenuTrigger, { nativeButton: true, disabled: disabled, render: renderItem(baseProps) });
310
+ }
311
+ const nativeButton = href === undefined;
312
+ const onKeyDown = (event) => {
313
+ props.onKeyDown?.(event);
314
+ /**
315
+ * Allow Space to activate menu items that are links. This may not be needed in the future (see
316
+ * https://github.com/mui/base-ui/issues/1746).
317
+ */
318
+ if (!event.baseUIHandlerPrevented && event.key === ' ' && href !== undefined) {
319
+ event.preventBaseUIHandler();
320
+ elementRef.current?.click();
321
+ }
322
+ };
323
+ if (type === 'checkbox') {
324
+ return (_jsx(CheckboxItem, { ...baseProps, nativeButton: nativeButton, closeOnClick: false, checked: checked, defaultChecked: defaultChecked, onCheckedChange: onChange, onKeyDown: onKeyDown, disabled: disabled, render: renderItem }));
325
+ }
326
+ if (type === 'radio') {
327
+ return (_jsx(Menu.RadioItem, { ...baseProps, nativeButton: nativeButton, closeOnClick: true, value: passedValue !== undefined ? passedValue : autoValue, onKeyDown: onKeyDown, disabled: disabled, render: renderItem }));
328
+ }
329
+ return (_jsx(Menu.Item, { ...baseProps, nativeButton: nativeButton, onKeyDown: onKeyDown, disabled: disabled, render: renderItem }));
344
330
  }
345
331
  MenuItem.displayName = 'Menu.Item';
346
332
  function MenuItemAddon({ className, children, ...props }) {
@@ -360,8 +346,8 @@ export function MenuSearch({ ref: passedRef, placeholder: passedPlaceholder, val
360
346
  }
361
347
  MenuSearch.displayName = 'Menu.Search';
362
348
  /**
363
- * Transparent wrapper for `Menu.CheckboxItem` to support `indeterminate`. TODO: This may not be
364
- * needed in the future (see https://github.com/mui/base-ui/issues/1983).
349
+ * Transparent wrapper for `Menu.CheckboxItem` to support `indeterminate`. This may not be needed in
350
+ * the future (see https://github.com/mui/base-ui/issues/1983).
365
351
  */
366
352
  function CheckboxItem({ checked: controlledChecked, defaultChecked, onCheckedChange, ...props }) {
367
353
  const [checked, setChecked] = useControlled(controlledChecked, defaultChecked ?? false, onCheckedChange);