@astryxdesign/core 0.3.0 → 0.4.0-canary.058f476

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 (664) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/dist/AlertDialog/AlertDialog.d.ts +10 -2
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +22 -3
  5. package/dist/AppShell/AppShell.d.ts +2 -2
  6. package/dist/AppShell/AppShell.d.ts.map +1 -1
  7. package/dist/AppShell/AppShell.js +40 -9
  8. package/dist/AspectRatio/AspectRatio.d.ts +13 -0
  9. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  10. package/dist/AspectRatio/AspectRatio.js +10 -2
  11. package/dist/AspectRatio/index.d.ts.map +1 -1
  12. package/dist/AspectRatio/index.js +1 -2
  13. package/dist/Avatar/Avatar.d.ts.map +1 -1
  14. package/dist/Avatar/Avatar.js +33 -20
  15. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  16. package/dist/AvatarGroup/AvatarGroupOverflow.js +2 -3
  17. package/dist/Badge/Badge.d.ts.map +1 -1
  18. package/dist/Badge/Badge.js +1 -2
  19. package/dist/Badge/index.d.ts.map +1 -1
  20. package/dist/Badge/index.js +1 -2
  21. package/dist/Banner/Banner.d.ts +3 -0
  22. package/dist/Banner/Banner.d.ts.map +1 -1
  23. package/dist/Banner/Banner.js +32 -17
  24. package/dist/Blockquote/Blockquote.d.ts.map +1 -1
  25. package/dist/Blockquote/Blockquote.js +1 -2
  26. package/dist/Blockquote/index.d.ts.map +1 -1
  27. package/dist/Blockquote/index.js +1 -2
  28. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  29. package/dist/Breadcrumbs/BreadcrumbItem.js +21 -8
  30. package/dist/Breadcrumbs/index.d.ts +2 -1
  31. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  32. package/dist/Breadcrumbs/index.js +1 -0
  33. package/dist/Button/Button.d.ts.map +1 -1
  34. package/dist/Button/Button.js +12 -16
  35. package/dist/Calendar/Calendar.d.ts.map +1 -1
  36. package/dist/Calendar/Calendar.js +2 -1
  37. package/dist/Calendar/styles.d.ts +0 -2
  38. package/dist/Calendar/styles.d.ts.map +1 -1
  39. package/dist/Calendar/styles.js +0 -2
  40. package/dist/Card/Card.d.ts.map +1 -1
  41. package/dist/Card/Card.js +1 -2
  42. package/dist/Card/index.d.ts.map +1 -1
  43. package/dist/Card/index.js +1 -2
  44. package/dist/Carousel/Carousel.d.ts.map +1 -1
  45. package/dist/Carousel/Carousel.js +8 -12
  46. package/dist/Center/Center.d.ts.map +1 -1
  47. package/dist/Center/Center.js +1 -2
  48. package/dist/Center/index.d.ts.map +1 -1
  49. package/dist/Center/index.js +1 -2
  50. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  51. package/dist/Chat/ChatDictationButton.js +2 -1
  52. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  53. package/dist/Chat/ChatLayoutScrollButton.js +3 -1
  54. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  55. package/dist/Chat/ChatSendButton.js +4 -3
  56. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  57. package/dist/Chat/ChatToolCalls.js +17 -17
  58. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  59. package/dist/Chat/useTriggerMenu.js +2 -6
  60. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  61. package/dist/CheckboxInput/CheckboxInput.js +36 -125
  62. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  63. package/dist/ClickableCard/ClickableCard.js +3 -11
  64. package/dist/Code/Code.d.ts.map +1 -1
  65. package/dist/Code/Code.js +1 -2
  66. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  67. package/dist/CodeBlock/CodeBlock.js +84 -67
  68. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  69. package/dist/Collapsible/Collapsible.js +35 -15
  70. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  71. package/dist/CommandPalette/CommandPalette.js +5 -0
  72. package/dist/CommandPalette/CommandPaletteItem.d.ts +1 -1
  73. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  74. package/dist/CommandPalette/CommandPaletteItem.js +6 -3
  75. package/dist/CommandPalette/CommandPaletteList.js +1 -1
  76. package/dist/ComplexSelector/ComplexSelector.d.ts +1 -1
  77. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  78. package/dist/ComplexSelector/ComplexSelector.js +32 -31
  79. package/dist/ContextMenu/ContextMenu.d.ts +2 -2
  80. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  81. package/dist/ContextMenu/ContextMenu.js +1 -1
  82. package/dist/ContextMenu/index.d.ts +2 -1
  83. package/dist/ContextMenu/index.d.ts.map +1 -1
  84. package/dist/ContextMenu/index.js +1 -0
  85. package/dist/DateInput/DateInput.d.ts +9 -2
  86. package/dist/DateInput/DateInput.d.ts.map +1 -1
  87. package/dist/DateInput/DateInput.js +47 -33
  88. package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
  89. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  90. package/dist/DateRangeInput/DateRangeInput.js +55 -32
  91. package/dist/DateTimeInput/DateTimeInput.d.ts +9 -1
  92. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  93. package/dist/DateTimeInput/DateTimeInput.js +54 -30
  94. package/dist/Dialog/Dialog.d.ts.map +1 -1
  95. package/dist/Dialog/Dialog.js +4 -4
  96. package/dist/DropdownMenu/DropdownMenu.d.ts +33 -8
  97. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  98. package/dist/DropdownMenu/DropdownMenu.js +62 -20
  99. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +8 -11
  100. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  101. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +32 -31
  102. package/dist/DropdownMenu/DropdownMenuDivider.d.ts +25 -0
  103. package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -0
  104. package/dist/DropdownMenu/DropdownMenuDivider.js +66 -0
  105. package/dist/DropdownMenu/DropdownMenuItem.d.ts +15 -2
  106. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  107. package/dist/DropdownMenu/DropdownMenuItem.js +20 -8
  108. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -1
  109. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  110. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +10 -3
  111. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +5 -5
  112. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  113. package/dist/DropdownMenu/DropdownMenuRadioItem.js +24 -67
  114. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  115. package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -8
  116. package/dist/DropdownMenu/index.d.ts +2 -1
  117. package/dist/DropdownMenu/index.d.ts.map +1 -1
  118. package/dist/DropdownMenu/index.js +4 -0
  119. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  120. package/dist/DropdownMenu/renderDropdownItems.js +35 -27
  121. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  122. package/dist/EmptyState/EmptyState.js +9 -5
  123. package/dist/Field/InputClearButton.d.ts +16 -3
  124. package/dist/Field/InputClearButton.d.ts.map +1 -1
  125. package/dist/Field/InputClearButton.js +15 -4
  126. package/dist/Field/PanelSearchInput.d.ts +81 -0
  127. package/dist/Field/PanelSearchInput.d.ts.map +1 -0
  128. package/dist/Field/PanelSearchInput.js +151 -0
  129. package/dist/FileInput/FileInput.d.ts.map +1 -1
  130. package/dist/FileInput/FileInput.js +21 -10
  131. package/dist/Grid/Grid.d.ts.map +1 -1
  132. package/dist/Grid/Grid.js +1 -2
  133. package/dist/Grid/index.d.ts.map +1 -1
  134. package/dist/Grid/index.js +1 -2
  135. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  136. package/dist/HoverCard/useHoverCard.js +3 -19
  137. package/dist/Icon/globalIconRegistry.d.ts +5 -4
  138. package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
  139. package/dist/Icon/globalIconRegistry.js +5 -4
  140. package/dist/Indicator/CheckIndicator.d.ts +25 -0
  141. package/dist/Indicator/CheckIndicator.d.ts.map +1 -0
  142. package/dist/Indicator/CheckIndicator.js +155 -0
  143. package/dist/Indicator/CheckboxIndicator.d.ts +22 -0
  144. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -0
  145. package/dist/Indicator/CheckboxIndicator.js +173 -0
  146. package/dist/Indicator/RadioIndicator.d.ts +23 -0
  147. package/dist/Indicator/RadioIndicator.d.ts.map +1 -0
  148. package/dist/Indicator/RadioIndicator.js +137 -0
  149. package/dist/Indicator/index.d.ts +24 -0
  150. package/dist/Indicator/index.d.ts.map +1 -0
  151. package/dist/Indicator/index.js +26 -0
  152. package/dist/Indicator/indicator.markers.stylex.d.ts +16 -0
  153. package/dist/Indicator/indicator.markers.stylex.d.ts.map +1 -0
  154. package/dist/Indicator/indicator.markers.stylex.js +21 -0
  155. package/dist/Indicator/indicatorRegistry.d.ts +71 -0
  156. package/dist/Indicator/indicatorRegistry.d.ts.map +1 -0
  157. package/dist/Indicator/indicatorRegistry.js +93 -0
  158. package/dist/Indicator/types.d.ts +177 -0
  159. package/dist/Indicator/types.d.ts.map +1 -0
  160. package/dist/Indicator/types.js +1 -0
  161. package/dist/Indicator/useIndicator.d.ts +18 -0
  162. package/dist/Indicator/useIndicator.d.ts.map +1 -0
  163. package/dist/Indicator/useIndicator.js +30 -0
  164. package/dist/Item/Item.d.ts.map +1 -1
  165. package/dist/Item/Item.js +4 -8
  166. package/dist/Layer/useLayer.d.ts +14 -0
  167. package/dist/Layer/useLayer.d.ts.map +1 -1
  168. package/dist/Layer/useLayer.js +25 -2
  169. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  170. package/dist/Lightbox/Lightbox.js +80 -103
  171. package/dist/Link/Link.d.ts.map +1 -1
  172. package/dist/Link/Link.js +4 -5
  173. package/dist/MobileNav/MobileNav.js +8 -8
  174. package/dist/MoreMenu/MoreMenu.d.ts +14 -1
  175. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  176. package/dist/MoreMenu/MoreMenu.js +4 -0
  177. package/dist/MultiSelector/MultiSelector.d.ts +8 -1
  178. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  179. package/dist/MultiSelector/MultiSelector.js +205 -170
  180. package/dist/NumberInput/NumberInput.d.ts +27 -1
  181. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  182. package/dist/NumberInput/NumberInput.js +230 -42
  183. package/dist/Outline/Outline.d.ts.map +1 -1
  184. package/dist/Outline/Outline.js +2 -3
  185. package/dist/Pagination/Pagination.d.ts.map +1 -1
  186. package/dist/Pagination/Pagination.js +61 -63
  187. package/dist/Popover/Popover.d.ts.map +1 -1
  188. package/dist/Popover/Popover.js +6 -8
  189. package/dist/Popover/usePopover.d.ts +15 -0
  190. package/dist/Popover/usePopover.d.ts.map +1 -1
  191. package/dist/Popover/usePopover.js +14 -2
  192. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  193. package/dist/PowerSearch/PowerSearch.js +1 -1
  194. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  195. package/dist/PowerSearch/PowerSearchEditPopover.js +7 -0
  196. package/dist/ProgressBar/ProgressBar.d.ts +11 -4
  197. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  198. package/dist/ProgressBar/ProgressBar.js +95 -6
  199. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  200. package/dist/RadioList/RadioListItem.js +29 -84
  201. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  202. package/dist/Resizable/ResizeHandle.js +2 -3
  203. package/dist/Section/Section.d.ts.map +1 -1
  204. package/dist/Section/Section.js +1 -2
  205. package/dist/Section/index.d.ts.map +1 -1
  206. package/dist/Section/index.js +1 -2
  207. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  208. package/dist/SegmentedControl/SegmentedControlItem.js +2 -3
  209. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  210. package/dist/SelectableCard/SelectableCard.js +3 -11
  211. package/dist/Selector/Selector.d.ts +12 -1
  212. package/dist/Selector/Selector.d.ts.map +1 -1
  213. package/dist/Selector/Selector.js +293 -183
  214. package/dist/Selector/hooks.d.ts +18 -6
  215. package/dist/Selector/hooks.d.ts.map +1 -1
  216. package/dist/Selector/hooks.js +57 -40
  217. package/dist/SideNav/SideNav.d.ts.map +1 -1
  218. package/dist/SideNav/SideNav.js +1 -1
  219. package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
  220. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  221. package/dist/SideNav/SideNavCollapseButton.js +29 -14
  222. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  223. package/dist/SideNav/SideNavHeading.js +56 -20
  224. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  225. package/dist/SideNav/SideNavItem.js +28 -22
  226. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  227. package/dist/Skeleton/Skeleton.js +1 -2
  228. package/dist/Skeleton/index.d.ts.map +1 -1
  229. package/dist/Skeleton/index.js +1 -2
  230. package/dist/Slider/Slider.d.ts.map +1 -1
  231. package/dist/Slider/Slider.js +2 -6
  232. package/dist/Stack/stack.stylex.d.ts +3 -3
  233. package/dist/Switch/Switch.d.ts.map +1 -1
  234. package/dist/Switch/Switch.js +14 -13
  235. package/dist/TabList/Tab.d.ts.map +1 -1
  236. package/dist/TabList/Tab.js +2 -3
  237. package/dist/TabList/TabMenu.d.ts.map +1 -1
  238. package/dist/TabList/TabMenu.js +41 -19
  239. package/dist/Table/BaseTable.d.ts.map +1 -1
  240. package/dist/Table/BaseTable.js +8 -0
  241. package/dist/Table/TableRow.d.ts +1 -1
  242. package/dist/Table/TableRow.d.ts.map +1 -1
  243. package/dist/Table/TableRow.js +4 -2
  244. package/dist/Table/index.d.ts +1 -1
  245. package/dist/Table/index.d.ts.map +1 -1
  246. package/dist/Table/index.js +1 -1
  247. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
  248. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  249. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +22 -18
  250. package/dist/Table/plugins/rowExpansion/index.d.ts +1 -1
  251. package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -1
  252. package/dist/Table/plugins/rowExpansion/index.js +1 -1
  253. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +41 -76
  254. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  255. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +94 -345
  256. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  257. package/dist/Table/plugins/sortable/useTableSortable.js +23 -4
  258. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  259. package/dist/Table/plugins/tree/useTableTreeData.js +29 -33
  260. package/dist/Table/tableContextMenu.d.ts.map +1 -1
  261. package/dist/Table/tableContextMenu.js +2 -1
  262. package/dist/Table/types.d.ts +11 -0
  263. package/dist/Table/types.d.ts.map +1 -1
  264. package/dist/TextArea/TextArea.d.ts +10 -1
  265. package/dist/TextArea/TextArea.d.ts.map +1 -1
  266. package/dist/TextArea/TextArea.js +16 -6
  267. package/dist/TextInput/TextInput.d.ts +10 -1
  268. package/dist/TextInput/TextInput.d.ts.map +1 -1
  269. package/dist/TextInput/TextInput.js +13 -19
  270. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  271. package/dist/Thumbnail/Thumbnail.js +32 -26
  272. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  273. package/dist/TimeInput/TimeInput.js +14 -17
  274. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  275. package/dist/Timestamp/Timestamp.js +14 -3
  276. package/dist/Timestamp/TimestampHoverCard.d.ts.map +1 -1
  277. package/dist/Timestamp/TimestampHoverCard.js +16 -34
  278. package/dist/Timestamp/formatInstant.d.ts +11 -1
  279. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  280. package/dist/Timestamp/formatInstant.js +3 -1
  281. package/dist/Token/Token.d.ts.map +1 -1
  282. package/dist/Token/Token.js +20 -11
  283. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  284. package/dist/Tokenizer/Tokenizer.js +4 -2
  285. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  286. package/dist/Tooltip/useTooltip.js +3 -19
  287. package/dist/TopNav/TopNav.d.ts.map +1 -1
  288. package/dist/TopNav/TopNav.js +6 -5
  289. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  290. package/dist/TopNav/TopNavHeading.js +54 -16
  291. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  292. package/dist/TopNav/TopNavItem.js +3 -9
  293. package/dist/TopNav/TopNavMegaMenu.d.ts +7 -0
  294. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  295. package/dist/TopNav/TopNavMegaMenu.js +146 -60
  296. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  297. package/dist/TopNav/TopNavMegaMenuItem.js +22 -3
  298. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  299. package/dist/TopNav/TopNavMenu.js +83 -38
  300. package/dist/TreeList/TreeList.d.ts.map +1 -1
  301. package/dist/TreeList/TreeList.js +13 -0
  302. package/dist/TreeList/TreeListBranches.d.ts +1 -1
  303. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  304. package/dist/TreeList/TreeListBranches.js +14 -4
  305. package/dist/TreeList/TreeListItem.d.ts +11 -1
  306. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  307. package/dist/TreeList/TreeListItem.js +57 -30
  308. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  309. package/dist/Typeahead/BaseTypeahead.js +16 -8
  310. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
  311. package/dist/VisuallyHidden/VisuallyHidden.js +1 -2
  312. package/dist/VisuallyHidden/index.d.ts.map +1 -1
  313. package/dist/VisuallyHidden/index.js +1 -2
  314. package/dist/astryx.css +86 -96
  315. package/dist/astryx.umd.js +56 -56
  316. package/dist/astryx.umd.js.map +4 -4
  317. package/dist/hooks/containerReveal.stylex.d.ts +61 -0
  318. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -0
  319. package/dist/hooks/containerReveal.stylex.js +63 -0
  320. package/dist/hooks/index.d.ts +3 -0
  321. package/dist/hooks/index.d.ts.map +1 -1
  322. package/dist/hooks/index.js +2 -0
  323. package/dist/hooks/useClipboard.d.ts +59 -0
  324. package/dist/hooks/useClipboard.d.ts.map +1 -0
  325. package/dist/hooks/useClipboard.js +106 -0
  326. package/dist/hooks/useContainerReveal.d.ts +14 -8
  327. package/dist/hooks/useContainerReveal.d.ts.map +1 -1
  328. package/dist/hooks/useContainerReveal.js +28 -69
  329. package/dist/hooks/useIndicatorFocusRing.d.ts +28 -0
  330. package/dist/hooks/useIndicatorFocusRing.d.ts.map +1 -0
  331. package/dist/hooks/useIndicatorFocusRing.js +96 -0
  332. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  333. package/dist/hooks/useInputStatusIcon.js +17 -4
  334. package/dist/hooks/useLongPress.d.ts.map +1 -1
  335. package/dist/hooks/useLongPress.js +12 -2
  336. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  337. package/dist/hooks/useScrollLock.js +33 -18
  338. package/dist/hooks/useStreamingText.d.ts +18 -3
  339. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  340. package/dist/hooks/useStreamingText.js +47 -7
  341. package/dist/hooks/useTreeFocus.d.ts.map +1 -1
  342. package/dist/hooks/useTreeFocus.js +9 -3
  343. package/dist/hooks/useTypeahead.d.ts +3 -2
  344. package/dist/hooks/useTypeahead.d.ts.map +1 -1
  345. package/dist/hooks/useTypeahead.js +19 -7
  346. package/dist/index.d.ts +1 -0
  347. package/dist/index.d.ts.map +1 -1
  348. package/dist/index.js +1 -0
  349. package/dist/theme/defineTheme.d.ts +18 -2
  350. package/dist/theme/defineTheme.d.ts.map +1 -1
  351. package/dist/theme/defineTheme.js +10 -1
  352. package/dist/theme/derivedVarRegistry.d.ts +8 -0
  353. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  354. package/dist/theme/derivedVarRegistry.js +14 -13
  355. package/dist/theme/expandColorScale.d.ts +3 -1
  356. package/dist/theme/expandColorScale.d.ts.map +1 -1
  357. package/dist/theme/expandColorScale.js +17 -7
  358. package/dist/theme/expandTypeScale.d.ts.map +1 -1
  359. package/dist/theme/expandTypeScale.js +17 -0
  360. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  361. package/dist/theme/generateThemeRules.js +11 -0
  362. package/dist/theme/index.d.ts +2 -1
  363. package/dist/theme/index.d.ts.map +1 -1
  364. package/dist/theme/index.js +1 -1
  365. package/dist/theme/tokens.stylex.d.ts +12 -0
  366. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  367. package/dist/theme/tokens.stylex.js +23 -0
  368. package/dist/utils/focusOutline.stylex.d.ts +122 -0
  369. package/dist/utils/focusOutline.stylex.d.ts.map +1 -0
  370. package/dist/utils/focusOutline.stylex.js +143 -0
  371. package/dist/utils/focusReturn.d.ts +24 -0
  372. package/dist/utils/focusReturn.d.ts.map +1 -0
  373. package/dist/utils/focusReturn.js +29 -0
  374. package/dist/utils/index.d.ts +2 -0
  375. package/dist/utils/index.d.ts.map +1 -1
  376. package/dist/utils/index.js +6 -1
  377. package/dist/utils/interactionModality.d.ts +34 -0
  378. package/dist/utils/interactionModality.d.ts.map +1 -0
  379. package/dist/utils/interactionModality.js +70 -0
  380. package/dist/utils/mergeRefs.d.ts.map +1 -1
  381. package/dist/utils/mergeRefs.js +7 -5
  382. package/dist/utils/rtlStyles.d.ts +2 -2
  383. package/dist/utils/rtlStyles.js +2 -2
  384. package/dist/utils/themeProps.d.ts +20 -1
  385. package/dist/utils/themeProps.d.ts.map +1 -1
  386. package/dist/utils/themeProps.js +8 -2
  387. package/locales/en.json +52 -0
  388. package/locales/pseudo.json +39 -0
  389. package/package.json +8 -3
  390. package/src/AlertDialog/AlertDialog.doc.mjs +16 -3
  391. package/src/AlertDialog/AlertDialog.test.tsx +208 -1
  392. package/src/AlertDialog/AlertDialog.tsx +21 -3
  393. package/src/AppShell/AppShell.doc.mjs +14 -0
  394. package/src/AppShell/AppShell.test.tsx +139 -0
  395. package/src/AppShell/AppShell.tsx +32 -22
  396. package/src/AspectRatio/AspectRatio.doc.mjs +27 -3
  397. package/src/AspectRatio/AspectRatio.test.tsx +30 -0
  398. package/src/AspectRatio/AspectRatio.tsx +13 -2
  399. package/src/AspectRatio/index.ts +0 -2
  400. package/src/Avatar/Avatar.doc.mjs +2 -13
  401. package/src/Avatar/Avatar.test.tsx +33 -8
  402. package/src/Avatar/Avatar.tsx +52 -50
  403. package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -9
  404. package/src/Badge/Badge.tsx +0 -2
  405. package/src/Badge/index.ts +0 -2
  406. package/src/Banner/Banner.test.tsx +58 -1
  407. package/src/Banner/Banner.tsx +33 -11
  408. package/src/Blockquote/Blockquote.tsx +0 -2
  409. package/src/Blockquote/index.ts +0 -2
  410. package/src/Breadcrumbs/BreadcrumbItem.tsx +16 -6
  411. package/src/Breadcrumbs/index.ts +5 -1
  412. package/src/Button/Button.doc.mjs +2 -2
  413. package/src/Button/Button.tsx +22 -41
  414. package/src/Calendar/Calendar.tsx +2 -1
  415. package/src/Calendar/styles.ts +0 -8
  416. package/src/Card/Card.tsx +0 -2
  417. package/src/Card/index.ts +0 -2
  418. package/src/Carousel/Carousel.doc.mjs +3 -0
  419. package/src/Carousel/Carousel.tsx +10 -6
  420. package/src/Center/Center.tsx +0 -2
  421. package/src/Center/index.ts +0 -2
  422. package/src/Chat/Chat.doc.mjs +2 -0
  423. package/src/Chat/ChatDictationButton.tsx +7 -1
  424. package/src/Chat/ChatLayoutScrollButton.test.tsx +22 -0
  425. package/src/Chat/ChatLayoutScrollButton.tsx +8 -1
  426. package/src/Chat/ChatSendButton.tsx +2 -3
  427. package/src/Chat/ChatToolCalls.test.tsx +35 -0
  428. package/src/Chat/ChatToolCalls.tsx +36 -16
  429. package/src/Chat/useTriggerMenu.tsx +2 -5
  430. package/src/CheckboxInput/CheckboxInput.doc.mjs +4 -2
  431. package/src/CheckboxInput/CheckboxInput.test.tsx +120 -0
  432. package/src/CheckboxInput/CheckboxInput.tsx +45 -202
  433. package/src/ClickableCard/ClickableCard.tsx +6 -11
  434. package/src/Code/Code.tsx +0 -2
  435. package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
  436. package/src/CodeBlock/CodeBlock.test.tsx +91 -0
  437. package/src/CodeBlock/CodeBlock.tsx +57 -80
  438. package/src/Collapsible/Collapsible.tsx +22 -18
  439. package/src/CommandPalette/CommandPalette.test.tsx +83 -0
  440. package/src/CommandPalette/CommandPalette.tsx +5 -0
  441. package/src/CommandPalette/CommandPaletteItem.tsx +7 -4
  442. package/src/CommandPalette/CommandPaletteList.tsx +2 -2
  443. package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
  444. package/src/ComplexSelector/ComplexSelector.test.tsx +73 -0
  445. package/src/ComplexSelector/ComplexSelector.tsx +41 -28
  446. package/src/ContextMenu/ContextMenu.doc.mjs +1 -1
  447. package/src/ContextMenu/ContextMenu.test.tsx +41 -0
  448. package/src/ContextMenu/ContextMenu.tsx +3 -3
  449. package/src/ContextMenu/index.ts +5 -1
  450. package/src/DateInput/DateInput.doc.mjs +18 -3
  451. package/src/DateInput/DateInput.test.tsx +112 -11
  452. package/src/DateInput/DateInput.tsx +44 -25
  453. package/src/DateRangeInput/DateRangeInput.doc.mjs +10 -2
  454. package/src/DateRangeInput/DateRangeInput.test.tsx +110 -14
  455. package/src/DateRangeInput/DateRangeInput.tsx +27 -21
  456. package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -2
  457. package/src/DateTimeInput/DateTimeInput.test.tsx +154 -1
  458. package/src/DateTimeInput/DateTimeInput.tsx +58 -17
  459. package/src/Dialog/Dialog.tsx +2 -9
  460. package/src/DropdownMenu/DropdownMenu.doc.mjs +5 -9
  461. package/src/DropdownMenu/DropdownMenu.test.tsx +534 -4
  462. package/src/DropdownMenu/DropdownMenu.tsx +113 -52
  463. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +27 -30
  464. package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +34 -0
  465. package/src/DropdownMenu/DropdownMenuDivider.tsx +81 -0
  466. package/src/DropdownMenu/DropdownMenuItem.doc.mjs +39 -4
  467. package/src/DropdownMenu/DropdownMenuItem.tsx +48 -10
  468. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +2 -1
  469. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +30 -76
  470. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +25 -19
  471. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +44 -14
  472. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +1 -5
  473. package/src/DropdownMenu/index.ts +8 -1
  474. package/src/DropdownMenu/renderDropdownItems.tsx +33 -34
  475. package/src/EmptyState/EmptyState.doc.mjs +4 -0
  476. package/src/EmptyState/EmptyState.test.tsx +62 -0
  477. package/src/EmptyState/EmptyState.tsx +16 -6
  478. package/src/Field/Field.doc.mjs +1 -0
  479. package/src/Field/InputClearButton.test.tsx +117 -0
  480. package/src/Field/InputClearButton.tsx +30 -3
  481. package/src/Field/PanelSearchInput.tsx +271 -0
  482. package/src/FileInput/FileInput.tsx +21 -8
  483. package/src/Grid/Grid.tsx +0 -2
  484. package/src/Grid/index.ts +0 -2
  485. package/src/HoverCard/useHoverCard.tsx +2 -23
  486. package/src/Icon/Icon.doc.mjs +2 -1
  487. package/src/Icon/globalIconRegistry.tsx +5 -4
  488. package/src/Indicator/CheckIndicator.tsx +174 -0
  489. package/src/Indicator/CheckboxIndicator.tsx +257 -0
  490. package/src/Indicator/Indicator.doc.mjs +344 -0
  491. package/src/Indicator/Indicator.test.tsx +393 -0
  492. package/src/Indicator/RadioIndicator.tsx +206 -0
  493. package/src/Indicator/index.ts +46 -0
  494. package/src/Indicator/indicator.markers.stylex.ts +19 -0
  495. package/src/Indicator/indicatorRegistry.test.tsx +106 -0
  496. package/src/Indicator/indicatorRegistry.ts +120 -0
  497. package/src/Indicator/types.ts +197 -0
  498. package/src/Indicator/useIndicator.ts +39 -0
  499. package/src/Item/Item.doc.mjs +1 -1
  500. package/src/Item/Item.tsx +7 -14
  501. package/src/Layer/useLayer.doc.mjs +2 -2
  502. package/src/Layer/useLayer.test.tsx +85 -0
  503. package/src/Layer/useLayer.tsx +39 -1
  504. package/src/Lightbox/Lightbox.doc.mjs +1 -1
  505. package/src/Lightbox/Lightbox.tsx +45 -49
  506. package/src/Link/Link.tsx +4 -11
  507. package/src/MobileNav/MobileNav.tsx +3 -3
  508. package/src/MoreMenu/MoreMenu.doc.mjs +31 -0
  509. package/src/MoreMenu/MoreMenu.test.tsx +68 -1
  510. package/src/MoreMenu/MoreMenu.tsx +19 -0
  511. package/src/MultiSelector/MultiSelector.doc.mjs +18 -1
  512. package/src/MultiSelector/MultiSelector.test.tsx +387 -18
  513. package/src/MultiSelector/MultiSelector.tsx +267 -220
  514. package/src/NumberInput/NumberInput.doc.mjs +265 -50
  515. package/src/NumberInput/NumberInput.test.tsx +726 -21
  516. package/src/NumberInput/NumberInput.tsx +353 -59
  517. package/src/Outline/Outline.tsx +2 -5
  518. package/src/Pagination/Pagination.doc.mjs +1 -1
  519. package/src/Pagination/Pagination.test.tsx +22 -7
  520. package/src/Pagination/Pagination.tsx +38 -35
  521. package/src/Popover/Popover.doc.mjs +2 -0
  522. package/src/Popover/Popover.tsx +6 -7
  523. package/src/Popover/usePopover.tsx +37 -4
  524. package/src/PowerSearch/PowerSearch.tsx +1 -1
  525. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +42 -0
  526. package/src/PowerSearch/PowerSearchEditPopover.tsx +7 -0
  527. package/src/ProgressBar/ProgressBar.doc.mjs +27 -5
  528. package/src/ProgressBar/ProgressBar.test.tsx +224 -1
  529. package/src/ProgressBar/ProgressBar.tsx +126 -30
  530. package/src/RadioList/RadioList.doc.mjs +4 -2
  531. package/src/RadioList/RadioListItem.tsx +31 -130
  532. package/src/Resizable/ResizeHandle.tsx +2 -9
  533. package/src/Section/Section.tsx +0 -2
  534. package/src/Section/index.ts +0 -2
  535. package/src/SegmentedControl/SegmentedControlItem.tsx +2 -9
  536. package/src/SelectableCard/SelectableCard.tsx +4 -9
  537. package/src/Selector/Selector.doc.mjs +17 -4
  538. package/src/Selector/Selector.test.tsx +1394 -100
  539. package/src/Selector/Selector.tsx +355 -212
  540. package/src/Selector/hooks.ts +77 -50
  541. package/src/SideNav/SideNav.test.tsx +46 -0
  542. package/src/SideNav/SideNav.tsx +1 -0
  543. package/src/SideNav/SideNavCollapseButton.tsx +15 -10
  544. package/src/SideNav/SideNavHeading.tsx +48 -10
  545. package/src/SideNav/SideNavItem.tsx +20 -12
  546. package/src/Skeleton/Skeleton.tsx +0 -2
  547. package/src/Skeleton/index.ts +0 -2
  548. package/src/Slider/Slider.tsx +2 -11
  549. package/src/Stack/Stack.doc.mjs +110 -0
  550. package/src/StatusDot/StatusDot.doc.mjs +12 -3
  551. package/src/Switch/Switch.test.tsx +32 -0
  552. package/src/Switch/Switch.tsx +18 -10
  553. package/src/TabList/Tab.tsx +2 -9
  554. package/src/TabList/TabMenu.tsx +14 -21
  555. package/src/Table/BaseTable.tsx +11 -0
  556. package/src/Table/Table.test.tsx +31 -0
  557. package/src/Table/TableRow.tsx +6 -0
  558. package/src/Table/index.ts +1 -4
  559. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +30 -14
  560. package/src/Table/plugins/rowExpansion/index.ts +1 -4
  561. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +125 -175
  562. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +115 -458
  563. package/src/Table/plugins/sortable/useTableSortable.tsx +2 -6
  564. package/src/Table/plugins/tree/useTableTreeData.tsx +43 -24
  565. package/src/Table/tableContextMenu.test.tsx +27 -0
  566. package/src/Table/tableContextMenu.tsx +1 -0
  567. package/src/Table/types.ts +11 -0
  568. package/src/Table/useTableGroupedRows.doc.mjs +1 -1
  569. package/src/Table/useTableRowExpansion.doc.mjs +43 -66
  570. package/src/TextArea/TextArea.doc.mjs +42 -2
  571. package/src/TextArea/TextArea.test.tsx +219 -0
  572. package/src/TextArea/TextArea.tsx +34 -7
  573. package/src/TextInput/TextInput.doc.mjs +18 -2
  574. package/src/TextInput/TextInput.test.tsx +189 -0
  575. package/src/TextInput/TextInput.tsx +25 -31
  576. package/src/Thumbnail/Thumbnail.tsx +2 -9
  577. package/src/TimeInput/TimeInput.doc.mjs +2 -2
  578. package/src/TimeInput/TimeInput.test.tsx +84 -3
  579. package/src/TimeInput/TimeInput.tsx +26 -28
  580. package/src/Timestamp/Timestamp.doc.mjs +4 -3
  581. package/src/Timestamp/Timestamp.test.tsx +91 -14
  582. package/src/Timestamp/Timestamp.tsx +14 -2
  583. package/src/Timestamp/TimestampHoverCard.tsx +13 -35
  584. package/src/Timestamp/formatInstant.ts +16 -1
  585. package/src/Token/Token.tsx +5 -28
  586. package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
  587. package/src/Tokenizer/Tokenizer.test.tsx +45 -3
  588. package/src/Tokenizer/Tokenizer.tsx +10 -2
  589. package/src/Tooltip/useTooltip.tsx +2 -23
  590. package/src/TopNav/TopNav.tsx +1 -3
  591. package/src/TopNav/TopNavHeading.tsx +42 -13
  592. package/src/TopNav/TopNavItem.tsx +3 -21
  593. package/src/TopNav/TopNavMegaMenu.doc.mjs +5 -0
  594. package/src/TopNav/TopNavMegaMenu.test.tsx +433 -33
  595. package/src/TopNav/TopNavMegaMenu.tsx +118 -53
  596. package/src/TopNav/TopNavMegaMenuItem.tsx +2 -9
  597. package/src/TopNav/TopNavMenu.tsx +34 -37
  598. package/src/TreeList/TreeList.doc.mjs +5 -0
  599. package/src/TreeList/TreeList.test.tsx +208 -8
  600. package/src/TreeList/TreeList.tsx +22 -0
  601. package/src/TreeList/TreeListBranches.tsx +25 -2
  602. package/src/TreeList/TreeListItem.tsx +89 -52
  603. package/src/Typeahead/BaseTypeahead.tsx +19 -6
  604. package/src/Typeahead/Typeahead.doc.mjs +1 -0
  605. package/src/Typeahead/Typeahead.test.tsx +76 -3
  606. package/src/VisuallyHidden/VisuallyHidden.tsx +0 -2
  607. package/src/VisuallyHidden/index.ts +0 -2
  608. package/src/hooks/containerReveal.stylex.ts +102 -0
  609. package/src/hooks/index.ts +4 -0
  610. package/src/hooks/useClipboard.doc.mjs +87 -0
  611. package/src/hooks/useClipboard.test.tsx +151 -0
  612. package/src/hooks/useClipboard.ts +135 -0
  613. package/src/hooks/useContainerReveal.doc.mjs +7 -7
  614. package/src/hooks/useContainerReveal.test.tsx +42 -62
  615. package/src/hooks/useContainerReveal.ts +36 -91
  616. package/src/hooks/useImageMode.test.ts +1 -1
  617. package/src/hooks/useIndicatorFocusRing.tsx +120 -0
  618. package/src/hooks/useInputStatusIcon.tsx +8 -8
  619. package/src/hooks/useLongPress.test.tsx +18 -0
  620. package/src/hooks/useLongPress.ts +12 -2
  621. package/src/hooks/useScrollLock.test.ts +72 -0
  622. package/src/hooks/useScrollLock.ts +51 -19
  623. package/src/hooks/useStreamingText.test.ts +46 -1
  624. package/src/hooks/useStreamingText.ts +49 -7
  625. package/src/hooks/useTreeFocus.test.tsx +50 -0
  626. package/src/hooks/useTreeFocus.ts +14 -3
  627. package/src/hooks/useTypeahead.test.tsx +150 -0
  628. package/src/hooks/useTypeahead.ts +24 -9
  629. package/src/i18n/InternationalizationProvider.doc.mjs +7 -2
  630. package/src/index.ts +1 -0
  631. package/src/serverSafeComponents.test.ts +665 -0
  632. package/src/theme/defineTheme.ts +27 -0
  633. package/src/theme/derivedVarRegistry.test.ts +21 -1
  634. package/src/theme/derivedVarRegistry.ts +19 -6
  635. package/src/theme/expandColorScale.test.ts +14 -0
  636. package/src/theme/expandColorScale.ts +24 -9
  637. package/src/theme/expandTypeScale.test.ts +43 -0
  638. package/src/theme/expandTypeScale.ts +17 -0
  639. package/src/theme/generateThemeRules.test.ts +78 -20
  640. package/src/theme/generateThemeRules.ts +11 -0
  641. package/src/theme/index.ts +15 -0
  642. package/src/theme/tokens.stylex.ts +18 -0
  643. package/src/theme/tokens.test.ts +37 -0
  644. package/src/utils/focusOutline.stylex.ts +177 -0
  645. package/src/utils/focusReturn.test.ts +42 -0
  646. package/src/utils/focusReturn.ts +31 -0
  647. package/src/utils/index.ts +5 -0
  648. package/src/utils/interactionModality.ts +74 -0
  649. package/src/utils/mergeRefs.test.ts +48 -0
  650. package/src/utils/mergeRefs.ts +12 -6
  651. package/src/utils/rtlStyles.ts +2 -2
  652. package/src/utils/themeProps.ts +26 -4
  653. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts +0 -9
  654. package/dist/CheckboxInput/checkbox.markers.stylex.d.ts.map +0 -1
  655. package/dist/CheckboxInput/checkbox.markers.stylex.js +0 -14
  656. package/dist/RadioList/radio.markers.stylex.d.ts +0 -7
  657. package/dist/RadioList/radio.markers.stylex.d.ts.map +0 -1
  658. package/dist/RadioList/radio.markers.stylex.js +0 -12
  659. package/dist/hooks/containerReveal.pool.stylex.d.ts +0 -303
  660. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +0 -1
  661. package/dist/hooks/containerReveal.pool.stylex.js +0 -292
  662. package/src/CheckboxInput/checkbox.markers.stylex.ts +0 -12
  663. package/src/RadioList/radio.markers.stylex.ts +0 -10
  664. package/src/hooks/containerReveal.pool.stylex.ts +0 -571
@@ -4,7 +4,8 @@
4
4
 
5
5
  /**
6
6
  * @file Selector.tsx
7
- * @input Uses React, StyleX, usePopover, useTooltip, Icon, InputGroupContext
7
+ * @input Uses React, StyleX, usePopover, useTooltip, Icon, InputGroupContext,
8
+ * and Selector positioning hooks
8
9
  * @output Exports Selector component
9
10
  * @position Core implementation; consumed by index.ts
10
11
  *
@@ -31,9 +32,12 @@ import * as stylex from '@stylexjs/stylex';
31
32
  import {usePopover} from '../Popover/usePopover';
32
33
  import {useTooltip} from '../Tooltip';
33
34
  import {Icon, renderIconSlot, type IconType} from '../Icon';
35
+ import {useIndicator} from '../Indicator';
36
+ import type {IndicatorPosition} from '../Indicator';
34
37
  import type {IconName} from '../Icon';
35
38
  import {
36
39
  Field,
40
+ InputClearButton,
37
41
  inputStatusBorderStyles,
38
42
  inputStatusHoverShadowStyles,
39
43
  inputWrapperStyles,
@@ -43,7 +47,7 @@ import {Divider} from '../Divider';
43
47
  import {layerAnimations} from '../Layer/layerAnimations.stylex';
44
48
  import type {LayerPlacement} from '../Layer/useLayer';
45
49
  import {Spinner} from '../Spinner';
46
- import {TextInput} from '../TextInput';
50
+ import {PanelSearchInput} from '../Field/PanelSearchInput';
47
51
  import {useAnnounce} from '../hooks/useAnnounce';
48
52
  import {
49
53
  colorVars,
@@ -66,12 +70,15 @@ import {
66
70
  getSelectableOptions,
67
71
  } from './utils';
68
72
  import {useCombobox, useSelectedItemOffset} from './hooks';
73
+ import {useTypeahead} from '../hooks/useTypeahead';
69
74
  import {SelectorOption} from './SelectorOption';
70
75
  import {getInputARIA, mergeProps} from '../utils';
71
76
  import {useSize} from '../SizeContext/SizeContext';
72
77
  import type {BaseProps} from '../BaseProps';
73
78
  import type {SizeValue} from '../utils/types';
74
79
  import {themeProps} from '../utils/themeProps';
80
+ import {focusOutlineStyles} from '../utils/focusOutline.stylex';
81
+ import {stableClassName} from '../naming';
75
82
  import {groupStyles} from '../InputGroup/groupStyles';
76
83
  import {useInputGroup} from '../InputGroup/InputGroupContext';
77
84
  import {VisuallyHidden} from '../VisuallyHidden';
@@ -134,26 +141,27 @@ const styles = stylex.create({
134
141
  whiteSpace: 'nowrap',
135
142
  textAlign: 'start',
136
143
  },
144
+ // Only what Icon does not already provide: `size="sm"` gives the 16px box
145
+ // and `color` the token, but the glyph still must not shrink inside the flex
146
+ // trigger.
137
147
  triggerIcon: {
138
148
  flexShrink: 0,
139
- display: 'flex',
140
- alignItems: 'center',
141
- justifyContent: 'center',
142
- width: 16,
143
- height: 16,
149
+ },
150
+ // Rotation lives on the chevron glyph itself (passed through `xstyle`), not
151
+ // on the layout wrapper above, so the icon's `selector-indicator-icon` theme
152
+ // target and the open/closed transform sit on one element — a theme can
153
+ // restyle the mark and its rotation through a single selector. The wrapper
154
+ // keeps only layout. The status branch renders a different icon, so it never
155
+ // picks these up and needs no transition opt-out.
156
+ triggerIconRotation: {
144
157
  transitionProperty: 'transform',
145
158
  transitionDuration: durationVars['--duration-fast'],
146
159
  transitionTimingFunction: easeVars['--ease-standard'],
147
160
  transformOrigin: 'center',
148
- color: colorVars['--color-icon-secondary'],
149
161
  },
150
162
  triggerIconOpen: {
151
163
  transform: 'rotate(180deg)',
152
164
  },
153
- triggerIconStatus: {
154
- // Disable rotation transition for status icons
155
- transition: 'none',
156
- },
157
165
  triggerGhost: {
158
166
  width: 'auto',
159
167
  borderWidth: 0,
@@ -173,14 +181,6 @@ const styles = stylex.create({
173
181
  ':focus-within': 'none',
174
182
  },
175
183
  fontWeight: fontWeightVars['--font-weight-medium'],
176
- outline: {
177
- default: 'none',
178
- ':has(:focus-visible)': `2px solid ${colorVars['--color-accent']}`,
179
- },
180
- outlineOffset: {
181
- default: '0',
182
- ':has(:focus-visible)': '3px',
183
- },
184
184
  transitionProperty:
185
185
  'background-image, background-color, color, opacity, transform',
186
186
  transform: {
@@ -197,23 +197,6 @@ const styles = stylex.create({
197
197
  },
198
198
 
199
199
  // Clear button
200
- clearButton: {
201
- display: 'flex',
202
- alignItems: 'center',
203
- justifyContent: 'center',
204
- padding: 0,
205
- margin: 0,
206
- borderWidth: 0,
207
- borderStyle: 'none',
208
- backgroundColor: 'transparent',
209
- cursor: 'pointer',
210
- borderRadius: radiusVars['--radius-element'],
211
- outline: {
212
- default: 'none',
213
- ':focus-visible': `${borderVars['--border-width']} solid ${colorVars['--color-accent']}`,
214
- },
215
- outlineOffset: 1,
216
- },
217
200
  statusButton: {
218
201
  display: 'flex',
219
202
  alignItems: 'center',
@@ -226,11 +209,6 @@ const styles = stylex.create({
226
209
  color: 'inherit',
227
210
  cursor: 'pointer',
228
211
  borderRadius: radiusVars['--radius-element'],
229
- outline: {
230
- default: 'none',
231
- ':focus-visible': `${borderVars['--border-width']} solid ${colorVars['--color-accent']}`,
232
- },
233
- outlineOffset: 1,
234
212
  },
235
213
 
236
214
  // Dropdown container
@@ -238,10 +216,21 @@ const styles = stylex.create({
238
216
  boxSizing: 'border-box',
239
217
  maxHeight: '300px',
240
218
  overflowY: 'auto',
241
- padding: spacingVars['--spacing-1'],
219
+ paddingBlock: spacingVars['--spacing-1'],
220
+ paddingInline: spacingVars['--spacing-1'],
242
221
  opacity: 1,
243
222
  transition: `opacity ${durationVars['--duration-fast']}`,
244
223
  },
224
+ dropdownInput: {
225
+ // The input trigger's text inset includes its border. Mirror that extra
226
+ // pixel in the menu; the borderless ghost variant needs no correction.
227
+ paddingInline: `calc(${spacingVars['--spacing-1']} + ${borderVars['--border-width']})`,
228
+ },
229
+ // Same correction for the search row's gutter, so the search field and the
230
+ // option rows share one left edge.
231
+ searchRowInput: {
232
+ paddingInline: `calc(${spacingVars['--spacing-1']} + ${borderVars['--border-width']})`,
233
+ },
245
234
  dropdownHidden: {
246
235
  opacity: 0,
247
236
  transition: 'none',
@@ -251,15 +240,6 @@ const styles = stylex.create({
251
240
  popover: {
252
241
  minWidth: 'anchor-size(width)',
253
242
  },
254
- // Search field. The inner TextInput owns the border, focus ring, magnifier
255
- // (startIcon), and clear button (hasClear); this wrapper only supplies the
256
- // dropdown's inline/block padding around it.
257
- searchWrapper: {
258
- display: 'flex',
259
- alignItems: 'center',
260
- paddingInline: spacingVars['--spacing-2'],
261
- paddingBlock: spacingVars['--spacing-1'],
262
- },
263
243
 
264
244
  // Empty state
265
245
  emptyState: {
@@ -270,9 +250,19 @@ const styles = stylex.create({
270
250
  fontSize: typeScaleVars['--text-label-size'],
271
251
  },
272
252
 
273
- // Section divider with label
274
- sectionDivider: {
275
- marginBlock: spacingVars['--spacing-1'],
253
+ // Section heading. Plain secondary text, no rules — the same treatment
254
+ // DropdownMenu and CommandPaletteGroup already use for a group heading in a
255
+ // panel list. A labeled Divider (line–text–line) reads as a separator, and
256
+ // next to the search row's own divider it stacked two rules a few pixels
257
+ // apart.
258
+ sectionHeading: {
259
+ paddingBlock: spacingVars['--spacing-1'],
260
+ paddingInline: spacingVars['--spacing-2'],
261
+ fontFamily: typographyVars['--font-family-body'],
262
+ fontSize: typeScaleVars['--text-supporting-size'],
263
+ lineHeight: typeScaleVars['--text-supporting-leading'],
264
+ color: colorVars['--color-text-secondary'],
265
+ userSelect: 'none',
276
266
  },
277
267
 
278
268
  // Divider
@@ -306,6 +296,19 @@ const styles = stylex.create({
306
296
  flex: 1,
307
297
  minWidth: 0,
308
298
  },
299
+ // The mark's column, reserved on every row and at either position, so a row
300
+ // occupies the same geometry whether or not it is the chosen one — the
301
+ // default check draws nothing when unchecked, and without the column a list
302
+ // would indent (or truncate) its chosen row differently from the rest.
303
+ // `minWidth` rather than `width`: a theme can replace `check` with a larger
304
+ // indicator (a radio is 20px at `sm`), and the column has to grow with it.
305
+ itemMarkColumn: {
306
+ display: 'inline-flex',
307
+ alignItems: 'center',
308
+ justifyContent: 'center',
309
+ flexShrink: 0,
310
+ minWidth: '1rem',
311
+ },
309
312
  itemCheckmark: {
310
313
  flexShrink: 0,
311
314
  width: 16,
@@ -523,6 +526,16 @@ interface SelectorPropsBase<
523
526
  */
524
527
  renderOption?: (option: SelectorOptionData) => ReactNode;
525
528
 
529
+ /**
530
+ * Which edge of the option row carries the selected mark. `start` reserves a
531
+ * mark column ahead of every label so they stay aligned, the way a native
532
+ * menu does; `end` is the house convention shared with Typeahead and
533
+ * CommandPalette.
534
+ *
535
+ * @default 'end'
536
+ */
537
+ indicatorPosition?: IndicatorPosition;
538
+
526
539
  /**
527
540
  * Whether to show a search input for filtering options.
528
541
  * @default false
@@ -673,6 +686,7 @@ export function Selector<T extends SelectorOptionType>(
673
686
  startIcon,
674
687
  htmlName,
675
688
  renderOption,
689
+ indicatorPosition = 'end',
676
690
  hasSearch = false,
677
691
  searchPlaceholder: searchPlaceholderFromProps,
678
692
  placement,
@@ -703,18 +717,22 @@ export function Selector<T extends SelectorOptionType>(
703
717
  const statusMessageId = useId();
704
718
  const inputLabelId = useId();
705
719
  const searchId = useId();
720
+ // Measure from the same outer control that usePopover anchors to; using the
721
+ // shorter inner button makes every size's selected row land too low.
722
+ const anchorRef = useRef<HTMLDivElement>(null);
706
723
  const triggerRef = useRef<HTMLButtonElement>(null);
707
724
  const searchRef = useRef<HTMLInputElement>(null);
708
725
  const inputGroup = useInputGroup();
709
726
 
710
727
  const [searchQuery, setSearchQuery] = useState('');
711
- // A typed query shows TextInput's built-in clear (✕) button, which becomes
728
+ // A typed query shows the search row's clear (✕) button, which becomes
712
729
  // the next tab stop after the search input.
713
730
  const hasQuery = searchQuery.length > 0;
714
731
 
715
732
  const [, startTransition] = useTransition();
716
733
  const [optimisticValue, setOptimisticValue] = useOptimistic(normalizedValue);
717
734
  const isBusy = isLoading || optimisticValue !== normalizedValue;
735
+ const announce = useAnnounce();
718
736
 
719
737
  // Disabled-reason tooltip. Disabled controls swallow pointer events, so the
720
738
  // tooltip listeners attach to the trigger container (which already exists)
@@ -775,15 +793,15 @@ export function Selector<T extends SelectorOptionType>(
775
793
  // Ref for listbox to measure selected item position
776
794
  const listboxRef = useRef<HTMLDivElement>(null);
777
795
 
778
- // Announce match counts / "No results found" politely as the user types, so
779
- // screen-reader users hear how many options remain. Filtering was previously
780
- // silent (comboboxes-7). Mirrors BaseTypeahead, which announces from its
781
- // query-change callback (not a reactive effect) via the same useAnnounce hook.
782
- const announce = useAnnounce();
796
+ // Typeahead is defined below (it needs the popover), but closing and clearing
797
+ // must drop its pending buffer — otherwise a stale prefix survives the reset
798
+ // window and poisons the next keystroke ("Dog" then "c" would search "dc").
799
+ const resetTypeaheadRef = useRef<() => void>(() => {});
783
800
 
784
801
  // Layer for dropdown positioning
785
802
  const handleLayerHide = useCallback(() => {
786
803
  setSearchQuery('');
804
+ resetTypeaheadRef.current();
787
805
  // Clear any lingering result count when the popover closes so stale status
788
806
  // text does not linger in the a11y tree.
789
807
  announce('');
@@ -798,6 +816,9 @@ export function Selector<T extends SelectorOptionType>(
798
816
  // The popup's own role="listbox" is the exposed semantics; the trigger
799
817
  // keeps DOM focus, so wrapping it in a modal dialog would misrepresent it.
800
818
  role: 'none',
819
+ // The theme target belongs on the SURFACE that paints the popup, which
820
+ // `usePopover` owns — not on the scrolling list inside it.
821
+ surfaceTarget: 'selector-popup',
801
822
  });
802
823
 
803
824
  // Open dropdown on mount when isDefaultOpen is true
@@ -840,7 +861,7 @@ export function Selector<T extends SelectorOptionType>(
840
861
  selectedItemIndex,
841
862
  listboxId,
842
863
  listboxRef,
843
- triggerRef,
864
+ anchorRef,
844
865
  });
845
866
 
846
867
  const selectedItemOffset = shouldOverlaySelectedItem ? rawOffset : 0;
@@ -854,6 +875,7 @@ export function Selector<T extends SelectorOptionType>(
854
875
  // Clear the current value. Shared by the clear button and the keyboard
855
876
  // Delete/Backspace path so clearing is reachable without a mouse.
856
877
  const clearValue = useCallback(() => {
878
+ resetTypeaheadRef.current();
857
879
  onChange?.(null);
858
880
  if (changeAction) {
859
881
  startTransition(async () => {
@@ -863,10 +885,29 @@ export function Selector<T extends SelectorOptionType>(
863
885
  }
864
886
  }, [onChange, changeAction, startTransition, setOptimisticValue]);
865
887
 
866
- // Selector behavior (keyboard nav, typeahead, selection)
888
+ // Type-to-find appends to the query rather than replacing it: characters
889
+ // typed before focus reaches the search input must not be dropped.
890
+ const appendSearchQuery = useCallback((char: string) => {
891
+ setSearchQuery(query => query + char);
892
+ }, []);
893
+
894
+ const commitValue = useCallback(
895
+ (newValue: string) => {
896
+ onChange?.(newValue);
897
+ if (changeAction) {
898
+ startTransition(async () => {
899
+ setOptimisticValue(newValue);
900
+ await changeAction(newValue);
901
+ });
902
+ }
903
+ },
904
+ [onChange, changeAction, startTransition, setOptimisticValue],
905
+ );
906
+
907
+ // Selector behavior (keyboard nav, selection)
867
908
  const {
868
909
  highlightedIndex,
869
- setHighlightedIndex: _setHighlightedIndex,
910
+ setHighlightedIndex,
870
911
  getItemId,
871
912
  onTriggerClick,
872
913
  onKeyDown,
@@ -874,7 +915,11 @@ export function Selector<T extends SelectorOptionType>(
874
915
  onItemMouseEnter,
875
916
  } = useCombobox({
876
917
  selectableItems: filteredItems,
877
- value: normalizedValue,
918
+ // The optimistic value, not the raw prop: with a pending changeAction the
919
+ // prop still holds the old selection, so the popup would open with the
920
+ // highlight on it and Delete/Backspace could clear a value the action has
921
+ // already replaced.
922
+ value: optimisticValue,
878
923
  isDisabled,
879
924
  isOpen: popover.isOpen,
880
925
  hasSearch,
@@ -882,27 +927,61 @@ export function Selector<T extends SelectorOptionType>(
882
927
  popover.show();
883
928
  if (hasSearch) {
884
929
  requestAnimationFrame(() => {
885
- searchRef.current?.focus();
930
+ const input = searchRef.current;
931
+ if (input) {
932
+ input.focus();
933
+ // When typing seeded the query, place the caret after it so the
934
+ // user keeps typing where they left off.
935
+ input.setSelectionRange(input.value.length, input.value.length);
936
+ }
886
937
  });
887
938
  }
888
939
  }, [popover, hasSearch]),
889
940
  onClose: popover.hide,
890
- onSelect: useCallback(
891
- (newValue: string) => {
892
- onChange?.(newValue);
893
- if (changeAction) {
894
- startTransition(async () => {
895
- setOptimisticValue(newValue);
896
- await changeAction(newValue);
897
- });
898
- }
899
- },
900
- [onChange, changeAction, startTransition, setOptimisticValue],
901
- ),
941
+ onSelect: commitValue,
902
942
  onClear: hasClear ? clearValue : undefined,
943
+ onSearchSeed: appendSearchQuery,
903
944
  listboxId,
904
945
  });
905
946
 
947
+ // Type-to-select, shared with the other collections (menus, listboxes).
948
+ // Open, it walks the highlight — aria-activedescendant announces each match.
949
+ // Closed, it commits the match like a native select, which changes the value
950
+ // without opening the popup or moving focus, so nothing else would prompt
951
+ // assistive tech to re-read the trigger: announce it explicitly.
952
+ const typeahead = useTypeahead({
953
+ getItemLabels: () => selectableItems.map(item => item.label ?? item.value),
954
+ isDisabled: index => selectableItems[index]?.disabled === true,
955
+ // Cycle onward from the highlight when open, from the committed selection
956
+ // when closed — the optimistic one, so a pending changeAction cannot strand
957
+ // cycling on the first match. -1 means nothing is selected or highlighted,
958
+ // which the hook reads as "search from the top".
959
+ getCurrentIndex: () =>
960
+ popover.isOpen ? highlightedIndex : selectedItemIndex,
961
+ onMatch: index => {
962
+ const item = selectableItems[index];
963
+ if (popover.isOpen) {
964
+ setHighlightedIndex(index);
965
+ } else if (item.value !== optimisticValue) {
966
+ commitValue(item.value);
967
+ announce(item.label ?? item.value);
968
+ }
969
+ },
970
+ });
971
+ resetTypeaheadRef.current = typeahead.reset;
972
+
973
+ const handleTriggerKeyDown = useCallback(
974
+ (e: React.KeyboardEvent) => {
975
+ // With hasSearch the query input owns typing, so type-to-select is off.
976
+ if (!isDisabled && !hasSearch && typeahead.onKeyDown(e)) {
977
+ e.preventDefault();
978
+ return;
979
+ }
980
+ onKeyDown(e);
981
+ },
982
+ [isDisabled, hasSearch, typeahead, onKeyDown],
983
+ );
984
+
906
985
  // Keep the highlighted option visible during keyboard navigation. The
907
986
  // listbox is a fixed-height scroll container, so without this the virtual
908
987
  // cursor walks off-screen once navigation passes the visible window. Mirrors
@@ -931,11 +1010,40 @@ export function Selector<T extends SelectorOptionType>(
931
1010
  return null;
932
1011
  }
933
1012
  return (
934
- <div
935
- {...stylex.props(styles.searchWrapper)}
936
- onKeyDown={e => {
937
- // The clear (✕) button lives inside the TextInput, after the input in
938
- // DOM order. When it is focused and the user tabs forward there is
1013
+ <PanelSearchInput
1014
+ ref={searchRef}
1015
+ id={searchId}
1016
+ // The search row is the panel's header: a magnifier, a borderless
1017
+ // input, and the shared clear (✕) button. It deliberately does NOT
1018
+ // render a bordered TextInput — the popup is already a bordered
1019
+ // surface, and a field inside it drew a second box within that box.
1020
+ label={t('@astryx.selector.searchOptions')}
1021
+ // Same accessible name the TextInput's built-in clear produced
1022
+ // ("Clear Search options"), so the affordance keeps its name while its
1023
+ // chrome changes.
1024
+ clearLabel={t('@astryx.textInput.clearLabel', {
1025
+ label: t('@astryx.selector.searchOptions'),
1026
+ })}
1027
+ {...themeProps('selector-search')}
1028
+ xstyle={variant !== 'ghost' && styles.searchRowInput}
1029
+ // When hasSearch is set, focus moves into this input on open, so it —
1030
+ // not the trigger — must be the combobox that reports the highlighted
1031
+ // option via aria-activedescendant (comboboxes-4). A bare searchbox
1032
+ // left the highlight silent to screen readers.
1033
+ role="combobox"
1034
+ aria-expanded={popover.isOpen}
1035
+ aria-controls={listboxId}
1036
+ aria-autocomplete="list"
1037
+ aria-activedescendant={
1038
+ popover.isOpen && highlightedIndex >= 0
1039
+ ? getItemId(highlightedIndex)
1040
+ : undefined
1041
+ }
1042
+ value={searchQuery}
1043
+ onValueChange={handleSearchChange}
1044
+ onContainerKeyDown={e => {
1045
+ // The clear (✕) button lives inside the row, after the input in DOM
1046
+ // order. When it is focused and the user tabs forward there is
939
1047
  // nothing else in the popup, so dismiss it (Shift+Tab returns to the
940
1048
  // input natively). Key events originating on the input are handled on
941
1049
  // the input below; ignore them here so we don't double-dismiss.
@@ -945,65 +1053,32 @@ export function Selector<T extends SelectorOptionType>(
945
1053
  if (e.key === 'Tab' && !e.shiftKey) {
946
1054
  onKeyDown(e);
947
1055
  }
948
- }}>
949
- <TextInput
950
- ref={searchRef}
951
- id={searchId}
952
- // The search field IS a TextInput: the leading magnifier is its
953
- // `startIcon` and the trailing clear (✕) is its built-in `hasClear`
954
- // (which resets the value and refocuses the input). We add no bespoke
955
- // affordance chrome — the field just looks and behaves like every
956
- // other Astryx input.
957
- label={t('@astryx.selector.searchOptions')}
958
- isLabelHidden
959
- startIcon="search"
960
- hasClear
961
- size="sm"
962
- // Fill the dropdown's width (minus the wrapper's inline padding) so
963
- // the field is flush end-to-end rather than sized to its content.
964
- width="100%"
965
- // When hasSearch is set, focus moves into this input on open, so it —
966
- // not the trigger — must be the combobox that reports the highlighted
967
- // option via aria-activedescendant (comboboxes-4). A bare searchbox
968
- // left the highlight silent to screen readers. role + aria-* pass
969
- // through to the underlying <input> via BaseProps.
970
- role="combobox"
971
- aria-expanded={popover.isOpen}
972
- aria-controls={listboxId}
973
- aria-autocomplete="list"
974
- aria-activedescendant={
975
- popover.isOpen && highlightedIndex >= 0
976
- ? getItemId(highlightedIndex)
977
- : undefined
1056
+ }}
1057
+ onKeyDown={e => {
1058
+ // Arrow keys navigate options; Enter selects; Escape closes.
1059
+ // Home/End are left to the input for caret movement (APG editable
1060
+ // combobox); PageUp/PageDown are the sanctioned substitute for
1061
+ // jumping to the first/last option.
1062
+ if (
1063
+ e.key === 'ArrowDown' ||
1064
+ e.key === 'ArrowUp' ||
1065
+ e.key === 'PageUp' ||
1066
+ e.key === 'PageDown' ||
1067
+ e.key === 'Enter' ||
1068
+ e.key === 'Escape'
1069
+ ) {
1070
+ onKeyDown(e);
1071
+ return;
978
1072
  }
979
- value={searchQuery}
980
- onChange={handleSearchChange}
981
- onKeyDown={e => {
982
- // Arrow keys navigate options; Enter selects; Escape closes.
983
- // Home/End are left to the input for caret movement (APG editable
984
- // combobox); PageUp/PageDown are the sanctioned substitute for
985
- // jumping to the first/last option.
986
- if (
987
- e.key === 'ArrowDown' ||
988
- e.key === 'ArrowUp' ||
989
- e.key === 'PageUp' ||
990
- e.key === 'PageDown' ||
991
- e.key === 'Enter' ||
992
- e.key === 'Escape'
993
- ) {
994
- onKeyDown(e);
995
- return;
996
- }
997
- // Tab: when a query is showing the clear (✕) button, forward-tab
998
- // moves focus to it (keeping the popup open) so the affordance is
999
- // keyboard-reachable. Every other Tab dismisses the popup as usual.
1000
- if (e.key === 'Tab' && (e.shiftKey || !hasQuery)) {
1001
- onKeyDown(e);
1002
- }
1003
- }}
1004
- placeholder={searchPlaceholder}
1005
- />
1006
- </div>
1073
+ // Tab: when a query is showing the clear (✕) button, forward-tab
1074
+ // moves focus to it (keeping the popup open) so the affordance is
1075
+ // keyboard-reachable. Every other Tab dismisses the popup as usual.
1076
+ if (e.key === 'Tab' && (e.shiftKey || !hasQuery)) {
1077
+ onKeyDown(e);
1078
+ }
1079
+ }}
1080
+ placeholder={searchPlaceholder}
1081
+ />
1007
1082
  );
1008
1083
  }, [
1009
1084
  hasSearch,
@@ -1017,15 +1092,60 @@ export function Selector<T extends SelectorOptionType>(
1017
1092
  popover.isOpen,
1018
1093
  highlightedIndex,
1019
1094
  getItemId,
1095
+ variant,
1020
1096
  t,
1021
1097
  ]);
1022
1098
 
1099
+ // The single-selection mark, resolved from the theme once per render. A
1100
+ // theme that maps `check` to another indicator (a radio, say) changes every
1101
+ // selected-option mark in the app through this one lookup.
1102
+ const SelectionMark = useIndicator('check');
1103
+
1023
1104
  // Render an individual item
1024
1105
  const renderItem = useCallback(
1025
1106
  (item: SelectorOptionData, flatIndex: number) => {
1026
1107
  const isHighlighted = flatIndex === highlightedIndex;
1027
1108
  const isSelected = item.value === normalizedValue;
1028
1109
 
1110
+ /*
1111
+ * Rendered UNCONDITIONALLY, with the state passed down: the default
1112
+ * check draws nothing when unchecked, but a theme that replaces the
1113
+ * `check` indicator with a radio needs the unselected state to draw
1114
+ * its empty circle. `{isSelected && …}` would make that impossible.
1115
+ *
1116
+ * `selector-check` stays the stable target for the mark's position
1117
+ * in the row; the indicator owns what the mark looks like.
1118
+ */
1119
+ const mark = (
1120
+ <span {...stylex.props(styles.itemMarkColumn)}>
1121
+ <SelectionMark
1122
+ state={isSelected ? 'checked' : 'unchecked'}
1123
+ size="sm"
1124
+ isDisabled={item.disabled ?? false}
1125
+ {...themeProps('selector-check')}
1126
+ />
1127
+ </span>
1128
+ );
1129
+
1130
+ const optionContent = (
1131
+ <span {...stylex.props(styles.itemContent)}>
1132
+ {renderOption ? renderOption(item) : <DefaultOption option={item} />}
1133
+ </span>
1134
+ );
1135
+
1136
+ const content =
1137
+ indicatorPosition === 'start' ? (
1138
+ <>
1139
+ {mark}
1140
+ {optionContent}
1141
+ </>
1142
+ ) : (
1143
+ <>
1144
+ {optionContent}
1145
+ {mark}
1146
+ </>
1147
+ );
1148
+
1029
1149
  return (
1030
1150
  <div
1031
1151
  key={item.value}
@@ -1042,25 +1162,20 @@ export function Selector<T extends SelectorOptionType>(
1042
1162
  isSelected && styles.itemSelected,
1043
1163
  item.disabled && styles.itemDisabled,
1044
1164
  )}>
1045
- <span {...stylex.props(styles.itemContent)}>
1046
- {renderOption ? (
1047
- renderOption(item)
1048
- ) : (
1049
- <DefaultOption option={item} />
1050
- )}
1051
- </span>
1052
- {isSelected && <Icon icon="check" size="sm" color="accent" />}
1165
+ {content}
1053
1166
  </div>
1054
1167
  );
1055
1168
  },
1056
1169
  [
1057
1170
  renderOption,
1171
+ indicatorPosition,
1058
1172
  highlightedIndex,
1059
1173
  size,
1060
1174
  normalizedValue,
1061
1175
  getItemId,
1062
1176
  onItemSelect,
1063
1177
  onItemMouseEnter,
1178
+ SelectionMark,
1064
1179
  ],
1065
1180
  );
1066
1181
 
@@ -1078,7 +1193,10 @@ export function Selector<T extends SelectorOptionType>(
1078
1193
  <div
1079
1194
  key="empty"
1080
1195
  role="presentation"
1081
- {...stylex.props(styles.emptyState)}>
1196
+ {...mergeProps(
1197
+ themeProps('selector-empty-state'),
1198
+ stylex.props(styles.emptyState),
1199
+ )}>
1082
1200
  No results found
1083
1201
  </div>,
1084
1202
  ];
@@ -1112,17 +1230,23 @@ export function Selector<T extends SelectorOptionType>(
1112
1230
  if (sectionItems.length === 0) {
1113
1231
  continue;
1114
1232
  }
1115
- if (option.title) {
1116
- elements.push(
1117
- <Divider
1118
- key={`section-divider-${i}`}
1119
- label={option.title}
1120
- xstyle={styles.sectionDivider}
1121
- />,
1122
- );
1123
- }
1233
+ // The heading lives INSIDE the group and is aria-hidden: the group
1234
+ // already carries the title as its accessible name, so exposing the
1235
+ // text again would announce it twice. This also keeps role="listbox"'s
1236
+ // children to option/group only — the old labeled Divider sat in the
1237
+ // listbox as a stray role="separator".
1124
1238
  elements.push(
1125
1239
  <div key={`section-${i}`} role="group" aria-label={option.title}>
1240
+ {option.title && (
1241
+ <div
1242
+ aria-hidden="true"
1243
+ {...mergeProps(
1244
+ themeProps('selector-section-heading'),
1245
+ stylex.props(styles.sectionHeading),
1246
+ )}>
1247
+ {option.title}
1248
+ </div>
1249
+ )}
1126
1250
  {sectionItems}
1127
1251
  </div>,
1128
1252
  );
@@ -1150,6 +1274,7 @@ export function Selector<T extends SelectorOptionType>(
1150
1274
  <>
1151
1275
  <div
1152
1276
  ref={el => {
1277
+ anchorRef.current = el;
1153
1278
  popover.triggerRef(el);
1154
1279
  // Anchor + hover/focus listeners for the disabled-message tooltip.
1155
1280
  // Handlers are gated internally by isEnabled, and anchor names
@@ -1163,12 +1288,14 @@ export function Selector<T extends SelectorOptionType>(
1163
1288
  variant,
1164
1289
  size,
1165
1290
  status: status?.type ?? null,
1291
+ disabled: isDisabled ? 'disabled' : null,
1166
1292
  }),
1167
1293
  stylex.props(
1168
1294
  inputWrapperStyles.base,
1169
1295
  styles.triggerContainer,
1170
1296
  sizeStyles[size],
1171
1297
  variant === 'ghost' && styles.triggerGhost,
1298
+ variant === 'ghost' && focusOutlineStyles.focusWithin,
1172
1299
  isDisabled && inputWrapperStyles.disabled,
1173
1300
  variant === 'ghost' && isDisabled && styles.triggerGhostDisabled,
1174
1301
  !selectedItem && styles.triggerPlaceholder,
@@ -1217,7 +1344,7 @@ export function Selector<T extends SelectorOptionType>(
1217
1344
  // still blocked by the isDisabled guards in useCombobox.
1218
1345
  disabled={isDisabled && !showsDisabledMessage}
1219
1346
  aria-disabled={showsDisabledMessage ? 'true' : undefined}
1220
- onKeyDown={onKeyDown}
1347
+ onKeyDown={handleTriggerKeyDown}
1221
1348
  tabIndex={isDisabled && !showsDisabledMessage ? -1 : 0}
1222
1349
  {...stylex.props(styles.trigger)}>
1223
1350
  <span {...stylex.props(styles.triggerLabel)}>
@@ -1236,80 +1363,89 @@ export function Selector<T extends SelectorOptionType>(
1236
1363
  )}
1237
1364
  {isBusy && <Spinner size="sm" />}
1238
1365
  {hasClear && value != null && !isDisabled && (
1239
- <button
1240
- type="button"
1366
+ <InputClearButton
1367
+ label={t('@astryx.selector.clearLabel', {label})}
1241
1368
  onClick={handleClear}
1242
- aria-label={t('@astryx.selector.clearLabel', {label})}
1243
- {...stylex.props(styles.clearButton)}>
1244
- <Icon
1245
- icon="close"
1246
- size="sm"
1247
- color="secondary"
1248
- // Stable theme target on the clear glyph itself, so a theme can
1249
- // restyle just this icon (color, size, hover) via `defineTheme`.
1250
- // Same-element rules in @layer astryx-theme win over the icon's
1251
- // own base color/size, which a button-level target could not
1252
- // reach.
1253
- {...themeProps('selector-clear-icon')}
1254
- />
1255
- </button>
1369
+ iconClassName={stableClassName('selector-clear-icon')}
1370
+ />
1256
1371
  )}
1257
- <span
1258
- {...stylex.props(
1259
- styles.triggerIcon,
1260
- !showStatusIcon && popover.isOpen && styles.triggerIconOpen,
1261
- showStatusIcon && styles.triggerIconStatus,
1262
- )}>
1263
- {showStatusIcon ? (
1264
- showStatusTooltip ? (
1265
- <button
1266
- ref={statusTooltip.ref}
1267
- type="button"
1268
- aria-label={t(STATUS_BUTTON_LABEL_KEY[status.type])}
1269
- aria-describedby={statusTooltip.describedBy}
1270
- onClick={e => e.stopPropagation()}
1271
- {...stylex.props(styles.statusButton)}>
1272
- <Icon
1273
- icon={STATUS_ICON_MAP[status.type]}
1274
- size="sm"
1275
- color={STATUS_ICON_COLOR_MAP[status.type]}
1276
- />
1277
- </button>
1278
- ) : (
1372
+ {/*
1373
+ No wrapper span: Icon's own span already provides the 16px box (`sm`)
1374
+ and the icon color, so the status glyph and the chevron are each
1375
+ directly targetable instead of sharing one untargetable parent — and
1376
+ the two affordances stop sharing a node.
1377
+ */}
1378
+ {showStatusIcon ? (
1379
+ showStatusTooltip ? (
1380
+ <button
1381
+ ref={statusTooltip.ref}
1382
+ type="button"
1383
+ aria-label={t(STATUS_BUTTON_LABEL_KEY[status.type])}
1384
+ aria-describedby={statusTooltip.describedBy}
1385
+ onClick={e => e.stopPropagation()}
1386
+ {...stylex.props(
1387
+ focusOutlineStyles.focusVisible,
1388
+ styles.statusButton,
1389
+ )}>
1279
1390
  <Icon
1280
1391
  icon={STATUS_ICON_MAP[status.type]}
1281
1392
  size="sm"
1282
1393
  color={STATUS_ICON_COLOR_MAP[status.type]}
1394
+ xstyle={styles.triggerIcon}
1283
1395
  />
1284
- )
1396
+ </button>
1285
1397
  ) : (
1286
1398
  <Icon
1287
- icon="chevronDown"
1399
+ icon={STATUS_ICON_MAP[status.type]}
1288
1400
  size="sm"
1289
- color="inherit"
1290
- // Stable theme target on the chevron glyph itself, so a theme can
1291
- // restyle just this icon (color, size, hover) — and its
1292
- // open/closed state — via `defineTheme`. Same-element rules in
1293
- // @layer astryx-theme win over the icon's own base color/size,
1294
- // which a button-level target could not reach.
1295
- {...themeProps('selector-indicator-icon', {
1296
- state: popover.isOpen ? 'expanded' : 'collapsed',
1297
- })}
1401
+ color={STATUS_ICON_COLOR_MAP[status.type]}
1402
+ xstyle={styles.triggerIcon}
1298
1403
  />
1299
- )}
1300
- </span>
1404
+ )
1405
+ ) : (
1406
+ <Icon
1407
+ icon="chevronDown"
1408
+ size="sm"
1409
+ color="secondary"
1410
+ // The rotation rides on the glyph, alongside the box and color
1411
+ // the wrapper used to provide, so one element carries the mark,
1412
+ // its open/closed transform, and the theme target.
1413
+ xstyle={[
1414
+ styles.triggerIcon,
1415
+ styles.triggerIconRotation,
1416
+ popover.isOpen && styles.triggerIconOpen,
1417
+ ]}
1418
+ // Stable theme target on the chevron glyph itself, so a theme can
1419
+ // restyle just this icon (color, size, hover) — and its
1420
+ // open/closed state — via `defineTheme`. Same-element rules in
1421
+ // @layer astryx-theme win over the icon's own base color/size,
1422
+ // which a button-level target could not reach.
1423
+ {...themeProps('selector-indicator-icon', {
1424
+ state: popover.isOpen ? 'expanded' : 'collapsed',
1425
+ })}
1426
+ />
1427
+ )}
1301
1428
  </div>
1302
1429
 
1303
1430
  {popover.render(
1304
1431
  hasSearch ? (
1305
1432
  <div>
1306
1433
  {renderSearch()}
1434
+ {/*
1435
+ Separates the header from the options and spans the panel: the
1436
+ search row and the listbox each hold their own inline padding,
1437
+ the line does not, so it reads as the panel's own edge.
1438
+ */}
1439
+ <Divider />
1307
1440
  <div
1308
1441
  ref={listboxRef}
1309
1442
  id={listboxId}
1310
1443
  role="listbox"
1311
1444
  aria-labelledby={triggerId}
1312
- {...stylex.props(styles.dropdown)}>
1445
+ {...stylex.props(
1446
+ styles.dropdown,
1447
+ variant !== 'ghost' && styles.dropdownInput,
1448
+ )}>
1313
1449
  {renderOptions()}
1314
1450
  </div>
1315
1451
  </div>
@@ -1321,6 +1457,7 @@ export function Selector<T extends SelectorOptionType>(
1321
1457
  aria-labelledby={triggerId}
1322
1458
  {...stylex.props(
1323
1459
  styles.dropdown,
1460
+ variant !== 'ghost' && styles.dropdownInput,
1324
1461
  !isPositioned && styles.dropdownHidden,
1325
1462
  )}>
1326
1463
  {renderOptions()}
@@ -1329,6 +1466,12 @@ export function Selector<T extends SelectorOptionType>(
1329
1466
  {
1330
1467
  placement: popoverPlacement,
1331
1468
  alignment: 'start',
1469
+ // The system's standard menu clearance, except in overlay mode:
1470
+ // there the measured negative margin owns the block geometry and
1471
+ // the menu is meant to sit on the trigger, not clear it.
1472
+ offset: shouldOverlaySelectedItem
1473
+ ? undefined
1474
+ : spacingVars['--spacing-1'],
1332
1475
  xstyle: [styles.popover, layerAnimations[popoverPlacement]],
1333
1476
  style: popoverOffsetStyle,
1334
1477
  },