@astryxdesign/core 0.5.2-canary.2da7a39 → 0.5.2-canary.2e51213

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 (375) hide show
  1. package/dist/AppShell/AppShell.d.ts +2 -2
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +10 -7
  4. package/dist/Banner/Banner.d.ts +5 -0
  5. package/dist/Banner/Banner.d.ts.map +1 -1
  6. package/dist/Banner/Banner.js +7 -2
  7. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +3 -2
  8. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  9. package/dist/Breadcrumbs/BreadcrumbItem.js +22 -15
  10. package/dist/Carousel/Carousel.d.ts.map +1 -1
  11. package/dist/Carousel/Carousel.js +2 -2
  12. package/dist/Chat/ChatComposer.d.ts +2 -2
  13. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  14. package/dist/Chat/ChatComposer.js +21 -2
  15. package/dist/Chat/ChatToolCalls.d.ts +1 -1
  16. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  17. package/dist/Chat/ChatToolCalls.js +12 -34
  18. package/dist/Chat/useChatNewMessages.js +3 -3
  19. package/dist/CheckboxList/CheckboxListItem.d.ts +5 -3
  20. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  21. package/dist/DateTimeInput/DateTimeInput.d.ts +47 -13
  22. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  23. package/dist/DateTimeInput/DateTimeInput.js +269 -162
  24. package/dist/DateTimeInput/NativeDateSegment.d.ts +24 -0
  25. package/dist/DateTimeInput/NativeDateSegment.d.ts.map +1 -0
  26. package/dist/DateTimeInput/NativeDateSegment.js +235 -0
  27. package/dist/DateTimeInput/NativeTimeSegment.d.ts +30 -0
  28. package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -0
  29. package/dist/DateTimeInput/NativeTimeSegment.js +248 -0
  30. package/dist/DateTimeInput/index.d.ts +1 -1
  31. package/dist/DateTimeInput/index.d.ts.map +1 -1
  32. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +95 -0
  33. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -0
  34. package/dist/DateTimeInput/nativePickerSegmentStyles.js +103 -0
  35. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  36. package/dist/DropdownMenu/DropdownMenu.js +2 -4
  37. package/dist/Field/Field.d.ts.map +1 -1
  38. package/dist/Field/Field.js +10 -4
  39. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  40. package/dist/Field/PanelSearchInput.js +3 -5
  41. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  42. package/dist/FieldStatus/FieldStatus.js +4 -2
  43. package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
  44. package/dist/Layer/useTouchTrigger.js +2 -4
  45. package/dist/Layout/Layout.d.ts +7 -8
  46. package/dist/Layout/Layout.d.ts.map +1 -1
  47. package/dist/Layout/Layout.js +7 -8
  48. package/dist/MultiSelector/MultiSelector.d.ts +11 -1
  49. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  50. package/dist/MultiSelector/MultiSelector.js +89 -45
  51. package/dist/RadioList/RadioListItem.d.ts +30 -5
  52. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  53. package/dist/RadioList/RadioListItem.js +17 -4
  54. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  55. package/dist/Resizable/ResizeHandle.js +102 -44
  56. package/dist/Resizable/index.d.ts +2 -0
  57. package/dist/Resizable/index.d.ts.map +1 -1
  58. package/dist/Resizable/index.js +1 -0
  59. package/dist/Resizable/useResizable.d.ts +89 -8
  60. package/dist/Resizable/useResizable.d.ts.map +1 -1
  61. package/dist/Resizable/useResizable.js +521 -38
  62. package/dist/Resizable/utils.d.ts +35 -0
  63. package/dist/Resizable/utils.d.ts.map +1 -0
  64. package/dist/Resizable/utils.js +27 -0
  65. package/dist/Selector/Selector.d.ts +10 -0
  66. package/dist/Selector/Selector.d.ts.map +1 -1
  67. package/dist/Selector/Selector.js +105 -57
  68. package/dist/Selector/useSelectorPresentation.d.ts +1 -0
  69. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
  70. package/dist/Selector/useSelectorPresentation.js +17 -2
  71. package/dist/Slider/Slider.d.ts.map +1 -1
  72. package/dist/Slider/Slider.js +3 -5
  73. package/dist/Spinner/Spinner.d.ts.map +1 -1
  74. package/dist/Spinner/Spinner.js +9 -10
  75. package/dist/Stepper/Step.d.ts +2 -1
  76. package/dist/Stepper/Step.d.ts.map +1 -1
  77. package/dist/Stepper/Step.js +75 -11
  78. package/dist/Stepper/Stepper.d.ts.map +1 -1
  79. package/dist/Stepper/Stepper.js +1 -0
  80. package/dist/TabList/TabList.d.ts.map +1 -1
  81. package/dist/TabList/TabList.js +2 -3
  82. package/dist/Table/index.d.ts +16 -1
  83. package/dist/Table/index.d.ts.map +1 -1
  84. package/dist/Table/index.js +4 -0
  85. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  86. package/dist/Table/plugins/columnResize/useTableColumnResize.js +8 -9
  87. package/dist/Table/plugins/rowStatus/index.d.ts +1 -1
  88. package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -1
  89. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +11 -30
  90. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  91. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +108 -62
  92. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  93. package/dist/Table/plugins/sortable/useTableSortable.js +9 -1
  94. package/dist/Text/useTruncation.d.ts +1 -1
  95. package/dist/Text/useTruncation.d.ts.map +1 -1
  96. package/dist/Text/useTruncation.js +8 -7
  97. package/dist/TimeInput/TimeInput.d.ts +16 -1
  98. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  99. package/dist/TimeInput/TimeInput.js +98 -60
  100. package/dist/TimeInput/index.d.ts +1 -1
  101. package/dist/TimeInput/index.d.ts.map +1 -1
  102. package/dist/Timestamp/Timestamp.d.ts +2 -2
  103. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  104. package/dist/Timestamp/Timestamp.js +4 -145
  105. package/dist/Timestamp/formatRelativeTime.d.ts +20 -0
  106. package/dist/Timestamp/formatRelativeTime.d.ts.map +1 -0
  107. package/dist/Timestamp/formatRelativeTime.js +81 -0
  108. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  109. package/dist/Toast/ToastViewport.js +125 -77
  110. package/dist/Tokenizer/Tokenizer.d.ts +0 -38
  111. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  112. package/dist/Tokenizer/Tokenizer.js +94 -26
  113. package/dist/Tokenizer/useEndLaneReserve.d.ts +31 -0
  114. package/dist/Tokenizer/useEndLaneReserve.d.ts.map +1 -0
  115. package/dist/Tokenizer/useEndLaneReserve.js +136 -0
  116. package/dist/Tooltip/useTooltip.d.ts +1 -1
  117. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  118. package/dist/Tooltip/useTooltip.js +53 -42
  119. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  120. package/dist/Typeahead/BaseTypeahead.js +85 -30
  121. package/dist/Typeahead/Typeahead.d.ts +0 -21
  122. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  123. package/dist/Typeahead/Typeahead.js +108 -67
  124. package/dist/Typeahead/busyIndicatorLane.d.ts +62 -0
  125. package/dist/Typeahead/busyIndicatorLane.d.ts.map +1 -0
  126. package/dist/Typeahead/busyIndicatorLane.js +98 -0
  127. package/dist/astryx.css +25 -7
  128. package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -1
  129. package/dist/hooks/useFocusReturnVisibility.js +3 -5
  130. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
  131. package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -1
  132. package/dist/hooks/useOverflow.js +11 -11
  133. package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
  134. package/dist/hooks/useScrollOverflow.js +7 -4
  135. package/dist/theme/defineTheme.d.ts +13 -0
  136. package/dist/theme/defineTheme.d.ts.map +1 -1
  137. package/dist/theme/defineTheme.js +7 -0
  138. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  139. package/dist/theme/generateThemeRules.js +1 -1
  140. package/dist/theme/localTokens.d.ts +18 -0
  141. package/dist/theme/localTokens.d.ts.map +1 -0
  142. package/dist/theme/localTokens.js +162 -0
  143. package/dist/utils/interactionModality.d.ts +6 -28
  144. package/dist/utils/interactionModality.d.ts.map +1 -1
  145. package/dist/utils/interactionModality.js +72 -37
  146. package/dist/utils/sharedResizeObserver.d.ts +17 -9
  147. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  148. package/dist/utils/sharedResizeObserver.js +54 -12
  149. package/locales/en.json +8 -0
  150. package/locales/pseudo.json +6 -0
  151. package/package.json +7 -2
  152. package/src/AlertDialog/useImperativeAlertDialog.test.tsx +163 -0
  153. package/src/AppShell/AppShell.doc.mjs +4 -3
  154. package/src/AppShell/AppShell.test.tsx +21 -0
  155. package/src/AppShell/AppShell.tsx +12 -7
  156. package/src/Banner/Banner.doc.mjs +5 -1
  157. package/src/Banner/Banner.tsx +12 -1
  158. package/src/BottomSheet/BottomSheet.doc.mjs +31 -0
  159. package/src/BottomSheet/BottomSheet.spec.md +178 -0
  160. package/src/Breadcrumbs/BreadcrumbItem.tsx +18 -9
  161. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +4 -1
  162. package/src/Breadcrumbs/Breadcrumbs.test.tsx +12 -0
  163. package/src/Button/Button.doc.mjs +56 -0
  164. package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
  165. package/src/Calendar/hooks/useCalendarConstraints.test.ts +153 -0
  166. package/src/Calendar/hooks/useCalendarDays.test.ts +265 -0
  167. package/src/Calendar/hooks/useCalendarNavigation.test.ts +252 -0
  168. package/src/Carousel/Carousel.test.tsx +83 -0
  169. package/src/Carousel/Carousel.tsx +8 -2
  170. package/src/Chat/ChatComposer.doc.mjs +7 -4
  171. package/src/Chat/ChatComposer.test.tsx +84 -2
  172. package/src/Chat/ChatComposer.tsx +45 -3
  173. package/src/Chat/ChatSendButton.test.tsx +189 -0
  174. package/src/Chat/ChatToolCalls.doc.mjs +1 -1
  175. package/src/Chat/ChatToolCalls.test.tsx +33 -1
  176. package/src/Chat/ChatToolCalls.tsx +13 -34
  177. package/src/Chat/useChatNewMessages.ts +3 -3
  178. package/src/Chat/useChatPasteAsToken.test.ts +191 -0
  179. package/src/CheckboxList/CheckboxList.doc.mjs +172 -31
  180. package/src/CheckboxList/CheckboxList.spec.md +215 -0
  181. package/src/CheckboxList/CheckboxList.test.tsx +45 -0
  182. package/src/CheckboxList/CheckboxListItem.doc.mjs +11 -9
  183. package/src/CheckboxList/CheckboxListItem.tsx +5 -3
  184. package/src/Collapsible/useCollapsible.test.tsx +236 -0
  185. package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
  186. package/src/CommandPalette/CommandPalette.spec.md +224 -0
  187. package/src/CommandPalette/CommandPaletteEmpty.test.tsx +101 -0
  188. package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
  189. package/src/ComplexSelector/ComplexSelector.spec.md +190 -0
  190. package/src/ContextMenu/ContextMenu.doc.mjs +48 -0
  191. package/src/ContextMenu/ContextMenu.spec.md +207 -0
  192. package/src/DateTimeInput/DateTimeInput.doc.mjs +43 -23
  193. package/src/DateTimeInput/DateTimeInput.tsx +388 -181
  194. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +10 -2
  195. package/src/DateTimeInput/NativeDateSegment.tsx +308 -0
  196. package/src/DateTimeInput/NativePickerSegments.test.tsx +626 -0
  197. package/src/DateTimeInput/NativeTimeSegment.tsx +331 -0
  198. package/src/DateTimeInput/index.ts +1 -0
  199. package/src/DateTimeInput/nativePickerSegmentStyles.ts +120 -0
  200. package/src/Divider/Divider.doc.mjs +24 -0
  201. package/src/Divider/Divider.spec.md +157 -0
  202. package/src/DropdownMenu/DropdownMenu.doc.mjs +104 -0
  203. package/src/DropdownMenu/DropdownMenu.spec.md +246 -0
  204. package/src/DropdownMenu/DropdownMenu.tsx +2 -4
  205. package/src/Field/Field.doc.mjs +1 -0
  206. package/src/Field/Field.test.tsx +39 -0
  207. package/src/Field/Field.tsx +18 -1
  208. package/src/Field/InputClearButton.test.tsx +68 -6
  209. package/src/Field/PanelSearchInput.tsx +3 -5
  210. package/src/FieldStatus/FieldStatus.doc.mjs +21 -0
  211. package/src/FieldStatus/FieldStatus.spec.md +213 -0
  212. package/src/FieldStatus/FieldStatus.test.tsx +17 -0
  213. package/src/FieldStatus/FieldStatus.tsx +7 -2
  214. package/src/Grid/Grid.doc.mjs +19 -0
  215. package/src/Grid/Grid.spec.md +162 -0
  216. package/src/Icon/Icon.doc.mjs +196 -48
  217. package/src/Icon/Icon.spec.md +192 -0
  218. package/src/IconButton/IconButton.doc.mjs +38 -0
  219. package/src/Kbd/Kbd.doc.mjs +18 -0
  220. package/src/Kbd/Kbd.spec.md +142 -0
  221. package/src/Layer/useTouchTrigger.ts +2 -4
  222. package/src/Layout/Layout.doc.mjs +57 -17
  223. package/src/Layout/Layout.spec.md +235 -0
  224. package/src/Layout/Layout.test.tsx +1 -1
  225. package/src/Layout/Layout.tsx +7 -8
  226. package/src/Layout/LayoutHeader.doc.mjs +9 -0
  227. package/src/Layout/LayoutPanel.doc.mjs +4 -3
  228. package/src/Lightbox/Lightbox.doc.mjs +149 -33
  229. package/src/Lightbox/Lightbox.spec.md +198 -0
  230. package/src/Lightbox/useLightbox.test.tsx +263 -0
  231. package/src/Markdown/Markdown.doc.mjs +60 -0
  232. package/src/Markdown/Markdown.spec.md +207 -0
  233. package/src/MobileNav/MobileNav.doc.mjs +140 -32
  234. package/src/MobileNav/MobileNav.spec.md +209 -0
  235. package/src/MoreMenu/MoreMenu.doc.mjs +42 -0
  236. package/src/MoreMenu/MoreMenu.spec.md +222 -0
  237. package/src/MultiSelector/MultiSelector.doc.mjs +124 -1
  238. package/src/MultiSelector/MultiSelector.spec.md +293 -0
  239. package/src/MultiSelector/MultiSelector.test.tsx +305 -2
  240. package/src/MultiSelector/MultiSelector.tsx +124 -55
  241. package/src/NavIcon/NavIcon.doc.mjs +17 -0
  242. package/src/NavIcon/NavIcon.spec.md +134 -0
  243. package/src/NavMenu/NavHeadingMenu.spec.md +210 -0
  244. package/src/NavMenu/NavMenu.doc.mjs +37 -0
  245. package/src/Outline/Outline.doc.mjs +35 -0
  246. package/src/Outline/Outline.spec.md +162 -0
  247. package/src/OverflowList/OverflowList.doc.mjs +24 -0
  248. package/src/OverflowList/OverflowList.spec.md +157 -0
  249. package/src/Pagination/Pagination.doc.mjs +74 -0
  250. package/src/Pagination/Pagination.spec.md +226 -0
  251. package/src/Popover/Popover.doc.mjs +264 -65
  252. package/src/Popover/Popover.spec.md +421 -0
  253. package/src/Popover/usePopover.doc.mjs +208 -33
  254. package/src/PowerSearch/PowerSearch.spec.md +291 -0
  255. package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +253 -0
  256. package/src/PowerSearch/PowerSearchToken.test.tsx +228 -0
  257. package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
  258. package/src/ProgressBar/ProgressBar.spec.md +261 -0
  259. package/src/RadioList/RadioList.test.tsx +136 -2
  260. package/src/RadioList/RadioListItem.doc.mjs +30 -11
  261. package/src/RadioList/RadioListItem.tsx +44 -8
  262. package/src/Resizable/Resizable.doc.mjs +130 -24
  263. package/src/Resizable/Resizable.spec.md +246 -0
  264. package/src/Resizable/ResizeHandle.test.tsx +177 -56
  265. package/src/Resizable/ResizeHandle.tsx +128 -45
  266. package/src/Resizable/index.ts +2 -0
  267. package/src/Resizable/shippedDirections.test.ts +462 -0
  268. package/src/Resizable/useResizable.doc.mjs +124 -29
  269. package/src/Resizable/useResizable.test.ts +1277 -3
  270. package/src/Resizable/useResizable.ts +760 -48
  271. package/src/Resizable/utils.test.ts +74 -0
  272. package/src/Resizable/utils.ts +35 -0
  273. package/src/Section/Section.doc.mjs +17 -0
  274. package/src/Section/Section.spec.md +139 -0
  275. package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
  276. package/src/SegmentedControl/SegmentedControl.spec.md +152 -0
  277. package/src/Selector/Selector.doc.mjs +133 -97
  278. package/src/Selector/Selector.spec.md +300 -0
  279. package/src/Selector/Selector.test.tsx +318 -1
  280. package/src/Selector/Selector.tsx +127 -60
  281. package/src/Selector/useSelectorPresentation.ts +24 -4
  282. package/src/SideNav/SideNav.test.tsx +3 -3
  283. package/src/SideNav/SideNavCollapseButton.doc.mjs +8 -0
  284. package/src/SideNav/SideNavItem.doc.mjs +1 -1
  285. package/src/Skeleton/Skeleton.doc.mjs +12 -0
  286. package/src/Skeleton/Skeleton.spec.md +127 -0
  287. package/src/Slider/Slider.doc.mjs +184 -30
  288. package/src/Slider/Slider.spec.md +224 -0
  289. package/src/Slider/Slider.tsx +2 -5
  290. package/src/Spinner/Spinner.doc.mjs +5 -5
  291. package/src/Spinner/Spinner.test.tsx +32 -7
  292. package/src/Spinner/Spinner.tsx +46 -14
  293. package/src/Stack/Stack.doc.mjs +22 -0
  294. package/src/Stack/Stack.spec.md +155 -0
  295. package/src/StatusDot/StatusDot.doc.mjs +17 -0
  296. package/src/StatusDot/StatusDot.spec.md +138 -0
  297. package/src/Stepper/Step.doc.mjs +1 -1
  298. package/src/Stepper/Step.tsx +118 -5
  299. package/src/Stepper/Stepper.doc.mjs +51 -1
  300. package/src/Stepper/Stepper.spec.md +245 -0
  301. package/src/Stepper/Stepper.test.tsx +315 -0
  302. package/src/Stepper/Stepper.tsx +8 -0
  303. package/src/Switch/Switch.doc.mjs +40 -0
  304. package/src/Switch/Switch.spec.md +175 -0
  305. package/src/TabList/TabList.tsx +2 -3
  306. package/src/Table/Table.doc.mjs +102 -24
  307. package/src/Table/Table.perf.test.tsx +51 -1
  308. package/src/Table/Table.spec.md +325 -0
  309. package/src/Table/TableHeaderCell.test.tsx +291 -0
  310. package/src/Table/index.ts +19 -4
  311. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -12
  312. package/src/Table/plugins/filtering/useTableFilterState.test.tsx +143 -0
  313. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +2 -1
  314. package/src/Table/plugins/rowStatus/index.ts +1 -4
  315. package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +92 -0
  316. package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +354 -0
  317. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +431 -56
  318. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +155 -84
  319. package/src/Table/plugins/sortable/useTableSortable.test.tsx +72 -0
  320. package/src/Table/plugins/sortable/useTableSortable.tsx +18 -1
  321. package/src/Table/useTableGroupedRows.doc.mjs +2 -2
  322. package/src/Table/useTableRowStatus.doc.mjs +5 -5
  323. package/src/Text/Text.doc.mjs +190 -43
  324. package/src/Text/Text.spec.md +206 -0
  325. package/src/Text/useTruncation.ts +8 -7
  326. package/src/TextArea/TextArea.doc.mjs +255 -45
  327. package/src/TextArea/TextArea.spec.md +205 -0
  328. package/src/TimeInput/NativeTimeInput.test.tsx +269 -0
  329. package/src/TimeInput/TimeInput.doc.mjs +47 -23
  330. package/src/TimeInput/TimeInput.tsx +109 -50
  331. package/src/TimeInput/index.ts +1 -0
  332. package/src/Timestamp/Timestamp.doc.mjs +2 -2
  333. package/src/Timestamp/Timestamp.test.tsx +75 -3
  334. package/src/Timestamp/Timestamp.tsx +7 -153
  335. package/src/Timestamp/formatRelativeTime.ts +96 -0
  336. package/src/Toast/ToastViewport.test.tsx +194 -0
  337. package/src/Toast/ToastViewport.tsx +136 -58
  338. package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
  339. package/src/Tokenizer/Tokenizer.doc.mjs +2 -0
  340. package/src/Tokenizer/Tokenizer.spec.md +293 -0
  341. package/src/Tokenizer/Tokenizer.test.tsx +335 -1
  342. package/src/Tokenizer/Tokenizer.tsx +129 -46
  343. package/src/Tokenizer/useEndLaneReserve.ts +146 -0
  344. package/src/Toolbar/Toolbar.doc.mjs +19 -0
  345. package/src/Toolbar/Toolbar.spec.md +174 -0
  346. package/src/Tooltip/Tooltip.doc.mjs +17 -0
  347. package/src/Tooltip/Tooltip.spec.md +142 -0
  348. package/src/Tooltip/Tooltip.test.tsx +21 -1
  349. package/src/Tooltip/useTooltip.test.tsx +318 -0
  350. package/src/Tooltip/useTooltip.tsx +60 -39
  351. package/src/TreeList/TreeList.doc.mjs +58 -0
  352. package/src/TreeList/TreeList.spec.md +224 -0
  353. package/src/Typeahead/BaseTypeahead.tsx +96 -25
  354. package/src/Typeahead/Typeahead.doc.mjs +89 -1
  355. package/src/Typeahead/Typeahead.spec.md +257 -0
  356. package/src/Typeahead/Typeahead.test.tsx +502 -1
  357. package/src/Typeahead/Typeahead.tsx +187 -69
  358. package/src/Typeahead/TypeaheadItem.test.tsx +93 -2
  359. package/src/Typeahead/busyIndicatorLane.tsx +109 -0
  360. package/src/__tests__/stylexDeclarations.ts +51 -0
  361. package/src/hooks/useFocusReturnVisibility.ts +3 -5
  362. package/src/hooks/useOverflow.ts +11 -11
  363. package/src/hooks/useScrollLock.test.ts +103 -0
  364. package/src/hooks/useScrollOverflow.ts +7 -4
  365. package/src/i18n/useTranslator.test.tsx +197 -0
  366. package/src/theme/defineTheme.test.ts +227 -0
  367. package/src/theme/defineTheme.ts +30 -0
  368. package/src/theme/derivedVarRegistry.test.ts +6 -0
  369. package/src/theme/generateThemeRules.ts +4 -1
  370. package/src/theme/localTokens.ts +272 -0
  371. package/src/theme/themingTargets.test.ts +126 -28
  372. package/src/utils/interactionModality.test.ts +83 -0
  373. package/src/utils/interactionModality.ts +88 -36
  374. package/src/utils/sharedResizeObserver.test.ts +124 -5
  375. package/src/utils/sharedResizeObserver.ts +60 -14
@@ -666,13 +666,147 @@ describe('RadioList', () => {
666
666
  value="a"
667
667
  data-testid="item-a"
668
668
  id="item-a-id"
669
- aria-label="First option"
669
+ aria-describedby="help-text"
670
670
  />
671
671
  </RadioList>,
672
672
  );
673
673
  const item = screen.getByTestId('item-a');
674
674
  expect(item).toHaveAttribute('id', 'item-a-id');
675
- expect(item).toHaveAttribute('aria-label', 'First option');
675
+ expect(item).toHaveAttribute('aria-describedby', 'help-text');
676
+ });
677
+
678
+ it('routes aria-label to the radio control, not the row', () => {
679
+ render(
680
+ <RadioList label="Preference" value="" onChange={() => {}}>
681
+ <RadioListItem
682
+ label="Option A"
683
+ value="a"
684
+ data-testid="item-a"
685
+ aria-label="First option"
686
+ />
687
+ </RadioList>,
688
+ );
689
+ expect(screen.getByTestId('item-a')).not.toHaveAttribute('aria-label');
690
+ expect(
691
+ screen.getByRole('radio', {name: 'First option'}),
692
+ ).toBeInTheDocument();
693
+ });
694
+ });
695
+
696
+ describe('RadioListItem rich content', () => {
697
+ it('names the radio from the text of a ReactNode label', () => {
698
+ render(
699
+ <RadioList label="Plans" value="" onChange={() => {}}>
700
+ <RadioListItem
701
+ label={
702
+ <span>
703
+ Pro plan <em>(recommended)</em>
704
+ </span>
705
+ }
706
+ value="pro"
707
+ />
708
+ </RadioList>,
709
+ );
710
+ // The radio points at its visible label, so the name is computed from
711
+ // the rich node's own text — unlike CheckboxListItem, whose control has
712
+ // a separate hidden label and needs aria-label to say anything useful.
713
+ expect(
714
+ screen.getByRole('radio', {name: 'Pro plan (recommended)'}),
715
+ ).toBeInTheDocument();
716
+ });
717
+
718
+ it('lets aria-label override the name a ReactNode label would compute', () => {
719
+ render(
720
+ <RadioList label="Plans" value="" onChange={() => {}}>
721
+ <RadioListItem
722
+ label={
723
+ <span>
724
+ Pro plan <em>(recommended)</em>
725
+ </span>
726
+ }
727
+ aria-label="Pro plan"
728
+ value="pro"
729
+ />
730
+ </RadioList>,
731
+ );
732
+ expect(screen.getByRole('radio', {name: 'Pro plan'})).toBeInTheDocument();
733
+ });
734
+
735
+ it('selects the option when a ReactNode label is clicked', async () => {
736
+ const onChange = vi.fn();
737
+ const user = userEvent.setup();
738
+ render(
739
+ <RadioList label="Plans" value="" onChange={onChange}>
740
+ <RadioListItem label={<span>Pro plan</span>} value="pro" />
741
+ </RadioList>,
742
+ );
743
+ await user.click(screen.getByText('Pro plan'));
744
+ expect(onChange).toHaveBeenCalledWith('pro');
745
+ });
746
+
747
+ it('keeps a link in a ReactNode label independent from selection', async () => {
748
+ const onChange = vi.fn();
749
+ const user = userEvent.setup();
750
+ render(
751
+ <RadioList label="Plans" value="" onChange={onChange}>
752
+ <RadioListItem
753
+ label={
754
+ <>
755
+ Pro plan <a href="#pricing">pricing details</a>
756
+ </>
757
+ }
758
+ aria-label="Pro plan"
759
+ value="pro"
760
+ />
761
+ </RadioList>,
762
+ );
763
+ const radio = screen.getByRole('radio', {name: 'Pro plan'});
764
+ const link = screen.getByRole('link', {name: 'pricing details'});
765
+ await user.tab();
766
+ expect(radio).toHaveFocus();
767
+ await user.tab();
768
+ expect(link).toHaveFocus();
769
+ await user.click(link);
770
+ expect(onChange).not.toHaveBeenCalled();
771
+ });
772
+
773
+ it('renders a ReactNode description and keeps it linked to the radio', async () => {
774
+ const onChange = vi.fn();
775
+ const user = userEvent.setup();
776
+ render(
777
+ <RadioList label="Plans" value="" onChange={onChange}>
778
+ <RadioListItem
779
+ label="Pro plan"
780
+ description={
781
+ <span>
782
+ See the <a href="#pricing">pricing page</a>
783
+ </span>
784
+ }
785
+ value="pro"
786
+ />
787
+ </RadioList>,
788
+ );
789
+ const radio = screen.getByRole('radio', {name: 'Pro plan'});
790
+ expect(radio).toHaveAccessibleDescription('See the pricing page');
791
+ // The row delegates surface clicks to the radio, but a nested link is
792
+ // its own click target — following it must not also select the option.
793
+ await user.click(screen.getByRole('link', {name: 'pricing page'}));
794
+ expect(onChange).not.toHaveBeenCalled();
795
+ });
796
+
797
+ it('leaves aria-describedby off when a conditional description renders nothing', () => {
798
+ const showDetails = false;
799
+ render(
800
+ <RadioList label="Plans" value="" onChange={() => {}}>
801
+ <RadioListItem
802
+ label="Pro plan"
803
+ // The common conditional-slot idiom yields `false`, not undefined.
804
+ description={showDetails && <span>Billing details</span>}
805
+ value="pro"
806
+ />
807
+ </RadioList>,
808
+ );
809
+ expect(screen.getByRole('radio')).not.toHaveAttribute('aria-describedby');
676
810
  });
677
811
  });
678
812
 
@@ -7,7 +7,8 @@ export const docs = {
7
7
  subComponentOf: 'RadioList',
8
8
  displayName: 'Radio List Item',
9
9
  isHiddenFromOverview: true,
10
- description: 'Individual radio item with label, description, and content slots.',
10
+ description:
11
+ 'Individual radio item with label, description, and content slots.',
11
12
  // RadioListItem requires RadioList context; wrap it so the preview doesn't throw.
12
13
  playground: {
13
14
  defaults: {value: 'option-1', label: 'Option'},
@@ -19,10 +20,17 @@ export const docs = {
19
20
  props: [
20
21
  {
21
22
  name: 'label',
22
- type: 'string',
23
- description: 'Label text for the radio item.',
23
+ type: 'ReactNode',
24
+ description:
25
+ 'Primary label for the radio item. Rich labels may contain links or buttons, which keep their own behavior without selecting the item. The label text names the radio; pair it with aria-label when that text does not read well on its own.',
24
26
  required: true,
25
27
  },
28
+ {
29
+ name: 'aria-label',
30
+ type: 'string',
31
+ description:
32
+ 'Plain-text accessible name for the radio, applied to the control rather than the row. It overrides whatever the label element computes — a plain string label included — so reach for it when a rich label\u2019s own text is absent or reads badly.',
33
+ },
26
34
  {
27
35
  name: 'value',
28
36
  type: 'string',
@@ -31,8 +39,9 @@ export const docs = {
31
39
  },
32
40
  {
33
41
  name: 'description',
34
- type: 'string',
35
- description: 'Description text displayed below the label.',
42
+ type: 'ReactNode',
43
+ description:
44
+ 'Secondary content displayed below the label. Links and buttons keep their own click behaviour — the row only delegates clicks from its non-interactive surface to the radio.',
36
45
  },
37
46
  {
38
47
  name: 'isDisabled',
@@ -85,10 +94,17 @@ export const docsZh = {
85
94
  props: [
86
95
  {
87
96
  name: 'label',
88
- type: 'string',
89
- description: '单选选项的标签文本。',
97
+ type: 'ReactNode',
98
+ description:
99
+ '单选选项的主标签。富内容标签可包含链接或按钮,它们保留自身行为且不会选中该选项。标签文本用于命名单选框;若朗读效果不佳,请同时传入 aria-label。',
90
100
  required: true,
91
101
  },
102
+ {
103
+ name: 'aria-label',
104
+ type: 'string',
105
+ description:
106
+ '单选框的纯文本无障碍名称,应用于控件本身而非整行。它会覆盖标签元素计算出的名称(包括纯字符串标签),因此仅在富文本标签自身缺少文本或朗读效果不佳时使用。',
107
+ },
92
108
  {
93
109
  name: 'value',
94
110
  type: 'string',
@@ -97,8 +113,9 @@ export const docsZh = {
97
113
  },
98
114
  {
99
115
  name: 'description',
100
- type: 'string',
101
- description: '显示在标签下方的描述文本。',
116
+ type: 'ReactNode',
117
+ description:
118
+ '显示在标签下方的次要内容。链接和按钮保留自身的点击行为——整行仅将非交互区域的点击委派给单选框。',
102
119
  },
103
120
  {
104
121
  name: 'isDisabled',
@@ -125,9 +142,11 @@ export const docsDense = {
125
142
  displayName: 'Radio List Item',
126
143
  description: 'Individual radio item w/ label, description, content slots.',
127
144
  propDescriptions: {
128
- label: 'Label text for radio item.',
145
+ label:
146
+ 'Primary label. String or ReactNode; nested controls keep their behavior.',
147
+ 'aria-label': 'Plain-text radio name; overrides any label.',
129
148
  value: 'Value of this radio item.',
130
- description: 'Description text below label.',
149
+ description: 'Secondary content below label. String or ReactNode.',
131
150
  isDisabled: 'Whether this individual radio item disabled.',
132
151
  startContent: 'Content rendered before radio circle.',
133
152
  endContent: 'Content rendered after label.',
@@ -113,17 +113,42 @@ const rowStyles = stylex.create({
113
113
  export interface RadioListItemProps extends BaseProps<HTMLDivElement> {
114
114
  ref?: React.Ref<HTMLDivElement>;
115
115
  /**
116
- * Label text for the radio item.
116
+ * Primary label for the radio item.
117
+ *
118
+ * Accepts a plain string or a ReactNode for rich content. Links and buttons
119
+ * in the label keep their own behavior; only non-interactive row clicks
120
+ * delegate to the radio. The radio points at the rendered label for its
121
+ * accessible name, so a rich label still names it from its own text — pass
122
+ * `aria-label` when that text is absent or too noisy to announce.
117
123
  */
118
- label: string;
124
+ label: ReactNode;
125
+ /**
126
+ * Plain-text accessible name for the radio, applied to the control rather
127
+ * than the row. It replaces the name the label would otherwise supply — a
128
+ * plain string label included — so reach for it when a rich label's own
129
+ * text is absent or reads badly, not as a routine addition.
130
+ *
131
+ * @example
132
+ * ```
133
+ * <RadioListItem
134
+ * label={<span>Pro plan <Badge label="Recommended" /></span>}
135
+ * aria-label="Pro plan"
136
+ * value="pro"
137
+ * />
138
+ * ```
139
+ */
140
+ 'aria-label'?: string;
119
141
  /**
120
142
  * Value of this radio item.
121
143
  */
122
144
  value: string;
123
145
  /**
124
- * Description text displayed below the label.
146
+ * Secondary content displayed below the label. Accepts a plain string or a
147
+ * ReactNode. Links and buttons anywhere in the row keep their own click
148
+ * behaviour — the row only delegates clicks from its non-interactive
149
+ * surface to the radio.
125
150
  */
126
- description?: string;
151
+ description?: ReactNode;
127
152
  /**
128
153
  * Whether this individual radio item is disabled.
129
154
  * @default false
@@ -155,6 +180,7 @@ export interface RadioListItemProps extends BaseProps<HTMLDivElement> {
155
180
  export function RadioListItem({
156
181
  ref,
157
182
  label,
183
+ 'aria-label': ariaLabel,
158
184
  value,
159
185
  description,
160
186
  isDisabled: isItemDisabled = false,
@@ -172,6 +198,7 @@ export function RadioListItem({
172
198
  }
173
199
 
174
200
  const id = useId();
201
+ const labelID = useId();
175
202
  const descriptionID = useId();
176
203
  const isDisabled = context.isDisabled || isItemDisabled;
177
204
  // When the whole group is disabled with a disabledMessage, radios stay
@@ -181,6 +208,10 @@ export function RadioListItem({
181
208
  const keepsFocusableForMessage =
182
209
  context.hasDisabledMessage && !isItemDisabled;
183
210
  const isChecked = context.value === value;
211
+ // One predicate for both the rendered element and the aria-describedby that
212
+ // points at it. A ReactNode description can be `false` or `''`, which render
213
+ // nothing — a `!= null` check would leave the link dangling.
214
+ const hasDescription = isRenderable(description);
184
215
  const size = context.size;
185
216
  // The radio visual is an indicator: a theme can restyle it through the
186
217
  // `radio` / `radio-dot` targets or replace the component outright.
@@ -211,7 +242,6 @@ export function RadioListItem({
211
242
  name={context.name}
212
243
  value={value}
213
244
  checked={isChecked}
214
- aria-label={label}
215
245
  disabled={isDisabled && !keepsFocusableForMessage}
216
246
  aria-disabled={keepsFocusableForMessage ? 'true' : undefined}
217
247
  // A focusable-disabled radio is not natively disabled, so detach it
@@ -229,7 +259,13 @@ export function RadioListItem({
229
259
  // both direct control clicks and row-surface clicks the row delegates
230
260
  // to the input — the same routing CheckboxListItem uses.
231
261
  onClick={onClick}
232
- aria-describedby={description ? descriptionID : undefined}
262
+ // The radio names itself from the visible label element, which works
263
+ // for a rich label as well as a plain string. `aria-label` replaces
264
+ // that name rather than adding to it, so the two are mutually
265
+ // exclusive — aria-labelledby would otherwise win over it.
266
+ aria-label={ariaLabel}
267
+ aria-labelledby={ariaLabel == null ? labelID : undefined}
268
+ aria-describedby={hasDescription ? descriptionID : undefined}
233
269
  {...stylex.props(
234
270
  styles.input,
235
271
  wrapperSizeStyles[size],
@@ -264,9 +300,9 @@ export function RadioListItem({
264
300
  // focusable control, so the row adds no second tab stop.
265
301
  interactiveRef={radioRef}
266
302
  isDisabled={isDisabled}
267
- label={<span>{label}</span>}
303
+ label={<span id={labelID}>{label}</span>}
268
304
  description={
269
- isRenderable(description) ? (
305
+ hasDescription ? (
270
306
  <span id={descriptionID}>{description}</span>
271
307
  ) : undefined
272
308
  }
@@ -1,5 +1,27 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
+ /** @type {import('@astryxdesign/cli/authoring').ComponentAnatomyElement[]} */
4
+ const anatomy = [
5
+ {
6
+ name: 'Handle',
7
+ required: true,
8
+ description:
9
+ 'Focusable separator that owns pointer and keyboard resize interaction.',
10
+ },
11
+ {
12
+ name: 'Grip pill',
13
+ required: false,
14
+ description:
15
+ 'Default visible grip indicator; custom handle content can replace it.',
16
+ },
17
+ {
18
+ name: 'Grab zone',
19
+ required: true,
20
+ description:
21
+ 'Invisible enlarged pointer region aligned with the grip or divider.',
22
+ },
23
+ ];
24
+
3
25
  /** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
4
26
  export const docs = {
5
27
  name: 'Resizable',
@@ -19,11 +41,17 @@ export const docs = {
19
41
  'grip',
20
42
  ],
21
43
  usage: {
44
+ anatomy,
22
45
  description:
23
46
  'Hook-based resizable panel system. useResizable() manages size state ' +
24
47
  'and ResizeHandle provides the interactive pill-grip separator. ' +
25
48
  'Pass resize props to existing layout components via their resizable prop.',
26
49
  bestPractices: [
50
+ {
51
+ guidance: true,
52
+ description:
53
+ 'Use percent(value, {min: pixel(value)}) or percent(value, {max: pixel(value)}) when a percentage needs exactly one pixel floor or ceiling. Reuse Table’s pixel() helper; numbers, exact Npx, and pixel(value) remain pixels. State, persistence, callbacks, paint, and ARIA remain resolved pixels.',
54
+ },
27
55
  {
28
56
  guidance: true,
29
57
  description:
@@ -57,24 +85,79 @@ export const docs = {
57
85
  description:
58
86
  'Hook that manages resize state for one or more panel regions. ' +
59
87
  'Returns size, isCollapsed, collapse/expand/resize methods, and props to pass to handles.',
88
+ examples: [
89
+ {
90
+ label: 'Structured fixed pixels',
91
+ code: `const region = useResizable({
92
+ defaultSize: pixel(333),
93
+ containerRef,
94
+ });`,
95
+ },
96
+ {
97
+ label: 'One-time structured default',
98
+ code: `import {useRef} from 'react';
99
+ import {ResizeHandle, useResizable} from '@astryxdesign/core/Resizable';
100
+ import {percent, pixel} from '@astryxdesign/core/Resizable/utils';
101
+
102
+ const containerRef = useRef<HTMLDivElement>(null);
103
+
104
+ const region = useResizable({
105
+ defaultSize: percent(40, {min: pixel(333)}),
106
+ containerRef,
107
+ });
108
+
109
+ <ResizeHandle direction="horizontal" resizable={region.props} />;`,
110
+ },
111
+ {
112
+ label: 'Live percentage floor',
113
+ code: `const region = useResizable({
114
+ defaultSize: 0,
115
+ minSize: percent(40, {min: pixel(333)}),
116
+ containerRef,
117
+ });`,
118
+ },
119
+ {
120
+ label: 'Live percentage ceiling',
121
+ code: `const region = useResizable({
122
+ defaultSize: 500,
123
+ maxSize: percent(10, {max: pixel(400)}),
124
+ containerRef,
125
+ });`,
126
+ },
127
+ ],
60
128
  props: [
61
129
  {
62
130
  name: 'defaultSize',
63
- type: 'number | string',
131
+ type: 'SizeValue | ResizableSize',
64
132
  description:
65
- 'Initial size in pixels or percentage string (e.g. "20%").',
133
+ 'Initial size. Numbers, exact Npx, and pixel(value) are pixels; exact N% has no additional pixel bound; percent(value, {min: pixel(value)}) or percent(value, {max: pixel(value)}) adds exactly one and resolves once.',
66
134
  default: '250',
67
135
  },
136
+ {
137
+ name: 'minSize',
138
+ type: 'ResizableSize',
139
+ description:
140
+ 'Live minimum. Numbers, exact Npx, and pixel(value) remain pixels; exact N% has no additional pixel bound; percent(value, {min: pixel(value)}) or percent(value, {max: pixel(value)}) adds exactly one.',
141
+ default: '50',
142
+ },
143
+ {
144
+ name: 'maxSize',
145
+ type: 'ResizableSize',
146
+ description:
147
+ 'Live maximum. Numbers, exact Npx, and pixel(value) remain pixels; exact N% has no additional pixel bound; percent(value, {min: pixel(value)}) or percent(value, {max: pixel(value)}) adds exactly one.',
148
+ default: 'Infinity',
149
+ },
68
150
  {
69
151
  name: 'minSizePx',
70
152
  type: 'number',
71
- description: 'Minimum size in pixels.',
153
+ description: 'Deprecated pixel-only alias for minSize.',
72
154
  default: '50',
73
155
  },
74
156
  {
75
157
  name: 'maxSizePx',
76
158
  type: 'number',
77
- description: 'Maximum size in pixels.',
159
+ description:
160
+ 'Deprecated pixel-only alias for maxSize. Explicit Infinity remains valid.',
78
161
  default: 'Infinity',
79
162
  },
80
163
  {
@@ -86,8 +169,7 @@ export const docs = {
86
169
  {
87
170
  name: 'collapsedSize',
88
171
  type: 'number',
89
- description:
90
- 'Pixel threshold that triggers collapse during drag.',
172
+ description: 'Pixel threshold that triggers collapse during drag.',
91
173
  default: '40',
92
174
  },
93
175
  {
@@ -98,13 +180,13 @@ export const docs = {
98
180
  {
99
181
  name: 'shrinkOrder',
100
182
  type: 'number',
101
- description:
102
- 'Cascade priority: lower number shrinks first.',
183
+ description: 'Cascade priority: lower number shrinks first.',
103
184
  },
104
185
  {
105
186
  name: 'autoSaveId',
106
187
  type: 'string',
107
- description: 'Key for persisting sizes and collapse state to localStorage.',
188
+ description:
189
+ 'Key for persisting sizes and collapse state to localStorage.',
108
190
  },
109
191
  ],
110
192
  },
@@ -168,7 +250,7 @@ export const docs = {
168
250
  name: 'resizable',
169
251
  type: 'ResizableProps',
170
252
  description:
171
- 'Resize props from useResizable: connects handle to panel.',
253
+ "Resize props from useResizable: connects handle to panel. Carries the region's axis ('horizontal' | 'vertical'), which must match this handle's direction.",
172
254
  required: true,
173
255
  },
174
256
  {
@@ -190,24 +272,42 @@ export const docs = {
190
272
 
191
273
  /** @type {import('@astryxdesign/cli/authoring').ComponentTranslationDoc} */
192
274
  export const docsDense = {
193
- description: 'Hook-based resizable panel system. useResizable() manages size state; ResizeHandle provides interactive pill-grip separator.',
275
+ description:
276
+ 'Hook-based resizable panel system. useResizable() manages size state; ResizeHandle provides interactive pill-grip separator.',
194
277
  usage: {
278
+ anatomy,
195
279
  description:
196
280
  'Hook-based resizable panel system. useResizable() manages size state; ResizeHandle provides interactive pill-grip separator. Pass resize props to existing layout components via their resizable prop.',
197
281
  bestPractices: [
198
- {guidance: true, description: 'Use useResizable() w/ existing Astryx layout components. Pass returned props to resizable prop on LayoutPanel or SideNav.'},
199
- {guidance: true, description: 'Provide accessible label on each ResizeHandle when multiple handles exist (e.g. "Resize sidebar", "Resize terminal").'},
200
- {guidance: false, description: 'Wrap panels in extra container components for resize. Hook-first architecture avoids extra DOM; use it directly on existing components.'},
282
+ {
283
+ guidance: true,
284
+ description:
285
+ 'Use useResizable() w/ existing Astryx layout components. Pass returned props to resizable prop on LayoutPanel or SideNav.',
286
+ },
287
+ {
288
+ guidance: true,
289
+ description:
290
+ 'Provide accessible label on each ResizeHandle when multiple handles exist (e.g. "Resize sidebar", "Resize terminal").',
291
+ },
292
+ {
293
+ guidance: false,
294
+ description:
295
+ 'Wrap panels in extra container components for resize. Hook-first architecture avoids extra DOM; use it directly on existing components.',
296
+ },
201
297
  ],
202
298
  },
203
299
  components: [
204
300
  {
205
301
  name: 'useResizable',
206
- description: 'Hook managing resize state for one or more panel regions. Returns size, isCollapsed, collapse/expand/resize methods, + props to pass to handles.',
302
+ description:
303
+ 'Hook managing resize state for one or more panel regions. Returns size, isCollapsed, collapse/expand/resize methods, + props to pass to handles.',
207
304
  propDescriptions: {
208
- defaultSize: 'initial size in px or % string (e.g. "20%")',
209
- minSizePx: 'minimum size in px',
210
- maxSizePx: 'maximum size in px',
305
+ defaultSize:
306
+ 'initial pixels, exact N%, or percent(value, {min: pixel(value)}) / percent(value, {max: pixel(value)}); resolves once',
307
+ minSize:
308
+ 'live minimum: pixels, exact N%, or percent(value, {min: pixel(value)}) / percent(value, {max: pixel(value)})',
309
+ maxSize:
310
+ 'live maximum: pixels, exact N%, or percent(value, {min: pixel(value)}) / percent(value, {max: pixel(value)})',
211
311
  collapsible: 'region can collapse to size 0?',
212
312
  collapsedSize: 'px threshold triggering collapse during drag',
213
313
  snaps: 'px values to snap to during resize',
@@ -217,14 +317,20 @@ export const docsDense = {
217
317
  },
218
318
  {
219
319
  name: 'ResizeHandle',
220
- description: 'Draggable separator between panels. Pill-grip: invisible at rest, visible on hover (0.6 opacity), fully opaque during drag (1.0). Keyboard-accessible.',
320
+ description:
321
+ 'Draggable separator between panels. Pill-grip: invisible at rest, visible on hover (0.6 opacity), fully opaque during drag (1.0). Keyboard-accessible.',
221
322
  propDescriptions: {
222
- direction: 'layout direction: determines cursor + indicator orientation',
223
- isReversed: 'reverse drag direction. Use when handle controls panel on end/right/bottom side',
323
+ direction:
324
+ 'layout direction: determines cursor + indicator orientation',
325
+ isReversed:
326
+ 'reverse drag direction. Use when handle controls panel on end/right/bottom side',
224
327
  isDisabled: 'handle interactive?',
225
- hasDivider: 'show full-length 1px divider line through handle. Use when adjacent panels share same background',
226
- isAlwaysVisible: 'show pill grip at rest instead of only on hover. Use when discoverability important',
227
- pillPlacement: 'which side of divider pill sits on. auto = content side (derived from isReversed), flips when collapsed; start = left/top, end = right/bottom, center = centered on divider',
328
+ hasDivider:
329
+ 'show full-length 1px divider line through handle. Use when adjacent panels share same background',
330
+ isAlwaysVisible:
331
+ 'show pill grip at rest instead of only on hover. Use when discoverability important',
332
+ pillPlacement:
333
+ 'which side of divider pill sits on. auto = content side (derived from isReversed), flips when collapsed; start = left/top, end = right/bottom, center = centered on divider',
228
334
  label: 'accessible label for separator',
229
335
  resizable: 'resize props from useResizable: connects handle to panel',
230
336
  },