@astryxdesign/core 0.4.4 → 0.4.5-canary.0472ec1

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 (522) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -1
  3. package/dist/Blockquote/Blockquote.d.ts +4 -3
  4. package/dist/Blockquote/Blockquote.d.ts.map +1 -1
  5. package/dist/Blockquote/Blockquote.js +9 -10
  6. package/dist/BottomSheet/BottomSheet.d.ts +11 -2
  7. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheet.js +4 -0
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
  10. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  11. package/dist/BottomSheet/BottomSheetPanel.js +77 -18
  12. package/dist/BottomSheet/index.d.ts +1 -1
  13. package/dist/BottomSheet/index.d.ts.map +1 -1
  14. package/dist/BottomSheet/snapOffsets.d.ts +57 -20
  15. package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
  16. package/dist/BottomSheet/snapOffsets.js +106 -30
  17. package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
  18. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  19. package/dist/BottomSheet/useSheetGestures.js +160 -64
  20. package/dist/Breadcrumbs/BreadcrumbItem.js +6 -6
  21. package/dist/Button/Button.js +5 -5
  22. package/dist/Calendar/Calendar.d.ts +17 -0
  23. package/dist/Calendar/Calendar.d.ts.map +1 -1
  24. package/dist/Calendar/Calendar.js +55 -15
  25. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
  26. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
  27. package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
  28. package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
  29. package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
  30. package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
  31. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  32. package/dist/Calendar/hooks/useCalendarDays.js +14 -10
  33. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  34. package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
  35. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
  36. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
  37. package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
  38. package/dist/Calendar/styles.js +3 -3
  39. package/dist/Center/Center.d.ts +23 -1
  40. package/dist/Center/Center.d.ts.map +1 -1
  41. package/dist/Center/Center.js +12 -6
  42. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  43. package/dist/Chat/ChatComposer.js +2 -2
  44. package/dist/Chat/ChatToolCalls.js +1 -1
  45. package/dist/Chat/useChatDictation.d.ts +1 -1
  46. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  47. package/dist/Chat/useSpeechRecognition.d.ts +1 -1
  48. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  49. package/dist/Chat/useSpeechRecognition.js +4 -3
  50. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  51. package/dist/CheckboxInput/CheckboxInput.js +9 -0
  52. package/dist/Citation/Citation.js +3 -3
  53. package/dist/ClickableCard/ClickableCard.js +2 -2
  54. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  55. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  56. package/dist/ComplexSelector/ComplexSelector.js +8 -3
  57. package/dist/DateInput/DateInput.d.ts +31 -2
  58. package/dist/DateInput/DateInput.d.ts.map +1 -1
  59. package/dist/DateInput/DateInput.js +92 -19
  60. package/dist/DateInput/MonthScroller.d.ts +35 -0
  61. package/dist/DateInput/MonthScroller.d.ts.map +1 -0
  62. package/dist/DateInput/MonthScroller.js +573 -0
  63. package/dist/DateInput/MonthYearWheels.d.ts +24 -0
  64. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
  65. package/dist/DateInput/MonthYearWheels.js +114 -0
  66. package/dist/DateInput/TouchDateField.d.ts +10 -0
  67. package/dist/DateInput/TouchDateField.d.ts.map +1 -0
  68. package/dist/DateInput/TouchDateField.js +810 -0
  69. package/dist/DateInput/Wheel.d.ts +41 -0
  70. package/dist/DateInput/Wheel.d.ts.map +1 -0
  71. package/dist/DateInput/Wheel.js +315 -0
  72. package/dist/DateInput/monthGeometry.d.ts +65 -0
  73. package/dist/DateInput/monthGeometry.d.ts.map +1 -0
  74. package/dist/DateInput/monthGeometry.js +98 -0
  75. package/dist/DateInput/tokens.stylex.d.ts +63 -0
  76. package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
  77. package/dist/DateInput/tokens.stylex.js +74 -0
  78. package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
  79. package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
  80. package/dist/DateInput/useOwnScrollGesture.js +202 -0
  81. package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
  82. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
  83. package/dist/DateInput/usePointerDragScroll.js +216 -0
  84. package/dist/DateInput/useScrollSettle.d.ts +26 -0
  85. package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
  86. package/dist/DateInput/useScrollSettle.js +149 -0
  87. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  88. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  89. package/dist/DateRangeInput/DateRangeInput.js +47 -9
  90. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.js +18 -10
  92. package/dist/Dialog/Dialog.d.ts.map +1 -1
  93. package/dist/Dialog/Dialog.js +3 -3
  94. package/dist/Field/FieldLabel.d.ts +2 -1
  95. package/dist/Field/FieldLabel.d.ts.map +1 -1
  96. package/dist/Field/FieldLabel.js +21 -3
  97. package/dist/Field/InputClearButton.d.ts +2 -1
  98. package/dist/Field/InputClearButton.d.ts.map +1 -1
  99. package/dist/Field/InputClearButton.js +12 -1
  100. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  101. package/dist/Field/inputStyles.stylex.js +4 -4
  102. package/dist/FileInput/FileInput.d.ts.map +1 -1
  103. package/dist/FileInput/FileInput.js +2 -2
  104. package/dist/FormLayout/FormLayout.d.ts +24 -2
  105. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  106. package/dist/FormLayout/FormLayout.js +7 -2
  107. package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
  108. package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
  109. package/dist/FormLayout/FormLayoutContext.js +19 -4
  110. package/dist/FormLayout/index.d.ts +1 -1
  111. package/dist/FormLayout/index.d.ts.map +1 -1
  112. package/dist/HoverCard/HoverCard.d.ts +13 -3
  113. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  114. package/dist/HoverCard/HoverCard.js +2 -0
  115. package/dist/HoverCard/index.d.ts +1 -1
  116. package/dist/HoverCard/index.d.ts.map +1 -1
  117. package/dist/HoverCard/useHoverCard.d.ts +17 -2
  118. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  119. package/dist/HoverCard/useHoverCard.js +78 -9
  120. package/dist/Item/Item.d.ts +9 -1
  121. package/dist/Item/Item.d.ts.map +1 -1
  122. package/dist/Item/Item.js +46 -8
  123. package/dist/Layer/index.d.ts +4 -2
  124. package/dist/Layer/index.d.ts.map +1 -1
  125. package/dist/Layer/index.js +2 -0
  126. package/dist/Layer/useLayer.d.ts.map +1 -1
  127. package/dist/Layer/useLayer.js +3 -2
  128. package/dist/Layer/useTouchTrigger.d.ts +113 -0
  129. package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
  130. package/dist/Layer/useTouchTrigger.js +241 -0
  131. package/dist/Layout/container.stylex.d.ts +4 -2
  132. package/dist/Layout/container.stylex.d.ts.map +1 -1
  133. package/dist/Layout/container.stylex.js +19 -11
  134. package/dist/Layout/index.d.ts +1 -0
  135. package/dist/Layout/index.d.ts.map +1 -1
  136. package/dist/Layout/index.js +4 -0
  137. package/dist/Layout/padding.stylex.d.ts +315 -12
  138. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  139. package/dist/Layout/padding.stylex.js +389 -12
  140. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  141. package/dist/Lightbox/Lightbox.js +2 -1
  142. package/dist/Link/Link.js +4 -4
  143. package/dist/Markdown/Markdown.d.ts +8 -0
  144. package/dist/Markdown/Markdown.d.ts.map +1 -1
  145. package/dist/Markdown/Markdown.js +31 -3
  146. package/dist/Markdown/parser.d.ts +14 -2
  147. package/dist/Markdown/parser.d.ts.map +1 -1
  148. package/dist/Markdown/parser.js +50 -2
  149. package/dist/MobileNav/MobileNav.d.ts +1 -0
  150. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  151. package/dist/MobileNav/MobileNav.js +24 -6
  152. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  153. package/dist/MultiSelector/MultiSelector.js +8 -3
  154. package/dist/NavItem/navItemStyles.stylex.d.ts +2 -2
  155. package/dist/NavItem/navItemStyles.stylex.js +2 -2
  156. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  157. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  158. package/dist/NumberInput/NumberInput.js +38 -5
  159. package/dist/Outline/Outline.js +2 -2
  160. package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
  161. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  162. package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
  163. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  164. package/dist/PowerSearch/PowerSearch.js +11 -12
  165. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  166. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  167. package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
  168. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  169. package/dist/PowerSearch/formatFilterValue.js +23 -8
  170. package/dist/RadioList/RadioList.d.ts.map +1 -1
  171. package/dist/RadioList/RadioList.js +12 -1
  172. package/dist/RadioList/RadioListItem.d.ts +2 -2
  173. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  174. package/dist/RadioList/RadioListItem.js +68 -38
  175. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  176. package/dist/Resizable/ResizeHandle.js +3 -3
  177. package/dist/Section/Section.d.ts +36 -1
  178. package/dist/Section/Section.d.ts.map +1 -1
  179. package/dist/Section/Section.js +12 -2
  180. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  181. package/dist/SegmentedControl/SegmentedControlItem.js +6 -1
  182. package/dist/SelectableCard/SelectableCard.js +1 -1
  183. package/dist/Selector/Selector.d.ts +26 -1
  184. package/dist/Selector/Selector.d.ts.map +1 -1
  185. package/dist/Selector/Selector.js +95 -17
  186. package/dist/Selector/SelectorOption.d.ts +14 -1
  187. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  188. package/dist/Selector/SelectorOption.js +6 -0
  189. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  190. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  191. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  192. package/dist/Selector/types.d.ts +1 -0
  193. package/dist/Selector/types.d.ts.map +1 -1
  194. package/dist/SideNav/SideNavHeading.js +1 -1
  195. package/dist/SideNav/SideNavItem.js +1 -1
  196. package/dist/Slider/Slider.d.ts.map +1 -1
  197. package/dist/Slider/Slider.js +3 -3
  198. package/dist/Stack/Stack.d.ts +23 -1
  199. package/dist/Stack/Stack.d.ts.map +1 -1
  200. package/dist/Stack/Stack.js +12 -6
  201. package/dist/StatusDot/StatusDot.d.ts +43 -3
  202. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  203. package/dist/StatusDot/StatusDot.js +42 -5
  204. package/dist/Switch/Switch.d.ts.map +1 -1
  205. package/dist/Switch/Switch.js +9 -0
  206. package/dist/TabList/TabMenu.js +1 -1
  207. package/dist/Table/TableRow.js +4 -4
  208. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  209. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  210. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  211. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +1 -1
  212. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  213. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  214. package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
  215. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  216. package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
  217. package/dist/Table/plugins/tree/useTableTreeData.js +2 -2
  218. package/dist/TextArea/TextArea.d.ts.map +1 -1
  219. package/dist/TextArea/TextArea.js +6 -1
  220. package/dist/TextInput/TextInput.d.ts.map +1 -1
  221. package/dist/TextInput/TextInput.js +6 -1
  222. package/dist/Thumbnail/Thumbnail.js +1 -1
  223. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  224. package/dist/TimeInput/TimeInput.js +6 -1
  225. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  226. package/dist/Timestamp/Timestamp.js +6 -4
  227. package/dist/Timestamp/formatInstant.d.ts +3 -2
  228. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  229. package/dist/Timestamp/formatInstant.js +8 -8
  230. package/dist/Timestamp/tooltipEntries.d.ts +2 -1
  231. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  232. package/dist/Timestamp/tooltipEntries.js +5 -3
  233. package/dist/Token/Token.js +1 -1
  234. package/dist/Tooltip/Tooltip.d.ts +16 -3
  235. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  236. package/dist/Tooltip/Tooltip.js +2 -0
  237. package/dist/Tooltip/index.d.ts +1 -1
  238. package/dist/Tooltip/index.d.ts.map +1 -1
  239. package/dist/Tooltip/useTooltip.d.ts +21 -2
  240. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  241. package/dist/Tooltip/useTooltip.js +71 -13
  242. package/dist/TopNav/TopNavHeading.js +2 -2
  243. package/dist/TopNav/TopNavItem.js +2 -2
  244. package/dist/TopNav/TopNavMegaMenu.js +1 -1
  245. package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
  246. package/dist/TopNav/TopNavMenu.js +2 -2
  247. package/dist/TreeList/TreeListItem.js +1 -1
  248. package/dist/astryx.css +123 -60
  249. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
  250. package/dist/hooks/containerReveal.stylex.js +18 -18
  251. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  252. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  253. package/dist/hooks/scrollbarGutter.js +103 -0
  254. package/dist/hooks/useResolvedRequired.d.ts +19 -0
  255. package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
  256. package/dist/hooks/useResolvedRequired.js +40 -0
  257. package/dist/hooks/useScrollLock.d.ts +4 -0
  258. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  259. package/dist/hooks/useScrollLock.js +13 -1
  260. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  261. package/dist/i18n/InternationalizationContext.js +2 -0
  262. package/dist/i18n/index.d.ts +6 -0
  263. package/dist/i18n/index.d.ts.map +1 -1
  264. package/dist/i18n/index.js +6 -0
  265. package/dist/i18n/useCollator.d.ts +12 -0
  266. package/dist/i18n/useCollator.d.ts.map +1 -0
  267. package/dist/i18n/useCollator.js +40 -0
  268. package/dist/i18n/useLocale.d.ts +3 -0
  269. package/dist/i18n/useLocale.d.ts.map +1 -0
  270. package/dist/i18n/useLocale.js +31 -0
  271. package/dist/theme/defineTheme.d.ts +5 -0
  272. package/dist/theme/defineTheme.d.ts.map +1 -1
  273. package/dist/theme/defineTheme.js +5 -0
  274. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  275. package/dist/theme/derivedVarRegistry.js +7 -0
  276. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  277. package/dist/theme/generateThemeRules.js +66 -5
  278. package/dist/theme/syntax/index.d.ts +6 -0
  279. package/dist/theme/syntax/index.d.ts.map +1 -1
  280. package/dist/theme/syntax/index.js +7 -2
  281. package/dist/utils/dateParser.d.ts +4 -3
  282. package/dist/utils/dateParser.d.ts.map +1 -1
  283. package/dist/utils/dateParser.js +8 -8
  284. package/dist/utils/index.d.ts +1 -1
  285. package/dist/utils/index.d.ts.map +1 -1
  286. package/dist/utils/index.js +1 -1
  287. package/dist/utils/plainDate.d.ts +11 -2
  288. package/dist/utils/plainDate.d.ts.map +1 -1
  289. package/dist/utils/plainDate.js +32 -4
  290. package/locales/af-ZA.json +958 -0
  291. package/locales/ar-SA.json +998 -0
  292. package/locales/ca-ES.json +974 -0
  293. package/locales/cs-CZ.json +990 -0
  294. package/locales/da-DK.json +966 -0
  295. package/locales/de-DE.json +966 -0
  296. package/locales/el-GR.json +990 -0
  297. package/locales/en.json +32 -0
  298. package/locales/es-ES.json +978 -0
  299. package/locales/fi-FI.json +990 -0
  300. package/locales/fr-FR.json +928 -0
  301. package/locales/he-IL.json +990 -0
  302. package/locales/hu-HU.json +990 -0
  303. package/locales/it-IT.json +978 -0
  304. package/locales/ja-JP.json +998 -0
  305. package/locales/ko-KR.json +990 -0
  306. package/locales/nl-NL.json +954 -0
  307. package/locales/no-NO.json +978 -0
  308. package/locales/pl-PL.json +982 -0
  309. package/locales/pseudo.json +24 -0
  310. package/locales/pt-BR.json +982 -0
  311. package/locales/pt-PT.json +982 -0
  312. package/locales/ro-RO.json +982 -0
  313. package/locales/ru-RU.json +990 -0
  314. package/locales/sr-SP.json +990 -0
  315. package/locales/sv-SE.json +986 -0
  316. package/locales/tr-TR.json +990 -0
  317. package/locales/uk-UA.json +990 -0
  318. package/locales/vi-VN.json +986 -0
  319. package/locales/zh-CN.json +998 -0
  320. package/locales/zh-TW.json +998 -0
  321. package/package.json +3 -3
  322. package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -1
  323. package/src/Banner/Banner.doc.mjs +2 -0
  324. package/src/Blockquote/Blockquote.doc.mjs +30 -7
  325. package/src/Blockquote/Blockquote.test.tsx +34 -3
  326. package/src/Blockquote/Blockquote.tsx +11 -9
  327. package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
  328. package/src/BottomSheet/BottomSheet.test.tsx +177 -2
  329. package/src/BottomSheet/BottomSheet.tsx +16 -2
  330. package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
  331. package/src/BottomSheet/BottomSheetPanel.tsx +121 -15
  332. package/src/BottomSheet/index.ts +5 -1
  333. package/src/BottomSheet/snapOffsets.test.ts +114 -47
  334. package/src/BottomSheet/snapOffsets.ts +119 -33
  335. package/src/BottomSheet/useSheetGestures.test.ts +113 -15
  336. package/src/BottomSheet/useSheetGestures.ts +196 -100
  337. package/src/Breadcrumbs/BreadcrumbItem.tsx +1 -1
  338. package/src/Button/Button.tsx +7 -7
  339. package/src/Calendar/Calendar.doc.mjs +16 -0
  340. package/src/Calendar/Calendar.test.tsx +137 -0
  341. package/src/Calendar/Calendar.tsx +80 -11
  342. package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
  343. package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
  344. package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
  345. package/src/Calendar/hooks/useCalendarDays.ts +13 -10
  346. package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
  347. package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
  348. package/src/Calendar/styles.ts +3 -3
  349. package/src/Center/Center.doc.mjs +48 -0
  350. package/src/Center/Center.test.tsx +158 -0
  351. package/src/Center/Center.tsx +50 -9
  352. package/src/Chat/ChatComposer.tsx +7 -4
  353. package/src/Chat/ChatToolCalls.tsx +1 -1
  354. package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
  355. package/src/Chat/useChatDictation.ts +1 -1
  356. package/src/Chat/useSpeechRecognition.ts +5 -3
  357. package/src/CheckboxInput/CheckboxInput.tsx +6 -0
  358. package/src/Citation/Citation.tsx +3 -3
  359. package/src/ClickableCard/ClickableCard.tsx +2 -2
  360. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  361. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
  362. package/src/ComplexSelector/ComplexSelector.tsx +8 -5
  363. package/src/DateInput/DateInput.test.tsx +17 -1
  364. package/src/DateInput/DateInput.tsx +90 -19
  365. package/src/DateInput/DateInputTouch.test.tsx +2393 -0
  366. package/src/DateInput/MonthScroller.tsx +784 -0
  367. package/src/DateInput/MonthYearWheels.tsx +147 -0
  368. package/src/DateInput/TouchDateField.tsx +1214 -0
  369. package/src/DateInput/Wheel.tsx +470 -0
  370. package/src/DateInput/monthGeometry.ts +118 -0
  371. package/src/DateInput/tokens.stylex.ts +99 -0
  372. package/src/DateInput/useOwnScrollGesture.ts +227 -0
  373. package/src/DateInput/usePointerDragScroll.ts +220 -0
  374. package/src/DateInput/useScrollSettle.ts +164 -0
  375. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  376. package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
  377. package/src/DateRangeInput/DateRangeInput.tsx +88 -8
  378. package/src/DateTimeInput/DateTimeInput.tsx +23 -8
  379. package/src/Dialog/Dialog.test.tsx +24 -0
  380. package/src/Dialog/Dialog.tsx +3 -0
  381. package/src/Field/Field.doc.mjs +3 -0
  382. package/src/Field/FieldLabel.tsx +20 -4
  383. package/src/Field/InputClearButton.test.tsx +134 -2
  384. package/src/Field/InputClearButton.tsx +42 -1
  385. package/src/Field/inputStyles.stylex.ts +16 -12
  386. package/src/FileInput/FileInput.tsx +5 -4
  387. package/src/FormLayout/FormLayout.doc.mjs +13 -0
  388. package/src/FormLayout/FormLayout.test.tsx +181 -4
  389. package/src/FormLayout/FormLayout.tsx +33 -2
  390. package/src/FormLayout/FormLayoutContext.ts +22 -7
  391. package/src/FormLayout/index.ts +1 -1
  392. package/src/HoverCard/HoverCard.doc.mjs +18 -0
  393. package/src/HoverCard/HoverCard.test.tsx +189 -0
  394. package/src/HoverCard/HoverCard.tsx +22 -2
  395. package/src/HoverCard/index.ts +1 -0
  396. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  397. package/src/HoverCard/useHoverCard.tsx +103 -7
  398. package/src/Item/Item.doc.mjs +1 -0
  399. package/src/Item/Item.test.tsx +50 -0
  400. package/src/Item/Item.tsx +41 -2
  401. package/src/Layer/index.ts +10 -0
  402. package/src/Layer/useLayer.tsx +13 -2
  403. package/src/Layer/useTouchTrigger.test.ts +70 -0
  404. package/src/Layer/useTouchTrigger.ts +366 -0
  405. package/src/Layout/Layout.doc.mjs +18 -0
  406. package/src/Layout/container.stylex.ts +11 -3
  407. package/src/Layout/index.ts +4 -0
  408. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  409. package/src/Layout/padding.stylex.ts +192 -12
  410. package/src/Lightbox/Lightbox.tsx +2 -1
  411. package/src/Link/Link.tsx +4 -4
  412. package/src/Markdown/Markdown.doc.mjs +3 -0
  413. package/src/Markdown/Markdown.test.tsx +78 -0
  414. package/src/Markdown/Markdown.tsx +41 -1
  415. package/src/Markdown/parser.ts +60 -2
  416. package/src/MobileNav/MobileNav.tsx +61 -5
  417. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  418. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  419. package/src/MultiSelector/MultiSelector.test.tsx +1 -1
  420. package/src/MultiSelector/MultiSelector.tsx +8 -5
  421. package/src/NavItem/navItemStyles.stylex.ts +2 -2
  422. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  423. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  424. package/src/NumberInput/NumberInput.test.tsx +138 -0
  425. package/src/NumberInput/NumberInput.tsx +44 -6
  426. package/src/Outline/Outline.doc.mjs +2 -0
  427. package/src/Outline/Outline.tsx +1 -1
  428. package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
  429. package/src/PowerSearch/PowerSearch.tsx +17 -8
  430. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  431. package/src/PowerSearch/formatFilterValue.test.ts +22 -2
  432. package/src/PowerSearch/formatFilterValue.ts +31 -6
  433. package/src/RadioList/RadioList.doc.mjs +1 -1
  434. package/src/RadioList/RadioList.test.tsx +170 -2
  435. package/src/RadioList/RadioList.tsx +9 -1
  436. package/src/RadioList/RadioListItem.tsx +83 -51
  437. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  438. package/src/Resizable/ResizeHandle.tsx +9 -3
  439. package/src/Section/Section.doc.mjs +55 -0
  440. package/src/Section/Section.test.tsx +201 -4
  441. package/src/Section/Section.tsx +69 -0
  442. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  443. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -2
  444. package/src/SelectableCard/SelectableCard.tsx +1 -1
  445. package/src/Selector/Selector.doc.mjs +16 -2
  446. package/src/Selector/Selector.test.tsx +525 -1
  447. package/src/Selector/Selector.tsx +166 -21
  448. package/src/Selector/SelectorOption.doc.mjs +7 -0
  449. package/src/Selector/SelectorOption.tsx +21 -0
  450. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  451. package/src/Selector/types.ts +4 -4
  452. package/src/SideNav/SideNavHeading.tsx +2 -2
  453. package/src/SideNav/SideNavItem.tsx +1 -1
  454. package/src/Slider/Slider.tsx +11 -1
  455. package/src/Stack/Stack.doc.mjs +72 -0
  456. package/src/Stack/Stack.test.tsx +156 -0
  457. package/src/Stack/Stack.tsx +50 -8
  458. package/src/StatusDot/StatusDot.doc.mjs +13 -0
  459. package/src/StatusDot/StatusDot.test.tsx +115 -8
  460. package/src/StatusDot/StatusDot.tsx +74 -9
  461. package/src/Switch/Switch.tsx +6 -0
  462. package/src/TabList/TabMenu.tsx +1 -1
  463. package/src/Table/TableRow.tsx +4 -4
  464. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
  465. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +2 -1
  466. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +22 -4
  467. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
  468. package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
  469. package/src/Table/plugins/tree/useTableTreeData.tsx +2 -2
  470. package/src/TextArea/TextArea.doc.mjs +1 -1
  471. package/src/TextArea/TextArea.tsx +3 -1
  472. package/src/TextInput/TextInput.tsx +3 -1
  473. package/src/Thumbnail/Thumbnail.tsx +1 -1
  474. package/src/TimeInput/TimeInput.tsx +3 -1
  475. package/src/Timestamp/Timestamp.test.tsx +27 -7
  476. package/src/Timestamp/Timestamp.tsx +8 -4
  477. package/src/Timestamp/formatInstant.ts +9 -7
  478. package/src/Timestamp/tooltipEntries.test.ts +11 -6
  479. package/src/Timestamp/tooltipEntries.ts +6 -2
  480. package/src/Token/Token.tsx +1 -1
  481. package/src/Tooltip/Tooltip.doc.mjs +18 -0
  482. package/src/Tooltip/Tooltip.test.tsx +254 -1
  483. package/src/Tooltip/Tooltip.tsx +22 -2
  484. package/src/Tooltip/index.ts +1 -0
  485. package/src/Tooltip/useTooltip.doc.mjs +2 -0
  486. package/src/Tooltip/useTooltip.tsx +99 -21
  487. package/src/TopNav/TopNavHeading.tsx +1 -1
  488. package/src/TopNav/TopNavItem.tsx +2 -2
  489. package/src/TopNav/TopNavMegaMenu.tsx +1 -1
  490. package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
  491. package/src/TopNav/TopNavMenu.tsx +2 -2
  492. package/src/TreeList/TreeListItem.tsx +1 -1
  493. package/src/hooks/containerReveal.stylex.ts +54 -18
  494. package/src/hooks/scrollbarGutter.test.ts +167 -0
  495. package/src/hooks/scrollbarGutter.ts +121 -0
  496. package/src/hooks/useResolvedRequired.ts +42 -0
  497. package/src/hooks/useScrollLock.doc.mjs +4 -4
  498. package/src/hooks/useScrollLock.test.ts +73 -0
  499. package/src/hooks/useScrollLock.ts +14 -0
  500. package/src/i18n/InternationalizationContext.ts +2 -0
  501. package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
  502. package/src/i18n/__tests__/useCollator.test.tsx +115 -0
  503. package/src/i18n/__tests__/useLocale.test.tsx +52 -0
  504. package/src/i18n/index.ts +6 -0
  505. package/src/i18n/useCollator.doc.mjs +84 -0
  506. package/src/i18n/useCollator.ts +44 -0
  507. package/src/i18n/useLocale.doc.mjs +70 -0
  508. package/src/i18n/useLocale.ts +34 -0
  509. package/src/i18n/useTranslator.doc.mjs +1 -1
  510. package/src/theme/defineTheme.test.ts +9 -3
  511. package/src/theme/defineTheme.ts +5 -0
  512. package/src/theme/derivedVarRegistry.test.ts +19 -5
  513. package/src/theme/derivedVarRegistry.ts +4 -0
  514. package/src/theme/generateThemeRules.test.ts +118 -0
  515. package/src/theme/generateThemeRules.ts +83 -5
  516. package/src/theme/syntax/index.ts +6 -2
  517. package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
  518. package/src/utils/dateParser.test.ts +20 -0
  519. package/src/utils/dateParser.ts +14 -7
  520. package/src/utils/index.ts +2 -0
  521. package/src/utils/plainDate.test.ts +56 -0
  522. package/src/utils/plainDate.ts +33 -4
@@ -116,6 +116,22 @@ describe('RadioList', () => {
116
116
  expect(handleChange).toHaveBeenCalledWith('b');
117
117
  });
118
118
 
119
+ it('calls onChange when clicking the description', async () => {
120
+ const user = userEvent.setup();
121
+ const handleChange = vi.fn();
122
+ render(
123
+ <RadioList label="Preference" value="a" onChange={handleChange}>
124
+ <RadioListItem label="Option A" value="a" description="First option" />
125
+ <RadioListItem label="Option B" value="b" description="Second option" />
126
+ </RadioList>,
127
+ );
128
+
129
+ // The whole row delegates surface clicks to the radio, so the description
130
+ // is a live target — not dead space as it was before.
131
+ await user.click(screen.getByText('Second option'));
132
+ expect(handleChange).toHaveBeenCalledWith('b');
133
+ });
134
+
119
135
  it('disables all radios when group isDisabled is true', () => {
120
136
  render(
121
137
  <RadioList label="Preference" value="" onChange={() => {}} isDisabled>
@@ -137,7 +153,13 @@ describe('RadioList', () => {
137
153
  </RadioList>,
138
154
  );
139
155
 
140
- await user.click(screen.getByLabelText('Option A'));
156
+ // userEvent honors `pointer-events: none`, so clicking the disabled row's
157
+ // delegate surface is genuinely blocked (it refuses and throws) rather than
158
+ // merely ignored by the handler — the guarantee this PR's delegation relies
159
+ // on.
160
+ await expect(user.click(screen.getByLabelText('Option A'))).rejects.toThrow(
161
+ /pointer-events/i,
162
+ );
141
163
  expect(handleChange).not.toHaveBeenCalled();
142
164
  });
143
165
 
@@ -162,7 +184,13 @@ describe('RadioList', () => {
162
184
  </RadioList>,
163
185
  );
164
186
 
165
- await user.click(screen.getByLabelText('Option A'));
187
+ // userEvent honors `pointer-events: none`, so clicking the disabled row's
188
+ // delegate surface is genuinely blocked (it refuses and throws) rather than
189
+ // merely ignored by the handler — the guarantee this PR's delegation relies
190
+ // on.
191
+ await expect(user.click(screen.getByLabelText('Option A'))).rejects.toThrow(
192
+ /pointer-events/i,
193
+ );
166
194
  expect(handleChange).not.toHaveBeenCalled();
167
195
  });
168
196
 
@@ -647,6 +675,146 @@ describe('RadioList', () => {
647
675
  expect(item).toHaveAttribute('aria-label', 'First option');
648
676
  });
649
677
  });
678
+
679
+ describe('radio-list-item theme target', () => {
680
+ it('renders astryx-radio-list-item, with its size, on every row', () => {
681
+ render(
682
+ <RadioList label="Preference" value="" onChange={() => {}} size="sm">
683
+ <RadioListItem label="Option A" value="a" data-testid="row-a" />
684
+ <RadioListItem label="Option B" value="b" data-testid="row-b" />
685
+ </RadioList>,
686
+ );
687
+ for (const testid of ['row-a', 'row-b']) {
688
+ const row = screen.getByTestId(testid);
689
+ expect(row).toHaveClass('astryx-radio-list-item');
690
+ expect(row).toHaveClass('sm');
691
+ expect(row).toHaveAttribute('data-size', 'sm');
692
+ }
693
+ });
694
+
695
+ it('carries the selected and disabled states a theme keys on', () => {
696
+ render(
697
+ <RadioList label="Preference" value="a" onChange={() => {}}>
698
+ <RadioListItem label="Option A" value="a" data-testid="selected" />
699
+ <RadioListItem label="Option B" value="b" data-testid="plain" />
700
+ <RadioListItem
701
+ label="Option C"
702
+ value="c"
703
+ isDisabled
704
+ data-testid="disabled"
705
+ />
706
+ </RadioList>,
707
+ );
708
+ const selected = screen.getByTestId('selected');
709
+ const plain = screen.getByTestId('plain');
710
+ const disabled = screen.getByTestId('disabled');
711
+
712
+ expect(selected).toHaveClass('selected');
713
+ expect(selected).toHaveAttribute('data-selected', 'selected');
714
+ expect(plain).not.toHaveClass('selected');
715
+ expect(plain).not.toHaveAttribute('data-selected');
716
+
717
+ expect(disabled).toHaveClass('disabled');
718
+ expect(disabled).toHaveAttribute('data-disabled', 'disabled');
719
+ expect(plain).not.toHaveAttribute('data-disabled');
720
+ });
721
+
722
+ it('rides the painting row element (astryx-item), not a bare layout wrapper', () => {
723
+ // The row target must sit on the element Item paints — the surface that
724
+ // renders hover, density padding, and radius — so a theme styling
725
+ // `radio-list-item`'s background/padding/borderRadius (and its `:hover`)
726
+ // actually takes effect. Converges with how ListItem lands `list-item`
727
+ // on the same element as `astryx-item`. The same element also carries
728
+ // the reflected `data-size`, proving the variant surface moved with it.
729
+ const {container} = render(
730
+ <RadioList label="Preference" value="" onChange={() => {}}>
731
+ <RadioListItem label="Option A" value="a" data-testid="row" />
732
+ </RadioList>,
733
+ );
734
+ const row = screen.getByTestId('row');
735
+ // A single element carries both the paint class and the theme target.
736
+ expect(row).toHaveClass('astryx-item');
737
+ expect(row).toHaveClass('astryx-radio-list-item');
738
+ expect(row).toHaveAttribute('data-size');
739
+ // No separate layout wrapper survives outside the painting row: the
740
+ // target-bearing element is the same one Item renders.
741
+ expect(
742
+ container.querySelectorAll('.astryx-radio-list-item'),
743
+ ).toHaveLength(1);
744
+ });
745
+
746
+ it('keeps the bare default row appearance: zeroed padding/radius, no default background', () => {
747
+ // The architectural win — the target rides the painting Item — must not
748
+ // change the DEFAULT look. The painting row zeroes Item's density
749
+ // padding, its radius, and its interactive hover/press background, so an
750
+ // unthemed RadioList renders as a flat surface (only the indicator tints
751
+ // on hover via `indicatorScope`). This matches the appearance before the
752
+ // target moved onto Item; a theme's `radio-list-item` overrides still win
753
+ // from the higher `astryx-theme` layer.
754
+ render(
755
+ <RadioList label="Preference" value="a" onChange={() => {}}>
756
+ <RadioListItem label="Selected" value="a" data-testid="selected" />
757
+ <RadioListItem label="Plain" value="b" data-testid="plain" />
758
+ </RadioList>,
759
+ );
760
+ const cssFor = (className: string): string => {
761
+ const rules: string[] = [];
762
+ const walk = (list: CSSRuleList) => {
763
+ for (const rule of Array.from(list)) {
764
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
765
+ const anyRule = rule as any;
766
+ if (anyRule.cssRules) {
767
+ walk(anyRule.cssRules);
768
+ }
769
+ if (
770
+ typeof anyRule.cssText === 'string' &&
771
+ anyRule.cssText.includes(`.${className}`)
772
+ ) {
773
+ rules.push(anyRule.cssText);
774
+ }
775
+ }
776
+ };
777
+ for (const sheet of Array.from(document.styleSheets)) {
778
+ try {
779
+ walk(sheet.cssRules);
780
+ } catch {
781
+ // cross-origin/inaccessible sheet — skip
782
+ }
783
+ }
784
+ return rules.join('\n');
785
+ };
786
+
787
+ const plain = screen.getByTestId('plain');
788
+ const atoms = plain.className
789
+ .split(/\s+/)
790
+ .filter(c => /^x[a-z0-9]+$/i.test(c));
791
+ const declarations = atoms.map(cssFor).join('\n');
792
+
793
+ // The bare-look declarations land on the painting row.
794
+ expect(declarations).toMatch(/padding-block:\s*0/);
795
+ expect(declarations).toMatch(/padding-inline:\s*0/);
796
+ expect(declarations).toMatch(/border-radius:\s*0/);
797
+ expect(declarations).toMatch(/background-color:\s*transparent/);
798
+
799
+ // No default full-row hover highlight: the flat transparent background
800
+ // replaces Item's interactive `:hover` overlay, so no hover rule paints
801
+ // the row's own background. (The indicator still tints via its scope.)
802
+ expect(declarations).not.toMatch(
803
+ /:hover[^{]*\{[^}]*background-color:\s*var\(--color-overlay-hover\)/,
804
+ );
805
+
806
+ // No default selected-row background: the selected row differs from the
807
+ // plain row only by state markers, not by a painted background class.
808
+ const selected = screen.getByTestId('selected');
809
+ const selectedAtoms = selected.className
810
+ .split(/\s+/)
811
+ .filter(c => /^x[a-z0-9]+$/i.test(c));
812
+ const selectedDecls = selectedAtoms.map(cssFor).join('\n');
813
+ expect(selectedDecls).not.toMatch(
814
+ /background-color:\s*var\(--color-accent-muted\)/,
815
+ );
816
+ });
817
+ });
650
818
  });
651
819
 
652
820
  // jsdom cannot emulate forced-colors rendering, so this asserts that the
@@ -29,6 +29,7 @@ import {spacingVars} from '../theme/tokens.stylex';
29
29
  import {Field} from '../Field/Field';
30
30
  import type {InputStatus} from '../Field/types';
31
31
  import {useTooltip} from '../Tooltip';
32
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
32
33
  import {mergeProps} from '../utils';
33
34
  import type {BaseProps} from '../BaseProps';
34
35
  import type {SizeValue} from '../utils/types';
@@ -218,6 +219,13 @@ export function RadioList({
218
219
 
219
220
  const groupRef = useRef<HTMLDivElement>(null);
220
221
 
222
+ // The radiogroup exposes the *effective* required state so a form-wide
223
+ // `defaultOptionality="required"` is announced even when the group carries no
224
+ // visible indicator. Individual radios keep their native `required` bound to
225
+ // the explicit `isRequired` (via context), so a layout default never switches
226
+ // on browser validation for the group.
227
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
228
+
221
229
  // Disabled-reason tooltip. Applies to the whole-group disabled state. Disabled
222
230
  // controls swallow pointer events, so the tooltip listeners attach to the
223
231
  // radiogroup container and the radios stay perceivable via aria-disabled
@@ -387,7 +395,7 @@ export function RadioList({
387
395
  .join(' ') || undefined
388
396
  }
389
397
  aria-invalid={status?.type === 'error' ? true : undefined}
390
- aria-required={isRequired || undefined}
398
+ aria-required={isEffectivelyRequired || undefined}
391
399
  {...mergeProps(
392
400
  themeProps('radio-list', {orientation, size}),
393
401
  stylex.props(
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file RadioListItem.tsx
7
- * @input Uses React use, useId, RadioListContext
7
+ * @input Uses React use, useId, useRef, RadioListContext, Item
8
8
  * @output Exports RadioListItem component, RadioListItemProps
9
9
  * @position Core implementation; consumed by index.ts, tested by RadioList.test.tsx
10
10
  *
@@ -20,10 +20,10 @@
20
20
 
21
21
  import React, {use, useId, useRef, type ReactNode} from 'react';
22
22
  import * as stylex from '@stylexjs/stylex';
23
+ import type {StyleXStyles} from '@stylexjs/stylex';
23
24
  import type {BaseProps} from '../BaseProps';
24
- import {colorVars, spacingVars} from '../theme/tokens.stylex';
25
25
  import {RadioListContext} from './RadioList';
26
- import {mergeProps} from '../utils';
26
+ import {mergeProps, isRenderable} from '../utils';
27
27
  import {indicatorScope} from '../Indicator/indicator.markers.stylex';
28
28
  import {useIndicatorFocusRing} from '../hooks/useIndicatorFocusRing';
29
29
  import {useIndicator} from '../Indicator';
@@ -31,11 +31,6 @@ import {Item} from '../Item';
31
31
  import {themeProps} from '../utils/themeProps';
32
32
 
33
33
  const styles = stylex.create({
34
- container: {
35
- display: 'flex',
36
- alignItems: 'center',
37
- gap: spacingVars['--spacing-2'],
38
- },
39
34
  radioWrapper: {
40
35
  position: 'relative',
41
36
  display: 'flex',
@@ -79,10 +74,6 @@ const styles = stylex.create({
79
74
  indicatorSlot: {
80
75
  display: 'contents',
81
76
  },
82
- labelDisabled: {
83
- color: colorVars['--color-text-disabled'],
84
- cursor: 'not-allowed',
85
- },
86
77
  });
87
78
 
88
79
  const wrapperSizeStyles = stylex.create({
@@ -96,13 +87,23 @@ const wrapperSizeStyles = stylex.create({
96
87
  },
97
88
  });
98
89
 
99
- const embeddedStyles = stylex.create({
90
+ const rowStyles = stylex.create({
91
+ // The row's default appearance is a bare surface: no density padding, no
92
+ // radius, and no full-row background — only the indicator tints on hover
93
+ // (via `indicatorScope`). Item paints padding/radius/hover as an interactive
94
+ // row, so this neutralizes them at the component level. A theme's
95
+ // `radio-list-item` overrides still win: they land in `@layer astryx-theme`,
96
+ // above the component's base StyleX layer, so themes opt back into row
97
+ // padding/radius/hover/selected styling. `minWidth: 0` preserves label
98
+ // truncation now that the Item is the row's flex child.
100
99
  root: {
101
100
  paddingBlock: 0,
102
101
  paddingInline: 0,
103
102
  borderRadius: 0,
104
- flex: 1,
105
103
  minWidth: 0,
104
+ // Suppress Item's interactive hover/press background so the resting and
105
+ // hovered row look identical by default (a theme can restyle either).
106
+ backgroundColor: 'transparent',
106
107
  },
107
108
  });
108
109
 
@@ -159,6 +160,7 @@ export function RadioListItem({
159
160
  xstyle,
160
161
  className,
161
162
  style,
163
+ onClick,
162
164
  ...rest
163
165
  }: RadioListItemProps) {
164
166
  const context = use(RadioListContext);
@@ -185,16 +187,28 @@ export function RadioListItem({
185
187
  const indicatorRef = useRef<HTMLSpanElement>(null);
186
188
  const {focusProps} = useIndicatorFocusRing(indicatorRef, isDisabled);
187
189
 
190
+ // The radio is the row's single keyboard control and action. The row is an
191
+ // enlarged click/tap target that delegates surface clicks — the description
192
+ // and the empty hover area, not just the control and its label — to the
193
+ // input via Item's `interactiveRef` (useClickableContainer). This matches
194
+ // CheckboxListItem so the whole row is clickable, and keeps one tab stop per
195
+ // option (WCAG 4.1.2). The radio carries its accessible name via `aria-label`
196
+ // since the visible label is now a plain (non-`<label>`) text node — a real
197
+ // `<label htmlFor>` would double-fire under delegation.
198
+ const radioRef = useRef<HTMLInputElement>(null);
199
+
188
200
  const radioCircle = (
189
201
  <div
190
202
  {...stylex.props(styles.radioWrapper, wrapperSizeStyles[size])}
191
203
  {...focusProps}>
192
204
  <input
205
+ ref={radioRef}
193
206
  id={id}
194
207
  type="radio"
195
208
  name={context.name}
196
209
  value={value}
197
210
  checked={isChecked}
211
+ aria-label={label}
198
212
  disabled={isDisabled && !keepsFocusableForMessage}
199
213
  aria-disabled={keepsFocusableForMessage ? 'true' : undefined}
200
214
  // A focusable-disabled radio is not natively disabled, so detach it
@@ -208,6 +222,10 @@ export function RadioListItem({
208
222
  }
209
223
  context.onChange(value);
210
224
  }}
225
+ // A consumer onClick rides on the radio input itself, so it fires for
226
+ // both direct control clicks and row-surface clicks the row delegates
227
+ // to the input — the same routing CheckboxListItem uses.
228
+ onClick={onClick}
211
229
  aria-describedby={description ? descriptionID : undefined}
212
230
  {...stylex.props(
213
231
  styles.input,
@@ -225,50 +243,64 @@ export function RadioListItem({
225
243
  </div>
226
244
  );
227
245
 
228
- const mediaContent =
229
- startContent != null ? (
230
- <>
231
- {radioCircle}
232
- {startContent}
233
- </>
234
- ) : (
235
- radioCircle
236
- );
246
+ const mediaContent = isRenderable(startContent) ? (
247
+ <>
248
+ {radioCircle}
249
+ {startContent}
250
+ </>
251
+ ) : (
252
+ radioCircle
253
+ );
237
254
 
238
255
  return (
239
- <div
256
+ <Item
240
257
  ref={ref}
241
- {...mergeProps(
242
- themeProps('radio-list-item'),
243
- stylex.props(
244
- styles.container,
258
+ startContent={mediaContent}
259
+ // Delegate row-surface clicks (label text, description, and the empty
260
+ // hover area) to the radio input. The input stays the option's sole
261
+ // focusable control, so the row adds no second tab stop.
262
+ interactiveRef={radioRef}
263
+ isDisabled={isDisabled}
264
+ label={<span>{label}</span>}
265
+ description={
266
+ isRenderable(description) ? (
267
+ <span id={descriptionID}>{description}</span>
268
+ ) : undefined
269
+ }
270
+ endContent={endContent}
271
+ xstyle={
272
+ [
245
273
  // Hover reaches the radio visual through this ancestor marker rather
246
- // than props, so hovering the row tints the control.
274
+ // than props, so hovering the row tints the control. The marker rides
275
+ // the painting row element (Item), the same element that carries the
276
+ // theme target, so a theme's hover styling stays in step with the tint.
247
277
  !isDisabled && indicatorScope,
278
+ // Restore the bare default look: zero Item's padding/radius and its
279
+ // interactive hover/press background. Applied after Item's own base
280
+ // styles so it wins within the base layer; a `radio-list-item` theme
281
+ // still overrides it from the higher `astryx-theme` layer.
282
+ rowStyles.root,
248
283
  xstyle,
249
- ),
250
- className,
251
- style,
284
+ ] as StyleXStyles
285
+ }
286
+ {...mergeProps(
287
+ // One target for every row, carrying its size and runtime state so a
288
+ // theme can express "selected option at large" or restyle disabled
289
+ // rows without reaching for structural selectors. It lands on the
290
+ // element Item paints — the row surface — so a theme styling
291
+ // `radio-list-item`'s background/padding/borderRadius (and its
292
+ // `:hover`) actually takes effect from the `astryx-theme` layer, even
293
+ // though the component zeroes those by default. Converges with how
294
+ // ListItem lands `list-item` on the same element as `astryx-item`.
295
+ themeProps('radio-list-item', {
296
+ size,
297
+ selected: isChecked ? 'selected' : null,
298
+ disabled: isDisabled ? 'disabled' : null,
299
+ }),
300
+ {className, style},
252
301
  )}
253
- {...rest}>
254
- <Item
255
- startContent={mediaContent}
256
- label={
257
- <label
258
- htmlFor={id}
259
- {...stylex.props(isDisabled && styles.labelDisabled)}>
260
- {label}
261
- </label>
262
- }
263
- description={
264
- description != null ? (
265
- <span id={descriptionID}>{description}</span>
266
- ) : undefined
267
- }
268
- endContent={endContent}
269
- xstyle={embeddedStyles.root}
270
- />
271
- </div>
302
+ {...rest}
303
+ />
272
304
  );
273
305
  }
274
306
 
@@ -344,6 +344,28 @@ describe('ResizeHandle', () => {
344
344
  expect(hitArea.className).not.toContain('hitAreaOffsetX');
345
345
  });
346
346
 
347
+ // The grab zone is stretched along the handle by its 0/0 insets, so anything
348
+ // that moves it across the handle displaces the whole zone off the divider —
349
+ // a percentage does it by half the handle's length, so the taller the panel
350
+ // the larger the dead region, and nothing about it is visible on screen.
351
+ it.each([
352
+ ['horizontal' as const, 'translateX'],
353
+ ['vertical' as const, 'translateY'],
354
+ ])('offsets the %s grab zone along the pill axis only', (direction, axis) => {
355
+ render(<Harness handleProps={{direction, pillPlacement: 'start'}} />);
356
+ const hitArea = getSeparator().firstElementChild as HTMLElement;
357
+ const translates = (hitArea.getAttribute('style') ?? '')
358
+ .split(';')
359
+ .map(decl => decl.split(/:(.*)/s)[1]?.trim() ?? '')
360
+ .filter(value => value.startsWith('translate'));
361
+
362
+ // Both the LTR and RTL declarations of the horizontal offset.
363
+ expect(translates.length).toBeGreaterThan(0);
364
+ for (const translate of translates) {
365
+ expect(translate.startsWith(`${axis}(`)).toBe(true);
366
+ }
367
+ });
368
+
347
369
  // --- Prop composition (ordering choice: handler sits after {...props}) ---
348
370
 
349
371
  it('runs a consumer onKeyDown alongside keyboard resizing', () => {
@@ -219,16 +219,22 @@ const dynamicStyles = stylex.create({
219
219
  // directions because the pill's own offset is physical. Mixing the previous
220
220
  // divider-relative `50%` anchor with a percentage translate stranded the grab
221
221
  // zone to one side under RTL; this construction keeps it on the pill.
222
+ //
223
+ // Only the offset axis is translated. Unlike the pill — a small box anchored
224
+ // at the divider's midpoint, so it needs a −50% self-shift to centre — the
225
+ // grab zone is STRETCHED along the handle by hitAreaHorizontal/Vertical's
226
+ // 0/0 insets, so it is already in place on that axis. A percentage there
227
+ // would displace it by half the handle's own length, growing with the panel.
222
228
  hitAreaOffsetX: (dir: number) => ({
223
229
  insetInlineStart: 0,
224
230
  transform: {
225
- default: `translate(calc(${dir} * (3px + ${spacingVars['--spacing-1']}) - 6.5px), -50%)`,
226
- ':is([dir="rtl"] *)': `translate(calc(${dir} * (3px + ${spacingVars['--spacing-1']}) + 6.5px), -50%)`,
231
+ default: `translateX(calc(${dir} * (3px + ${spacingVars['--spacing-1']}) - 6.5px))`,
232
+ ':is([dir="rtl"] *)': `translateX(calc(${dir} * (3px + ${spacingVars['--spacing-1']}) + 6.5px))`,
227
233
  },
228
234
  }),
229
235
  hitAreaOffsetY: (dir: number) => ({
230
236
  insetBlockStart: 0,
231
- transform: `translate(-50%, calc(${dir} * (3px + ${spacingVars['--spacing-1']}) - 6.5px))`,
237
+ transform: `translateY(calc(${dir} * (3px + ${spacingVars['--spacing-1']}) - 6.5px))`,
232
238
  }),
233
239
  pillOffsetX: (dir: number) => ({
234
240
  insetInlineStart: 0,
@@ -53,11 +53,36 @@ export const docs = {
53
53
  description: 'Internal padding using the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10). Use padding={0} for edge-to-edge content.',
54
54
  default: '4',
55
55
  },
56
+ {
57
+ name: 'paddingInline',
58
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
59
+ description: 'Inline (horizontal) padding override. Overrides only the inline-axis padding while preserving block padding from `padding` or the container theme default. Accepts the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10).',
60
+ },
61
+ {
62
+ name: 'paddingInlineStart',
63
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
64
+ description: 'Inline-start padding override (left in LTR, right in RTL). Overrides paddingInline and padding on that edge only.',
65
+ },
66
+ {
67
+ name: 'paddingInlineEnd',
68
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
69
+ description: 'Inline-end padding override (right in LTR, left in RTL). Overrides paddingInline and padding on that edge only.',
70
+ },
56
71
  {
57
72
  name: 'paddingBlock',
58
73
  type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
59
74
  description: 'Block (vertical) padding override. Overrides only the block-axis padding while preserving inline padding from `padding` or the container theme default. Accepts the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10).',
60
75
  },
76
+ {
77
+ name: 'paddingBlockStart',
78
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
79
+ description: 'Block-start (top) padding, using the spacing scale. Overrides paddingBlock and padding on that edge only.',
80
+ },
81
+ {
82
+ name: 'paddingBlockEnd',
83
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
84
+ description: 'Block-end (bottom) padding, using the spacing scale. Overrides paddingBlock and padding on that edge only.',
85
+ },
61
86
  {
62
87
  name: 'xstyle',
63
88
  type: 'StyleXStyles',
@@ -135,11 +160,36 @@ export const docsZh = {
135
160
  description: '使用间距比例的内部内边距(0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10)。使用 padding={0} 实现全宽内容。',
136
161
  default: '4',
137
162
  },
163
+ {
164
+ name: 'paddingInline',
165
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
166
+ description: '行内(水平)方向内边距覆盖。仅覆盖行内轴内边距,同时保留来自 padding 或容器主题默认值的块内边距。使用间距比例(0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10)。',
167
+ },
168
+ {
169
+ name: 'paddingInlineStart',
170
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
171
+ description: '行内起始内边距覆盖(LTR 中为左侧,RTL 中为右侧)。仅在该边上覆盖 paddingInline 和 padding。',
172
+ },
173
+ {
174
+ name: 'paddingInlineEnd',
175
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
176
+ description: '行内结束内边距覆盖(LTR 中为右侧,RTL 中为左侧)。仅在该边上覆盖 paddingInline 和 padding。',
177
+ },
138
178
  {
139
179
  name: 'paddingBlock',
140
180
  type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
141
181
  description: '块(垂直)方向内边距覆盖。仅覆盖块轴内边距,同时保留来自 padding 或容器主题默认值的行内内边距。使用间距比例(0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10)。',
142
182
  },
183
+ {
184
+ name: 'paddingBlockStart',
185
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
186
+ description: '块起始(顶部)内边距,使用间距刻度。仅在该边上覆盖 paddingBlock 和 padding。',
187
+ },
188
+ {
189
+ name: 'paddingBlockEnd',
190
+ type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
191
+ description: '块结束(底部)内边距,使用间距刻度。仅在该边上覆盖 paddingBlock 和 padding。',
192
+ },
143
193
  {
144
194
  name: 'xstyle',
145
195
  type: 'StyleXStyles',
@@ -192,7 +242,12 @@ export const docsDense = {
192
242
  children: 'Content rendered inside section.',
193
243
  dividers: 'Which sides of section have divider borders.',
194
244
  padding: 'Internal padding via spacing scale; 0 for edge-to-edge content.',
245
+ paddingInline: 'Inline-axis padding override; preserves block padding from padding/theme.',
246
+ paddingInlineStart: 'Inline-start (left in LTR) padding override; wins over paddingInline/padding on that edge.',
247
+ paddingInlineEnd: 'Inline-end (right in LTR) padding override; wins over paddingInline/padding on that edge.',
195
248
  paddingBlock: 'Block-axis padding override; preserves inline padding from padding/theme.',
249
+ paddingBlockStart: 'Block-start (top) padding override; wins over paddingBlock/padding on that edge.',
250
+ paddingBlockEnd: 'Block-end (bottom) padding override; wins over paddingBlock/padding on that edge.',
196
251
  xstyle: 'StyleX styles for layout customization; must be stylex.create() value.',
197
252
  },
198
253
  };