@dashforge/tw 1.0.0 → 1.1.0

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 (396) hide show
  1. package/CHANGELOG.md +221 -0
  2. package/README.md +74 -15
  3. package/dashforge-tw-1.0.0.tgz +0 -0
  4. package/dist/index.d.ts +1 -146
  5. package/dist/index.esm.js +3127 -748
  6. package/dist/src/components/Alert/Alert.d.ts +65 -0
  7. package/dist/src/components/Alert/Alert.d.ts.map +1 -0
  8. package/dist/src/components/Alert/alert.types.d.ts +130 -0
  9. package/dist/src/components/Alert/alert.types.d.ts.map +1 -0
  10. package/dist/src/components/Alert/alert.variants.d.ts +85 -0
  11. package/dist/src/components/Alert/alert.variants.d.ts.map +1 -0
  12. package/dist/src/components/Avatar/Avatar.d.ts +48 -0
  13. package/dist/src/components/Avatar/Avatar.d.ts.map +1 -0
  14. package/dist/src/components/Avatar/avatar.types.d.ts +162 -0
  15. package/dist/src/components/Avatar/avatar.types.d.ts.map +1 -0
  16. package/dist/src/components/Avatar/avatar.variants.d.ts +208 -0
  17. package/dist/src/components/Avatar/avatar.variants.d.ts.map +1 -0
  18. package/dist/src/components/Badge/Badge.d.ts +63 -0
  19. package/dist/src/components/Badge/Badge.d.ts.map +1 -0
  20. package/dist/src/components/Badge/badge.types.d.ts +124 -0
  21. package/dist/src/components/Badge/badge.types.d.ts.map +1 -0
  22. package/dist/src/components/Badge/badge.variants.d.ts +262 -0
  23. package/dist/src/components/Badge/badge.variants.d.ts.map +1 -0
  24. package/dist/src/components/Box/Box.d.ts.map +1 -1
  25. package/dist/src/components/Box/box.types.d.ts +53 -0
  26. package/dist/src/components/Box/box.types.d.ts.map +1 -1
  27. package/dist/src/components/Button/Button.d.ts.map +1 -1
  28. package/dist/src/components/Button/button.types.d.ts +35 -0
  29. package/dist/src/components/Button/button.types.d.ts.map +1 -1
  30. package/dist/src/components/Card/Card.d.ts +107 -0
  31. package/dist/src/components/Card/Card.d.ts.map +1 -0
  32. package/dist/src/components/Card/card.types.d.ts +119 -0
  33. package/dist/src/components/Card/card.types.d.ts.map +1 -0
  34. package/dist/src/components/Chip/Chip.d.ts +67 -0
  35. package/dist/src/components/Chip/Chip.d.ts.map +1 -0
  36. package/dist/src/components/Chip/chip.types.d.ts +113 -0
  37. package/dist/src/components/Chip/chip.types.d.ts.map +1 -0
  38. package/dist/src/components/Chip/chip.variants.d.ts +155 -0
  39. package/dist/src/components/Chip/chip.variants.d.ts.map +1 -0
  40. package/dist/src/components/IconButton/IconButton.d.ts +57 -0
  41. package/dist/src/components/IconButton/IconButton.d.ts.map +1 -0
  42. package/dist/src/components/IconButton/iconButton.types.d.ts +96 -0
  43. package/dist/src/components/IconButton/iconButton.types.d.ts.map +1 -0
  44. package/dist/src/components/IconButton/iconButton.variants.d.ts +26 -0
  45. package/dist/src/components/IconButton/iconButton.variants.d.ts.map +1 -0
  46. package/dist/src/components/Menu/Menu.d.ts +118 -0
  47. package/dist/src/components/Menu/Menu.d.ts.map +1 -0
  48. package/dist/src/components/Menu/menu.types.d.ts +179 -0
  49. package/dist/src/components/Menu/menu.types.d.ts.map +1 -0
  50. package/dist/src/components/Menu/menu.variants.d.ts +129 -0
  51. package/dist/src/components/Menu/menu.variants.d.ts.map +1 -0
  52. package/dist/src/components/Snackbar/Snackbar.d.ts.map +1 -1
  53. package/dist/src/components/Snackbar/snackbar.types.d.ts +40 -3
  54. package/dist/src/components/Snackbar/snackbar.types.d.ts.map +1 -1
  55. package/dist/src/components/Snackbar/snackbar.variants.d.ts +12 -57
  56. package/dist/src/components/Snackbar/snackbar.variants.d.ts.map +1 -1
  57. package/dist/src/components/Spinner/Spinner.d.ts +44 -0
  58. package/dist/src/components/Spinner/Spinner.d.ts.map +1 -0
  59. package/dist/src/components/Spinner/spinner.types.d.ts +89 -0
  60. package/dist/src/components/Spinner/spinner.types.d.ts.map +1 -0
  61. package/dist/src/components/Spinner/spinner.variants.d.ts +111 -0
  62. package/dist/src/components/Spinner/spinner.variants.d.ts.map +1 -0
  63. package/dist/src/components/Table/cells/RenderChip.d.ts +15 -72
  64. package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -1
  65. package/dist/src/components/_shared/severity/index.d.ts +21 -0
  66. package/dist/src/components/_shared/severity/index.d.ts.map +1 -0
  67. package/dist/src/components/_shared/severity/severity.types.d.ts +48 -0
  68. package/dist/src/components/_shared/severity/severity.types.d.ts.map +1 -0
  69. package/dist/src/components/_shared/severity/severityIcons.d.ts +45 -0
  70. package/dist/src/components/_shared/severity/severityIcons.d.ts.map +1 -0
  71. package/dist/src/components/_shared/severity/severityVariants.d.ts +22 -0
  72. package/dist/src/components/_shared/severity/severityVariants.d.ts.map +1 -0
  73. package/dist/src/index.d.ts +27 -2
  74. package/dist/src/index.d.ts.map +1 -1
  75. package/package.json +2 -1
  76. package/src/components/Alert/Alert.test.tsx +302 -0
  77. package/src/components/Alert/Alert.tsx +186 -0
  78. package/src/components/Alert/alert.types.ts +144 -0
  79. package/src/components/Alert/alert.variants.ts +71 -0
  80. package/src/components/Autocomplete/autocomplete.variants.ts +1 -1
  81. package/src/components/Avatar/Avatar.test.tsx +287 -0
  82. package/src/components/Avatar/Avatar.tsx +304 -0
  83. package/src/components/Avatar/avatar.types.ts +205 -0
  84. package/src/components/Avatar/avatar.variants.ts +194 -0
  85. package/src/components/Badge/Badge.test.tsx +385 -0
  86. package/src/components/Badge/Badge.tsx +174 -0
  87. package/src/components/Badge/badge.types.ts +154 -0
  88. package/src/components/Badge/badge.variants.ts +161 -0
  89. package/src/components/Box/Box.test.tsx +21 -0
  90. package/src/components/Box/Box.tsx +32 -3
  91. package/src/components/Box/box.types.ts +55 -0
  92. package/src/components/Button/Button.test.tsx +21 -0
  93. package/src/components/Button/Button.tsx +28 -27
  94. package/src/components/Button/button.types.ts +36 -0
  95. package/src/components/Card/Card.test.tsx +291 -0
  96. package/src/components/Card/Card.tsx +241 -0
  97. package/src/components/Card/card.types.ts +132 -0
  98. package/src/components/Chip/Chip.test.tsx +316 -0
  99. package/src/components/Chip/Chip.tsx +224 -0
  100. package/src/components/Chip/chip.types.ts +128 -0
  101. package/src/components/Chip/chip.variants.ts +173 -0
  102. package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +1 -1
  103. package/src/components/IconButton/IconButton.test.tsx +367 -0
  104. package/src/components/IconButton/IconButton.tsx +159 -0
  105. package/src/components/IconButton/iconButton.types.ts +106 -0
  106. package/src/components/IconButton/iconButton.variants.ts +31 -0
  107. package/src/components/LeftNav/leftNav.variants.ts +2 -2
  108. package/src/components/Menu/Menu.test.tsx +408 -0
  109. package/src/components/Menu/Menu.tsx +335 -0
  110. package/src/components/Menu/menu.types.ts +221 -0
  111. package/src/components/Menu/menu.variants.ts +132 -0
  112. package/src/components/Pagination/pagination.variants.ts +1 -1
  113. package/src/components/Snackbar/Snackbar.tsx +46 -28
  114. package/src/components/Snackbar/snackbar.types.ts +47 -3
  115. package/src/components/Snackbar/snackbar.variants.ts +29 -22
  116. package/src/components/Spinner/Spinner.test.tsx +199 -0
  117. package/src/components/Spinner/Spinner.tsx +158 -0
  118. package/src/components/Spinner/spinner.types.ts +113 -0
  119. package/src/components/Spinner/spinner.variants.ts +83 -0
  120. package/src/components/Table/cells/RenderChip.tsx +24 -87
  121. package/src/components/Table/cells/RowActionsMenu.tsx +1 -1
  122. package/src/components/_shared/severity/index.ts +33 -0
  123. package/src/components/_shared/severity/severity.types.ts +50 -0
  124. package/src/components/_shared/severity/severityIcons.tsx +104 -0
  125. package/src/components/_shared/severity/severityVariants.test.ts +136 -0
  126. package/src/components/_shared/severity/severityVariants.ts +115 -0
  127. package/src/index.ts +163 -1
  128. package/LICENSE +0 -21
  129. package/dist/components/Accordion/Accordion.d.ts +0 -21
  130. package/dist/components/Accordion/Accordion.d.ts.map +0 -1
  131. package/dist/components/Accordion/accordion.types.d.ts +0 -74
  132. package/dist/components/Accordion/accordion.types.d.ts.map +0 -1
  133. package/dist/components/Accordion/accordion.variants.d.ts +0 -58
  134. package/dist/components/Accordion/accordion.variants.d.ts.map +0 -1
  135. package/dist/components/AppShell/AppShell.d.ts +0 -46
  136. package/dist/components/AppShell/AppShell.d.ts.map +0 -1
  137. package/dist/components/AppShell/appShell.types.d.ts +0 -62
  138. package/dist/components/AppShell/appShell.types.d.ts.map +0 -1
  139. package/dist/components/AppShell/appShell.variants.d.ts +0 -65
  140. package/dist/components/AppShell/appShell.variants.d.ts.map +0 -1
  141. package/dist/components/AspectRatio/AspectRatio.d.ts +0 -36
  142. package/dist/components/AspectRatio/AspectRatio.d.ts.map +0 -1
  143. package/dist/components/AspectRatio/aspectRatio.types.d.ts +0 -50
  144. package/dist/components/AspectRatio/aspectRatio.types.d.ts.map +0 -1
  145. package/dist/components/Autocomplete/Autocomplete.d.ts +0 -32
  146. package/dist/components/Autocomplete/Autocomplete.d.ts.map +0 -1
  147. package/dist/components/Autocomplete/autocomplete.types.d.ts +0 -214
  148. package/dist/components/Autocomplete/autocomplete.types.d.ts.map +0 -1
  149. package/dist/components/Autocomplete/autocomplete.variants.d.ts +0 -214
  150. package/dist/components/Autocomplete/autocomplete.variants.d.ts.map +0 -1
  151. package/dist/components/Box/Box.d.ts +0 -36
  152. package/dist/components/Box/Box.d.ts.map +0 -1
  153. package/dist/components/Box/box.types.d.ts +0 -54
  154. package/dist/components/Box/box.types.d.ts.map +0 -1
  155. package/dist/components/Box/box.variants.d.ts +0 -402
  156. package/dist/components/Box/box.variants.d.ts.map +0 -1
  157. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +0 -23
  158. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts.map +0 -1
  159. package/dist/components/Breadcrumbs/breadcrumbs.types.d.ts +0 -98
  160. package/dist/components/Breadcrumbs/breadcrumbs.types.d.ts.map +0 -1
  161. package/dist/components/Breadcrumbs/breadcrumbs.variants.d.ts +0 -85
  162. package/dist/components/Breadcrumbs/breadcrumbs.variants.d.ts.map +0 -1
  163. package/dist/components/Button/Button.d.ts +0 -44
  164. package/dist/components/Button/Button.d.ts.map +0 -1
  165. package/dist/components/Button/button.types.d.ts +0 -66
  166. package/dist/components/Button/button.types.d.ts.map +0 -1
  167. package/dist/components/Button/button.variants.d.ts +0 -104
  168. package/dist/components/Button/button.variants.d.ts.map +0 -1
  169. package/dist/components/Calendar/Calendar.d.ts +0 -14
  170. package/dist/components/Calendar/Calendar.d.ts.map +0 -1
  171. package/dist/components/Calendar/calendar.types.d.ts +0 -72
  172. package/dist/components/Calendar/calendar.types.d.ts.map +0 -1
  173. package/dist/components/Calendar/calendar.variants.d.ts +0 -99
  174. package/dist/components/Calendar/calendar.variants.d.ts.map +0 -1
  175. package/dist/components/Checkbox/Checkbox.d.ts +0 -31
  176. package/dist/components/Checkbox/Checkbox.d.ts.map +0 -1
  177. package/dist/components/Checkbox/checkbox.types.d.ts +0 -86
  178. package/dist/components/Checkbox/checkbox.types.d.ts.map +0 -1
  179. package/dist/components/Checkbox/checkbox.variants.d.ts +0 -109
  180. package/dist/components/Checkbox/checkbox.variants.d.ts.map +0 -1
  181. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +0 -38
  182. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +0 -1
  183. package/dist/components/ConfirmDialog/confirmDialog.types.d.ts +0 -80
  184. package/dist/components/ConfirmDialog/confirmDialog.types.d.ts.map +0 -1
  185. package/dist/components/ConfirmDialog/confirmDialog.variants.d.ts +0 -90
  186. package/dist/components/ConfirmDialog/confirmDialog.variants.d.ts.map +0 -1
  187. package/dist/components/Container/Container.d.ts +0 -35
  188. package/dist/components/Container/Container.d.ts.map +0 -1
  189. package/dist/components/Container/container.types.d.ts +0 -41
  190. package/dist/components/Container/container.types.d.ts.map +0 -1
  191. package/dist/components/Container/container.variants.d.ts +0 -93
  192. package/dist/components/Container/container.variants.d.ts.map +0 -1
  193. package/dist/components/DataGrid/DataGrid.d.ts +0 -29
  194. package/dist/components/DataGrid/DataGrid.d.ts.map +0 -1
  195. package/dist/components/DataGrid/dataGrid.types.d.ts +0 -214
  196. package/dist/components/DataGrid/dataGrid.types.d.ts.map +0 -1
  197. package/dist/components/DataGrid/dataGrid.variants.d.ts +0 -222
  198. package/dist/components/DataGrid/dataGrid.variants.d.ts.map +0 -1
  199. package/dist/components/DataGrid/filters/ColumnFilters.d.ts +0 -23
  200. package/dist/components/DataGrid/filters/ColumnFilters.d.ts.map +0 -1
  201. package/dist/components/DataGrid/reorder/useColumnReorder.d.ts +0 -50
  202. package/dist/components/DataGrid/reorder/useColumnReorder.d.ts.map +0 -1
  203. package/dist/components/DataGrid/resize/useColumnResize.d.ts +0 -39
  204. package/dist/components/DataGrid/resize/useColumnResize.d.ts.map +0 -1
  205. package/dist/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts +0 -44
  206. package/dist/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts.map +0 -1
  207. package/dist/components/DatePicker/DatePicker.d.ts +0 -14
  208. package/dist/components/DatePicker/DatePicker.d.ts.map +0 -1
  209. package/dist/components/DatePicker/datePicker.types.d.ts +0 -88
  210. package/dist/components/DatePicker/datePicker.types.d.ts.map +0 -1
  211. package/dist/components/DatePicker/datePicker.variants.d.ts +0 -97
  212. package/dist/components/DatePicker/datePicker.variants.d.ts.map +0 -1
  213. package/dist/components/DateRangePicker/DateRangePicker.d.ts +0 -13
  214. package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +0 -1
  215. package/dist/components/DateRangePicker/dateRangePicker.types.d.ts +0 -85
  216. package/dist/components/DateRangePicker/dateRangePicker.types.d.ts.map +0 -1
  217. package/dist/components/DateRangePicker/dateRangePicker.variants.d.ts +0 -183
  218. package/dist/components/DateRangePicker/dateRangePicker.variants.d.ts.map +0 -1
  219. package/dist/components/DateTimePicker/DateTimePicker.d.ts +0 -13
  220. package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +0 -1
  221. package/dist/components/DateTimePicker/dateTimePicker.types.d.ts +0 -90
  222. package/dist/components/DateTimePicker/dateTimePicker.types.d.ts.map +0 -1
  223. package/dist/components/DateTimePicker/dateTimePicker.variants.d.ts +0 -107
  224. package/dist/components/DateTimePicker/dateTimePicker.variants.d.ts.map +0 -1
  225. package/dist/components/Dialog/Dialog.d.ts +0 -17
  226. package/dist/components/Dialog/Dialog.d.ts.map +0 -1
  227. package/dist/components/Dialog/dialog.types.d.ts +0 -75
  228. package/dist/components/Dialog/dialog.types.d.ts.map +0 -1
  229. package/dist/components/Dialog/dialog.variants.d.ts +0 -80
  230. package/dist/components/Dialog/dialog.variants.d.ts.map +0 -1
  231. package/dist/components/Divider/Divider.d.ts +0 -50
  232. package/dist/components/Divider/Divider.d.ts.map +0 -1
  233. package/dist/components/Divider/divider.types.d.ts +0 -47
  234. package/dist/components/Divider/divider.types.d.ts.map +0 -1
  235. package/dist/components/Divider/divider.variants.d.ts +0 -129
  236. package/dist/components/Divider/divider.variants.d.ts.map +0 -1
  237. package/dist/components/Grid/Grid.d.ts +0 -32
  238. package/dist/components/Grid/Grid.d.ts.map +0 -1
  239. package/dist/components/Grid/grid.types.d.ts +0 -103
  240. package/dist/components/Grid/grid.types.d.ts.map +0 -1
  241. package/dist/components/Grid/grid.variants.d.ts +0 -453
  242. package/dist/components/Grid/grid.variants.d.ts.map +0 -1
  243. package/dist/components/LeftNav/LeftNav.d.ts +0 -34
  244. package/dist/components/LeftNav/LeftNav.d.ts.map +0 -1
  245. package/dist/components/LeftNav/leftNav.types.d.ts +0 -136
  246. package/dist/components/LeftNav/leftNav.types.d.ts.map +0 -1
  247. package/dist/components/LeftNav/leftNav.variants.d.ts +0 -143
  248. package/dist/components/LeftNav/leftNav.variants.d.ts.map +0 -1
  249. package/dist/components/NumberField/NumberField.d.ts +0 -18
  250. package/dist/components/NumberField/NumberField.d.ts.map +0 -1
  251. package/dist/components/NumberField/numberField.types.d.ts +0 -79
  252. package/dist/components/NumberField/numberField.types.d.ts.map +0 -1
  253. package/dist/components/NumberField/numberField.variants.d.ts +0 -169
  254. package/dist/components/NumberField/numberField.variants.d.ts.map +0 -1
  255. package/dist/components/OTPField/OTPField.d.ts +0 -25
  256. package/dist/components/OTPField/OTPField.d.ts.map +0 -1
  257. package/dist/components/OTPField/otpField.types.d.ts +0 -74
  258. package/dist/components/OTPField/otpField.types.d.ts.map +0 -1
  259. package/dist/components/OTPField/otpField.variants.d.ts +0 -105
  260. package/dist/components/OTPField/otpField.variants.d.ts.map +0 -1
  261. package/dist/components/Pagination/Pagination.d.ts +0 -32
  262. package/dist/components/Pagination/Pagination.d.ts.map +0 -1
  263. package/dist/components/Pagination/pagination.helpers.d.ts +0 -23
  264. package/dist/components/Pagination/pagination.helpers.d.ts.map +0 -1
  265. package/dist/components/Pagination/pagination.types.d.ts +0 -120
  266. package/dist/components/Pagination/pagination.types.d.ts.map +0 -1
  267. package/dist/components/Pagination/pagination.variants.d.ts +0 -150
  268. package/dist/components/Pagination/pagination.variants.d.ts.map +0 -1
  269. package/dist/components/Popover/Popover.d.ts +0 -15
  270. package/dist/components/Popover/Popover.d.ts.map +0 -1
  271. package/dist/components/Popover/popover.types.d.ts +0 -45
  272. package/dist/components/Popover/popover.types.d.ts.map +0 -1
  273. package/dist/components/Popover/popover.variants.d.ts +0 -34
  274. package/dist/components/Popover/popover.variants.d.ts.map +0 -1
  275. package/dist/components/RadioGroup/RadioGroup.d.ts +0 -35
  276. package/dist/components/RadioGroup/RadioGroup.d.ts.map +0 -1
  277. package/dist/components/RadioGroup/radioGroup.types.d.ts +0 -103
  278. package/dist/components/RadioGroup/radioGroup.types.d.ts.map +0 -1
  279. package/dist/components/RadioGroup/radioGroup.variants.d.ts +0 -166
  280. package/dist/components/RadioGroup/radioGroup.variants.d.ts.map +0 -1
  281. package/dist/components/Skeleton/Skeleton.d.ts +0 -23
  282. package/dist/components/Skeleton/Skeleton.d.ts.map +0 -1
  283. package/dist/components/Skeleton/skeleton.types.d.ts +0 -56
  284. package/dist/components/Skeleton/skeleton.types.d.ts.map +0 -1
  285. package/dist/components/Skeleton/skeleton.variants.d.ts +0 -110
  286. package/dist/components/Skeleton/skeleton.variants.d.ts.map +0 -1
  287. package/dist/components/Snackbar/Snackbar.d.ts +0 -37
  288. package/dist/components/Snackbar/Snackbar.d.ts.map +0 -1
  289. package/dist/components/Snackbar/snackbar.types.d.ts +0 -86
  290. package/dist/components/Snackbar/snackbar.types.d.ts.map +0 -1
  291. package/dist/components/Snackbar/snackbar.variants.d.ts +0 -153
  292. package/dist/components/Snackbar/snackbar.variants.d.ts.map +0 -1
  293. package/dist/components/Stack/Stack.d.ts +0 -24
  294. package/dist/components/Stack/Stack.d.ts.map +0 -1
  295. package/dist/components/Stack/stack.types.d.ts +0 -61
  296. package/dist/components/Stack/stack.types.d.ts.map +0 -1
  297. package/dist/components/Stack/stack.variants.d.ts +0 -163
  298. package/dist/components/Stack/stack.variants.d.ts.map +0 -1
  299. package/dist/components/Switch/Switch.d.ts +0 -15
  300. package/dist/components/Switch/Switch.d.ts.map +0 -1
  301. package/dist/components/Switch/switch.types.d.ts +0 -47
  302. package/dist/components/Switch/switch.types.d.ts.map +0 -1
  303. package/dist/components/Switch/switch.variants.d.ts +0 -105
  304. package/dist/components/Switch/switch.variants.d.ts.map +0 -1
  305. package/dist/components/Table/Table.d.ts +0 -24
  306. package/dist/components/Table/Table.d.ts.map +0 -1
  307. package/dist/components/Table/cells/RenderButton.d.ts +0 -13
  308. package/dist/components/Table/cells/RenderButton.d.ts.map +0 -1
  309. package/dist/components/Table/cells/RenderChip.d.ts +0 -80
  310. package/dist/components/Table/cells/RenderChip.d.ts.map +0 -1
  311. package/dist/components/Table/cells/RenderText.d.ts +0 -21
  312. package/dist/components/Table/cells/RenderText.d.ts.map +0 -1
  313. package/dist/components/Table/cells/RenderTwoLine.d.ts +0 -20
  314. package/dist/components/Table/cells/RenderTwoLine.d.ts.map +0 -1
  315. package/dist/components/Table/cells/RowActionsMenu.d.ts +0 -36
  316. package/dist/components/Table/cells/RowActionsMenu.d.ts.map +0 -1
  317. package/dist/components/Table/cells/index.d.ts +0 -11
  318. package/dist/components/Table/cells/index.d.ts.map +0 -1
  319. package/dist/components/Table/table.types.d.ts +0 -399
  320. package/dist/components/Table/table.types.d.ts.map +0 -1
  321. package/dist/components/Table/table.variants.d.ts +0 -285
  322. package/dist/components/Table/table.variants.d.ts.map +0 -1
  323. package/dist/components/Tabs/Tabs.d.ts +0 -19
  324. package/dist/components/Tabs/Tabs.d.ts.map +0 -1
  325. package/dist/components/Tabs/tabs.types.d.ts +0 -61
  326. package/dist/components/Tabs/tabs.types.d.ts.map +0 -1
  327. package/dist/components/Tabs/tabs.variants.d.ts +0 -82
  328. package/dist/components/Tabs/tabs.variants.d.ts.map +0 -1
  329. package/dist/components/Tabs/useTabs.d.ts +0 -55
  330. package/dist/components/Tabs/useTabs.d.ts.map +0 -1
  331. package/dist/components/TextField/TextField.d.ts +0 -25
  332. package/dist/components/TextField/TextField.d.ts.map +0 -1
  333. package/dist/components/TextField/textField.types.d.ts +0 -98
  334. package/dist/components/TextField/textField.types.d.ts.map +0 -1
  335. package/dist/components/TextField/textField.variants.d.ts +0 -166
  336. package/dist/components/TextField/textField.variants.d.ts.map +0 -1
  337. package/dist/components/Textarea/Textarea.d.ts +0 -16
  338. package/dist/components/Textarea/Textarea.d.ts.map +0 -1
  339. package/dist/components/Textarea/textarea.types.d.ts +0 -63
  340. package/dist/components/Textarea/textarea.types.d.ts.map +0 -1
  341. package/dist/components/Textarea/textarea.variants.d.ts +0 -197
  342. package/dist/components/Textarea/textarea.variants.d.ts.map +0 -1
  343. package/dist/components/TimePicker/TimePicker.d.ts +0 -12
  344. package/dist/components/TimePicker/TimePicker.d.ts.map +0 -1
  345. package/dist/components/TimePicker/timePicker.types.d.ts +0 -80
  346. package/dist/components/TimePicker/timePicker.types.d.ts.map +0 -1
  347. package/dist/components/TimePicker/timePicker.variants.d.ts +0 -103
  348. package/dist/components/TimePicker/timePicker.variants.d.ts.map +0 -1
  349. package/dist/components/Tooltip/Tooltip.d.ts +0 -29
  350. package/dist/components/Tooltip/Tooltip.d.ts.map +0 -1
  351. package/dist/components/Tooltip/tooltip.types.d.ts +0 -47
  352. package/dist/components/Tooltip/tooltip.types.d.ts.map +0 -1
  353. package/dist/components/Tooltip/tooltip.variants.d.ts +0 -34
  354. package/dist/components/Tooltip/tooltip.variants.d.ts.map +0 -1
  355. package/dist/components/TopBar/TopBar.d.ts +0 -33
  356. package/dist/components/TopBar/TopBar.d.ts.map +0 -1
  357. package/dist/components/TopBar/topBar.types.d.ts +0 -49
  358. package/dist/components/TopBar/topBar.types.d.ts.map +0 -1
  359. package/dist/components/TopBar/topBar.variants.d.ts +0 -79
  360. package/dist/components/TopBar/topBar.variants.d.ts.map +0 -1
  361. package/dist/components/Typography/Typography.d.ts +0 -42
  362. package/dist/components/Typography/Typography.d.ts.map +0 -1
  363. package/dist/components/Typography/typography.types.d.ts +0 -61
  364. package/dist/components/Typography/typography.types.d.ts.map +0 -1
  365. package/dist/components/Typography/typography.variants.d.ts +0 -167
  366. package/dist/components/Typography/typography.variants.d.ts.map +0 -1
  367. package/dist/components/VisuallyHidden/VisuallyHidden.d.ts +0 -42
  368. package/dist/components/VisuallyHidden/VisuallyHidden.d.ts.map +0 -1
  369. package/dist/components/VisuallyHidden/visuallyHidden.types.d.ts +0 -42
  370. package/dist/components/VisuallyHidden/visuallyHidden.types.d.ts.map +0 -1
  371. package/dist/components/_shared/data/getNestedValue.d.ts +0 -20
  372. package/dist/components/_shared/data/getNestedValue.d.ts.map +0 -1
  373. package/dist/components/_shared/data/useColumnAutoDetect.d.ts +0 -45
  374. package/dist/components/_shared/data/useColumnAutoDetect.d.ts.map +0 -1
  375. package/dist/components/_shared/data/useControllableState.d.ts +0 -23
  376. package/dist/components/_shared/data/useControllableState.d.ts.map +0 -1
  377. package/dist/components/_shared/data/useDebouncedValue.d.ts +0 -10
  378. package/dist/components/_shared/data/useDebouncedValue.d.ts.map +0 -1
  379. package/dist/components/_shared/data/useTableFilter.d.ts +0 -36
  380. package/dist/components/_shared/data/useTableFilter.d.ts.map +0 -1
  381. package/dist/components/_shared/data/useTableSearch.d.ts +0 -23
  382. package/dist/components/_shared/data/useTableSearch.d.ts.map +0 -1
  383. package/dist/components/_shared/data/useTableSelection.d.ts +0 -25
  384. package/dist/components/_shared/data/useTableSelection.d.ts.map +0 -1
  385. package/dist/components/_shared/data/useTableSort.d.ts +0 -20
  386. package/dist/components/_shared/data/useTableSort.d.ts.map +0 -1
  387. package/dist/components/_shared/data/useVirtualizer.d.ts +0 -107
  388. package/dist/components/_shared/data/useVirtualizer.d.ts.map +0 -1
  389. package/dist/components/_shared/resolveValidationState.d.ts +0 -42
  390. package/dist/components/_shared/resolveValidationState.d.ts.map +0 -1
  391. package/dist/hooks/useAccessState.d.ts +0 -37
  392. package/dist/hooks/useAccessState.d.ts.map +0 -1
  393. package/dist/index.d.ts.map +0 -1
  394. package/dist/tsconfig.lib.tsbuildinfo +0 -1
  395. package/dist/utils/cn.d.ts +0 -26
  396. package/dist/utils/cn.d.ts.map +0 -1
@@ -0,0 +1,154 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ClassValue } from 'tailwind-variants';
3
+ import type { Engine } from '@dashforge/ui-core';
4
+ import type { AccessRequirement } from '@dashforge/rbac';
5
+
6
+ /**
7
+ * Intent color — drives the badge background. Default is `danger`
8
+ * because the most common notification UX expects a red dot/count
9
+ * for "needs attention" affordance.
10
+ */
11
+ export type BadgeColor =
12
+ | 'neutral'
13
+ | 'primary'
14
+ | 'secondary'
15
+ | 'success'
16
+ | 'warning'
17
+ | 'danger'
18
+ | 'info';
19
+
20
+ /** 4 corner positions for the floating badge. */
21
+ export type BadgePlacement =
22
+ | 'top-right'
23
+ | 'top-left'
24
+ | 'bottom-right'
25
+ | 'bottom-left';
26
+
27
+ /**
28
+ * Anchor shape:
29
+ * - `'rectangular'` (default) — badge sits at the bounding-box
30
+ * corner. Use for square-ish anchors like IconButton, Card.
31
+ * - `'circular'` — badge offset to align with the circular edge.
32
+ * Use for round anchors like Avatar.
33
+ */
34
+ export type BadgeOverlap = 'rectangular' | 'circular';
35
+
36
+ /**
37
+ * Per-slot className overrides for `<Badge>`.
38
+ */
39
+ export interface BadgeSlotProps {
40
+ /** Outer wrapper (relative-positioned, contains the anchor + badge). */
41
+ root?: { className?: string };
42
+ /** The floating badge pill / dot itself. */
43
+ badge?: { className?: string };
44
+ }
45
+
46
+ /**
47
+ * Props for `<Badge>` — anchored indicator (count / dot / short text).
48
+ *
49
+ * Wrapper-only mode: `<Badge>` always wraps an anchor element passed
50
+ * as `children`. For standalone inline pills (status labels, tags),
51
+ * use `<Chip>` — Badge and Chip are complementary, not interchangeable.
52
+ *
53
+ * Relationship with Chip:
54
+ * - `<Chip>` = inline pill (interactive — `onClick`, `onDelete`,
55
+ * `selected`). Standalone, no anchor.
56
+ * - `<Badge>` = anchored indicator (passive — small count / dot
57
+ * overlaid on top of another element).
58
+ */
59
+ export interface BadgeProps {
60
+ // ─── Required ──────────────────────────────────────────────────
61
+ /** The anchor element (Avatar / IconButton / button / Card / custom). */
62
+ children: ReactNode;
63
+
64
+ // ─── Content ───────────────────────────────────────────────────
65
+ /**
66
+ * Numeric or string content to display inside the badge.
67
+ * - `number` → formatted via `max` (overflow renders as `"N+"`)
68
+ * - `string` → rendered verbatim (e.g., `"NEW"`)
69
+ * - omitted + `dot=false` → no badge rendered (or only at zero if
70
+ * `showZero=true`)
71
+ */
72
+ content?: number | string;
73
+
74
+ /**
75
+ * Dot-only mode — small circle without content. When `true`,
76
+ * `content` and `max` are ignored.
77
+ */
78
+ dot?: boolean;
79
+
80
+ /**
81
+ * Overflow threshold for numeric `content`. Values above render
82
+ * as `{max}+`. Set to `-1` to disable overflow (always raw number).
83
+ * @default 99
84
+ */
85
+ max?: number;
86
+
87
+ /**
88
+ * Whether to render the badge when numeric `content` is `0`.
89
+ * Hidden by default — the typical notification UX is "no badge =
90
+ * nothing to see".
91
+ * @default false
92
+ */
93
+ showZero?: boolean;
94
+
95
+ /**
96
+ * Imperative hide — keeps the badge in the DOM but applies
97
+ * `display: none`. Use for opacity/scale fade animations without
98
+ * unmounting.
99
+ * @default false
100
+ */
101
+ invisible?: boolean;
102
+
103
+ // ─── Visual ────────────────────────────────────────────────────
104
+ /** @default 'danger' — typical "needs attention" notification color. */
105
+ color?: BadgeColor;
106
+
107
+ /** @default 'top-right' */
108
+ placement?: BadgePlacement;
109
+
110
+ /**
111
+ * Anchor shape — controls badge offset.
112
+ * - `'rectangular'` (default) sits at the bounding-box corner
113
+ * - `'circular'` offsets to align with the circular anchor edge
114
+ * (use with `<Avatar shape="circle">`)
115
+ * @default 'rectangular'
116
+ */
117
+ overlap?: BadgeOverlap;
118
+
119
+ /**
120
+ * White/neutral ring around the badge — visually separates from
121
+ * the anchor surface. Token-driven via `ring-neutral-50` which
122
+ * auto-inverts via the dashforgePreset CSS-var swap (no `dark:`
123
+ * needed).
124
+ * @default true
125
+ */
126
+ withRing?: boolean;
127
+
128
+ // ─── Bridge integration (Sprint 4.4) ───────────────────────────
129
+ /**
130
+ * RBAC requirement — hides the badge for unauthorized subjects.
131
+ * The wrapped anchor element remains visible (use Box `access`
132
+ * to gate the anchor too).
133
+ *
134
+ * Use case: admin-only notification count, role-gated indicators.
135
+ */
136
+ access?: AccessRequirement;
137
+
138
+ /**
139
+ * Reactive visibility predicate. When `false`, the badge dot/count
140
+ * is not rendered (children always render). Use for state-driven
141
+ * indicators tied to engine values.
142
+ */
143
+ visibleWhen?: (engine: Engine) => boolean;
144
+
145
+ // ─── Override ──────────────────────────────────────────────────
146
+ /** Root-element class shortcut. */
147
+ sx?: ClassValue;
148
+
149
+ /** Standard className — appended to the root via `cn()`. */
150
+ className?: string;
151
+
152
+ /** Per-slot overrides — root + badge. */
153
+ slotProps?: BadgeSlotProps;
154
+ }
@@ -0,0 +1,161 @@
1
+ import { tv, type VariantProps } from 'tailwind-variants';
2
+
3
+ /**
4
+ * Tailwind-variants recipe for `<Badge>`.
5
+ *
6
+ * Slot layout:
7
+ * - `root` — outer span (relative-positioned wrapper around the
8
+ * anchor). `inline-flex` so the wrapper shrinks to fit
9
+ * the anchor element.
10
+ * - `badge` — the floating absolute-positioned pill / dot. Two
11
+ * variants (`dot=true` → tiny circle, `dot=false` →
12
+ * pill with min-width to fit content).
13
+ *
14
+ * Color axis emits the `badge` background + text classes. The 7
15
+ * intents map to:
16
+ * - solid bg: `bg-{intent}-500` (vivid, attention-grabbing for
17
+ * notifications — different from Chip which uses 600 for solid
18
+ * because chip surface is larger; small badge needs the brighter
19
+ * mid-tone)
20
+ * - text: `text-white` for primary/secondary/success/warning/danger/
21
+ * info; `text-neutral-50` for neutral (auto-inverts via CSS-var
22
+ * swap, no `dark:` needed)
23
+ *
24
+ * Placement axis emits absolute-position + translate utilities:
25
+ * - top-right (default): `top-0 right-0 -translate-y-1/2 translate-x-1/2`
26
+ * - top-left: `top-0 left-0 -translate-y-1/2 -translate-x-1/2`
27
+ * - bottom-right: `bottom-0 right-0 translate-y-1/2 translate-x-1/2`
28
+ * - bottom-left: `bottom-0 left-0 translate-y-1/2 -translate-x-1/2`
29
+ *
30
+ * Overlap axis adds an extra inset for circular anchors so the
31
+ * badge sits along the round edge instead of the bounding box corner.
32
+ */
33
+ export const badgeVariants = tv({
34
+ slots: {
35
+ root: 'relative inline-flex shrink-0',
36
+ badge: [
37
+ // Absolute positioning is owned by the placement compound rules.
38
+ 'absolute z-10',
39
+ // Layout / typography — pill defaults; dot mode overrides
40
+ // dimensions below.
41
+ 'inline-flex items-center justify-center',
42
+ 'rounded-full',
43
+ 'text-[10px] font-medium leading-none',
44
+ 'pointer-events-none select-none',
45
+ // Smooth show/hide for `invisible` toggle (consumer-side
46
+ // animation hook). Gated on motion-reduce per WCAG 2.3.3.
47
+ 'transition-transform duration-150 motion-reduce:transition-none motion-reduce:duration-0',
48
+ ],
49
+ },
50
+ variants: {
51
+ /**
52
+ * `dot=true` → tiny circle (8px), no content. The badge slot
53
+ * collapses to a fixed-size circle without the pill min-width.
54
+ */
55
+ dot: {
56
+ true: {
57
+ badge: 'w-2 h-2 p-0',
58
+ },
59
+ false: {
60
+ // Content pill — 16px tall, padded inline, min-width so
61
+ // single-digit counts still read centered.
62
+ badge: 'min-w-4 h-4 px-1',
63
+ },
64
+ },
65
+ /** Whether the floating badge is hidden via `display: none`. */
66
+ invisible: {
67
+ true: {
68
+ badge: 'hidden',
69
+ },
70
+ },
71
+ /** Halo ring for visual separation from the anchor surface. */
72
+ withRing: {
73
+ true: {
74
+ // ring-neutral-50 auto-inverts via dashforgePreset CSS var
75
+ // swap (no `dark:` needed for the neutral palette).
76
+ badge: 'ring-2 ring-neutral-50',
77
+ },
78
+ },
79
+ /** 7 intents — drives the badge background + text colour. */
80
+ color: {
81
+ neutral: {
82
+ // Both classes on the neutral palette — auto-invert via CSS
83
+ // var swap. No `dark:` variants needed.
84
+ badge: 'bg-neutral-700 text-neutral-50',
85
+ },
86
+ primary: { badge: 'bg-primary-500 text-white' },
87
+ secondary: { badge: 'bg-secondary-500 text-white' },
88
+ success: { badge: 'bg-success-500 text-white' },
89
+ warning: { badge: 'bg-warning-500 text-white' },
90
+ danger: { badge: 'bg-danger-500 text-white' },
91
+ info: { badge: 'bg-info-500 text-white' },
92
+ },
93
+ placement: {
94
+ 'top-right': {
95
+ badge: 'top-0 right-0 -translate-y-1/2 translate-x-1/2',
96
+ },
97
+ 'top-left': {
98
+ badge: 'top-0 left-0 -translate-y-1/2 -translate-x-1/2',
99
+ },
100
+ 'bottom-right': {
101
+ badge: 'bottom-0 right-0 translate-y-1/2 translate-x-1/2',
102
+ },
103
+ 'bottom-left': {
104
+ badge: 'bottom-0 left-0 translate-y-1/2 -translate-x-1/2',
105
+ },
106
+ },
107
+ /**
108
+ * `overlap='circular'` adds an inward inset so the badge sits
109
+ * along the circular anchor edge instead of the bounding-box
110
+ * corner. The 14% offset is empirically tuned to match the
111
+ * standard avatar / round-button geometry (matches MUI's value).
112
+ */
113
+ overlap: {
114
+ rectangular: {},
115
+ circular: {},
116
+ },
117
+ },
118
+ compoundVariants: [
119
+ // ─── overlap='circular' × placement — additional inset ─────────
120
+ // The inward shift is in addition to the placement translate,
121
+ // achieved via an extra `-{translate-corner}` adjustment.
122
+ {
123
+ overlap: 'circular',
124
+ placement: 'top-right',
125
+ class: {
126
+ badge: 'top-[14%] right-[14%] translate-x-1/2 -translate-y-1/2',
127
+ },
128
+ },
129
+ {
130
+ overlap: 'circular',
131
+ placement: 'top-left',
132
+ class: {
133
+ badge: 'top-[14%] left-[14%] -translate-x-1/2 -translate-y-1/2',
134
+ },
135
+ },
136
+ {
137
+ overlap: 'circular',
138
+ placement: 'bottom-right',
139
+ class: {
140
+ badge: 'bottom-[14%] right-[14%] translate-x-1/2 translate-y-1/2',
141
+ },
142
+ },
143
+ {
144
+ overlap: 'circular',
145
+ placement: 'bottom-left',
146
+ class: {
147
+ badge: 'bottom-[14%] left-[14%] -translate-x-1/2 translate-y-1/2',
148
+ },
149
+ },
150
+ ],
151
+ defaultVariants: {
152
+ dot: false,
153
+ invisible: false,
154
+ withRing: true,
155
+ color: 'danger',
156
+ placement: 'top-right',
157
+ overlap: 'rectangular',
158
+ },
159
+ });
160
+
161
+ export type BadgeVariants = VariantProps<typeof badgeVariants>;
@@ -367,4 +367,25 @@ describe('<Box>', () => {
367
367
  expect(container.firstElementChild?.className).toContain('rounded-none');
368
368
  });
369
369
  });
370
+
371
+ describe('bridge integration — visibleWhen (Sprint 4.4 surface alignment)', () => {
372
+ it('renders when visibleWhen returns true', () => {
373
+ const { container } = render(
374
+ <Box visibleWhen={() => true}>shown</Box>
375
+ );
376
+ expect(container.firstChild).toBeTruthy();
377
+ });
378
+
379
+ it('returns null when visibleWhen returns false', () => {
380
+ const { container } = render(
381
+ <Box visibleWhen={() => false}>hidden</Box>
382
+ );
383
+ expect(container.firstChild).toBeNull();
384
+ });
385
+
386
+ it('renders normally when visibleWhen is omitted', () => {
387
+ const { container } = render(<Box>always</Box>);
388
+ expect(container.firstChild).toBeTruthy();
389
+ });
390
+ });
370
391
  });
@@ -1,6 +1,8 @@
1
- import { forwardRef, type ElementType, type ReactElement } from 'react';
1
+ import { forwardRef, useContext, type ElementType, type ReactElement } from 'react';
2
2
  import { Slot } from '@radix-ui/react-slot';
3
+ import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
3
4
  import { cn } from '../../utils/cn.js';
5
+ import { useAccessState } from '../../hooks/useAccessState.js';
4
6
  import { boxVariants } from './box.variants.js';
5
7
  import type { BoxProps } from './box.types.js';
6
8
 
@@ -50,22 +52,49 @@ export const Box = forwardRef<HTMLElement, BoxProps>(
50
52
  as,
51
53
  asChild = false,
52
54
  sx,
55
+ visibleWhen,
56
+ access,
53
57
  children,
54
58
  ...rest
55
59
  } = props;
56
60
 
61
+ // Bridge — hooks called unconditionally (rules-of-hooks).
62
+ // `useEngineVisibility` subscribes to engine state inside a
63
+ // `<DashForm>` and re-evaluates the predicate reactively; outside
64
+ // a form, it evaluates the predicate as a plain closure.
65
+ // `useAccessState` consults the @dashforge/rbac policy engine.
66
+ // Both default to no-op when the corresponding prop is omitted.
67
+ const bridge = useContext(DashFormContext);
68
+ const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
69
+ const accessState = useAccessState(access);
70
+
71
+ // Early return — predicate false OR RBAC denies visibility.
72
+ if (!isVisible || !accessState.visible) return null;
73
+
57
74
  const classes = cn(
58
75
  boxVariants({
59
76
  variant, color, elevation, rounded,
60
77
  p, px, py, m, mx, my,
61
78
  fullWidth, fullHeight,
62
79
  }),
80
+ // RBAC-disabled / readonly surfaces dim visually + carry
81
+ // semantic ARIA attributes (assigned below) so descendants and
82
+ // assistive tech can react.
83
+ accessState.disabled && 'opacity-60',
84
+ accessState.readonly && 'opacity-80',
63
85
  sx,
64
86
  );
65
87
 
88
+ const ariaProps = {
89
+ 'aria-disabled': accessState.disabled || undefined,
90
+ 'aria-readonly': accessState.readonly || undefined,
91
+ 'data-disabled': accessState.disabled || undefined,
92
+ 'data-readonly': accessState.readonly || undefined,
93
+ };
94
+
66
95
  if (asChild) {
67
96
  return (
68
- <Slot ref={ref} className={classes} {...rest}>
97
+ <Slot ref={ref} className={classes} {...ariaProps} {...rest}>
69
98
  {children as ReactElement}
70
99
  </Slot>
71
100
  );
@@ -73,7 +102,7 @@ export const Box = forwardRef<HTMLElement, BoxProps>(
73
102
 
74
103
  const Tag = (as ?? 'div') as ElementType;
75
104
  return (
76
- <Tag ref={ref as never} className={classes} {...rest}>
105
+ <Tag ref={ref as never} className={classes} {...ariaProps} {...rest}>
77
106
  {children}
78
107
  </Tag>
79
108
  );
@@ -1,4 +1,6 @@
1
1
  import type { ElementType, HTMLAttributes } from 'react';
2
+ import type { Engine } from '@dashforge/ui-core';
3
+ import type { AccessRequirement } from '@dashforge/rbac';
2
4
  import type { BoxVariants } from './box.variants.js';
3
5
 
4
6
  /**
@@ -58,4 +60,57 @@ export interface BoxProps
58
60
  * position, animation, etc.).
59
61
  */
60
62
  sx?: string;
63
+
64
+ /**
65
+ * Reactive visibility predicate — added in 1.1.0 (Sprint 4.4
66
+ * surface alignment). When the predicate returns `false`, the
67
+ * component renders `null`. Inside a `<DashForm>` it subscribes
68
+ * reactively to engine state changes; outside a form, it's
69
+ * evaluated as a plain closure.
70
+ *
71
+ * Use for state-driven hiding of dashboard cards, conditional
72
+ * sections, gated content, etc. **For permission-driven hiding,
73
+ * prefer `access` with `onUnauthorized: 'hide'`** — it's semantically
74
+ * the correct path and surfaces better in RBAC dev tools.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * // Dashboard card visible only when there are pending shipments
79
+ * <Box variant="outlined" rounded="lg" p={4}
80
+ * visibleWhen={() => pendingCount > 0}>
81
+ * <Typography variant="h3">{pendingCount} pending</Typography>
82
+ * </Box>
83
+ * ```
84
+ */
85
+ visibleWhen?: (engine: Engine) => boolean;
86
+
87
+ /**
88
+ * RBAC requirement — added in 1.1.0 (Sprint 4.4 surface alignment).
89
+ * Controls Box visibility / disabled-state via the centralized
90
+ * `@dashforge/rbac` policy engine.
91
+ *
92
+ * - `onUnauthorized: 'hide'` → Box does not render
93
+ * - `onUnauthorized: 'disable'` → adds `aria-disabled` + dimmed
94
+ * visual; interactive children should derive their disabled state
95
+ * from `data-disabled` on the Box or pass their own `access`
96
+ * - `onUnauthorized: 'readonly'` → adds `aria-readonly`; mostly used
97
+ * when Box wraps form sections that propagate readonly to children
98
+ *
99
+ * Use for permission-gated dashboard cards, admin-only sections,
100
+ * tenant-aware layouts. The hide path is the common case.
101
+ *
102
+ * @example
103
+ * ```tsx
104
+ * // Revenue card visible only to users with billing:read permission
105
+ * <Box variant="elevated" rounded="lg" elevation={2} p={4}
106
+ * access={{
107
+ * resource: 'billing',
108
+ * action: 'read',
109
+ * onUnauthorized: 'hide'
110
+ * }}>
111
+ * <Typography variant="h3">Q3 Revenue</Typography>
112
+ * </Box>
113
+ * ```
114
+ */
115
+ access?: AccessRequirement;
61
116
  }
@@ -181,3 +181,24 @@ describe('Button — asChild polymorphism', () => {
181
181
  expect(node.getAttribute('aria-disabled')).toBe('true');
182
182
  });
183
183
  });
184
+
185
+ describe('Button — visibleWhen (engine-reactive visibility, Sprint 4.4)', () => {
186
+ it('renders when visibleWhen returns true (no DashForm context)', () => {
187
+ const { container } = render(
188
+ <Button visibleWhen={() => true}>shown</Button>
189
+ );
190
+ expect(container.firstChild).toBeTruthy();
191
+ });
192
+
193
+ it('returns null when visibleWhen returns false', () => {
194
+ const { container } = render(
195
+ <Button visibleWhen={() => false}>hidden</Button>
196
+ );
197
+ expect(container.firstChild).toBeNull();
198
+ });
199
+
200
+ it('renders normally when visibleWhen is omitted', () => {
201
+ const { container } = render(<Button>always</Button>);
202
+ expect(container.firstChild).toBeTruthy();
203
+ });
204
+ });
@@ -1,36 +1,22 @@
1
- import { forwardRef } from 'react';
1
+ import { forwardRef, useContext } from 'react';
2
2
  import { Slot } from '@radix-ui/react-slot';
3
+ import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
3
4
  import { cn } from '../../utils/cn.js';
4
5
  import { useAccessState } from '../../hooks/useAccessState.js';
6
+ import { Spinner } from '../Spinner/Spinner.js';
7
+ import type { SpinnerSize } from '../Spinner/spinner.types.js';
5
8
  import { buttonVariants } from './button.variants.js';
6
9
  import type { ButtonProps } from './button.types.js';
7
10
 
8
11
  /**
9
- * Inline spinner shown when `loading` is true. Kept inline (≈10 lines
10
- * of SVG) so the package adds no icon-library dependency.
12
+ * Map Button size to Spinner size. Button has 3 sizes (sm/md/lg);
13
+ * Spinner has 5 (xs/sm/md/lg/xl). Picking the closest match keeps
14
+ * the spinner visually proportional to the button label.
11
15
  *
12
16
  * @internal
13
17
  */
14
- function LoadingSpinner({ size }: { size: 'sm' | 'md' | 'lg' }) {
15
- const dim = size === 'sm' ? 14 : size === 'lg' ? 20 : 16;
16
- return (
17
- <svg
18
- aria-hidden="true"
19
- width={dim}
20
- height={dim}
21
- viewBox="0 0 24 24"
22
- fill="none"
23
- className="animate-spin"
24
- >
25
- <circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2.5" strokeOpacity="0.25" />
26
- <path
27
- d="M21 12a9 9 0 0 0-9-9"
28
- stroke="currentColor"
29
- strokeWidth="2.5"
30
- strokeLinecap="round"
31
- />
32
- </svg>
33
- );
18
+ function buttonSizeToSpinnerSize(size: 'sm' | 'md' | 'lg'): SpinnerSize {
19
+ return size === 'sm' ? 'xs' : size === 'lg' ? 'md' : 'sm';
34
20
  }
35
21
 
36
22
  /**
@@ -80,6 +66,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
80
66
  ) {
81
67
  const {
82
68
  access,
69
+ visibleWhen,
83
70
  disabled,
84
71
  variant,
85
72
  color,
@@ -92,11 +79,18 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
92
79
  ...rest
93
80
  } = props;
94
81
 
95
- // RBAC always called unconditionally (rules-of-hooks compliance).
82
+ // Bridge — both hooks called unconditionally (rules-of-hooks).
83
+ // Inside a `<DashForm>`, `useEngineVisibility` subscribes to engine
84
+ // state and re-evaluates the predicate on changes; outside a form,
85
+ // the predicate is called with `null` engine (consumer captures
86
+ // external state in the closure).
87
+ const bridge = useContext(DashFormContext);
88
+ const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
96
89
  const accessState = useAccessState(access);
97
90
 
98
- // Early return for hidden state.
99
- if (!accessState.visible) return null;
91
+ // Early return for hidden state — either RBAC denies visibility or
92
+ // the engine-reactive predicate returned false.
93
+ if (!isVisible || !accessState.visible) return null;
100
94
 
101
95
  // Effective disabled = explicit OR RBAC-disabled OR RBAC-readonly OR loading.
102
96
  // Buttons do not support a true readonly state — RBAC readonly is mapped
@@ -143,7 +137,14 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
143
137
  className={classes}
144
138
  {...rest}
145
139
  >
146
- {loading && <LoadingSpinner size={size ?? 'md'} />}
140
+ {loading && (
141
+ <Spinner
142
+ size={buttonSizeToSpinnerSize(size ?? 'md')}
143
+ thickness="thick"
144
+ withTrack
145
+ label=""
146
+ />
147
+ )}
147
148
  {children}
148
149
  </button>
149
150
  );
@@ -1,4 +1,5 @@
1
1
  import type { ButtonHTMLAttributes } from 'react';
2
+ import type { Engine } from '@dashforge/ui-core';
2
3
  import type { AccessRequirement } from '@dashforge/rbac';
3
4
  import type { ButtonVariants } from './button.variants.js';
4
5
 
@@ -45,6 +46,41 @@ export interface ButtonProps
45
46
  */
46
47
  access?: AccessRequirement;
47
48
 
49
+ /**
50
+ * Reactive visibility predicate. Re-evaluated on every engine state
51
+ * change when the button is mounted inside a `<DashForm>`; outside
52
+ * a form, evaluated as a plain predicate (the consumer captures
53
+ * any external state in the closure).
54
+ *
55
+ * When the predicate returns `false`, the component renders `null`.
56
+ *
57
+ * **Added in 1.1.0 (Sprint 4.4 alignment)** — extends the
58
+ * engine-reactive visibility pattern previously available only on
59
+ * form fields + `<Alert>` to every interactive component in the
60
+ * Dashforge TW catalog (Button, IconButton, Chip, …).
61
+ *
62
+ * Note: `visibleWhen` is for **state-driven** hide. For
63
+ * **permission-driven** hide, use `access` with
64
+ * `onUnauthorized: 'hide'` — it's the semantically correct path
65
+ * and provides better error messages in RBAC dev tools.
66
+ *
67
+ * @example
68
+ * ```tsx
69
+ * // Inside a DashForm — reactive on engine state
70
+ * <Button
71
+ * visibleWhen={(engine) =>
72
+ * engine.getNode('plan')?.value === 'premium'
73
+ * }
74
+ * >
75
+ * Upgrade extras
76
+ * </Button>
77
+ *
78
+ * // Outside a form — closure over external React state
79
+ * <Button visibleWhen={() => itemCount > 0}>Bulk delete</Button>
80
+ * ```
81
+ */
82
+ visibleWhen?: (engine: Engine) => boolean;
83
+
48
84
  /**
49
85
  * When `true`, the immediate child element is rendered with the
50
86
  * Button's classes merged in (via `@radix-ui/react-slot`). The