@dashforge/tw 1.7.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/dist/{src/components → components}/Accordion/accordion.variants.d.ts +3 -3
  3. package/dist/{src/components → components}/AppShell/appShell.types.d.ts +8 -0
  4. package/dist/{src/components → components}/AppShell/appShell.variants.d.ts +39 -2
  5. package/dist/{src/components → components}/Box/box.types.d.ts +19 -1
  6. package/dist/{src/components → components}/Box/box.variants.d.ts +18 -0
  7. package/dist/{src/components → components}/Button/button.types.d.ts +21 -0
  8. package/dist/{src/components → components}/Button/button.variants.d.ts +60 -0
  9. package/dist/{src/components → components}/Calendar/calendar.types.d.ts +52 -2
  10. package/dist/{src/components → components}/Chip/chip.types.d.ts +42 -0
  11. package/dist/{src/components → components}/Chip/chip.variants.d.ts +9 -0
  12. package/dist/{src/components → components}/Grid/grid.types.d.ts +42 -0
  13. package/dist/components/Kbd/Kbd.d.ts +13 -0
  14. package/dist/components/Kbd/kbd.types.d.ts +62 -0
  15. package/dist/components/Kbd/kbd.variants.d.ts +54 -0
  16. package/dist/{src/components → components}/Select/Select.d.ts +1 -1
  17. package/dist/{src/components → components}/Slider/Slider.d.ts +1 -1
  18. package/dist/{src/components → components}/Stack/stack.types.d.ts +42 -0
  19. package/dist/{src/components → components}/Stack/stack.variants.d.ts +8 -0
  20. package/dist/{src/components → components}/TopBar/TopBar.d.ts +16 -1
  21. package/dist/components/TopBar/topBar.types.d.ts +142 -0
  22. package/dist/components/TopBar/topBar.variants.d.ts +136 -0
  23. package/dist/index.d.ts +212 -1
  24. package/dist/index.esm.js +815 -112
  25. package/package.json +10 -8
  26. package/LICENSE +0 -21
  27. package/dist/src/components/Accordion/Accordion.d.ts.map +0 -1
  28. package/dist/src/components/Accordion/accordion.types.d.ts.map +0 -1
  29. package/dist/src/components/Accordion/accordion.variants.d.ts.map +0 -1
  30. package/dist/src/components/Alert/Alert.d.ts.map +0 -1
  31. package/dist/src/components/Alert/alert.types.d.ts.map +0 -1
  32. package/dist/src/components/Alert/alert.variants.d.ts.map +0 -1
  33. package/dist/src/components/AppShell/AppShell.d.ts.map +0 -1
  34. package/dist/src/components/AppShell/appShell.types.d.ts.map +0 -1
  35. package/dist/src/components/AppShell/appShell.variants.d.ts.map +0 -1
  36. package/dist/src/components/AspectRatio/AspectRatio.d.ts.map +0 -1
  37. package/dist/src/components/AspectRatio/aspectRatio.types.d.ts.map +0 -1
  38. package/dist/src/components/Autocomplete/Autocomplete.d.ts.map +0 -1
  39. package/dist/src/components/Autocomplete/autocomplete.props.type-test.d.ts +0 -2
  40. package/dist/src/components/Autocomplete/autocomplete.props.type-test.d.ts.map +0 -1
  41. package/dist/src/components/Autocomplete/autocomplete.types.d.ts.map +0 -1
  42. package/dist/src/components/Autocomplete/autocomplete.variants.d.ts.map +0 -1
  43. package/dist/src/components/Avatar/Avatar.d.ts.map +0 -1
  44. package/dist/src/components/Avatar/avatar.types.d.ts.map +0 -1
  45. package/dist/src/components/Avatar/avatar.variants.d.ts.map +0 -1
  46. package/dist/src/components/Badge/Badge.d.ts.map +0 -1
  47. package/dist/src/components/Badge/badge.types.d.ts.map +0 -1
  48. package/dist/src/components/Badge/badge.variants.d.ts.map +0 -1
  49. package/dist/src/components/Box/Box.d.ts.map +0 -1
  50. package/dist/src/components/Box/box.types.d.ts.map +0 -1
  51. package/dist/src/components/Box/box.variants.d.ts.map +0 -1
  52. package/dist/src/components/Breadcrumbs/Breadcrumbs.d.ts.map +0 -1
  53. package/dist/src/components/Breadcrumbs/breadcrumbs.types.d.ts.map +0 -1
  54. package/dist/src/components/Breadcrumbs/breadcrumbs.variants.d.ts.map +0 -1
  55. package/dist/src/components/Button/Button.d.ts.map +0 -1
  56. package/dist/src/components/Button/button.types.d.ts.map +0 -1
  57. package/dist/src/components/Button/button.variants.d.ts.map +0 -1
  58. package/dist/src/components/Calendar/Calendar.d.ts.map +0 -1
  59. package/dist/src/components/Calendar/calendar.types.d.ts.map +0 -1
  60. package/dist/src/components/Calendar/calendar.variants.d.ts.map +0 -1
  61. package/dist/src/components/Card/Card.d.ts.map +0 -1
  62. package/dist/src/components/Card/card.types.d.ts.map +0 -1
  63. package/dist/src/components/Checkbox/Checkbox.d.ts.map +0 -1
  64. package/dist/src/components/Checkbox/checkbox.types.d.ts.map +0 -1
  65. package/dist/src/components/Checkbox/checkbox.variants.d.ts.map +0 -1
  66. package/dist/src/components/Chip/Chip.d.ts.map +0 -1
  67. package/dist/src/components/Chip/chip.types.d.ts.map +0 -1
  68. package/dist/src/components/Chip/chip.variants.d.ts.map +0 -1
  69. package/dist/src/components/ConfirmDialog/ConfirmDialog.d.ts.map +0 -1
  70. package/dist/src/components/ConfirmDialog/confirmDialog.types.d.ts.map +0 -1
  71. package/dist/src/components/ConfirmDialog/confirmDialog.variants.d.ts.map +0 -1
  72. package/dist/src/components/Container/Container.d.ts.map +0 -1
  73. package/dist/src/components/Container/container.types.d.ts.map +0 -1
  74. package/dist/src/components/Container/container.variants.d.ts.map +0 -1
  75. package/dist/src/components/DataGrid/DataGrid.d.ts.map +0 -1
  76. package/dist/src/components/DataGrid/dataGrid.types.d.ts.map +0 -1
  77. package/dist/src/components/DataGrid/dataGrid.variants.d.ts.map +0 -1
  78. package/dist/src/components/DataGrid/filters/ColumnFilters.d.ts.map +0 -1
  79. package/dist/src/components/DataGrid/reorder/useColumnReorder.d.ts.map +0 -1
  80. package/dist/src/components/DataGrid/resize/useColumnResize.d.ts.map +0 -1
  81. package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts.map +0 -1
  82. package/dist/src/components/DatePicker/DatePicker.d.ts.map +0 -1
  83. package/dist/src/components/DatePicker/datePicker.types.d.ts.map +0 -1
  84. package/dist/src/components/DatePicker/datePicker.variants.d.ts.map +0 -1
  85. package/dist/src/components/DateRangePicker/DateRangePicker.d.ts.map +0 -1
  86. package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts.map +0 -1
  87. package/dist/src/components/DateRangePicker/dateRangePicker.variants.d.ts.map +0 -1
  88. package/dist/src/components/DateTimePicker/DateTimePicker.d.ts.map +0 -1
  89. package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts.map +0 -1
  90. package/dist/src/components/DateTimePicker/dateTimePicker.variants.d.ts.map +0 -1
  91. package/dist/src/components/Dialog/Dialog.d.ts.map +0 -1
  92. package/dist/src/components/Dialog/dialog.types.d.ts.map +0 -1
  93. package/dist/src/components/Dialog/dialog.variants.d.ts.map +0 -1
  94. package/dist/src/components/Divider/Divider.d.ts.map +0 -1
  95. package/dist/src/components/Divider/divider.types.d.ts.map +0 -1
  96. package/dist/src/components/Divider/divider.variants.d.ts.map +0 -1
  97. package/dist/src/components/Drawer/Drawer.d.ts.map +0 -1
  98. package/dist/src/components/Drawer/drawer.types.d.ts.map +0 -1
  99. package/dist/src/components/Drawer/drawer.variants.d.ts.map +0 -1
  100. package/dist/src/components/Grid/Grid.d.ts.map +0 -1
  101. package/dist/src/components/Grid/grid.types.d.ts.map +0 -1
  102. package/dist/src/components/Grid/grid.variants.d.ts.map +0 -1
  103. package/dist/src/components/IconButton/IconButton.d.ts.map +0 -1
  104. package/dist/src/components/IconButton/iconButton.types.d.ts.map +0 -1
  105. package/dist/src/components/IconButton/iconButton.variants.d.ts.map +0 -1
  106. package/dist/src/components/Image/Image.d.ts.map +0 -1
  107. package/dist/src/components/Image/image.types.d.ts.map +0 -1
  108. package/dist/src/components/Image/image.variants.d.ts.map +0 -1
  109. package/dist/src/components/LeftNav/LeftNav.d.ts.map +0 -1
  110. package/dist/src/components/LeftNav/leftNav.types.d.ts.map +0 -1
  111. package/dist/src/components/LeftNav/leftNav.variants.d.ts.map +0 -1
  112. package/dist/src/components/Link/Link.d.ts.map +0 -1
  113. package/dist/src/components/Link/link.types.d.ts.map +0 -1
  114. package/dist/src/components/Link/link.variants.d.ts.map +0 -1
  115. package/dist/src/components/Menu/Menu.d.ts.map +0 -1
  116. package/dist/src/components/Menu/menu.types.d.ts.map +0 -1
  117. package/dist/src/components/Menu/menu.variants.d.ts.map +0 -1
  118. package/dist/src/components/NumberField/NumberField.d.ts.map +0 -1
  119. package/dist/src/components/NumberField/numberField.types.d.ts.map +0 -1
  120. package/dist/src/components/NumberField/numberField.variants.d.ts.map +0 -1
  121. package/dist/src/components/OTPField/OTPField.d.ts.map +0 -1
  122. package/dist/src/components/OTPField/otpField.types.d.ts.map +0 -1
  123. package/dist/src/components/OTPField/otpField.variants.d.ts.map +0 -1
  124. package/dist/src/components/Pagination/Pagination.d.ts.map +0 -1
  125. package/dist/src/components/Pagination/pagination.helpers.d.ts.map +0 -1
  126. package/dist/src/components/Pagination/pagination.types.d.ts.map +0 -1
  127. package/dist/src/components/Pagination/pagination.variants.d.ts.map +0 -1
  128. package/dist/src/components/Popover/Popover.d.ts.map +0 -1
  129. package/dist/src/components/Popover/popover.types.d.ts.map +0 -1
  130. package/dist/src/components/Popover/popover.variants.d.ts.map +0 -1
  131. package/dist/src/components/Progress/Progress.d.ts.map +0 -1
  132. package/dist/src/components/Progress/progress.types.d.ts.map +0 -1
  133. package/dist/src/components/Progress/progress.variants.d.ts.map +0 -1
  134. package/dist/src/components/RadioGroup/RadioGroup.d.ts.map +0 -1
  135. package/dist/src/components/RadioGroup/radioGroup.types.d.ts.map +0 -1
  136. package/dist/src/components/RadioGroup/radioGroup.variants.d.ts.map +0 -1
  137. package/dist/src/components/Select/Select.d.ts.map +0 -1
  138. package/dist/src/components/Select/select.types.d.ts.map +0 -1
  139. package/dist/src/components/Select/select.variants.d.ts.map +0 -1
  140. package/dist/src/components/Skeleton/Skeleton.d.ts.map +0 -1
  141. package/dist/src/components/Skeleton/skeleton.types.d.ts.map +0 -1
  142. package/dist/src/components/Skeleton/skeleton.variants.d.ts.map +0 -1
  143. package/dist/src/components/Slider/Slider.d.ts.map +0 -1
  144. package/dist/src/components/Slider/slider.types.d.ts.map +0 -1
  145. package/dist/src/components/Slider/slider.variants.d.ts.map +0 -1
  146. package/dist/src/components/Snackbar/Snackbar.d.ts.map +0 -1
  147. package/dist/src/components/Snackbar/snackbar.types.d.ts.map +0 -1
  148. package/dist/src/components/Snackbar/snackbar.variants.d.ts.map +0 -1
  149. package/dist/src/components/Spinner/Spinner.d.ts.map +0 -1
  150. package/dist/src/components/Spinner/spinner.types.d.ts.map +0 -1
  151. package/dist/src/components/Spinner/spinner.variants.d.ts.map +0 -1
  152. package/dist/src/components/Stack/Stack.d.ts.map +0 -1
  153. package/dist/src/components/Stack/stack.types.d.ts.map +0 -1
  154. package/dist/src/components/Stack/stack.variants.d.ts.map +0 -1
  155. package/dist/src/components/Stepper/Step.d.ts.map +0 -1
  156. package/dist/src/components/Stepper/Stepper.d.ts.map +0 -1
  157. package/dist/src/components/Stepper/StepperContext.d.ts.map +0 -1
  158. package/dist/src/components/Stepper/stepper.types.d.ts.map +0 -1
  159. package/dist/src/components/Stepper/stepper.variants.d.ts.map +0 -1
  160. package/dist/src/components/Stepper/useStep.d.ts.map +0 -1
  161. package/dist/src/components/Switch/Switch.d.ts.map +0 -1
  162. package/dist/src/components/Switch/switch.types.d.ts.map +0 -1
  163. package/dist/src/components/Switch/switch.variants.d.ts.map +0 -1
  164. package/dist/src/components/Table/Table.d.ts.map +0 -1
  165. package/dist/src/components/Table/cells/RenderButton.d.ts.map +0 -1
  166. package/dist/src/components/Table/cells/RenderChip.d.ts.map +0 -1
  167. package/dist/src/components/Table/cells/RenderText.d.ts.map +0 -1
  168. package/dist/src/components/Table/cells/RenderTwoLine.d.ts.map +0 -1
  169. package/dist/src/components/Table/cells/RowActionsMenu.d.ts.map +0 -1
  170. package/dist/src/components/Table/cells/index.d.ts.map +0 -1
  171. package/dist/src/components/Table/table.types.d.ts.map +0 -1
  172. package/dist/src/components/Table/table.variants.d.ts.map +0 -1
  173. package/dist/src/components/Tabs/Tabs.d.ts.map +0 -1
  174. package/dist/src/components/Tabs/tabs.types.d.ts.map +0 -1
  175. package/dist/src/components/Tabs/tabs.variants.d.ts.map +0 -1
  176. package/dist/src/components/Tabs/useTabs.d.ts.map +0 -1
  177. package/dist/src/components/TextField/TextField.d.ts.map +0 -1
  178. package/dist/src/components/TextField/textField.types.d.ts.map +0 -1
  179. package/dist/src/components/TextField/textField.variants.d.ts.map +0 -1
  180. package/dist/src/components/Textarea/Textarea.d.ts.map +0 -1
  181. package/dist/src/components/Textarea/textarea.types.d.ts.map +0 -1
  182. package/dist/src/components/Textarea/textarea.variants.d.ts.map +0 -1
  183. package/dist/src/components/TimePicker/TimePicker.d.ts.map +0 -1
  184. package/dist/src/components/TimePicker/timePicker.types.d.ts.map +0 -1
  185. package/dist/src/components/TimePicker/timePicker.variants.d.ts.map +0 -1
  186. package/dist/src/components/Tooltip/Tooltip.d.ts.map +0 -1
  187. package/dist/src/components/Tooltip/tooltip.types.d.ts.map +0 -1
  188. package/dist/src/components/Tooltip/tooltip.variants.d.ts.map +0 -1
  189. package/dist/src/components/TopBar/TopBar.d.ts.map +0 -1
  190. package/dist/src/components/TopBar/topBar.types.d.ts +0 -73
  191. package/dist/src/components/TopBar/topBar.types.d.ts.map +0 -1
  192. package/dist/src/components/TopBar/topBar.variants.d.ts +0 -79
  193. package/dist/src/components/TopBar/topBar.variants.d.ts.map +0 -1
  194. package/dist/src/components/Typography/Typography.d.ts.map +0 -1
  195. package/dist/src/components/Typography/typography.types.d.ts.map +0 -1
  196. package/dist/src/components/Typography/typography.variants.d.ts.map +0 -1
  197. package/dist/src/components/Video/Video.d.ts.map +0 -1
  198. package/dist/src/components/Video/video.types.d.ts.map +0 -1
  199. package/dist/src/components/Video/video.variants.d.ts.map +0 -1
  200. package/dist/src/components/VisuallyHidden/VisuallyHidden.d.ts.map +0 -1
  201. package/dist/src/components/VisuallyHidden/visuallyHidden.types.d.ts.map +0 -1
  202. package/dist/src/components/_shared/data/getNestedValue.d.ts.map +0 -1
  203. package/dist/src/components/_shared/data/useColumnAutoDetect.d.ts.map +0 -1
  204. package/dist/src/components/_shared/data/useControllableState.d.ts.map +0 -1
  205. package/dist/src/components/_shared/data/useDebouncedValue.d.ts.map +0 -1
  206. package/dist/src/components/_shared/data/useTableFilter.d.ts.map +0 -1
  207. package/dist/src/components/_shared/data/useTableSearch.d.ts.map +0 -1
  208. package/dist/src/components/_shared/data/useTableSelection.d.ts.map +0 -1
  209. package/dist/src/components/_shared/data/useTableSort.d.ts.map +0 -1
  210. package/dist/src/components/_shared/data/useVirtualizer.d.ts.map +0 -1
  211. package/dist/src/components/_shared/fieldTooltip.d.ts.map +0 -1
  212. package/dist/src/components/_shared/resolveValidationState.d.ts.map +0 -1
  213. package/dist/src/components/_shared/severity/index.d.ts.map +0 -1
  214. package/dist/src/components/_shared/severity/severity.types.d.ts.map +0 -1
  215. package/dist/src/components/_shared/severity/severityIcons.d.ts.map +0 -1
  216. package/dist/src/components/_shared/severity/severityVariants.d.ts.map +0 -1
  217. package/dist/src/hooks/useAccessState.d.ts.map +0 -1
  218. package/dist/src/hooks/useStandaloneFieldWarning.d.ts.map +0 -1
  219. package/dist/src/index.d.ts +0 -199
  220. package/dist/src/index.d.ts.map +0 -1
  221. package/dist/src/utils/cn.d.ts.map +0 -1
  222. /package/dist/{src/components → components}/Accordion/Accordion.d.ts +0 -0
  223. /package/dist/{src/components → components}/Accordion/accordion.types.d.ts +0 -0
  224. /package/dist/{src/components → components}/Alert/Alert.d.ts +0 -0
  225. /package/dist/{src/components → components}/Alert/alert.types.d.ts +0 -0
  226. /package/dist/{src/components → components}/Alert/alert.variants.d.ts +0 -0
  227. /package/dist/{src/components → components}/AppShell/AppShell.d.ts +0 -0
  228. /package/dist/{src/components → components}/AspectRatio/AspectRatio.d.ts +0 -0
  229. /package/dist/{src/components → components}/AspectRatio/aspectRatio.types.d.ts +0 -0
  230. /package/dist/{src/components → components}/Autocomplete/Autocomplete.d.ts +0 -0
  231. /package/dist/{src/components → components}/Autocomplete/autocomplete.types.d.ts +0 -0
  232. /package/dist/{src/components → components}/Autocomplete/autocomplete.variants.d.ts +0 -0
  233. /package/dist/{src/components → components}/Avatar/Avatar.d.ts +0 -0
  234. /package/dist/{src/components → components}/Avatar/avatar.types.d.ts +0 -0
  235. /package/dist/{src/components → components}/Avatar/avatar.variants.d.ts +0 -0
  236. /package/dist/{src/components → components}/Badge/Badge.d.ts +0 -0
  237. /package/dist/{src/components → components}/Badge/badge.types.d.ts +0 -0
  238. /package/dist/{src/components → components}/Badge/badge.variants.d.ts +0 -0
  239. /package/dist/{src/components → components}/Box/Box.d.ts +0 -0
  240. /package/dist/{src/components → components}/Breadcrumbs/Breadcrumbs.d.ts +0 -0
  241. /package/dist/{src/components → components}/Breadcrumbs/breadcrumbs.types.d.ts +0 -0
  242. /package/dist/{src/components → components}/Breadcrumbs/breadcrumbs.variants.d.ts +0 -0
  243. /package/dist/{src/components → components}/Button/Button.d.ts +0 -0
  244. /package/dist/{src/components → components}/Calendar/Calendar.d.ts +0 -0
  245. /package/dist/{src/components → components}/Calendar/calendar.variants.d.ts +0 -0
  246. /package/dist/{src/components → components}/Card/Card.d.ts +0 -0
  247. /package/dist/{src/components → components}/Card/card.types.d.ts +0 -0
  248. /package/dist/{src/components → components}/Checkbox/Checkbox.d.ts +0 -0
  249. /package/dist/{src/components → components}/Checkbox/checkbox.types.d.ts +0 -0
  250. /package/dist/{src/components → components}/Checkbox/checkbox.variants.d.ts +0 -0
  251. /package/dist/{src/components → components}/Chip/Chip.d.ts +0 -0
  252. /package/dist/{src/components → components}/ConfirmDialog/ConfirmDialog.d.ts +0 -0
  253. /package/dist/{src/components → components}/ConfirmDialog/confirmDialog.types.d.ts +0 -0
  254. /package/dist/{src/components → components}/ConfirmDialog/confirmDialog.variants.d.ts +0 -0
  255. /package/dist/{src/components → components}/Container/Container.d.ts +0 -0
  256. /package/dist/{src/components → components}/Container/container.types.d.ts +0 -0
  257. /package/dist/{src/components → components}/Container/container.variants.d.ts +0 -0
  258. /package/dist/{src/components → components}/DataGrid/DataGrid.d.ts +0 -0
  259. /package/dist/{src/components → components}/DataGrid/dataGrid.types.d.ts +0 -0
  260. /package/dist/{src/components → components}/DataGrid/dataGrid.variants.d.ts +0 -0
  261. /package/dist/{src/components → components}/DataGrid/filters/ColumnFilters.d.ts +0 -0
  262. /package/dist/{src/components → components}/DataGrid/reorder/useColumnReorder.d.ts +0 -0
  263. /package/dist/{src/components → components}/DataGrid/resize/useColumnResize.d.ts +0 -0
  264. /package/dist/{src/components → components}/DataGrid/visibility/ColumnVisibilityMenu.d.ts +0 -0
  265. /package/dist/{src/components → components}/DatePicker/DatePicker.d.ts +0 -0
  266. /package/dist/{src/components → components}/DatePicker/datePicker.types.d.ts +0 -0
  267. /package/dist/{src/components → components}/DatePicker/datePicker.variants.d.ts +0 -0
  268. /package/dist/{src/components → components}/DateRangePicker/DateRangePicker.d.ts +0 -0
  269. /package/dist/{src/components → components}/DateRangePicker/dateRangePicker.types.d.ts +0 -0
  270. /package/dist/{src/components → components}/DateRangePicker/dateRangePicker.variants.d.ts +0 -0
  271. /package/dist/{src/components → components}/DateTimePicker/DateTimePicker.d.ts +0 -0
  272. /package/dist/{src/components → components}/DateTimePicker/dateTimePicker.types.d.ts +0 -0
  273. /package/dist/{src/components → components}/DateTimePicker/dateTimePicker.variants.d.ts +0 -0
  274. /package/dist/{src/components → components}/Dialog/Dialog.d.ts +0 -0
  275. /package/dist/{src/components → components}/Dialog/dialog.types.d.ts +0 -0
  276. /package/dist/{src/components → components}/Dialog/dialog.variants.d.ts +0 -0
  277. /package/dist/{src/components → components}/Divider/Divider.d.ts +0 -0
  278. /package/dist/{src/components → components}/Divider/divider.types.d.ts +0 -0
  279. /package/dist/{src/components → components}/Divider/divider.variants.d.ts +0 -0
  280. /package/dist/{src/components → components}/Drawer/Drawer.d.ts +0 -0
  281. /package/dist/{src/components → components}/Drawer/drawer.types.d.ts +0 -0
  282. /package/dist/{src/components → components}/Drawer/drawer.variants.d.ts +0 -0
  283. /package/dist/{src/components → components}/Grid/Grid.d.ts +0 -0
  284. /package/dist/{src/components → components}/Grid/grid.variants.d.ts +0 -0
  285. /package/dist/{src/components → components}/IconButton/IconButton.d.ts +0 -0
  286. /package/dist/{src/components → components}/IconButton/iconButton.types.d.ts +0 -0
  287. /package/dist/{src/components → components}/IconButton/iconButton.variants.d.ts +0 -0
  288. /package/dist/{src/components → components}/Image/Image.d.ts +0 -0
  289. /package/dist/{src/components → components}/Image/image.types.d.ts +0 -0
  290. /package/dist/{src/components → components}/Image/image.variants.d.ts +0 -0
  291. /package/dist/{src/components → components}/LeftNav/LeftNav.d.ts +0 -0
  292. /package/dist/{src/components → components}/LeftNav/leftNav.types.d.ts +0 -0
  293. /package/dist/{src/components → components}/LeftNav/leftNav.variants.d.ts +0 -0
  294. /package/dist/{src/components → components}/Link/Link.d.ts +0 -0
  295. /package/dist/{src/components → components}/Link/link.types.d.ts +0 -0
  296. /package/dist/{src/components → components}/Link/link.variants.d.ts +0 -0
  297. /package/dist/{src/components → components}/Menu/Menu.d.ts +0 -0
  298. /package/dist/{src/components → components}/Menu/menu.types.d.ts +0 -0
  299. /package/dist/{src/components → components}/Menu/menu.variants.d.ts +0 -0
  300. /package/dist/{src/components → components}/NumberField/NumberField.d.ts +0 -0
  301. /package/dist/{src/components → components}/NumberField/numberField.types.d.ts +0 -0
  302. /package/dist/{src/components → components}/NumberField/numberField.variants.d.ts +0 -0
  303. /package/dist/{src/components → components}/OTPField/OTPField.d.ts +0 -0
  304. /package/dist/{src/components → components}/OTPField/otpField.types.d.ts +0 -0
  305. /package/dist/{src/components → components}/OTPField/otpField.variants.d.ts +0 -0
  306. /package/dist/{src/components → components}/Pagination/Pagination.d.ts +0 -0
  307. /package/dist/{src/components → components}/Pagination/pagination.helpers.d.ts +0 -0
  308. /package/dist/{src/components → components}/Pagination/pagination.types.d.ts +0 -0
  309. /package/dist/{src/components → components}/Pagination/pagination.variants.d.ts +0 -0
  310. /package/dist/{src/components → components}/Popover/Popover.d.ts +0 -0
  311. /package/dist/{src/components → components}/Popover/popover.types.d.ts +0 -0
  312. /package/dist/{src/components → components}/Popover/popover.variants.d.ts +0 -0
  313. /package/dist/{src/components → components}/Progress/Progress.d.ts +0 -0
  314. /package/dist/{src/components → components}/Progress/progress.types.d.ts +0 -0
  315. /package/dist/{src/components → components}/Progress/progress.variants.d.ts +0 -0
  316. /package/dist/{src/components → components}/RadioGroup/RadioGroup.d.ts +0 -0
  317. /package/dist/{src/components → components}/RadioGroup/radioGroup.types.d.ts +0 -0
  318. /package/dist/{src/components → components}/RadioGroup/radioGroup.variants.d.ts +0 -0
  319. /package/dist/{src/components → components}/Select/select.types.d.ts +0 -0
  320. /package/dist/{src/components → components}/Select/select.variants.d.ts +0 -0
  321. /package/dist/{src/components → components}/Skeleton/Skeleton.d.ts +0 -0
  322. /package/dist/{src/components → components}/Skeleton/skeleton.types.d.ts +0 -0
  323. /package/dist/{src/components → components}/Skeleton/skeleton.variants.d.ts +0 -0
  324. /package/dist/{src/components → components}/Slider/slider.types.d.ts +0 -0
  325. /package/dist/{src/components → components}/Slider/slider.variants.d.ts +0 -0
  326. /package/dist/{src/components → components}/Snackbar/Snackbar.d.ts +0 -0
  327. /package/dist/{src/components → components}/Snackbar/snackbar.types.d.ts +0 -0
  328. /package/dist/{src/components → components}/Snackbar/snackbar.variants.d.ts +0 -0
  329. /package/dist/{src/components → components}/Spinner/Spinner.d.ts +0 -0
  330. /package/dist/{src/components → components}/Spinner/spinner.types.d.ts +0 -0
  331. /package/dist/{src/components → components}/Spinner/spinner.variants.d.ts +0 -0
  332. /package/dist/{src/components → components}/Stack/Stack.d.ts +0 -0
  333. /package/dist/{src/components → components}/Stepper/Step.d.ts +0 -0
  334. /package/dist/{src/components → components}/Stepper/Stepper.d.ts +0 -0
  335. /package/dist/{src/components → components}/Stepper/StepperContext.d.ts +0 -0
  336. /package/dist/{src/components → components}/Stepper/stepper.types.d.ts +0 -0
  337. /package/dist/{src/components → components}/Stepper/stepper.variants.d.ts +0 -0
  338. /package/dist/{src/components → components}/Stepper/useStep.d.ts +0 -0
  339. /package/dist/{src/components → components}/Switch/Switch.d.ts +0 -0
  340. /package/dist/{src/components → components}/Switch/switch.types.d.ts +0 -0
  341. /package/dist/{src/components → components}/Switch/switch.variants.d.ts +0 -0
  342. /package/dist/{src/components → components}/Table/Table.d.ts +0 -0
  343. /package/dist/{src/components → components}/Table/cells/RenderButton.d.ts +0 -0
  344. /package/dist/{src/components → components}/Table/cells/RenderChip.d.ts +0 -0
  345. /package/dist/{src/components → components}/Table/cells/RenderText.d.ts +0 -0
  346. /package/dist/{src/components → components}/Table/cells/RenderTwoLine.d.ts +0 -0
  347. /package/dist/{src/components → components}/Table/cells/RowActionsMenu.d.ts +0 -0
  348. /package/dist/{src/components → components}/Table/cells/index.d.ts +0 -0
  349. /package/dist/{src/components → components}/Table/table.types.d.ts +0 -0
  350. /package/dist/{src/components → components}/Table/table.variants.d.ts +0 -0
  351. /package/dist/{src/components → components}/Tabs/Tabs.d.ts +0 -0
  352. /package/dist/{src/components → components}/Tabs/tabs.types.d.ts +0 -0
  353. /package/dist/{src/components → components}/Tabs/tabs.variants.d.ts +0 -0
  354. /package/dist/{src/components → components}/Tabs/useTabs.d.ts +0 -0
  355. /package/dist/{src/components → components}/TextField/TextField.d.ts +0 -0
  356. /package/dist/{src/components → components}/TextField/textField.types.d.ts +0 -0
  357. /package/dist/{src/components → components}/TextField/textField.variants.d.ts +0 -0
  358. /package/dist/{src/components → components}/Textarea/Textarea.d.ts +0 -0
  359. /package/dist/{src/components → components}/Textarea/textarea.types.d.ts +0 -0
  360. /package/dist/{src/components → components}/Textarea/textarea.variants.d.ts +0 -0
  361. /package/dist/{src/components → components}/TimePicker/TimePicker.d.ts +0 -0
  362. /package/dist/{src/components → components}/TimePicker/timePicker.types.d.ts +0 -0
  363. /package/dist/{src/components → components}/TimePicker/timePicker.variants.d.ts +0 -0
  364. /package/dist/{src/components → components}/Tooltip/Tooltip.d.ts +0 -0
  365. /package/dist/{src/components → components}/Tooltip/tooltip.types.d.ts +0 -0
  366. /package/dist/{src/components → components}/Tooltip/tooltip.variants.d.ts +0 -0
  367. /package/dist/{src/components → components}/Typography/Typography.d.ts +0 -0
  368. /package/dist/{src/components → components}/Typography/typography.types.d.ts +0 -0
  369. /package/dist/{src/components → components}/Typography/typography.variants.d.ts +0 -0
  370. /package/dist/{src/components → components}/Video/Video.d.ts +0 -0
  371. /package/dist/{src/components → components}/Video/video.types.d.ts +0 -0
  372. /package/dist/{src/components → components}/Video/video.variants.d.ts +0 -0
  373. /package/dist/{src/components → components}/VisuallyHidden/VisuallyHidden.d.ts +0 -0
  374. /package/dist/{src/components → components}/VisuallyHidden/visuallyHidden.types.d.ts +0 -0
  375. /package/dist/{src/components → components}/_shared/data/getNestedValue.d.ts +0 -0
  376. /package/dist/{src/components → components}/_shared/data/useColumnAutoDetect.d.ts +0 -0
  377. /package/dist/{src/components → components}/_shared/data/useControllableState.d.ts +0 -0
  378. /package/dist/{src/components → components}/_shared/data/useDebouncedValue.d.ts +0 -0
  379. /package/dist/{src/components → components}/_shared/data/useTableFilter.d.ts +0 -0
  380. /package/dist/{src/components → components}/_shared/data/useTableSearch.d.ts +0 -0
  381. /package/dist/{src/components → components}/_shared/data/useTableSelection.d.ts +0 -0
  382. /package/dist/{src/components → components}/_shared/data/useTableSort.d.ts +0 -0
  383. /package/dist/{src/components → components}/_shared/data/useVirtualizer.d.ts +0 -0
  384. /package/dist/{src/components → components}/_shared/fieldTooltip.d.ts +0 -0
  385. /package/dist/{src/components → components}/_shared/resolveValidationState.d.ts +0 -0
  386. /package/dist/{src/components → components}/_shared/severity/index.d.ts +0 -0
  387. /package/dist/{src/components → components}/_shared/severity/severity.types.d.ts +0 -0
  388. /package/dist/{src/components → components}/_shared/severity/severityIcons.d.ts +0 -0
  389. /package/dist/{src/components → components}/_shared/severity/severityVariants.d.ts +0 -0
  390. /package/dist/{src/hooks → hooks}/useAccessState.d.ts +0 -0
  391. /package/dist/{src/hooks → hooks}/useStandaloneFieldWarning.d.ts +0 -0
  392. /package/dist/{src/utils → utils}/cn.d.ts +0 -0
package/dist/index.esm.js CHANGED
@@ -373,7 +373,13 @@ Spinner.displayName = 'Spinner';
373
373
  secondary: '',
374
374
  success: '',
375
375
  warning: '',
376
- danger: ''
376
+ danger: '',
377
+ /**
378
+ * For a surface that is dark regardless of the theme: a dark hero,
379
+ * an ink footer, an inverted panel. Reads the theme-invariant
380
+ * `inverse` token role, so it does NOT flip with light/dark the way
381
+ * a `neutral`-based treatment would. See kensaadi/dashforge#140.
382
+ */ inverse: ''
377
383
  },
378
384
  size: {
379
385
  sm: 'h-8 px-3 text-sm',
@@ -385,6 +391,18 @@ Spinner.displayName = 'Spinner';
385
391
  },
386
392
  loading: {
387
393
  true: 'cursor-wait'
394
+ },
395
+ /**
396
+ * Toggle state. Styling lives in `compoundVariants` because "on" reads
397
+ * differently on a filled button than on a quiet one: the quiet
398
+ * variants gain a surface, `solid` deepens the one it already has.
399
+ *
400
+ * The treatment is not invented. It is LeftNav's `itemActive`
401
+ * (`bg-*-100 text-*-900 font-medium`), the catalog's existing way of
402
+ * saying "this is the current thing". kensaadi/dashforge#63 gap C.
403
+ */ pressed: {
404
+ true: '',
405
+ false: ''
388
406
  }
389
407
  },
390
408
  compoundVariants: [
@@ -491,6 +509,136 @@ Spinner.displayName = 'Spinner';
491
509
  variant: 'link',
492
510
  color: 'danger',
493
511
  class: 'text-danger-700 hover:text-danger-800'
512
+ },
513
+ // ───── × inverse ─────
514
+ //
515
+ // `focus-visible:ring-offset-transparent` on every row is load-bearing.
516
+ // The base sets `focus-visible:ring-offset-2`, and neither the preset
517
+ // nor the base declares a ring-offset COLOUR, so it falls through to
518
+ // Tailwind v4's default of `#fff`. On a dark surface that paints a
519
+ // white halo around the button the moment it takes keyboard focus.
520
+ {
521
+ variant: 'solid',
522
+ color: 'inverse',
523
+ class: 'bg-inverse-50 text-inverse-900 hover:bg-inverse-200 active:bg-inverse-300 ' + 'focus-visible:ring-inverse-50 focus-visible:ring-offset-transparent'
524
+ },
525
+ {
526
+ variant: 'outline',
527
+ color: 'inverse',
528
+ class: 'border-inverse-50/40 text-inverse-50 hover:bg-inverse-50/10 ' + 'focus-visible:ring-inverse-50 focus-visible:ring-offset-transparent'
529
+ },
530
+ {
531
+ variant: 'ghost',
532
+ color: 'inverse',
533
+ class: 'text-inverse-50 hover:bg-inverse-50/10 ' + 'focus-visible:ring-inverse-50 focus-visible:ring-offset-transparent'
534
+ },
535
+ {
536
+ variant: 'link',
537
+ color: 'inverse',
538
+ class: 'text-inverse-50 hover:text-inverse-200'
539
+ },
540
+ // ───── pressed × color, on the quiet variants ─────
541
+ //
542
+ // `outline` and `ghost` have no surface of their own, so an "on" toggle
543
+ // gains one. Shape borrowed from LeftNav's `itemActive` rather than
544
+ // invented, so a pressed Button and an active nav row read the same.
545
+ {
546
+ variant: [
547
+ 'outline',
548
+ 'ghost'
549
+ ],
550
+ pressed: true,
551
+ color: 'primary',
552
+ class: 'bg-primary-100 text-primary-900 font-medium hover:bg-primary-200'
553
+ },
554
+ {
555
+ variant: [
556
+ 'outline',
557
+ 'ghost'
558
+ ],
559
+ pressed: true,
560
+ color: 'secondary',
561
+ class: 'bg-secondary-100 text-secondary-900 font-medium hover:bg-secondary-200'
562
+ },
563
+ {
564
+ variant: [
565
+ 'outline',
566
+ 'ghost'
567
+ ],
568
+ pressed: true,
569
+ color: 'success',
570
+ class: 'bg-success-100 text-success-900 font-medium hover:bg-success-200'
571
+ },
572
+ {
573
+ variant: [
574
+ 'outline',
575
+ 'ghost'
576
+ ],
577
+ pressed: true,
578
+ color: 'warning',
579
+ class: 'bg-warning-100 text-warning-900 font-medium hover:bg-warning-200'
580
+ },
581
+ {
582
+ variant: [
583
+ 'outline',
584
+ 'ghost'
585
+ ],
586
+ pressed: true,
587
+ color: 'danger',
588
+ class: 'bg-danger-100 text-danger-900 font-medium hover:bg-danger-200'
589
+ },
590
+ {
591
+ // `inverse` keeps its own idiom: a wash over the dark surface rather
592
+ // than a tint from a scale that does not follow the theme. The hover
593
+ // rows above use `/10`, so "on" sits one step up at `/20`.
594
+ variant: [
595
+ 'outline',
596
+ 'ghost'
597
+ ],
598
+ pressed: true,
599
+ color: 'inverse',
600
+ class: 'bg-inverse-50/20 text-inverse-50 font-medium hover:bg-inverse-50/25 ' + 'focus-visible:ring-offset-transparent'
601
+ },
602
+ // ───── pressed × color, on solid ─────
603
+ //
604
+ // Already filled, so "on" deepens instead of tinting: it reuses each
605
+ // row's own `active:` tier, the shade that already means "being pressed
606
+ // right now".
607
+ {
608
+ variant: 'solid',
609
+ pressed: true,
610
+ color: 'primary',
611
+ class: 'bg-primary-700 hover:bg-primary-800'
612
+ },
613
+ {
614
+ variant: 'solid',
615
+ pressed: true,
616
+ color: 'secondary',
617
+ class: 'bg-secondary-700 hover:bg-secondary-800'
618
+ },
619
+ {
620
+ variant: 'solid',
621
+ pressed: true,
622
+ color: 'success',
623
+ class: 'bg-success-700 hover:bg-success-800'
624
+ },
625
+ {
626
+ variant: 'solid',
627
+ pressed: true,
628
+ color: 'warning',
629
+ class: 'bg-warning-700 hover:bg-warning-800'
630
+ },
631
+ {
632
+ variant: 'solid',
633
+ pressed: true,
634
+ color: 'danger',
635
+ class: 'bg-danger-700 hover:bg-danger-800'
636
+ },
637
+ {
638
+ variant: 'solid',
639
+ pressed: true,
640
+ color: 'inverse',
641
+ class: 'bg-inverse-300 hover:bg-inverse-400'
494
642
  }
495
643
  ],
496
644
  defaultVariants: {
@@ -563,7 +711,7 @@ Spinner.displayName = 'Spinner';
563
711
  // omit a field, TV picks its `defaultVariants` value (step 1).
564
712
  const themeDefaults = useComponentDefaults('Button');
565
713
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
566
- const { access, visibleWhen, disabled, variant, color, size, fullWidth, loading, asChild, sx, children } = merged, rest = _object_without_properties_loose(merged, [
714
+ const { access, visibleWhen, disabled, variant, color, size, fullWidth, loading, pressed, asChild, sx, children } = merged, rest = _object_without_properties_loose(merged, [
567
715
  "access",
568
716
  "visibleWhen",
569
717
  "disabled",
@@ -572,6 +720,7 @@ Spinner.displayName = 'Spinner';
572
720
  "size",
573
721
  "fullWidth",
574
722
  "loading",
723
+ "pressed",
575
724
  "asChild",
576
725
  "sx",
577
726
  "children"
@@ -596,7 +745,8 @@ Spinner.displayName = 'Spinner';
596
745
  color,
597
746
  size,
598
747
  fullWidth,
599
- loading
748
+ loading,
749
+ pressed
600
750
  }), sx);
601
751
  /*
602
752
  * `aria-busy` announces the loading state to assistive tech.
@@ -614,6 +764,7 @@ Spinner.displayName = 'Spinner';
614
764
  "data-disabled": effectiveDisabled || undefined,
615
765
  "aria-disabled": effectiveDisabled || undefined,
616
766
  "aria-busy": ariaBusy,
767
+ "aria-pressed": pressed,
617
768
  children: children
618
769
  });
619
770
  }
@@ -622,6 +773,7 @@ Spinner.displayName = 'Spinner';
622
773
  type: (_rest_type = rest.type) != null ? _rest_type : 'button',
623
774
  disabled: effectiveDisabled,
624
775
  "aria-busy": ariaBusy,
776
+ "aria-pressed": pressed,
625
777
  className: classes
626
778
  }, rest, {
627
779
  children: [
@@ -859,7 +1011,6 @@ const tooltipVariants = tv({
859
1011
  if (onChange !== undefined) return;
860
1012
  hasWarnedRef.current = true;
861
1013
  const nameSegment = typeof name === 'string' && name.length > 0 ? ` name="${name}"` : '';
862
- // eslint-disable-next-line no-console -- dev-only guard, guarded by NODE_ENV above.
863
1014
  console.warn(`[@dashforge/tw] <${componentName}${nameSegment}> is not inside a ` + `DashFormProvider and no value/onChange were provided. Did you ` + `forget the provider, or intend controlled mode? The widget will ` + `render but never emit changes upward. See the "Controlled vs ` + `bridge mode" docs.`);
864
1015
  // The check runs once on mount; the ref guards re-runs even if React
865
1016
  // Strict Mode double-invokes the effect in development.
@@ -1260,11 +1411,25 @@ const tooltipVariants = tv({
1260
1411
  * - `error` : bool — swaps borders + helper-text color to danger tones
1261
1412
  */ const checkboxVariants = tv({
1262
1413
  slots: {
1263
- root: 'inline-flex items-start gap-2',
1414
+ /*
1415
+ * `relative` is load-bearing, not cosmetic. Radix renders a hidden
1416
+ * native input for form participation with inline
1417
+ * `position: absolute; opacity: 0; transform: translateX(-100%)`.
1418
+ * Without a positioned ancestor it anchors to the BODY, so it escapes
1419
+ * any `overflow: hidden` ancestor and extends the document's
1420
+ * scrollable area down to wherever the field happens to sit.
1421
+ *
1422
+ * Measured on `learn/dash` with a checkbox ~1870px down the page:
1423
+ * `document.documentElement.scrollHeight` 1891 against a 768px
1424
+ * viewport, and the window scrolled 800px inside an AppShell that had
1425
+ * just been given `h-dvh overflow-hidden`. Adding this one declaration
1426
+ * dropped scrollHeight to 768 and the window scroll to 0.
1427
+ * See README-BUG § BUG 36.
1428
+ */ root: 'relative inline-flex items-start gap-2',
1264
1429
  control: [
1265
1430
  'inline-flex items-center justify-center shrink-0',
1266
1431
  // bg-neutral-50 inverts — dark-mode aware via the dashforge preset.
1267
- 'rounded border bg-neutral-50',
1432
+ 'rounded-sm border bg-neutral-50',
1268
1433
  'border-neutral-300',
1269
1434
  'transition-colors',
1270
1435
  // Radix.Checkbox.Root renders a `<button>`, whose UA cursor is
@@ -1613,7 +1778,21 @@ const tooltipVariants = tv({
1613
1778
  * - `helperText` / `errorText` — informational lines below
1614
1779
  */ const switchVariants = tv({
1615
1780
  slots: {
1616
- root: 'inline-flex items-start gap-3',
1781
+ /*
1782
+ * `relative` is load-bearing, not cosmetic. Radix renders a hidden
1783
+ * native input for form participation with inline
1784
+ * `position: absolute; opacity: 0; transform: translateX(-100%)`.
1785
+ * Without a positioned ancestor it anchors to the BODY, so it escapes
1786
+ * any `overflow: hidden` ancestor and extends the document's
1787
+ * scrollable area down to wherever the field happens to sit.
1788
+ *
1789
+ * Measured on `learn/dash` with a checkbox ~1870px down the page:
1790
+ * `document.documentElement.scrollHeight` 1891 against a 768px
1791
+ * viewport, and the window scrolled 800px inside an AppShell that had
1792
+ * just been given `h-dvh overflow-hidden`. Adding this one declaration
1793
+ * dropped scrollHeight to 768 and the window scroll to 0.
1794
+ * See README-BUG § BUG 36.
1795
+ */ root: 'relative inline-flex items-start gap-3',
1617
1796
  control: [
1618
1797
  'relative inline-flex shrink-0 cursor-pointer items-center',
1619
1798
  'rounded-full border-2 border-transparent',
@@ -1882,7 +2061,21 @@ const tooltipVariants = tv({
1882
2061
  * - `error` : bool — swaps borders + helperText color to danger tones
1883
2062
  */ const radioGroupVariants = tv({
1884
2063
  slots: {
1885
- root: 'flex flex-col gap-1.5',
2064
+ /*
2065
+ * `relative` is load-bearing, not cosmetic. Radix renders a hidden
2066
+ * native input for form participation with inline
2067
+ * `position: absolute; opacity: 0; transform: translateX(-100%)`.
2068
+ * Without a positioned ancestor it anchors to the BODY, so it escapes
2069
+ * any `overflow: hidden` ancestor and extends the document's
2070
+ * scrollable area down to wherever the field happens to sit.
2071
+ *
2072
+ * Measured on `learn/dash` with a checkbox ~1870px down the page:
2073
+ * `document.documentElement.scrollHeight` 1891 against a 768px
2074
+ * viewport, and the window scrolled 800px inside an AppShell that had
2075
+ * just been given `h-dvh overflow-hidden`. Adding this one declaration
2076
+ * dropped scrollHeight to 768 and the window scroll to 0.
2077
+ * See README-BUG § BUG 36.
2078
+ */ root: 'relative flex flex-col gap-1.5',
1886
2079
  label: 'block text-sm font-medium text-neutral-900',
1887
2080
  requiredMark: 'text-danger-500 ml-0.5',
1888
2081
  optionList: 'flex gap-3',
@@ -4294,7 +4487,7 @@ function Autocomplete(props) {
4294
4487
  slots: {
4295
4488
  root: 'inline-flex w-fit flex-col gap-2 rounded-lg border border-neutral-200 bg-neutral-50 p-3 select-none',
4296
4489
  header: 'flex items-center justify-between gap-1',
4297
- navButton: 'inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-[1rem] text-neutral-600 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:pointer-events-none disabled:opacity-40',
4490
+ navButton: 'inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-base text-neutral-600 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 disabled:pointer-events-none disabled:opacity-40',
4298
4491
  monthLabel: 'flex-1 text-center text-sm font-semibold text-neutral-900',
4299
4492
  grid: 'flex flex-col gap-1 focus:outline-none',
4300
4493
  weekdayRow: 'grid grid-cols-7 gap-1',
@@ -4319,7 +4512,26 @@ function Autocomplete(props) {
4319
4512
  base: 'flex h-9 w-9 items-center justify-center rounded-md text-sm text-neutral-900 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500',
4320
4513
  variants: {
4321
4514
  siblingMonth: {
4322
- true: 'text-neutral-400'
4515
+ /*
4516
+ * `neutral-600`, not `neutral-400`, and not `neutral-500` either.
4517
+ *
4518
+ * A sibling-month cell is ACTIVE: it is selectable, so its label is
4519
+ * subject to WCAG 1.4.3, and at 14px / weight 400 the threshold is
4520
+ * 4.5:1. Measured on the running app, `neutral-400` gave **2.42:1**
4521
+ * in light and **2.53:1** in dark. Both fail. (The disabled cells sit
4522
+ * at 1.23:1 and are fine: WCAG exempts the text of inactive
4523
+ * components.)
4524
+ *
4525
+ * `neutral-500` is the pivot of the scale — it stays rgb(115,115,115)
4526
+ * in both themes — so it clears light at 4.54:1 but **fails dark at
4527
+ * 4.18:1**. `neutral-600` is the first tier that passes both:
4528
+ * 7.49:1 light, 7.85:1 dark, while still reading clearly muted
4529
+ * against the current month's 17:1.
4530
+ *
4531
+ * See README-BUG § BUG 31. Do not soften this without re-measuring
4532
+ * BOTH themes: the neutral scale inverts, so one number proves
4533
+ * nothing.
4534
+ */ true: 'text-neutral-600'
4323
4535
  },
4324
4536
  today: {
4325
4537
  true: 'font-bold ring-1 ring-inset ring-primary-400'
@@ -4395,7 +4607,7 @@ function ChevronRightIcon$2() {
4395
4607
  const themeDefaults = useComponentDefaults('Calendar');
4396
4608
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
4397
4609
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
4398
- const { value, defaultValue, onChange, month, year, defaultMonth, defaultYear, onMonthChange, minDate, maxDate, disabledDates, isDateDisabled, weekStartDay, locale, today, disabled = false, autoFocus = false, sx, slotProps, testId, 'aria-label': ariaLabel = 'Calendar' } = merged;
4610
+ const { value, defaultValue, onChange, month, year, defaultMonth, defaultYear, onMonthChange, minDate, maxDate, disabledDates, isDateDisabled, weekStartDay, locale, today, disabled = false, showSiblingDays = true, autoFocus = false, sx, slotProps, testId, 'aria-label': ariaLabel = 'Calendar' } = merged;
4399
4611
  const isValueControlled = value !== undefined;
4400
4612
  const [internalValue, setInternalValue] = useState(defaultValue != null ? defaultValue : null);
4401
4613
  const selectedValue = isValueControlled ? value : internalValue;
@@ -4468,6 +4680,14 @@ function ChevronRightIcon$2() {
4468
4680
  calendar
4469
4681
  ]);
4470
4682
  const resolvedLocale = locale != null ? locale : 'en-US';
4683
+ /**
4684
+ * `slotProps.day` may be a flat object or a function of the cell state.
4685
+ * Resolving it here keeps the call site in the grid readable and means
4686
+ * the theme-level and instance-level slots go through the same path.
4687
+ */ const resolveDaySlot = (slot, state)=>{
4688
+ var _this;
4689
+ return (_this = typeof slot === 'function' ? slot(state) : slot) == null ? void 0 : _this.className;
4690
+ };
4471
4691
  const v = calendarVariants({
4472
4692
  disabled
4473
4693
  });
@@ -4524,8 +4744,26 @@ function ChevronRightIcon$2() {
4524
4744
  role: "row",
4525
4745
  className: v.weekRow(),
4526
4746
  children: week.days.map((day)=>{
4527
- var _themeSlotProps_day, _slotProps_day;
4528
4747
  const isActiveCell = day.iso === calendar.focusedDate;
4748
+ // `showSiblingDays={false}` keeps the 7-column geometry with
4749
+ // an empty cell rather than dropping the element, so the grid
4750
+ // does not reflow and the row stays a row.
4751
+ if (day.isSiblingMonth && !showSiblingDays) {
4752
+ return jsx("span", {
4753
+ role: "gridcell",
4754
+ "aria-hidden": "true",
4755
+ className: "flex",
4756
+ children: jsx("span", {
4757
+ className: "h-9 w-9"
4758
+ })
4759
+ }, day.iso);
4760
+ }
4761
+ const dayState = {
4762
+ siblingMonth: day.isSiblingMonth,
4763
+ today: day.isToday,
4764
+ selected: day.isSelected,
4765
+ disabled: day.isDisabled
4766
+ };
4529
4767
  return jsx("span", {
4530
4768
  role: "gridcell",
4531
4769
  className: "flex",
@@ -4545,12 +4783,7 @@ function ChevronRightIcon$2() {
4545
4783
  onClick: ()=>{
4546
4784
  calendar.selectDate(day.iso);
4547
4785
  },
4548
- className: cn(calendarDayVariants({
4549
- siblingMonth: day.isSiblingMonth,
4550
- today: day.isToday,
4551
- selected: day.isSelected,
4552
- disabled: day.isDisabled
4553
- }), themeSlotProps == null ? void 0 : (_themeSlotProps_day = themeSlotProps.day) == null ? void 0 : _themeSlotProps_day.className, slotProps == null ? void 0 : (_slotProps_day = slotProps.day) == null ? void 0 : _slotProps_day.className),
4786
+ className: cn(calendarDayVariants(dayState), resolveDaySlot(themeSlotProps == null ? void 0 : themeSlotProps.day, dayState), resolveDaySlot(slotProps == null ? void 0 : slotProps.day, dayState)),
4554
4787
  children: day.day
4555
4788
  })
4556
4789
  }, day.iso);
@@ -4646,7 +4879,7 @@ const popoverVariants = tv({
4646
4879
  trigger: 'flex items-center gap-2 h-10 min-w-[12rem] rounded-md border border-neutral-300 bg-neutral-50 px-3 text-base text-neutral-900 cursor-pointer transition-colors hover:border-neutral-400 focus-visible:outline-none focus-visible:border-primary-500 focus-visible:ring-2 focus-visible:ring-primary-500/30 disabled:cursor-not-allowed disabled:opacity-60 disabled:bg-neutral-200',
4647
4880
  value: 'flex-1 truncate text-left',
4648
4881
  placeholder: 'flex-1 truncate text-left text-neutral-400',
4649
- icon: 'shrink-0 text-[1rem] text-neutral-500',
4882
+ icon: 'shrink-0 text-base text-neutral-500',
4650
4883
  helperText: 'mt-1 text-sm text-neutral-600',
4651
4884
  errorText: 'mt-1 text-sm text-danger-600'
4652
4885
  },
@@ -4953,9 +5186,9 @@ function CalendarIcon$2() {
4953
5186
  trigger: 'flex items-center gap-2 h-10 min-w-[10rem] rounded-md border border-neutral-300 bg-neutral-50 px-3 text-base text-neutral-900 cursor-pointer transition-colors hover:border-neutral-400 focus-visible:outline-none focus-visible:border-primary-500 focus-visible:ring-2 focus-visible:ring-primary-500/30 disabled:cursor-not-allowed disabled:opacity-60 disabled:bg-neutral-200',
4954
5187
  value: 'flex-1 truncate text-left',
4955
5188
  placeholder: 'flex-1 truncate text-left text-neutral-400',
4956
- icon: 'shrink-0 text-[1rem] text-neutral-500',
5189
+ icon: 'shrink-0 text-base text-neutral-500',
4957
5190
  list: 'flex max-h-64 min-w-[8rem] flex-col gap-0.5 overflow-y-auto p-1',
4958
- option: 'flex w-full cursor-pointer items-center rounded px-2.5 py-1.5 text-sm text-neutral-900 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500 aria-selected:bg-primary-600 aria-selected:text-white aria-selected:hover:bg-primary-600 aria-disabled:cursor-default aria-disabled:text-neutral-300 aria-disabled:opacity-60 aria-disabled:hover:bg-transparent',
5191
+ option: 'flex w-full cursor-pointer items-center rounded-md px-2.5 py-1.5 text-sm text-neutral-900 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500 aria-selected:bg-primary-600 aria-selected:text-white aria-selected:hover:bg-primary-600 aria-disabled:cursor-default aria-disabled:text-neutral-300 aria-disabled:opacity-60 aria-disabled:hover:bg-transparent',
4959
5192
  helperText: 'mt-1 text-sm text-neutral-600',
4960
5193
  errorText: 'mt-1 text-sm text-danger-600'
4961
5194
  },
@@ -5249,10 +5482,10 @@ function ClockIcon() {
5249
5482
  trigger: 'flex items-center gap-2 h-10 min-w-[13rem] rounded-md border border-neutral-300 bg-neutral-50 px-3 text-base text-neutral-900 cursor-pointer transition-colors hover:border-neutral-400 focus-visible:outline-none focus-visible:border-primary-500 focus-visible:ring-2 focus-visible:ring-primary-500/30 disabled:cursor-not-allowed disabled:opacity-60 disabled:bg-neutral-200',
5250
5483
  value: 'flex-1 truncate text-left',
5251
5484
  placeholder: 'flex-1 truncate text-left text-neutral-400',
5252
- icon: 'shrink-0 text-[1rem] text-neutral-500',
5485
+ icon: 'shrink-0 text-base text-neutral-500',
5253
5486
  panel: 'flex items-stretch',
5254
5487
  list: 'flex max-h-[19rem] min-w-[6.5rem] flex-col gap-0.5 overflow-y-auto border-l border-neutral-200 p-1',
5255
- option: 'flex w-full cursor-pointer items-center rounded px-2.5 py-1.5 text-sm text-neutral-900 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500 aria-selected:bg-primary-600 aria-selected:text-white aria-selected:hover:bg-primary-600',
5488
+ option: 'flex w-full cursor-pointer items-center rounded-md px-2.5 py-1.5 text-sm text-neutral-900 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500 aria-selected:bg-primary-600 aria-selected:text-white aria-selected:hover:bg-primary-600',
5256
5489
  helperText: 'mt-1 text-sm text-neutral-600',
5257
5490
  errorText: 'mt-1 text-sm text-danger-600'
5258
5491
  },
@@ -5599,11 +5832,11 @@ const DATETIME_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})/;
5599
5832
  trigger: 'flex items-center gap-2 h-10 min-w-[15rem] rounded-md border border-neutral-300 bg-neutral-50 px-3 text-base text-neutral-900 cursor-pointer transition-colors hover:border-neutral-400 focus-visible:outline-none focus-visible:border-primary-500 focus-visible:ring-2 focus-visible:ring-primary-500/30 disabled:cursor-not-allowed disabled:opacity-60 disabled:bg-neutral-200',
5600
5833
  value: 'flex-1 truncate text-left',
5601
5834
  placeholder: 'flex-1 truncate text-left text-neutral-400',
5602
- icon: 'shrink-0 text-[1rem] text-neutral-500',
5835
+ icon: 'shrink-0 text-base text-neutral-500',
5603
5836
  panel: 'flex gap-3 p-3 select-none',
5604
5837
  month: 'flex flex-col gap-2',
5605
5838
  header: 'flex items-center justify-between gap-1',
5606
- navButton: 'inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-[1rem] text-neutral-600 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
5839
+ navButton: 'inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-base text-neutral-600 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
5607
5840
  navSpacer: 'h-7 w-7 shrink-0',
5608
5841
  monthLabel: 'flex-1 text-center text-sm font-semibold text-neutral-900',
5609
5842
  grid: 'flex flex-col gap-1',
@@ -6382,7 +6615,7 @@ function formatRange(range, locale) {
6382
6615
  itemLabel: 'truncate flex-1 min-w-0 text-left',
6383
6616
  itemBadge: [
6384
6617
  'shrink-0 inline-flex items-center justify-center',
6385
- 'px-1.5 h-5 rounded-full text-[10px] font-medium',
6618
+ 'px-1.5 h-5 rounded-full text-2xs font-medium',
6386
6619
  'bg-neutral-200 text-neutral-800'
6387
6620
  ],
6388
6621
  group: 'flex flex-col gap-0.5',
@@ -6684,7 +6917,16 @@ function formatRange(range, locale) {
6684
6917
  'flex items-center gap-3 w-full px-4 shrink-0',
6685
6918
  'bg-neutral-50 border-b border-neutral-200'
6686
6919
  ],
6687
- start: 'flex items-center gap-2 min-w-0 shrink-0',
6920
+ /*
6921
+ * `shrink-0` removed (README-BUG § BUG 42): it sat next to `min-w-0`,
6922
+ * which only has an effect on an item that is allowed to shrink, so the
6923
+ * two contradicted each other and `shrink-0` won. The slot kept its
6924
+ * content width whatever happened, which meant a long brand pushed
6925
+ * `center` and `end` out of the bar instead of ellipsing.
6926
+ *
6927
+ * Only the already-broken case changes: where there is room, a
6928
+ * shrinkable item and a non-shrinkable one lay out identically.
6929
+ */ start: 'flex items-center gap-2 min-w-0',
6688
6930
  center: 'flex items-center gap-2 min-w-0 flex-1',
6689
6931
  end: 'flex items-center gap-2 shrink-0'
6690
6932
  },
@@ -6711,6 +6953,22 @@ function formatRange(range, locale) {
6711
6953
  sticky: true
6712
6954
  }
6713
6955
  });
6956
+ /**
6957
+ * Recipe for `<TopBarBrand>`.
6958
+ *
6959
+ * `min-w-0` plus `truncate` on both lines is the load-bearing part: a bar
6960
+ * is a fixed-height row, and a long subtitle (a file path, which is the
6961
+ * case this exists for) would otherwise push the `center` and `end` slots
6962
+ * out of the bar rather than ellipsing.
6963
+ */ const topBarBrandVariants = tv({
6964
+ slots: {
6965
+ root: 'flex items-center gap-2 min-w-0',
6966
+ logo: 'shrink-0 flex items-center',
6967
+ text: 'flex flex-col justify-center min-w-0 leading-tight',
6968
+ title: 'truncate text-sm font-semibold text-neutral-900',
6969
+ subtitle: 'truncate text-xs text-neutral-500'
6970
+ }
6971
+ });
6714
6972
 
6715
6973
  /**
6716
6974
  * Dashforge TW TopBar — sticky header with 3 named slots.
@@ -6770,22 +7028,70 @@ function formatRange(range, locale) {
6770
7028
  ]
6771
7029
  });
6772
7030
  }
7031
+ /**
7032
+ * `<TopBarBrand>` — the mark-plus-text block for a `<TopBar>`'s `start`
7033
+ * slot.
7034
+ *
7035
+ * ```tsx
7036
+ * <TopBar
7037
+ * start={<TopBarBrand logo={<Logo />} title="Dashforge" subtitle="src/App.tsx" />}
7038
+ * end={<UserMenu />}
7039
+ * />
7040
+ * ```
7041
+ *
7042
+ * See {@link TopBarBrandProps} for why it is a sibling export rather than
7043
+ * `TopBar.Brand`, and why it stays layout-only.
7044
+ */ const TopBarBrand = /*#__PURE__*/ forwardRef(function TopBarBrand({ logo, title, subtitle, sx, slotProps }, ref) {
7045
+ var _slotProps_root, _slotProps_logo, _slotProps_text, _slotProps_title, _slotProps_subtitle;
7046
+ const v = topBarBrandVariants();
7047
+ return jsxs("div", {
7048
+ ref: ref,
7049
+ className: cn(v.root(), slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className, sx),
7050
+ children: [
7051
+ logo != null && jsx("span", {
7052
+ className: cn(v.logo(), slotProps == null ? void 0 : (_slotProps_logo = slotProps.logo) == null ? void 0 : _slotProps_logo.className),
7053
+ children: logo
7054
+ }),
7055
+ jsxs("span", {
7056
+ className: cn(v.text(), slotProps == null ? void 0 : (_slotProps_text = slotProps.text) == null ? void 0 : _slotProps_text.className),
7057
+ children: [
7058
+ jsx("span", {
7059
+ className: cn(v.title(), slotProps == null ? void 0 : (_slotProps_title = slotProps.title) == null ? void 0 : _slotProps_title.className),
7060
+ children: title
7061
+ }),
7062
+ subtitle != null && jsx("span", {
7063
+ className: cn(v.subtitle(), slotProps == null ? void 0 : (_slotProps_subtitle = slotProps.subtitle) == null ? void 0 : _slotProps_subtitle.className),
7064
+ children: subtitle
7065
+ })
7066
+ ]
7067
+ })
7068
+ ]
7069
+ });
7070
+ });
7071
+ TopBarBrand.displayName = 'TopBarBrand';
6773
7072
 
6774
7073
  /**
6775
7074
  * Tailwind-variants recipe for `<AppShell>`.
6776
7075
  *
6777
7076
  * Slots:
6778
- * - `root` — outer flex column (full viewport)
7077
+ * - `root` — outer flex column
6779
7078
  * - `header` — top region
6780
7079
  * - `body` — flex row holding nav + main
6781
7080
  * - `nav` — desktop nav rail (md+)
6782
7081
  * - `navMobile` — mobile drawer (slide-in)
6783
- * - `main` — scrollable content area
7082
+ * - `main` — content area
6784
7083
  * - `footer` — bottom region
6785
7084
  * - `backdrop` — semi-opaque overlay behind the mobile drawer
7085
+ *
7086
+ * Which element scrolls is decided by the `layout` axis, NOT by the
7087
+ * slots. Before BUG 27 it was decided by neither: `root` carried
7088
+ * `min-h-screen` while `main` carried `overflow-y-auto`, which describe
7089
+ * two different layouts, and `min-h-screen` won. The root grew with the
7090
+ * content, the window scrolled, and `main` never overflowed, so its
7091
+ * `overflow-y-auto` was dead on every page long enough to need it.
6786
7092
  */ const appShellVariants = tv({
6787
7093
  slots: {
6788
- root: 'flex flex-col min-h-screen bg-neutral-100',
7094
+ root: 'flex flex-col bg-neutral-100',
6789
7095
  header: 'shrink-0',
6790
7096
  body: 'flex flex-1 min-h-0',
6791
7097
  nav: 'hidden md:flex shrink-0',
@@ -6799,7 +7105,7 @@ function formatRange(range, locale) {
6799
7105
  'transition-transform duration-200 ease-out motion-reduce:transition-none motion-reduce:duration-0',
6800
7106
  '-translate-x-full'
6801
7107
  ],
6802
- main: 'flex-1 min-w-0 overflow-y-auto',
7108
+ main: 'flex-1 min-w-0',
6803
7109
  footer: 'shrink-0',
6804
7110
  backdrop: [
6805
7111
  'md:hidden fixed inset-0 z-30 bg-black/40',
@@ -6809,6 +7115,36 @@ function formatRange(range, locale) {
6809
7115
  ]
6810
7116
  },
6811
7117
  variants: {
7118
+ /*
7119
+ * Both shells are legitimate, so this is an axis rather than a
7120
+ * decision baked into the slots. See README-BUG § BUG 27.
7121
+ *
7122
+ * `viewport` — the shell fills the window and `main` scrolls inside
7123
+ * it, so header, nav and footer stay put. This is the layout the
7124
+ * component's own header diagram draws and the one
7125
+ * `main: overflow-y-auto` was written for, so it is the default.
7126
+ *
7127
+ * `page` — the window scrolls and the whole shell moves with it,
7128
+ * which is what a marketing-style shell wants. `main` gets no
7129
+ * overflow here: it could never be the scroller in this mode, and
7130
+ * advertising one is how the two ended up contradicting.
7131
+ */ layout: {
7132
+ viewport: {
7133
+ /*
7134
+ * `h-dvh`, never `h-screen`. `100vh` is the height the screen
7135
+ * has only while a phone's address bar is hidden, so `h-screen`
7136
+ * yields a shell taller than the window and the page scrolls
7137
+ * again, on exactly the devices where that is worst.
7138
+ */ root: 'h-dvh overflow-hidden',
7139
+ // Fixed must not mean clipped: on a short screen the last nav
7140
+ // items have to stay reachable.
7141
+ nav: 'overflow-y-auto',
7142
+ main: 'overflow-y-auto'
7143
+ },
7144
+ page: {
7145
+ root: 'min-h-screen'
7146
+ }
7147
+ },
6812
7148
  navOpen: {
6813
7149
  true: {
6814
7150
  navMobile: 'translate-x-0',
@@ -6817,6 +7153,7 @@ function formatRange(range, locale) {
6817
7153
  }
6818
7154
  },
6819
7155
  defaultVariants: {
7156
+ layout: 'viewport',
6820
7157
  navOpen: false
6821
7158
  }
6822
7159
  });
@@ -6888,10 +7225,14 @@ function formatRange(range, locale) {
6888
7225
  */ function AppShell(props) {
6889
7226
  var _themeSlotProps_root, _slotProps_root, _themeSlotProps_header, _slotProps_header, _themeSlotProps_nav, _slotProps_nav, _themeSlotProps_navMobile, _slotProps_navMobile, _themeSlotProps_backdrop, _slotProps_backdrop, _themeSlotProps_main, _slotProps_main, _themeSlotProps_footer, _slotProps_footer;
6890
7227
  const themeDefaults = useComponentDefaults('AppShell');
6891
- const { header, nav, footer, children, navOpen = false, onNavOpenChange, sx, slotProps } = props;
7228
+ // Instance props win over the theme, same precedence as every other
7229
+ // component that supports `theme.components.<Name>.defaults`.
7230
+ const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
7231
+ const { header, nav, footer, children, layout = 'viewport', navOpen = false, onNavOpenChange, sx, slotProps } = merged;
6892
7232
  // Theme-level slotProps (Option C Track B).
6893
7233
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
6894
7234
  const v = appShellVariants({
7235
+ layout,
6895
7236
  navOpen
6896
7237
  });
6897
7238
  // Lock body scroll while the mobile drawer is open.
@@ -7893,7 +8234,7 @@ const SnackbarContext = /*#__PURE__*/ createContext(null);
7893
8234
  root: 'px-4 py-3'
7894
8235
  },
7895
8236
  compact: {
7896
- root: 'px-3 py-2 text-[13px]'
8237
+ root: 'px-3 py-2 text-xs'
7897
8238
  }
7898
8239
  }
7899
8240
  },
@@ -8539,6 +8880,21 @@ Progress.displayName = 'Progress';
8539
8880
  *
8540
8881
  * Motion is gated by `prefers-reduced-motion`: slide animations collapse
8541
8882
  * to instantaneous appear/disappear for users who opt out.
8883
+ */ /*
8884
+ * Layering: the Drawer sits on the catalog's `z-50` overlay tier, like
8885
+ * Dialog, Menu, Popover, Tooltip, Snackbar and the two comboboxes. It used
8886
+ * to carry `z-[1400]` / `z-[1410]`, MUI's ladder, which is a different
8887
+ * scale entirely — and authored alone it looked fine.
8888
+ *
8889
+ * What it broke, which only shows when two overlays meet: a Dialog raised
8890
+ * from inside a Drawer rendered BEHIND it (50 against 1410), so the user
8891
+ * got a drawer with an invisible modal holding their focus, and a Snackbar
8892
+ * confirming an action taken in the drawer was invisible too.
8893
+ *
8894
+ * Overlay and content are both `z-50` on purpose, matching Dialog: within
8895
+ * one component DOM order settles it (content renders after the overlay),
8896
+ * and between components the one mounted later wins, which is what
8897
+ * "opened on top" means.
8542
8898
  */ const drawerVariants = tv({
8543
8899
  slots: {
8544
8900
  overlay: [
@@ -8546,7 +8902,7 @@ Progress.displayName = 'Progress';
8546
8902
  // z-1300; Chakra AppShell uses ~1000). z-[1400] sits above them
8547
8903
  // without touching the reserved "topmost" (~9999) tier for host
8548
8904
  // error overlays / dev tools. Matches Chakra Drawer's own default.
8549
- 'fixed inset-0 z-[1400] bg-neutral-950/60 backdrop-blur-sm',
8905
+ 'fixed inset-0 z-50 bg-neutral-950/60 backdrop-blur-sm',
8550
8906
  // Fade the backdrop in/out via a pure CSS keyframe (defined in
8551
8907
  // Drawer.tsx's module-level style injection).
8552
8908
  'data-[state=open]:animate-[df-drawer-fade-in_300ms_ease-out]',
@@ -8556,7 +8912,7 @@ Progress.displayName = 'Progress';
8556
8912
  content: [
8557
8913
  // Same z-tier as the overlay (see note above) plus 10 so the
8558
8914
  // drawer panel stacks above its own backdrop reliably.
8559
- 'fixed z-[1410] flex flex-col',
8915
+ 'fixed z-50 flex flex-col',
8560
8916
  // bg-white hardcoded (doesn't auto-invert) so `dark:` is needed.
8561
8917
  // Same pattern as Dialog for cross-primitive consistency.
8562
8918
  'bg-white dark:bg-neutral-100 shadow-xl',
@@ -8588,7 +8944,11 @@ Progress.displayName = 'Progress';
8588
8944
  // mode without a `dark:` variant.
8589
8945
  'rounded-md border border-neutral-200',
8590
8946
  'text-neutral-500 hover:text-neutral-900 hover:bg-neutral-100 hover:border-neutral-300',
8591
- 'focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-1',
8947
+ // `focus-visible:`, not `focus:` — see BUG 28. Radix focuses the
8948
+ // panel on open and this is its first focusable child, so a plain
8949
+ // `focus:ring` framed the × on every mouse-opened drawer. The
8950
+ // `resizeHandle` slot below already had it right.
8951
+ 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1',
8592
8952
  'transition-colors motion-reduce:transition-none'
8593
8953
  ],
8594
8954
  body: 'flex-1 min-h-0 overflow-y-auto p-4',
@@ -8852,7 +9212,6 @@ injectDrawerKeyframes();
8852
9212
  if (hasWarnedRef.current) return;
8853
9213
  if (process.env.NODE_ENV === 'production') return;
8854
9214
  hasWarnedRef.current = true;
8855
- // eslint-disable-next-line no-console -- dev-only, guarded above.
8856
9215
  console.warn('[@dashforge/tw] <Drawer resize> was used without a `resizeKey`. ' + 'The resized dimension will not persist across sessions. Pass a ' + 'string identifier to `resizeKey` (e.g. `resizeKey="inspector"`) ' + 'to enable localStorage persistence.');
8857
9216
  }, [
8858
9217
  resize,
@@ -9168,7 +9527,7 @@ if (process.env.NODE_ENV !== 'production') {
9168
9527
  'group-data-[state=invalid]/step:text-danger-700'
9169
9528
  ],
9170
9529
  helperText: 'text-xs text-neutral-600 truncate',
9171
- optionalTag: 'text-[10px] italic text-neutral-500',
9530
+ optionalTag: 'text-2xs italic text-neutral-500',
9172
9531
  connector: 'bg-neutral-200',
9173
9532
  content: 'w-full',
9174
9533
  footer: 'flex items-center justify-between mt-4'
@@ -9227,7 +9586,7 @@ if (process.env.NODE_ENV !== 'production') {
9227
9586
  sm: {
9228
9587
  indicator: 'w-6 h-6 text-xs',
9229
9588
  label: 'text-xs',
9230
- helperText: 'text-[10px]'
9589
+ helperText: 'text-2xs'
9231
9590
  },
9232
9591
  md: {
9233
9592
  indicator: 'w-7 h-7 text-sm',
@@ -9359,7 +9718,6 @@ if (process.env.NODE_ENV !== 'production') {
9359
9718
  }, `stepper-passthrough-${i}`));
9360
9719
  });
9361
9720
  if (sawStrayDom && process.env.NODE_ENV !== 'production') {
9362
- // eslint-disable-next-line no-console -- dev-only, guarded by NODE_ENV.
9363
9721
  console.warn('[@dashforge/tw] <Stepper> received bare DOM children (text or ' + 'intrinsic elements like <div>). Only <Step> configs and ' + 'component children (e.g. a footer reading useStep()) are ' + 'recognized; stray DOM was ignored.');
9364
9722
  }
9365
9723
  return {
@@ -9398,7 +9756,6 @@ if (process.env.NODE_ENV !== 'production') {
9398
9756
  return initialStep;
9399
9757
  }
9400
9758
  if (initialStep && process.env.NODE_ENV !== 'production') {
9401
- // eslint-disable-next-line no-console -- dev-only warning.
9402
9759
  console.warn(`[@dashforge/tw] <Stepper initialStep="${initialStep}"> did not ` + `match any visible step. Falling back to the first visible step.`);
9403
9760
  }
9404
9761
  return (_visibleStepNames_ = visibleStepNames[0]) != null ? _visibleStepNames_ : '';
@@ -9489,7 +9846,6 @@ if (process.env.NODE_ENV !== 'production') {
9489
9846
  return false;
9490
9847
  }
9491
9848
  } else if (process.env.NODE_ENV !== 'production') {
9492
- // eslint-disable-next-line no-console -- dev-only guard.
9493
9849
  console.warn(`[@dashforge/tw] <Step name="${step.name}" fields={[...]}> was ` + `used outside a <DashForm> (or with a bridge that does not ` + `implement trigger). The fields validation is skipped.`);
9494
9850
  }
9495
9851
  }
@@ -9900,7 +10256,7 @@ Stepper.displayName = 'Stepper';
9900
10256
  ],
9901
10257
  valueLabel: [
9902
10258
  'absolute -translate-x-1/2 -translate-y-full',
9903
- 'px-1.5 py-0.5 rounded text-xs font-medium text-neutral-50',
10259
+ 'px-1.5 py-0.5 rounded-md text-xs font-medium text-neutral-50',
9904
10260
  'pointer-events-none whitespace-nowrap',
9905
10261
  'shadow-sm',
9906
10262
  // background color applied via variant below
@@ -9949,7 +10305,7 @@ Stepper.displayName = 'Stepper';
9949
10305
  track: 'h-1',
9950
10306
  thumb: 'w-3.5 h-3.5',
9951
10307
  mark: 'w-0.5 h-0.5',
9952
- valueLabel: 'text-[10px] px-1'
10308
+ valueLabel: 'text-2xs px-1'
9953
10309
  },
9954
10310
  md: {
9955
10311
  controlWrapper: 'py-2 h-8',
@@ -10298,6 +10654,7 @@ const DEFAULT_STEP = 1;
10298
10654
  return v <= displayValueArr[0];
10299
10655
  };
10300
10656
  return jsxs("div", {
10657
+ ref: ref,
10301
10658
  className: rootClasses,
10302
10659
  "data-testid": testId,
10303
10660
  children: [
@@ -10618,7 +10975,8 @@ Slider.displayName = 'Slider';
10618
10975
  *
10619
10976
  * `V` inference — TypeScript narrows the union from the `options`
10620
10977
  * array so `onChange` gets the precise literal type.
10621
- */ function SelectInner(props, ref) {
10978
+ */ function SelectInner(props, // The trigger is a `<div role="combobox">`, not a `<button>` — see BUG 23.
10979
+ ref) {
10622
10980
  var _ref;
10623
10981
  var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_triggerText, _slotProps_triggerText, _themeSlotProps_triggerPlaceholder, _slotProps_triggerPlaceholder, _themeSlotProps_chevron, _slotProps_chevron, _themeSlotProps_popover, _slotProps_popover, _themeSlotProps_listBox, _slotProps_listBox, _themeSlotProps_emptyState, _slotProps_emptyState, _themeSlotProps_helperText, _slotProps_helperText, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_chipsList, _slotProps_chipsList, _themeSlotProps_chip, _slotProps_chip, _themeSlotProps_chipRemove, _slotProps_chipRemove, _triggerRef_current;
10624
10982
  const themeDefaults = useComponentDefaults('Select');
@@ -10635,6 +10993,7 @@ Slider.displayName = 'Slider';
10635
10993
  const controlId = useId();
10636
10994
  const listboxId = `${controlId}-listbox`;
10637
10995
  const helperId = `${controlId}-help`;
10996
+ const labelId = `${controlId}-label`;
10638
10997
  const isFormMode = Boolean(bridge == null ? void 0 : bridge.register);
10639
10998
  useStandaloneFieldWarning('Select', name, isFormMode, userValue, onChange);
10640
10999
  // Mirror of useStandaloneFieldWarning: warn when running under a
@@ -10999,8 +11358,18 @@ Slider.displayName = 'Slider';
10999
11358
  "data-testid": testId,
11000
11359
  children: [
11001
11360
  label != null && jsx("label", {
11361
+ id: labelId,
11002
11362
  htmlFor: controlId,
11003
11363
  className: labelClasses,
11364
+ // `htmlFor` no longer associates anything: the trigger is a div,
11365
+ // and `<label for>` only binds to a labelable element. It is kept
11366
+ // because it is harmless and consumers may key CSS off it, but
11367
+ // the real name comes from `aria-labelledby` on the trigger and
11368
+ // the focus-on-click has to be done by hand. BUG 23.
11369
+ onClick: ()=>{
11370
+ var _triggerRef_current;
11371
+ return (_triggerRef_current = triggerRef.current) == null ? void 0 : _triggerRef_current.focus();
11372
+ },
11004
11373
  children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
11005
11374
  className: requiredMarkClasses,
11006
11375
  children: "*"
@@ -11012,24 +11381,27 @@ Slider.displayName = 'Slider';
11012
11381
  children: [
11013
11382
  jsx(RadixPopover.Trigger, {
11014
11383
  asChild: true,
11015
- children: jsxs("button", {
11384
+ children: jsxs("div", _extends({
11016
11385
  ref: (node)=>{
11017
11386
  triggerRef.current = node;
11018
11387
  if (typeof ref === 'function') ref(node);
11019
11388
  else if (ref) ref.current = node;
11020
11389
  },
11021
- id: controlId,
11022
- type: "button",
11390
+ id: controlId
11391
+ }, {
11392
+ type: undefined
11393
+ }, {
11023
11394
  role: "combobox",
11395
+ tabIndex: effectiveDisabled ? -1 : 0,
11024
11396
  "aria-haspopup": "listbox",
11025
11397
  "aria-expanded": isOpen,
11026
11398
  "aria-controls": listboxId,
11399
+ "aria-labelledby": label != null ? labelId : undefined,
11027
11400
  "aria-required": required || undefined,
11028
11401
  "aria-invalid": hasError || undefined,
11029
11402
  "aria-describedby": resolvedHelperText != null ? helperId : undefined,
11030
11403
  "aria-disabled": effectiveDisabled || undefined,
11031
- disabled: effectiveDisabled,
11032
- name: name,
11404
+ "data-name": name,
11033
11405
  className: triggerClasses,
11034
11406
  onKeyDown: handleTriggerKeyDown,
11035
11407
  children: [
@@ -11038,7 +11410,7 @@ Slider.displayName = 'Slider';
11038
11410
  className: cn(chevronClasses)
11039
11411
  })
11040
11412
  ]
11041
- })
11413
+ }))
11042
11414
  }),
11043
11415
  jsx(RadixPopover.Portal, {
11044
11416
  children: jsx(RadixPopover.Content, {
@@ -11165,7 +11537,7 @@ Select.displayName = 'Select';
11165
11537
  'inline-flex items-center gap-1',
11166
11538
  // Anchor semantics — cursor + focus-visible ring using primary token.
11167
11539
  'cursor-pointer',
11168
- 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 focus-visible:rounded',
11540
+ 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 focus-visible:rounded-sm',
11169
11541
  // Motion-reduce safe transition on color / decoration.
11170
11542
  'transition-colors',
11171
11543
  'motion-reduce:transition-none'
@@ -11264,7 +11636,6 @@ Select.displayName = 'Select';
11264
11636
  // the Slot pattern paints classes onto a foreign child, and there is
11265
11637
  // no seam for us to inject start/end icon wrappers.
11266
11638
  if (process.env.NODE_ENV !== 'production' && (startIcon != null || endIcon != null)) {
11267
- // eslint-disable-next-line no-console -- dev-only nudge.
11268
11639
  console.warn('[@dashforge/tw] <Link asChild> ignores startIcon / endIcon — the ' + 'child element renders its own content. Move the icons inside the ' + 'child instead.');
11269
11640
  }
11270
11641
  return jsx(Slot, _extends({
@@ -11706,7 +12077,7 @@ MenuItem.displayName = 'MenuItem';
11706
12077
  // dimensions below.
11707
12078
  'inline-flex items-center justify-center',
11708
12079
  'rounded-full',
11709
- 'text-[10px] font-medium leading-none',
12080
+ 'text-2xs font-medium leading-none',
11710
12081
  'pointer-events-none select-none',
11711
12082
  // Smooth show/hide for `invisible` toggle (consumer-side
11712
12083
  // animation hook). Gated on motion-reduce per WCAG 2.3.3.
@@ -11956,6 +12327,78 @@ MenuItem.displayName = 'MenuItem';
11956
12327
  });
11957
12328
  Badge.displayName = 'Badge';
11958
12329
 
12330
+ /**
12331
+ * Tailwind-variants recipe for `<Kbd>`.
12332
+ *
12333
+ * One axis, `size`, because a keycap has no intent: it is chrome around a
12334
+ * literal key, not a status or an action. Colour is fixed to the neutral
12335
+ * ramp, which auto-inverts through the preset's CSS vars, so the cap reads
12336
+ * as a raised surface in light and a recessed one in dark with no `dark:`
12337
+ * variant to keep in sync.
12338
+ *
12339
+ * The border is what makes the cap read as a cap, and it is at `-500`
12340
+ * rather than the `-300` a hairline invites. Measured on `learn/dash`
12341
+ * against both surfaces a keycap realistically sits on:
12342
+ *
12343
+ * surface neutral-100 ... 1.09 vs page, 1.04 vs card
12344
+ * surface neutral-200 ... 1.26 / 1.21
12345
+ * border neutral-300 ... 1.48 / 1.42
12346
+ * border neutral-400 ... 2.52 / 2.42
12347
+ * border neutral-500 ... 4.74 / 4.54 <- the first that clears 3:1
12348
+ *
12349
+ * The first draft assumed the `bg-neutral-100` surface would do the
12350
+ * separating and left the border at `-300`. It does not: a neutral surface
12351
+ * one step off the page is ~1.1:1 by construction, and in dark mode it
12352
+ * lands on exactly the same colour as a card, so the cap disappeared into
12353
+ * the panel and only the hairline was left. That is the same shape that
12354
+ * failed on the outline Chip (README-BUG § BUG 40), and it reached the
12355
+ * same tier for the same reason.
12356
+ *
12357
+ * The surface stays as a faint lift, not as the separator.
12358
+ *
12359
+ * `rounded-md` rather than a bare `rounded`, which is hard-coded at
12360
+ * 0.25rem and immune to the radius tokens (README-BUG § BUG 26).
12361
+ */ const kbdVariants = tv({
12362
+ base: [
12363
+ 'inline-flex items-center justify-center',
12364
+ 'font-mono font-medium leading-none whitespace-nowrap select-none',
12365
+ 'bg-neutral-100 text-neutral-700',
12366
+ 'border border-neutral-500 rounded-md shadow-sm'
12367
+ ],
12368
+ variants: {
12369
+ size: {
12370
+ sm: 'h-5 min-w-5 px-1 text-2xs',
12371
+ md: 'h-6 min-w-6 px-1.5 text-xs',
12372
+ lg: 'h-7 min-w-7 px-2 text-sm'
12373
+ }
12374
+ },
12375
+ defaultVariants: {
12376
+ size: 'md'
12377
+ }
12378
+ });
12379
+
12380
+ /**
12381
+ * `<Kbd>` — a single keycap.
12382
+ *
12383
+ * ```tsx
12384
+ * Press <Kbd>Esc</Kbd> to close
12385
+ * ```
12386
+ *
12387
+ * See {@link KbdProps} for the full API surface, including why chords are
12388
+ * composed rather than passed as an array.
12389
+ */ const Kbd = /*#__PURE__*/ forwardRef(function Kbd(rawProps, ref) {
12390
+ const themeDefaults = useComponentDefaults('Kbd');
12391
+ const { size, sx, className, children } = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, rawProps);
12392
+ return jsx("kbd", {
12393
+ ref: ref,
12394
+ className: cn(kbdVariants({
12395
+ size
12396
+ }), className, sx),
12397
+ children: children
12398
+ });
12399
+ });
12400
+ Kbd.displayName = 'Kbd';
12401
+
11959
12402
  /**
11960
12403
  * Tailwind-variants recipe for `<Avatar>`.
11961
12404
  *
@@ -11990,7 +12433,7 @@ Badge.displayName = 'Badge';
11990
12433
  variants: {
11991
12434
  size: {
11992
12435
  xs: {
11993
- root: 'w-5 h-5 text-[10px]',
12436
+ root: 'w-5 h-5 text-2xs',
11994
12437
  initials: ''
11995
12438
  },
11996
12439
  sm: {
@@ -12430,7 +12873,7 @@ AvatarGroup.displayName = 'AvatarGroup';
12430
12873
  variants: {
12431
12874
  variant: {
12432
12875
  text: {
12433
- root: 'rounded h-[1em] w-full'
12876
+ root: 'rounded-sm h-[1em] w-full'
12434
12877
  },
12435
12878
  rectangle: {
12436
12879
  root: 'rounded-md w-full h-[100px]'
@@ -13136,6 +13579,18 @@ Video.displayName = 'Video';
13136
13579
  4: 'shadow-lg',
13137
13580
  5: 'shadow-xl'
13138
13581
  },
13582
+ /*
13583
+ * Border style. Only visible where a border-width is already set:
13584
+ * `variant="outlined"` sets one, and a consumer can bring their own
13585
+ * through `sx`. Declared as its own axis rather than folded into
13586
+ * `variant` because the two are orthogonal — a dashed placeholder
13587
+ * can be outlined, soft or solid. kensaadi/dashforge#63 gap I.
13588
+ */ borderStyle: {
13589
+ solid: 'border-solid',
13590
+ dashed: 'border-dashed',
13591
+ dotted: 'border-dotted',
13592
+ double: 'border-double'
13593
+ },
13139
13594
  rounded: {
13140
13595
  none: 'rounded-none',
13141
13596
  sm: 'rounded-sm',
@@ -13412,11 +13867,12 @@ Video.displayName = 'Video';
13412
13867
  // theme < instance; `sx` layers last via `cn()` + tailwind-merge.
13413
13868
  const themeDefaults = useComponentDefaults('Box');
13414
13869
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
13415
- const { variant, color, elevation, rounded, p, px, py, m, mx, my, fullWidth, fullHeight, as, asChild = false, sx, visibleWhen, access, children } = merged, rest = _object_without_properties_loose(merged, [
13870
+ const { variant, color, elevation, rounded, borderStyle, p, px, py, m, mx, my, fullWidth, fullHeight, as, asChild = false, sx, visibleWhen, access, children } = merged, rest = _object_without_properties_loose(merged, [
13416
13871
  "variant",
13417
13872
  "color",
13418
13873
  "elevation",
13419
13874
  "rounded",
13875
+ "borderStyle",
13420
13876
  "p",
13421
13877
  "px",
13422
13878
  "py",
@@ -13454,6 +13910,7 @@ Video.displayName = 'Video';
13454
13910
  color,
13455
13911
  elevation,
13456
13912
  rounded,
13913
+ borderStyle,
13457
13914
  p,
13458
13915
  px,
13459
13916
  py,
@@ -13744,7 +14201,18 @@ CardActionArea.displayName = 'CardActionArea';
13744
14201
  * (one step up the elevation ladder of its current variant).
13745
14202
  * Compound rules below apply the actual shift per (variant, color)
13746
14203
  * cell.
13747
- */ selected: {
14204
+ */ /*
14205
+ * Pointer affordance for a chip used as a drag source, e.g. a palette
14206
+ * of items dragged onto a canvas. Native HTML5 drag-and-drop, so the
14207
+ * library takes on no dnd dependency and the consumer keeps ownership
14208
+ * of the transfer payload. kensaadi/dashforge#63 gap D.
14209
+ *
14210
+ * `active:cursor-grabbing` rather than a `:hover` swap: the closed
14211
+ * hand belongs to the moment the pointer is down, not to hovering.
14212
+ */ draggable: {
14213
+ true: 'cursor-grab active:cursor-grabbing'
14214
+ },
14215
+ selected: {
13748
14216
  true: 'ring-2 ring-offset-1'
13749
14217
  },
13750
14218
  /** Disabled state for clickable chips. */ disabled: {
@@ -13838,7 +14306,7 @@ CardActionArea.displayName = 'CardActionArea';
13838
14306
  {
13839
14307
  variant: 'outline',
13840
14308
  color: 'neutral',
13841
- class: 'border border-neutral-300 text-neutral-700'
14309
+ class: 'border border-neutral-500 text-neutral-700'
13842
14310
  },
13843
14311
  {
13844
14312
  variant: 'outline',
@@ -14172,7 +14640,7 @@ CardActionArea.displayName = 'CardActionArea';
14172
14640
  */ const Chip = /*#__PURE__*/ forwardRef(function Chip(props, ref) {
14173
14641
  const themeDefaults = useComponentDefaults('Chip');
14174
14642
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
14175
- const { label, icon, avatar, variant, color, size, clickable: clickableProp, onClick, onDelete, deleteIcon, deleteLabel = 'Remove', selected, disabled: disabledProp, visibleWhen, access, sx, className } = merged;
14643
+ const { label, icon, avatar, variant, color, size, clickable: clickableProp, onClick, onDelete, deleteIcon, deleteLabel = 'Remove', selected, disabled: disabledProp, draggable, onDragStart, onDragEnd, visibleWhen, access, sx, className } = merged;
14176
14644
  // Bridge — both hooks called unconditionally (rules-of-hooks).
14177
14645
  // Inside a `<DashForm>`, `useEngineVisibility` subscribes to engine
14178
14646
  // state and re-evaluates the predicate on changes; outside a form,
@@ -14191,7 +14659,8 @@ CardActionArea.displayName = 'CardActionArea';
14191
14659
  size,
14192
14660
  clickable: isClickable || undefined,
14193
14661
  selected: selected || undefined,
14194
- disabled: isDisabled || undefined
14662
+ disabled: isDisabled || undefined,
14663
+ draggable: draggable || undefined
14195
14664
  }), sx, className);
14196
14665
  // ─── Inner content — leading slot + label + delete ────────────
14197
14666
  // Avatar wins over icon when both provided (MUI parity).
@@ -14201,6 +14670,46 @@ CardActionArea.displayName = 'CardActionArea';
14201
14670
  // `inline-flex items-center` provides vertical alignment with
14202
14671
  // any leading / trailing slots.
14203
14672
  const leading = avatar != null ? avatar : icon;
14673
+ const deleteClasses = cn('ml-0.5 -mr-1 inline-flex items-center justify-center', 'h-4 w-4 rounded-full opacity-70 hover:opacity-100', 'transition-opacity');
14674
+ /*
14675
+ * The delete affordance has TWO shapes, and which one is legal depends
14676
+ * on what the root turned out to be. See README-BUG § BUG 35.
14677
+ *
14678
+ * Static root (`<span>`): a real `<button>`. A span is not a widget, so
14679
+ * a focusable button inside it is valid HTML and is the only keyboard
14680
+ * path to delete. Unchanged.
14681
+ *
14682
+ * Clickable root (`role="button"`): NOT a button, and not focusable.
14683
+ * Both `<button>` and `role="button"` forbid interactive descendants —
14684
+ * HTML by its content model, ARIA by the presentational-children rule,
14685
+ * which strips the semantics of everything inside a `button` role. So a
14686
+ * nested control is either invalid markup or invisible to AT, depending
14687
+ * on which spelling you pick. The keyboard path moves to Backspace /
14688
+ * Delete on the chip itself, which is what MUI does and what this
14689
+ * component's own `onKeyDown` comment already anticipated.
14690
+ */ const deleteNode = onDelete == null ? null : isClickable ? jsx("span", {
14691
+ "data-chip-delete": "",
14692
+ "aria-hidden": "true",
14693
+ onClick: (e)=>{
14694
+ // Stop propagation so the chip's own onClick doesn't fire when
14695
+ // the user clicks the × — MUI matches this behaviour.
14696
+ e.stopPropagation();
14697
+ if (!isDisabled) onDelete(e);
14698
+ },
14699
+ className: cn(deleteClasses, !isDisabled && 'cursor-pointer'),
14700
+ children: deleteIcon != null ? deleteIcon : jsx(DefaultDeleteIcon, {})
14701
+ }) : jsx("button", {
14702
+ "data-chip-delete": "",
14703
+ type: "button",
14704
+ "aria-label": deleteLabel,
14705
+ onClick: (e)=>{
14706
+ e.stopPropagation();
14707
+ if (!isDisabled) onDelete(e);
14708
+ },
14709
+ disabled: isDisabled,
14710
+ className: cn(deleteClasses, 'outline-none focus-visible:ring-2 focus-visible:ring-current'),
14711
+ children: deleteIcon != null ? deleteIcon : jsx(DefaultDeleteIcon, {})
14712
+ });
14204
14713
  const innerContent = jsxs(Fragment, {
14205
14714
  children: [
14206
14715
  leading != null && jsx("span", {
@@ -14208,45 +14717,70 @@ CardActionArea.displayName = 'CardActionArea';
14208
14717
  children: leading
14209
14718
  }),
14210
14719
  label,
14211
- onDelete != null && jsx("button", {
14212
- type: "button",
14213
- "aria-label": deleteLabel,
14214
- onClick: (e)=>{
14215
- // Stop propagation so the chip's own onClick doesn't fire
14216
- // when the user clicks the × — MUI matches this behaviour.
14217
- e.stopPropagation();
14218
- if (!isDisabled) onDelete(e);
14219
- },
14220
- disabled: isDisabled,
14221
- className: cn('ml-0.5 -mr-1 inline-flex items-center justify-center', 'h-4 w-4 rounded-full opacity-70 hover:opacity-100', 'outline-none focus-visible:ring-2 focus-visible:ring-current', 'transition-opacity'),
14222
- children: deleteIcon != null ? deleteIcon : jsx(DefaultDeleteIcon, {})
14223
- })
14720
+ deleteNode
14224
14721
  ]
14225
14722
  });
14226
14723
  // ─── Interactive root (clickable) ─────────────────────────────
14724
+ /*
14725
+ * A `<div role="button">`, not a `<button>`. With `onDelete` also set,
14726
+ * the native element nested a `<button>` inside a `<button>`, which is
14727
+ * invalid HTML: React reported a hydration error and the parser hoisted
14728
+ * the inner control out. BUG 35.
14729
+ *
14730
+ * Everything the native element gave away is re-supplied below, because
14731
+ * a div gives none of it: focusability, Enter / Space activation, and
14732
+ * inertness while disabled.
14733
+ */ // A disabled chip must not be a drag source either: `pointer-events-none`
14734
+ // already blocks the pointer, but the attribute would still advertise it.
14735
+ const dragProps = {
14736
+ draggable: draggable && !isDisabled ? true : undefined,
14737
+ onDragStart: draggable && !isDisabled ? onDragStart : undefined,
14738
+ onDragEnd: draggable && !isDisabled ? onDragEnd : undefined
14739
+ };
14227
14740
  if (isClickable) {
14228
- return jsx("button", {
14741
+ return jsx("div", _extends({
14229
14742
  ref: ref,
14230
- type: "button",
14231
- className: classes,
14232
- disabled: isDisabled,
14743
+ role: "button",
14744
+ tabIndex: isDisabled ? -1 : 0,
14745
+ className: classes
14746
+ }, dragProps, {
14747
+ "aria-disabled": isDisabled || undefined,
14233
14748
  "aria-pressed": selected ? true : undefined,
14234
14749
  onClick: (e)=>{
14235
14750
  if (isDisabled) return;
14236
14751
  onClick == null ? void 0 : onClick(e);
14237
14752
  },
14238
14753
  onKeyDown: (e)=>{
14754
+ if (isDisabled) return;
14755
+ // Ignore anything bubbling up from a child, so a focusable slot
14756
+ // (an interactive avatar, say) keeps its own keys. Mirrors
14757
+ // MUI's `event.currentTarget === event.target` guard.
14758
+ if (e.currentTarget !== e.target) return;
14759
+ // A div has no implicit activation. Space is prevented first so
14760
+ // the page does not scroll under the chip.
14761
+ if (e.key === 'Enter' || e.key === ' ') {
14762
+ e.preventDefault();
14763
+ onClick == null ? void 0 : onClick(e);
14764
+ return;
14765
+ }
14766
+ // The keyboard path to the delete affordance, which is not
14767
+ // focusable in this branch. Same keys as MUI.
14768
+ if (onDelete != null && (e.key === 'Backspace' || e.key === 'Delete')) {
14769
+ e.preventDefault();
14770
+ onDelete(e);
14771
+ }
14239
14772
  },
14240
14773
  children: innerContent
14241
- });
14774
+ }));
14242
14775
  }
14243
14776
  // ─── Static root (display only) ───────────────────────────────
14244
- return jsx("span", {
14777
+ return jsx("span", _extends({
14245
14778
  ref: ref,
14246
14779
  className: classes,
14247
- "aria-disabled": isDisabled || undefined,
14780
+ "aria-disabled": isDisabled || undefined
14781
+ }, dragProps, {
14248
14782
  children: innerContent
14249
- });
14783
+ }));
14250
14784
  });
14251
14785
 
14252
14786
  /**
@@ -14566,7 +15100,19 @@ Typography.displayName = 'Typography';
14566
15100
  * Runtime allow-list, for the dev-warn to check against a passed
14567
15101
  * `gap` value at render time. Same set as {@link StackGap}. Frozen
14568
15102
  * so callers can't mutate the source of truth.
14569
- */ const STACK_GAP_VALUES = Object.freeze([
15103
+ */ /**
15104
+ * The accepted `direction` values, for the dev-time guard in `Stack.tsx`.
15105
+ *
15106
+ * Frozen and exported rather than inlined so the warning cannot drift from
15107
+ * the variant recipe: adding an axis value without adding it here would
15108
+ * make the guard warn about something that works.
15109
+ */ const STACK_DIRECTION_VALUES = Object.freeze([
15110
+ 'row',
15111
+ 'col',
15112
+ 'row-reverse',
15113
+ 'col-reverse'
15114
+ ]);
15115
+ const STACK_GAP_VALUES = Object.freeze([
14570
15116
  0,
14571
15117
  0.5,
14572
15118
  1,
@@ -14586,6 +15132,25 @@ Typography.displayName = 'Typography';
14586
15132
  * useStandaloneFieldWarning "warn once" ergonomic. `Set<unknown>` so
14587
15133
  * `null` / arbitrary strings share the same bucket as `NaN`.
14588
15134
  */ const warnedGapValues = new Set();
15135
+ /** Same "warn once per value" bucket, for `direction`. */ const warnedDirectionValues = new Set();
15136
+ /** Whether the `spacing`-instead-of-`gap` warning has already fired. */ let warnedSpacingAlias = false;
15137
+ /**
15138
+ * Names people reach for instead of the ones this component uses, mapped to
15139
+ * what they meant. kensaadi/dashforge#63 gap K reported the surprise;
15140
+ * accepting both spellings was the alternative and was not taken, because a
15141
+ * second name for one axis is a fork every consumer, every theme default
15142
+ * and every doc example then has to pick a side of, forever.
15143
+ *
15144
+ * TypeScript already rejects these. The guard is for the consumers TS does
15145
+ * not reach: JS callers, `{...anyProps}` spreads, values read from config.
15146
+ * Left alone the value is simply dropped and the Stack renders its default
15147
+ * axis, which is the silent failure the report described as "surprising".
15148
+ */ const DIRECTION_ALIASES = {
15149
+ column: 'col',
15150
+ 'column-reverse': 'col-reverse',
15151
+ vertical: 'col',
15152
+ horizontal: 'row'
15153
+ };
14589
15154
  /**
14590
15155
  * Walk the children, inserting `divider` BETWEEN every consecutive pair.
14591
15156
  *
@@ -14601,7 +15166,28 @@ Typography.displayName = 'Typography';
14601
15166
  * • If `divider` is a valid element, we `cloneElement` once per
14602
15167
  * boundary (cheaper than re-rendering the JSX expression N-1 times).
14603
15168
  * For string/number dividers we wrap in a span automatically.
14604
- */ function interleaveDividers(children, divider) {
15169
+ */ /**
15170
+ * The divider orientation that separates items along each axis. A row is
15171
+ * separated by vertical rules and a column by horizontal ones, which is the
15172
+ * opposite of what the names suggest and the reason this was worth deriving
15173
+ * rather than leaving to the caller. kensaadi/dashforge#63 gap F.
15174
+ */ const DIVIDER_ORIENTATION_FOR = {
15175
+ row: 'vertical',
15176
+ 'row-reverse': 'vertical',
15177
+ col: 'horizontal',
15178
+ 'col-reverse': 'horizontal'
15179
+ };
15180
+ /**
15181
+ * True for our own `<Divider>`, read off `displayName` rather than by
15182
+ * importing the component: Stack has no business depending on Divider, and
15183
+ * the check has to fail safely for anything else. Injecting an
15184
+ * `orientation` prop into a foreign element is how `tooltip` once landed on
15185
+ * the DOM as an unknown attribute (README-BUG § BUG 9).
15186
+ */ function isDashforgeDivider(node) {
15187
+ var _node_type;
15188
+ return ((_node_type = node.type) == null ? void 0 : _node_type.displayName) === 'Divider';
15189
+ }
15190
+ function interleaveDividers(children, divider, direction) {
14605
15191
  const items = Children.toArray(children);
14606
15192
  if (items.length <= 1) return items;
14607
15193
  const result = [];
@@ -14610,9 +15196,20 @@ Typography.displayName = 'Typography';
14610
15196
  if (i < items.length - 1) {
14611
15197
  const key = `df-stack-divider-${i}`;
14612
15198
  if (/*#__PURE__*/ isValidElement(divider)) {
14613
- result.push(/*#__PURE__*/ cloneElement(divider, {
15199
+ var _DIVIDER_ORIENTATION_FOR_direction;
15200
+ // A `<Divider>` defaults to `horizontal`, so dropping one into a
15201
+ // row Stack gave a zero-height rule at `w-full`: it did not
15202
+ // separate anything, it demanded the whole width and squeezed the
15203
+ // items instead. The Stack knows its own axis, so it supplies the
15204
+ // orientation the caller did not choose. An explicit `orientation`
15205
+ // always wins, and a non-Divider node is passed through untouched.
15206
+ const props = divider.props;
15207
+ const shouldDerive = isDashforgeDivider(divider) && props.orientation === undefined;
15208
+ result.push(/*#__PURE__*/ cloneElement(divider, _extends({
14614
15209
  key
14615
- }));
15210
+ }, shouldDerive ? {
15211
+ orientation: (_DIVIDER_ORIENTATION_FOR_direction = DIVIDER_ORIENTATION_FOR[direction]) != null ? _DIVIDER_ORIENTATION_FOR_direction : 'horizontal'
15212
+ } : {})));
14616
15213
  } else {
14617
15214
  result.push(jsx(Fragment$1, {
14618
15215
  children: divider
@@ -14645,7 +15242,7 @@ Typography.displayName = 'Typography';
14645
15242
  */ const Stack = /*#__PURE__*/ forwardRef(function Stack(props, ref) {
14646
15243
  const themeDefaults = useComponentDefaults('Stack');
14647
15244
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
14648
- const { direction, align, justify, gap, wrap, fullWidth, fullHeight, divider, as, asChild = false, sx, children } = merged, rest = _object_without_properties_loose(merged, [
15245
+ const { direction, align, justify, gap, wrap, fullWidth, fullHeight, divider, as, asChild = false, sx, visibleWhen, access, children } = merged, rest = _object_without_properties_loose(merged, [
14649
15246
  "direction",
14650
15247
  "align",
14651
15248
  "justify",
@@ -14657,6 +15254,8 @@ Typography.displayName = 'Typography';
14657
15254
  "as",
14658
15255
  "asChild",
14659
15256
  "sx",
15257
+ "visibleWhen",
15258
+ "access",
14660
15259
  "children"
14661
15260
  ]);
14662
15261
  // Dev-only guard for #111 (G-27): `<Stack gap>` is typed to the
@@ -14666,9 +15265,18 @@ Typography.displayName = 'Typography';
14666
15265
  // consumers get a real signal instead of silent `rowGap: normal`.
14667
15266
  if (process.env.NODE_ENV !== 'production' && gap !== undefined && !STACK_GAP_VALUES.includes(gap) && !warnedGapValues.has(gap)) {
14668
15267
  warnedGapValues.add(gap);
14669
- // eslint-disable-next-line no-console -- dev-only guard, guarded by NODE_ENV above.
14670
15268
  console.warn(`[@dashforge/tw] <Stack gap={${JSON.stringify(gap)}}> is not on the ` + `token-scale set (${STACK_GAP_VALUES.join(', ')}). The variant ` + `mapping silently falls back to no gap. Use a numeric literal ` + `from the accepted set — token strings like "sm" / "md" / "lg" ` + `are not supported.`);
14671
15269
  }
15270
+ // Same shape of guard for `direction`, which fails the same silent way:
15271
+ // an unrecognised value is dropped by the variant recipe and the Stack
15272
+ // falls back to `defaultVariants.direction`, so a column Stack asked
15273
+ // for as "column" quietly lays out as a column anyway and a "vertical"
15274
+ // row does not. See kensaadi/dashforge#63 gap K.
15275
+ if (process.env.NODE_ENV !== 'production' && direction !== undefined && !STACK_DIRECTION_VALUES.includes(direction) && !warnedDirectionValues.has(direction)) {
15276
+ warnedDirectionValues.add(direction);
15277
+ const meant = DIRECTION_ALIASES[String(direction)];
15278
+ console.warn(`[@dashforge/tw] <Stack direction={${JSON.stringify(direction)}}> is ` + `not an accepted value (${STACK_DIRECTION_VALUES.join(', ')}). ` + `The variant mapping drops it and the Stack falls back to ` + `"${'col'}".` + (meant ? ` Did you mean "${meant}"?` : ''));
15279
+ }
14672
15280
  // Runtime safety-net for #112 (G-28): the `StackProps` interface
14673
15281
  // Omit-excludes `className`, forcing typed consumers to use `sx`. But
14674
15282
  // TS-loose consumers (unchecked casts, `{...anyProps}` spreads) can
@@ -14679,9 +15287,40 @@ Typography.displayName = 'Typography';
14679
15287
  // Extract it, feed it through `cn` so tailwind-merge preserves the
14680
15288
  // non-conflicting utility (e.g. consumer's `min-h-0` + variant
14681
15289
  // `flex flex-col gap-3`), and drop it from the DOM spread.
14682
- const { className: consumerClassName } = rest, safeRest = _object_without_properties_loose(rest, [
14683
- "className"
15290
+ // Bridge — hooks called unconditionally, ABOVE the early return
15291
+ // (rules-of-hooks; see README-BUG § BUG 33 for what happens when a
15292
+ // subscription is made conditional instead). `useEngineVisibility`
15293
+ // re-evaluates the predicate reactively inside a `<DashForm>` and
15294
+ // watches nothing when `visibleWhen` is omitted; `useAccessState`
15295
+ // consults the @dashforge/rbac policy engine. Both are no-ops when
15296
+ // their prop is absent, so a consumer passing neither renders
15297
+ // exactly as before.
15298
+ const bridge = useContext(DashFormContext);
15299
+ const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
15300
+ const accessState = useAccessState(access);
15301
+ // Early return — predicate false OR RBAC denies visibility.
15302
+ if (!isVisible || !accessState.visible) return null;
15303
+ const ariaProps = {
15304
+ 'aria-disabled': accessState.disabled || undefined,
15305
+ 'aria-readonly': accessState.readonly || undefined,
15306
+ 'data-disabled': accessState.disabled || undefined,
15307
+ 'data-readonly': accessState.readonly || undefined
15308
+ };
15309
+ const { className: consumerClassName, // `spacing` is MUI's name for this axis and the one consumers reach
15310
+ // for first (kensaadi/dashforge#63 gap K). Pulled out of the spread
15311
+ // rather than passed through: React 19 writes an unknown lowercase
15312
+ // attribute to the DOM without a word, so `spacing={2}` would ship as
15313
+ // `spacing="2"` on the element while doing nothing to the layout.
15314
+ // That is BUG 9's failure mode, and the warning below is the signal
15315
+ // the consumer would otherwise never get.
15316
+ spacing: spacingAlias } = rest, safeRest = _object_without_properties_loose(rest, [
15317
+ "className",
15318
+ "spacing"
14684
15319
  ]);
15320
+ if (process.env.NODE_ENV !== 'production' && spacingAlias !== undefined && !warnedSpacingAlias) {
15321
+ warnedSpacingAlias = true;
15322
+ console.warn(`[@dashforge/tw] <Stack spacing={${JSON.stringify(spacingAlias)}}> ` + `has no effect: this component calls the axis \`gap\`. The value ` + `is dropped rather than forwarded, so it does not reach the DOM ` + `either. Use gap={${JSON.stringify(spacingAlias)}}.`);
15323
+ }
14685
15324
  const classes = cn(stackVariants({
14686
15325
  direction,
14687
15326
  align,
@@ -14698,22 +15337,24 @@ Typography.displayName = 'Typography';
14698
15337
  wrap,
14699
15338
  fullWidth,
14700
15339
  fullHeight
14701
- }), consumerClassName, sx);
15340
+ }), // RBAC-denied surfaces dim and carry the ARIA attributes assigned
15341
+ // below, so descendants and assistive tech can react.
15342
+ accessState.disabled && 'opacity-60', accessState.readonly && 'opacity-80', consumerClassName, sx);
14702
15343
  if (asChild) {
14703
15344
  // Slot expects a single child; divider has no place here.
14704
15345
  return jsx(Slot, _extends({
14705
15346
  ref: ref,
14706
15347
  className: classes
14707
- }, safeRest, {
15348
+ }, ariaProps, safeRest, {
14708
15349
  children: children
14709
15350
  }));
14710
15351
  }
14711
15352
  const Tag = as != null ? as : 'div';
14712
- const content = divider != null ? interleaveDividers(children, divider) : children;
15353
+ const content = divider != null ? interleaveDividers(children, divider, direction != null ? direction : 'col') : children;
14713
15354
  return jsx(Tag, _extends({
14714
15355
  ref: ref,
14715
15356
  className: classes
14716
- }, safeRest, {
15357
+ }, ariaProps, safeRest, {
14717
15358
  children: content
14718
15359
  }));
14719
15360
  });
@@ -14943,13 +15584,34 @@ Stack.displayName = 'Stack';
14943
15584
  // branches of the discriminated union.
14944
15585
  const themeDefaults = useComponentDefaults('Grid');
14945
15586
  const props = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, _props);
14946
- const { as, asChild = false, sx, children, className: consumerClassName } = props, rest = _object_without_properties_loose(props, [
15587
+ const { as, asChild = false, sx, visibleWhen, access, children, className: consumerClassName } = props, rest = _object_without_properties_loose(props, [
14947
15588
  "as",
14948
15589
  "asChild",
14949
15590
  "sx",
15591
+ "visibleWhen",
15592
+ "access",
14950
15593
  "children",
14951
15594
  "className"
14952
15595
  ]);
15596
+ // Bridge — hooks called unconditionally, ABOVE the early return and
15597
+ // above the union branching (rules-of-hooks; see README-BUG § BUG 33
15598
+ // for what a conditional subscription costs). Both are no-ops when
15599
+ // their prop is absent, so a consumer passing neither renders exactly
15600
+ // as before. Destructured out of `rest` so neither can reach the DOM.
15601
+ const bridge = useContext(DashFormContext);
15602
+ const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
15603
+ const accessState = useAccessState(access);
15604
+ // Early return — predicate false OR RBAC denies visibility.
15605
+ if (!isVisible || !accessState.visible) return null;
15606
+ // RBAC-denied surfaces dim and carry the ARIA attributes below, so
15607
+ // descendants and assistive tech can react.
15608
+ const accessClasses = cn(accessState.disabled && 'opacity-60', accessState.readonly && 'opacity-80');
15609
+ const ariaProps = {
15610
+ 'aria-disabled': accessState.disabled || undefined,
15611
+ 'aria-readonly': accessState.readonly || undefined,
15612
+ 'data-disabled': accessState.disabled || undefined,
15613
+ 'data-readonly': accessState.readonly || undefined
15614
+ };
14953
15615
  // #112 (G-28): salvage a stray untyped `className` that snuck in via
14954
15616
  // spread props so the JSX spread doesn't clobber the variant chain
14955
15617
  // via last-wins prop override. Merged through `cn` in both branches
@@ -14982,7 +15644,7 @@ Stack.displayName = 'Stack';
14982
15644
  spacingX: containerPayload.spacingX,
14983
15645
  spacingY: containerPayload.spacingY,
14984
15646
  autoFlow: containerPayload.autoFlow
14985
- }), consumerClassName, sx);
15647
+ }), accessClasses, consumerClassName, sx);
14986
15648
  } else {
14987
15649
  var _itemPayload_xs;
14988
15650
  itemPayload = props;
@@ -14995,7 +15657,7 @@ Stack.displayName = 'Stack';
14995
15657
  md: itemPayload.md,
14996
15658
  lg: itemPayload.lg,
14997
15659
  xl: itemPayload.xl
14998
- }), consumerClassName, sx);
15660
+ }), accessClasses, consumerClassName, sx);
14999
15661
  }
15000
15662
  /*
15001
15663
  * Strip role-specific props from `rest` before spreading on the DOM
@@ -15022,7 +15684,7 @@ Stack.displayName = 'Stack';
15022
15684
  return jsx(Slot, _extends({
15023
15685
  ref: ref,
15024
15686
  className: classes
15025
- }, domRest, {
15687
+ }, ariaProps, domRest, {
15026
15688
  children: children
15027
15689
  }));
15028
15690
  }
@@ -15030,7 +15692,7 @@ Stack.displayName = 'Stack';
15030
15692
  return jsx(Tag, _extends({
15031
15693
  ref: ref,
15032
15694
  className: classes
15033
- }, domRest, {
15695
+ }, ariaProps, domRest, {
15034
15696
  children: children
15035
15697
  }));
15036
15698
  });
@@ -15236,13 +15898,29 @@ Container.displayName = 'Container';
15236
15898
  * border-* color token to the intent.
15237
15899
  *
15238
15900
  * The `segment` axis distinguishes whether this is a line-only render
15239
- * (full width) vs a labeled-mode segment (flex-1 grows to share space).
15901
+ * (spans its own main axis) vs a labeled-mode segment (flex-1 grows to
15902
+ * share space).
15903
+ *
15904
+ * `full` means "span the divider's OWN main axis", which is the width
15905
+ * for a horizontal rule and the HEIGHT for a vertical one. It is
15906
+ * therefore orientation-dependent and lives in `compoundVariants`, not
15907
+ * on the plain axis. See README-BUG § BUG 25: an unconditional
15908
+ * `w-full` here fought the `w-0` from the orientation axis, tailwind-
15909
+ * merge kept the later `w-full`, and every vertical line-only divider
15910
+ * came out as a full-width bar with a left border.
15240
15911
  */ const dividerLineVariants = tv({
15241
15912
  base: '',
15242
15913
  variants: {
15243
15914
  orientation: {
15244
15915
  horizontal: 'h-0 border-t',
15245
- vertical: 'w-0 border-l self-stretch'
15916
+ /*
15917
+ * `w-0` does double duty and must NOT be dropped:
15918
+ * - in a `flex-row` parent it is the main-axis size, so the
15919
+ * visible width is exactly the 1px `border-l`;
15920
+ * - in a `flex-col` parent (labeled vertical mode) it is the
15921
+ * CROSS size, and being definite it stops `self-stretch` from
15922
+ * stretching the rule to the full width.
15923
+ */ vertical: 'w-0 border-l self-stretch'
15246
15924
  },
15247
15925
  variant: {
15248
15926
  solid: 'border-solid',
@@ -15260,13 +15938,30 @@ Container.displayName = 'Container';
15260
15938
  info: 'border-info-300 dark:border-info-700'
15261
15939
  },
15262
15940
  /*
15263
- * `segment` controls whether the line spans full width (line-only
15264
- * mode) or grows to fill space (labeled-mode flex segment).
15941
+ * `segment` controls whether the line spans its own main axis
15942
+ * (line-only mode) or grows to fill space (labeled-mode flex
15943
+ * segment).
15944
+ *
15945
+ * `full` is empty here on purpose: what "full" resolves to depends
15946
+ * on the orientation, so it is emitted from `compoundVariants`.
15947
+ * `grow` is genuinely orientation-agnostic — `flex-1` grows along
15948
+ * whichever main axis the parent sets — so it stays on the axis.
15265
15949
  */ segment: {
15266
- full: 'w-full',
15950
+ full: '',
15267
15951
  grow: 'flex-1'
15268
15952
  }
15269
15953
  },
15954
+ compoundVariants: [
15955
+ /*
15956
+ * Horizontal: `w-full` is load-bearing. A block child does NOT fill
15957
+ * the width once it is a flex item, which is exactly the toolbar
15958
+ * case, so the rule would collapse without this.
15959
+ */ {
15960
+ orientation: 'horizontal',
15961
+ segment: 'full',
15962
+ class: 'w-full'
15963
+ }
15964
+ ],
15270
15965
  defaultVariants: {
15271
15966
  orientation: 'horizontal',
15272
15967
  variant: 'solid',
@@ -15574,7 +16269,11 @@ VisuallyHidden.displayName = 'VisuallyHidden';
15574
16269
  'absolute top-4 right-4 inline-flex items-center justify-center',
15575
16270
  'h-8 w-8 rounded-md text-neutral-500 hover:text-neutral-900',
15576
16271
  'hover:bg-neutral-100',
15577
- 'focus:outline-none focus:ring-2 focus:ring-primary-500',
16272
+ // `focus-visible:`, not `focus:` — Radix moves focus into the panel
16273
+ // on open and this button is the first focusable thing in it, so a
16274
+ // plain `focus:ring` painted a ring on every mouse-opened dialog.
16275
+ // BUG 28. Matches the catalog's dominant form (9 other slots).
16276
+ 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
15578
16277
  'transition-colors'
15579
16278
  ],
15580
16279
  body: 'flex-1 overflow-y-auto',
@@ -15929,8 +16628,12 @@ const accordionVariants = tv({
15929
16628
  trigger: [
15930
16629
  'flex flex-1 items-center justify-between py-3 text-left',
15931
16630
  'text-sm font-medium text-neutral-900',
15932
- 'transition-all hover:underline',
15933
- 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:rounded',
16631
+ // `transition-all` covers transform-able properties, so it is
16632
+ // motion under WCAG 2.3.3 and needs the gate. Every other
16633
+ // `transition-transform` in the catalog has one; this was the
16634
+ // only movement left ungated.
16635
+ 'transition-all hover:underline motion-reduce:transition-none',
16636
+ 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:rounded-sm',
15934
16637
  '[&[data-state=open]>svg]:rotate-180',
15935
16638
  'disabled:opacity-50 disabled:pointer-events-none',
15936
16639
  'motion-reduce:transition-none'
@@ -17598,7 +18301,7 @@ function Row(props) {
17598
18301
  "aria-label": isExpanded ? labels.ariaCollapseRow : labels.ariaExpandRow,
17599
18302
  "aria-expanded": isExpanded,
17600
18303
  disabled: !isInteractive,
17601
- className: cn('inline-flex items-center justify-center h-6 w-6 rounded', // text-neutral-500 + hover bump; both auto-invert via CSS-var preset.
18304
+ className: cn('inline-flex items-center justify-center h-6 w-6 rounded-md', // text-neutral-500 + hover bump; both auto-invert via CSS-var preset.
17602
18305
  'text-neutral-500 hover:text-neutral-900', 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500', 'transition-transform motion-reduce:transition-none', isExpanded && 'rotate-90'),
17603
18306
  children: jsx(ChevronRightIcon, {})
17604
18307
  })
@@ -18345,7 +19048,7 @@ function ColumnFilterTrigger(props) {
18345
19048
  "aria-label": labels.filterColumn,
18346
19049
  "aria-pressed": active,
18347
19050
  disabled: disabled,
18348
- className: cn('inline-flex items-center justify-center h-6 w-6 rounded', 'text-neutral-500 hover:text-neutral-900', active && 'text-primary-700', 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500', 'transition-colors motion-reduce:transition-none', 'disabled:opacity-50 disabled:cursor-not-allowed'),
19051
+ className: cn('inline-flex items-center justify-center h-6 w-6 rounded-md', 'text-neutral-500 hover:text-neutral-900', active && 'text-primary-700', 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500', 'transition-colors motion-reduce:transition-none', 'disabled:opacity-50 disabled:cursor-not-allowed'),
18349
19052
  children: jsx(FilterIcon, {})
18350
19053
  })
18351
19054
  });
@@ -18727,7 +19430,7 @@ function ColumnVisibilityTrigger(props) {
18727
19430
  const header = typeof col.header === 'function' ? col.header() : col.header;
18728
19431
  return jsx("li", {
18729
19432
  children: jsxs("label", {
18730
- className: "flex items-center gap-2 cursor-pointer py-1 px-1 rounded hover:bg-neutral-100",
19433
+ className: "flex items-center gap-2 cursor-pointer py-1 px-1 rounded-md hover:bg-neutral-100",
18731
19434
  children: [
18732
19435
  jsx("input", {
18733
19436
  type: "checkbox",
@@ -19819,6 +20522,6 @@ function SearchIcon(props) {
19819
20522
  */ // ───── Components ─────
19820
20523
  /**
19821
20524
  * Package version (synced with `package.json` at publish time).
19822
- */ const VERSION = '1.5.2';
20525
+ */ const VERSION = '2.0.1';
19823
20526
 
19824
- export { AVATAR_SOFT_FALLBACK, AVATAR_TONE_FALLBACK, Accordion, Alert, AlertTitle, AppShell, AspectRatio, Autocomplete, Avatar, AvatarGroup, Badge, Box, Breadcrumbs, Button, Calendar, Card, CardActionArea, CardContent, Checkbox, Chip, ConfirmDialogProvider, Container, DRAWER_SIZE_PRESETS, DataGrid, DatePicker, DateRangePicker, DateTimePicker, Dialog, Divider, Drawer, Grid, ICON_BUTTON_BASE, ICON_BUTTON_SIZE_OVERRIDES, IconButton, Image, LeftNav, Link, Menu, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuSkeleton, MenuTrigger, NumberField, OTPField, Pagination, Popover, Progress, RadioGroup, RenderButton, RenderChip, RenderText, RenderTwoLine, RowActionsMenu, SPINNER_COLORS, SPINNER_STROKE_WIDTH, SPINNER_TRACK_OPACITY, Select, Skeleton, Slider, SnackbarProvider, Spinner, Stack, Step, Stepper, Switch, Table, Tabs, TextField, Textarea, TimePicker, Tooltip, TopBar, Typography, VERSION, Video, VisuallyHidden, accordionVariants, alertVariants, appShellVariants, autocompleteVariants, avatarVariants, badgeVariants, boxVariants, breadcrumbsVariants, buttonVariants, calendarDayVariants, calendarVariants, checkboxVariants, chipVariants, cn, confirmDialogVariants, containerVariants, dataGridVariants, datePickerVariants, dateRangeDayVariants, dateRangePickerVariants, dateTimePickerVariants, dialogVariants, dividerLineVariants, dividerVariants, drawerVariants, getNestedValue, gridVariants, imageVariants, leftNavVariants, linkVariants, menuVariants, numberFieldVariants, otpFieldVariants, paginationVariants, popoverVariants, progressVariants, radioGroupVariants, selectVariants, skeletonVariants, sliderVariants, snackbarVariants, spinnerVariants, stackVariants, stepperVariants, switchVariants, tableVariants, tabsVariants, textFieldVariants, textareaVariants, timePickerVariants, tooltipVariants, topBarVariants, typographyVariants, useAccessState, useConfirm, useSnackbar, useStep, videoVariants };
20527
+ export { AVATAR_SOFT_FALLBACK, AVATAR_TONE_FALLBACK, Accordion, Alert, AlertTitle, AppShell, AspectRatio, Autocomplete, Avatar, AvatarGroup, Badge, Box, Breadcrumbs, Button, Calendar, Card, CardActionArea, CardContent, Checkbox, Chip, ConfirmDialogProvider, Container, DRAWER_SIZE_PRESETS, DataGrid, DatePicker, DateRangePicker, DateTimePicker, Dialog, Divider, Drawer, Grid, ICON_BUTTON_BASE, ICON_BUTTON_SIZE_OVERRIDES, IconButton, Image, Kbd, LeftNav, Link, Menu, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuSkeleton, MenuTrigger, NumberField, OTPField, Pagination, Popover, Progress, RadioGroup, RenderButton, RenderChip, RenderText, RenderTwoLine, RowActionsMenu, SPINNER_COLORS, SPINNER_STROKE_WIDTH, SPINNER_TRACK_OPACITY, Select, Skeleton, Slider, SnackbarProvider, Spinner, Stack, Step, Stepper, Switch, Table, Tabs, TextField, Textarea, TimePicker, Tooltip, TopBar, TopBarBrand, Typography, VERSION, Video, VisuallyHidden, accordionVariants, alertVariants, appShellVariants, autocompleteVariants, avatarVariants, badgeVariants, boxVariants, breadcrumbsVariants, buttonVariants, calendarDayVariants, calendarVariants, checkboxVariants, chipVariants, cn, confirmDialogVariants, containerVariants, dataGridVariants, datePickerVariants, dateRangeDayVariants, dateRangePickerVariants, dateTimePickerVariants, dialogVariants, dividerLineVariants, dividerVariants, drawerVariants, getNestedValue, gridVariants, imageVariants, kbdVariants, leftNavVariants, linkVariants, menuVariants, numberFieldVariants, otpFieldVariants, paginationVariants, popoverVariants, progressVariants, radioGroupVariants, selectVariants, skeletonVariants, sliderVariants, snackbarVariants, spinnerVariants, stackVariants, stepperVariants, switchVariants, tableVariants, tabsVariants, textFieldVariants, textareaVariants, timePickerVariants, tooltipVariants, topBarVariants, typographyVariants, useAccessState, useConfirm, useSnackbar, useStep, videoVariants };