@lerianstudio/sindarian-ui 2.0.0-beta.24 → 2.0.0-beta.26

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 (337) hide show
  1. package/dist/charts/chart.js +4 -231
  2. package/dist/charts/index.js +1 -11
  3. package/dist/components/breadcrumb/get-breadcrumb-paths.js +1 -18
  4. package/dist/components/breadcrumb/index.js +1 -37
  5. package/dist/components/card/account-card/index.js +1 -69
  6. package/dist/components/card/basic-card/index.js +1 -20
  7. package/dist/components/card/dashboard-card/index.js +1 -20
  8. package/dist/components/card/entity-card/index.js +1 -68
  9. package/dist/components/card/index.js +1 -20
  10. package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  11. package/dist/components/dialog/confirmation-dialog/index.js +1 -96
  12. package/dist/components/dialog/confirmation-dialog/use-confirm-dialog.js +1 -55
  13. package/dist/components/dialog/index.js +1 -19
  14. package/dist/components/dialog/large-dialog/index.d.ts +2 -2
  15. package/dist/components/dialog/large-dialog/index.d.ts.map +1 -1
  16. package/dist/components/dialog/large-dialog/index.js +1 -21
  17. package/dist/components/entity-box/index.js +1 -67
  18. package/dist/components/entity-data-table/index.js +1 -20
  19. package/dist/components/form/combo-box-field/index.js +1 -35
  20. package/dist/components/form/country-field/index.js +1 -11
  21. package/dist/components/form/date-picker-field/index.js +1 -83
  22. package/dist/components/form/date-range-field/index.js +1 -58
  23. package/dist/components/form/date-time-picker-field/index.js +1 -114
  24. package/dist/components/form/file-upload-field/index.js +1 -69
  25. package/dist/components/form/index.js +1 -31
  26. package/dist/components/form/input-field/index.js +1 -96
  27. package/dist/components/form/otp-field/index.js +1 -19
  28. package/dist/components/form/pagination-limit-field/index.js +1 -10
  29. package/dist/components/form/password-field/index.d.ts.map +1 -1
  30. package/dist/components/form/password-field/index.js +1 -16
  31. package/dist/components/form/radio-group-field/index.js +1 -36
  32. package/dist/components/form/renderable-label.js +1 -57
  33. package/dist/components/form/select-field/index.js +1 -68
  34. package/dist/components/form/state-field/index.js +1 -42
  35. package/dist/components/form/switch-field/index.js +1 -16
  36. package/dist/components/form/textarea-field/index.js +1 -23
  37. package/dist/components/page/index.js +1 -20
  38. package/dist/components/page-header/index.js +1 -80
  39. package/dist/components/pagination/index.js +1 -10
  40. package/dist/components/table/id-table-cell.js +1 -109
  41. package/dist/components/table/index.js +1 -19
  42. package/dist/components/table/locked-table-actions.js +1 -41
  43. package/dist/components/table/name-table-cell.js +1 -58
  44. package/dist/components/ui/accordion/index.js +1 -62
  45. package/dist/components/ui/alert/index.js +1 -45
  46. package/dist/components/ui/alert-dialog/index.js +1 -84
  47. package/dist/components/ui/autocomplete/index.js +1 -440
  48. package/dist/components/ui/autosize-textarea/index.js +1 -89
  49. package/dist/components/ui/avatar/index.js +1 -51
  50. package/dist/components/ui/badge/index.js +1 -83
  51. package/dist/components/ui/breadcrumb/index.js +1 -35
  52. package/dist/components/ui/button/index.js +1 -65
  53. package/dist/components/ui/button/styles.css +2 -1
  54. package/dist/components/ui/calendar/index.js +1 -118
  55. package/dist/components/ui/card/index.js +1 -32
  56. package/dist/components/ui/checkbox/index.js +1 -44
  57. package/dist/components/ui/collapsible/index.js +1 -50
  58. package/dist/components/ui/command/index.js +1 -95
  59. package/dist/components/ui/copy-field/index.js +1 -163
  60. package/dist/components/ui/dialog/index.d.ts +4 -1
  61. package/dist/components/ui/dialog/index.d.ts.map +1 -1
  62. package/dist/components/ui/dialog/index.js +1 -80
  63. package/dist/components/ui/dialog/styles.css +2 -1
  64. package/dist/components/ui/dropdown-menu/index.js +1 -110
  65. package/dist/components/ui/field/index.js +1 -82
  66. package/dist/components/ui/file-upload/index.js +1 -574
  67. package/dist/components/ui/form.js +1 -162
  68. package/dist/components/ui/hover-card/index.js +1 -51
  69. package/dist/components/ui/icon-button/index.js +1 -35
  70. package/dist/components/ui/input/adornment.js +1 -21
  71. package/dist/components/ui/input/index.js +1 -99
  72. package/dist/components/ui/input/styles.css +29 -12
  73. package/dist/components/ui/label/index.js +1 -45
  74. package/dist/components/ui/lerian-wordmark/index.js +1 -7
  75. package/dist/components/ui/loading-button/index.js +1 -9
  76. package/dist/components/ui/multiple-select/index.js +1 -235
  77. package/dist/components/ui/otp-input/index.js +1 -62
  78. package/dist/components/ui/paper/index.js +1 -8
  79. package/dist/components/ui/paper-collapsible/index.js +1 -24
  80. package/dist/components/ui/popover/index.js +1 -55
  81. package/dist/components/ui/progress/index.js +1 -66
  82. package/dist/components/ui/qr-code/index.js +1 -27
  83. package/dist/components/ui/radio-group/index.js +1 -48
  84. package/dist/components/ui/scroll-area/index.js +1 -49
  85. package/dist/components/ui/select/index.js +1 -119
  86. package/dist/components/ui/select/styles.css +6 -3
  87. package/dist/components/ui/separator/index.js +1 -43
  88. package/dist/components/ui/sheet/index.d.ts +7 -2
  89. package/dist/components/ui/sheet/index.d.ts.map +1 -1
  90. package/dist/components/ui/sheet/index.js +1 -136
  91. package/dist/components/ui/sidebar/index.js +1 -27
  92. package/dist/components/ui/sidebar/next-router.cjs +1 -119
  93. package/dist/components/ui/sidebar/sidebar-back-button.js +1 -8
  94. package/dist/components/ui/sidebar/sidebar-components.js +1 -23
  95. package/dist/components/ui/sidebar/sidebar-expand-button.js +1 -49
  96. package/dist/components/ui/sidebar/sidebar-item-button.js +1 -21
  97. package/dist/components/ui/sidebar/sidebar-item-collapsible.js +1 -52
  98. package/dist/components/ui/sidebar/sidebar-item-icon-button.js +1 -18
  99. package/dist/components/ui/sidebar/sidebar-item.js +1 -44
  100. package/dist/components/ui/sidebar/sidebar-provider.js +1 -201
  101. package/dist/components/ui/sidebar/sidebar-root.d.ts +3 -1
  102. package/dist/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
  103. package/dist/components/ui/sidebar/sidebar-root.js +1 -130
  104. package/dist/components/ui/sidebar/sidebar-router.js +1 -126
  105. package/dist/components/ui/sidebar/sidebar-trigger.js +1 -57
  106. package/dist/components/ui/skeleton/index.js +1 -8
  107. package/dist/components/ui/stepper/index.js +1 -29
  108. package/dist/components/ui/switch/index.js +1 -43
  109. package/dist/components/ui/table/index.js +1 -56
  110. package/dist/components/ui/tabs/index.js +1 -55
  111. package/dist/components/ui/textarea/index.js +1 -8
  112. package/dist/components/ui/time-picker/index.js +1 -85
  113. package/dist/components/ui/toast/index.js +1 -3
  114. package/dist/components/ui/toast/toaster.js +1 -16
  115. package/dist/components/ui/toggle-group/index.js +1 -156
  116. package/dist/components/ui/tooltip/index.js +1 -81
  117. package/dist/domain/blotter/index.js +1 -20
  118. package/dist/domain/delinquency-aging/aging-buckets.js +1 -120
  119. package/dist/domain/delinquency-aging/index.js +1 -222
  120. package/dist/domain/figure/index.js +1 -19
  121. package/dist/domain/format.js +1 -137
  122. package/dist/domain/index.js +1 -43
  123. package/dist/domain/key-id/index.js +1 -174
  124. package/dist/domain/ledger-sheet/index.js +1 -28
  125. package/dist/domain/money-diff.js +1 -48
  126. package/dist/domain/money-math.js +1 -104
  127. package/dist/domain/money-text/index.js +1 -123
  128. package/dist/domain/section-label/index.js +1 -17
  129. package/dist/domain/status-rail/index.js +1 -76
  130. package/dist/domain/threshold-gauge/index.js +1 -161
  131. package/dist/enterprise/alert-banner/index.js +1 -24
  132. package/dist/enterprise/app-shell/index.js +1 -87
  133. package/dist/enterprise/cursor-pager/index.js +1 -26
  134. package/dist/enterprise/data-table/column-size.js +1 -103
  135. package/dist/enterprise/data-table/index.d.ts.map +1 -1
  136. package/dist/enterprise/data-table/index.js +1 -345
  137. package/dist/enterprise/date-range-picker/index.js +1 -115
  138. package/dist/enterprise/detail-panel/index.js +1 -20
  139. package/dist/enterprise/empty-state/index.d.ts +6 -1
  140. package/dist/enterprise/empty-state/index.d.ts.map +1 -1
  141. package/dist/enterprise/empty-state/index.js +1 -13
  142. package/dist/enterprise/index.js +1 -39
  143. package/dist/enterprise/number-input/index.js +1 -252
  144. package/dist/enterprise/search-input/index.js +1 -121
  145. package/dist/enterprise/stat-card/index.js +1 -75
  146. package/dist/enterprise/status-badge/index.js +1 -120
  147. package/dist/enterprise/use-is-mobile.js +1 -68
  148. package/dist/enterprise/virtualized-table/index.js +1 -141
  149. package/dist/esm/charts/chart.js +4 -190
  150. package/dist/esm/charts/index.js +1 -3
  151. package/dist/esm/components/breadcrumb/get-breadcrumb-paths.js +1 -12
  152. package/dist/esm/components/breadcrumb/index.js +1 -30
  153. package/dist/esm/components/card/account-card/index.js +1 -53
  154. package/dist/esm/components/card/basic-card/index.js +1 -14
  155. package/dist/esm/components/card/dashboard-card/index.js +1 -14
  156. package/dist/esm/components/card/entity-card/index.js +1 -52
  157. package/dist/esm/components/card/index.js +1 -4
  158. package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
  159. package/dist/esm/components/dialog/confirmation-dialog/index.js +1 -60
  160. package/dist/esm/components/dialog/confirmation-dialog/use-confirm-dialog.js +1 -49
  161. package/dist/esm/components/dialog/index.js +1 -3
  162. package/dist/esm/components/dialog/large-dialog/index.d.ts +2 -2
  163. package/dist/esm/components/dialog/large-dialog/index.d.ts.map +1 -1
  164. package/dist/esm/components/dialog/large-dialog/index.js +1 -16
  165. package/dist/esm/components/entity-box/index.js +1 -56
  166. package/dist/esm/components/entity-data-table/index.js +1 -17
  167. package/dist/esm/components/form/combo-box-field/index.js +1 -28
  168. package/dist/esm/components/form/country-field/index.js +1 -7
  169. package/dist/esm/components/form/date-picker-field/index.js +1 -43
  170. package/dist/esm/components/form/date-range-field/index.js +1 -18
  171. package/dist/esm/components/form/date-time-picker-field/index.js +1 -74
  172. package/dist/esm/components/form/file-upload-field/index.js +1 -65
  173. package/dist/esm/components/form/index.js +1 -15
  174. package/dist/esm/components/form/input-field/index.js +1 -92
  175. package/dist/esm/components/form/otp-field/index.js +1 -15
  176. package/dist/esm/components/form/pagination-limit-field/index.js +1 -6
  177. package/dist/esm/components/form/password-field/index.d.ts.map +1 -1
  178. package/dist/esm/components/form/password-field/index.js +1 -10
  179. package/dist/esm/components/form/radio-group-field/index.js +1 -32
  180. package/dist/esm/components/form/renderable-label.js +1 -54
  181. package/dist/esm/components/form/select-field/index.js +1 -64
  182. package/dist/esm/components/form/state-field/index.js +1 -35
  183. package/dist/esm/components/form/switch-field/index.js +1 -12
  184. package/dist/esm/components/form/textarea-field/index.js +1 -19
  185. package/dist/esm/components/page/index.js +1 -15
  186. package/dist/esm/components/page-header/index.js +1 -71
  187. package/dist/esm/components/pagination/index.js +1 -6
  188. package/dist/esm/components/table/id-table-cell.js +1 -105
  189. package/dist/esm/components/table/index.js +1 -3
  190. package/dist/esm/components/table/locked-table-actions.js +1 -37
  191. package/dist/esm/components/table/name-table-cell.js +1 -54
  192. package/dist/esm/components/ui/accordion/index.js +1 -24
  193. package/dist/esm/components/ui/alert/index.js +1 -38
  194. package/dist/esm/components/ui/alert-dialog/index.js +1 -39
  195. package/dist/esm/components/ui/autocomplete/index.js +1 -392
  196. package/dist/esm/components/ui/autosize-textarea/index.js +1 -51
  197. package/dist/esm/components/ui/avatar/index.js +1 -14
  198. package/dist/esm/components/ui/badge/index.js +1 -79
  199. package/dist/esm/components/ui/breadcrumb/index.js +1 -27
  200. package/dist/esm/components/ui/button/index.js +1 -60
  201. package/dist/esm/components/ui/calendar/index.js +1 -82
  202. package/dist/esm/components/ui/card/index.js +1 -24
  203. package/dist/esm/components/ui/checkbox/index.js +1 -9
  204. package/dist/esm/components/ui/collapsible/index.js +1 -13
  205. package/dist/esm/components/ui/command/index.js +1 -51
  206. package/dist/esm/components/ui/copy-field/index.js +1 -127
  207. package/dist/esm/components/ui/dialog/index.d.ts +4 -1
  208. package/dist/esm/components/ui/dialog/index.d.ts.map +1 -1
  209. package/dist/esm/components/ui/dialog/index.js +1 -36
  210. package/dist/esm/components/ui/dropdown-menu/index.js +1 -60
  211. package/dist/esm/components/ui/field/index.js +1 -71
  212. package/dist/esm/components/ui/file-upload/index.js +1 -536
  213. package/dist/esm/components/ui/form.js +1 -118
  214. package/dist/esm/components/ui/hover-card/index.js +1 -14
  215. package/dist/esm/components/ui/icon-button/index.js +1 -31
  216. package/dist/esm/components/ui/input/adornment.js +1 -17
  217. package/dist/esm/components/ui/input/index.js +1 -60
  218. package/dist/esm/components/ui/label/index.js +1 -10
  219. package/dist/esm/components/ui/lerian-wordmark/index.js +1 -4
  220. package/dist/esm/components/ui/loading-button/index.js +1 -7
  221. package/dist/esm/components/ui/multiple-select/index.js +1 -196
  222. package/dist/esm/components/ui/otp-input/index.js +1 -21
  223. package/dist/esm/components/ui/paper/index.js +1 -5
  224. package/dist/esm/components/ui/paper-collapsible/index.js +1 -19
  225. package/dist/esm/components/ui/popover/index.js +1 -17
  226. package/dist/esm/components/ui/progress/index.js +1 -31
  227. package/dist/esm/components/ui/qr-code/index.js +1 -24
  228. package/dist/esm/components/ui/radio-group/index.js +1 -12
  229. package/dist/esm/components/ui/scroll-area/index.js +1 -13
  230. package/dist/esm/components/ui/select/index.js +1 -74
  231. package/dist/esm/components/ui/separator/index.js +1 -8
  232. package/dist/esm/components/ui/sheet/index.d.ts +7 -2
  233. package/dist/esm/components/ui/sheet/index.d.ts.map +1 -1
  234. package/dist/esm/components/ui/sheet/index.js +1 -92
  235. package/dist/esm/components/ui/sidebar/index.js +1 -11
  236. package/dist/esm/components/ui/sidebar/next-router.cjs +1 -119
  237. package/dist/esm/components/ui/sidebar/sidebar-back-button.js +1 -5
  238. package/dist/esm/components/ui/sidebar/sidebar-components.js +1 -15
  239. package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +1 -42
  240. package/dist/esm/components/ui/sidebar/sidebar-item-button.js +1 -18
  241. package/dist/esm/components/ui/sidebar/sidebar-item-collapsible.js +1 -44
  242. package/dist/esm/components/ui/sidebar/sidebar-item-icon-button.js +1 -14
  243. package/dist/esm/components/ui/sidebar/sidebar-item.js +1 -40
  244. package/dist/esm/components/ui/sidebar/sidebar-provider.js +1 -193
  245. package/dist/esm/components/ui/sidebar/sidebar-root.d.ts +3 -1
  246. package/dist/esm/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
  247. package/dist/esm/components/ui/sidebar/sidebar-root.js +1 -126
  248. package/dist/esm/components/ui/sidebar/sidebar-router.js +1 -89
  249. package/dist/esm/components/ui/sidebar/sidebar-trigger.js +1 -53
  250. package/dist/esm/components/ui/skeleton/index.js +1 -6
  251. package/dist/esm/components/ui/stepper/index.js +1 -20
  252. package/dist/esm/components/ui/switch/index.js +1 -8
  253. package/dist/esm/components/ui/table/index.js +1 -44
  254. package/dist/esm/components/ui/tabs/index.js +1 -17
  255. package/dist/esm/components/ui/textarea/index.js +1 -6
  256. package/dist/esm/components/ui/time-picker/index.js +1 -49
  257. package/dist/esm/components/ui/toast/index.js +1 -2
  258. package/dist/esm/components/ui/toast/toaster.js +1 -13
  259. package/dist/esm/components/ui/toggle-group/index.js +1 -120
  260. package/dist/esm/components/ui/tooltip/index.js +1 -43
  261. package/dist/esm/domain/blotter/index.js +1 -16
  262. package/dist/esm/domain/delinquency-aging/aging-buckets.js +1 -115
  263. package/dist/esm/domain/delinquency-aging/index.js +1 -218
  264. package/dist/esm/domain/figure/index.js +1 -15
  265. package/dist/esm/domain/format.js +1 -128
  266. package/dist/esm/domain/index.js +1 -19
  267. package/dist/esm/domain/key-id/index.js +1 -169
  268. package/dist/esm/domain/ledger-sheet/index.js +1 -24
  269. package/dist/esm/domain/money-diff.js +1 -45
  270. package/dist/esm/domain/money-math.js +1 -98
  271. package/dist/esm/domain/money-text/index.js +1 -118
  272. package/dist/esm/domain/section-label/index.js +1 -14
  273. package/dist/esm/domain/status-rail/index.js +1 -71
  274. package/dist/esm/domain/threshold-gauge/index.js +1 -157
  275. package/dist/esm/enterprise/alert-banner/index.js +1 -21
  276. package/dist/esm/enterprise/app-shell/index.js +1 -51
  277. package/dist/esm/enterprise/cursor-pager/index.js +1 -23
  278. package/dist/esm/enterprise/data-table/column-size.js +1 -97
  279. package/dist/esm/enterprise/data-table/index.d.ts.map +1 -1
  280. package/dist/esm/enterprise/data-table/index.js +1 -342
  281. package/dist/esm/enterprise/date-range-picker/index.js +1 -112
  282. package/dist/esm/enterprise/detail-panel/index.js +1 -17
  283. package/dist/esm/enterprise/empty-state/index.d.ts +6 -1
  284. package/dist/esm/enterprise/empty-state/index.d.ts.map +1 -1
  285. package/dist/esm/enterprise/empty-state/index.js +1 -10
  286. package/dist/esm/enterprise/index.js +1 -22
  287. package/dist/esm/enterprise/number-input/index.js +1 -214
  288. package/dist/esm/enterprise/search-input/index.js +1 -85
  289. package/dist/esm/enterprise/stat-card/index.js +1 -72
  290. package/dist/esm/enterprise/status-badge/index.js +1 -116
  291. package/dist/esm/enterprise/use-is-mobile.js +1 -31
  292. package/dist/esm/enterprise/virtualized-table/index.js +1 -138
  293. package/dist/esm/hooks/use-click-away.js +1 -22
  294. package/dist/esm/hooks/use-pagination.js +1 -38
  295. package/dist/esm/hooks/use-stepper.js +1 -22
  296. package/dist/esm/hooks/use-time.js +1 -13
  297. package/dist/esm/hooks/use-toast.js +1 -107
  298. package/dist/esm/index.js +1 -77
  299. package/dist/esm/lib/storage/get-storage-object.js +1 -17
  300. package/dist/esm/lib/storage/get-storage.js +1 -14
  301. package/dist/esm/lib/storage/index.js +1 -2
  302. package/dist/esm/lib/typography.js +1 -31
  303. package/dist/esm/lib/utils.js +1 -41
  304. package/dist/esm/theme/get-theme-script.js +1 -41
  305. package/dist/esm/theme/index.js +1 -4
  306. package/dist/esm/theme/mode-toggle.js +1 -45
  307. package/dist/esm/theme/theme-provider.js +1 -122
  308. package/dist/esm/toast/helpers.js +1 -36
  309. package/dist/esm/toast/index.js +1 -4
  310. package/dist/esm/types/metadata-type.js +1 -1
  311. package/dist/esm/utils/countries.cjs +1 -17
  312. package/dist/esm/utils/country-utils.js +1 -18
  313. package/dist/esm/utils/currency-codes.js +1 -181
  314. package/dist/globals.css +1 -0
  315. package/dist/hooks/use-click-away.js +1 -29
  316. package/dist/hooks/use-pagination.js +1 -41
  317. package/dist/hooks/use-stepper.js +1 -26
  318. package/dist/hooks/use-time.js +1 -20
  319. package/dist/hooks/use-toast.js +1 -111
  320. package/dist/index.js +1 -96
  321. package/dist/lib/storage/get-storage-object.js +1 -23
  322. package/dist/lib/storage/get-storage.js +1 -17
  323. package/dist/lib/storage/index.js +1 -18
  324. package/dist/lib/typography.js +1 -34
  325. package/dist/lib/utils.js +1 -45
  326. package/dist/theme/get-theme-script.js +1 -44
  327. package/dist/theme/index.js +1 -11
  328. package/dist/theme/mode-toggle.js +1 -48
  329. package/dist/theme/theme-provider.js +1 -160
  330. package/dist/toast/helpers.js +1 -41
  331. package/dist/toast/index.js +1 -10
  332. package/dist/tokens.css +7 -4
  333. package/dist/types/metadata-type.js +1 -2
  334. package/dist/utils/countries.cjs +1 -17
  335. package/dist/utils/country-utils.js +1 -25
  336. package/dist/utils/currency-codes.js +1 -184
  337. package/package.json +4 -3
@@ -1,123 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.normalizeAmount = normalizeAmount;
4
- exports.formatMoneyParts = formatMoneyParts;
5
- exports.MoneyText = MoneyText;
6
- const jsx_runtime_1 = require("react/jsx-runtime");
7
- /**
8
- * MoneyText renders a monetary amount with optional ISO currency code,
9
- * tabular figures so columns line up. The amount is formatted losslessly: when
10
- * passed as a string, `Intl.NumberFormat.format()` (ES2020+) parses it as an
11
- * arbitrary-precision value and rounds to `fractionDigits` without ever
12
- * round-tripping through an IEEE-754 double — so 16+ significant-digit tokens
13
- * keep every digit. Pass the raw decimal string (not a pre-coerced Number) to
14
- * preserve that guarantee.
15
- *
16
- * The currency code is shown as a suffix rather than a symbol so mixed-currency
17
- * ledgers stay unambiguous. Negative amounts get the error sign color;
18
- * null/undefined/empty render the muted no-value placeholder.
19
- *
20
- * SIGN COLOR IS NOT THE CREDIT ROLE. The sign ink marks a negative/alarm
21
- * amount; `--credit` is the accounting reading of a credit amount. They are two
22
- * roles, and a consumer layers the credit role on top (matcher's fork passes
23
- * `signColor={false}` with `tone="credit"` precisely so the two never fight).
24
- * Collapsing the sign color into `text-credit` would erase that distinction.
25
- *
26
- * THE SIGN INK IS THE `system-error` H1A INK, not `--destructive`. A signed
27
- * amount is TEXT, so it answers to WCAG AA on whatever surface holds it, and
28
- * `--destructive` is a FILL family (buttons, badges, tinted chips) whose dark
29
- * value reads 3.80:1 as ink on `--card`, an axe finding on a live console.
30
- * `--system-error-h1a` is the error INK of the same family and reads 8.28:1
31
- * light / 7.12:1 dark on that surface. `__tests__/tokens-contract.test.ts`
32
- * re-measures whichever token this line applies, so the pairing is measured
33
- * rather than trusted.
34
- */
35
- const utils_1 = require("../../lib/utils");
36
- const format_1 = require("../format");
37
- /**
38
- * Normalize a raw amount into a string the Intl formatter accepts while
39
- * preserving precision: trim, convert the unicode minus U+2212 to ASCII '-',
40
- * and rewrite accounting parens `(123.45)` → `-123.45`. Returns null when the
41
- * input is empty after trimming (→ NO_VALUE upstream).
42
- *
43
- * Internal: exported for its unit tests, never from `src/domain/index.ts`.
44
- */
45
- function normalizeAmount(amount) {
46
- let s = String(amount).trim();
47
- if (s === '')
48
- return null;
49
- s = s.replace(/−/g, '-');
50
- const parens = s.match(/^\((.*)\)$/);
51
- if (parens)
52
- s = `-${parens[1].trim()}`;
53
- return s;
54
- }
55
- /**
56
- * Pure money formatting: normalize the amount, format it via Intl (preserving
57
- * precision through the ES2020 string overload), and derive sign + finiteness
58
- * from the formatted parts — so color and glyph can never disagree. Returns
59
- * null for empty, non-finite, or unparseable input (→ NO_VALUE upstream).
60
- *
61
- * Internal: exported for its unit tests, never from `src/domain/index.ts`.
62
- */
63
- function formatMoneyParts(amount, fractionDigits, locale) {
64
- // Reject non-finite numeric inputs (NaN / ±Infinity) before they reach Intl,
65
- // which would otherwise render literal "NaN" / "∞".
66
- if (typeof amount === 'number' && !Number.isFinite(amount))
67
- return null;
68
- // A caller-supplied digit count reaches Intl directly; an out-of-range one
69
- // would throw a RangeError and blank the amount instead of degrading to
70
- // NO_VALUE.
71
- if (!(0, format_1.isValidDigitCount)(fractionDigits))
72
- return null;
73
- const normalized = normalizeAmount(amount);
74
- if (normalized === null)
75
- return null;
76
- // DELIBERATE DIVERGENCE from sindarian-x@0.15.0: an exact zero written with a
77
- // sign ('-0', '-0.00', '(0)') formatted as "-0.00" and reported negative:true,
78
- // which painted a zero balance in the destructive sign color. Zero is neither
79
- // positive nor negative — a signed-zero ledger cell is a rendering artifact of
80
- // the input notation, never a fact about the money. The sign is dropped for an
81
- // EXACT zero only; '-0.004' still rounds to "-0.00" and stays negative,
82
- // because that one really is below zero.
83
- const exactZero = /\d/.test(normalized) && /^-?0*(\.0*)?$/.test(normalized);
84
- const forFormat = exactZero ? normalized.replace(/^-/, '') : normalized;
85
- // A malformed tag would throw a RangeError out of this constructor and take
86
- // the whole amount down; degrade to the runtime locale instead.
87
- const formatter = new Intl.NumberFormat((0, format_1.safeLocale)(locale), {
88
- minimumFractionDigits: fractionDigits,
89
- maximumFractionDigits: fractionDigits,
90
- signDisplay: 'auto'
91
- });
92
- // The bundled lib types only model a `number | bigint` overload; the ES2020
93
- // string overload (which preserves precision) is unmodelled, so the
94
- // normalized amount is cast at the boundary.
95
- //
96
- // RUNTIME FLOOR: this relies on a V8 with exact decimal-STRING Intl support
97
- // (Node >= 20, evergreen browsers) — the whole point is that a 20-digit amount
98
- // never round-trips through an IEEE-754 double. There is deliberately NO
99
- // Number-coercion fallback for older runtimes: that fallback would silently
100
- // reintroduce the precision loss this function exists to prevent.
101
- const parts = formatter.formatToParts(forFormat);
102
- // Intl emits a literal "nan"/"∞" part for non-finite values; treat those as
103
- // no-value rather than rendering them.
104
- if (parts.some((p) => p.type === 'nan' || p.type === 'infinity'))
105
- return null;
106
- return {
107
- formatted: parts.map((p) => p.value).join(''),
108
- negative: parts.some((p) => p.type === 'minusSign')
109
- };
110
- }
111
- function MoneyText({ amount, currency, fractionDigits = 2, hideCurrency = false, signColor = true, locale, className }) {
112
- const noValue = ((0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-muted-foreground tabular-nums', className), children: format_1.NO_VALUE }));
113
- if (amount === null || amount === undefined || amount === '')
114
- return noValue;
115
- // Sign and finiteness are derived from the formatted parts, not a raw string
116
- // prefix — so color and glyph can never disagree, and "-0" / "(0)" are
117
- // treated as the non-negative zero Intl renders.
118
- const result = formatMoneyParts(amount, fractionDigits, locale);
119
- if (result === null)
120
- return noValue;
121
- const { formatted, negative } = result;
122
- return ((0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)('tabular-nums', signColor && negative && 'text-system-error-h1a', className), children: [formatted, !hideCurrency && currency ? ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground ml-1 text-xs", children: currency })) : null] }));
123
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.normalizeAmount=normalizeAmount;exports.formatMoneyParts=formatMoneyParts;exports.MoneyText=MoneyText;const jsx_runtime_1=require("react/jsx-runtime");const utils_1=require("../../lib/utils");const format_1=require("../format");function normalizeAmount(t){let e=String(t).trim();if(e==="")return null;e=e.replace(/−/g,"-");const s=e.match(/^\((.*)\)$/);if(s)e=`-${s[1].trim()}`;return e}function formatMoneyParts(t,e,s){if(typeof t==="number"&&!Number.isFinite(t))return null;if(!(0,format_1.isValidDigitCount)(e))return null;const n=normalizeAmount(t);if(n===null)return null;const u=/\d/.test(n)&&/^-?0*(\.0*)?$/.test(n);const l=u?n.replace(/^-/,""):n;const o=new Intl.NumberFormat((0,format_1.safeLocale)(s),{minimumFractionDigits:e,maximumFractionDigits:e,signDisplay:"auto"});const i=o.formatToParts(l);if(i.some(r=>r.type==="nan"||r.type==="infinity"))return null;return{formatted:i.map(r=>r.value).join(""),negative:i.some(r=>r.type==="minusSign")}}function MoneyText({amount:t,currency:e,fractionDigits:s=2,hideCurrency:n=false,signColor:u=true,locale:l,className:o}){const i=(0,jsx_runtime_1.jsx)("span",{className:(0,utils_1.cn)("text-muted-foreground tabular-nums",o),children:format_1.NO_VALUE});if(t===null||t===void 0||t==="")return i;const r=formatMoneyParts(t,s,l);if(r===null)return i;const{formatted:a,negative:m}=r;return(0,jsx_runtime_1.jsxs)("span",{className:(0,utils_1.cn)("tabular-nums",u&&m&&"text-system-error-h1a",o),children:[a,!n&&e?(0,jsx_runtime_1.jsx)("span",{className:"text-muted-foreground ml-1 text-xs",children:e}):null]})}
@@ -1,17 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SectionLabel = SectionLabel;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const typography_1 = require("../../lib/typography");
6
- const utils_1 = require("../../lib/utils");
7
- /** The entry-section head treatment: a hairline double rule under the label.
8
- * `border-border`, NOT the register head's ink — this is the quieter of the two
9
- * head rules. Pinned here because ~20 call sites were restating it. */
10
- const RULED_CLASS = 'border-b-[3px] border-double border-border pb-2';
11
- function SectionLabel({ children, className, as: Tag = 'h2', ruled = false, ...rest }) {
12
- // The remaining element props reach the rendered tag, so a panel can point
13
- // `aria-labelledby` at this heading via `id`, and tests can hang a `data-*`
14
- // hook off it. Without the spread there was no way to reference the heading
15
- // from its own container.
16
- return ((0, jsx_runtime_1.jsx)(Tag, { ...rest, "data-variant": ruled ? 'ruled' : undefined, className: (0, utils_1.cn)(typography_1.SECTION_LABEL_CLASS, ruled && RULED_CLASS, className), children: children }));
17
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SectionLabel=SectionLabel;const jsx_runtime_1=require("react/jsx-runtime");const typography_1=require("../../lib/typography");const utils_1=require("../../lib/utils");const RULED_CLASS="border-b-[3px] border-double border-border pb-2";function SectionLabel({children:r,className:t,as:o="h2",ruled:e=false,...s}){return(0,jsx_runtime_1.jsx)(o,{...s,"data-variant":e?"ruled":void 0,className:(0,utils_1.cn)(typography_1.SECTION_LABEL_CLASS,e&&RULED_CLASS,t),children:r})}
@@ -1,76 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StatusRail = StatusRail;
4
- exports.Dot = Dot;
5
- exports.LivePulse = LivePulse;
6
- const jsx_runtime_1 = require("react/jsx-runtime");
7
- /**
8
- * StatusRail — Row 0 of every console screen. A thin, full-width recessed strip
9
- * that reads "the terminal is live": a dot-separated mono tape on the recessed
10
- * page surface (`bg-body-surface`), with optional right-pinned count chips.
11
- *
12
- * <StatusRail
13
- * lead={contextName}
14
- * items={[
15
- * { value: '90d' },
16
- * { label: 'Updated', value: '12:04 UTC' },
17
- * { value: <><LivePulse /> Live</> }
18
- * ]}
19
- * chips={[
20
- * { label: 'Open', value: '12' },
21
- * { label: 'Pending overdue', value: '3', alarm: true }
22
- * ]}
23
- * />
24
- *
25
- * The first token (`lead`) is `text-foreground font-medium`. Tape items are
26
- * dot-separated; an item with a `label` renders the label inline before its
27
- * value, in the rail's own `font-medium`. Chips pin right via `ml-auto`;
28
- * `alarm` escalates a chip to destructive.
29
- *
30
- * Labels carry weight only: the rail root already supplies size, family and
31
- * ink (`font-mono text-xs text-muted-foreground`), so re-stating
32
- * LABEL_VOICE_CLASS here would import a `text-sm` that fights the tape.
33
- */
34
- const lucide_react_1 = require("lucide-react");
35
- const utils_1 = require("../../lib/utils");
36
- function StatusRail({ lead, items = [], chips = [], className }) {
37
- // ONE test, used by both the lead span and the first item's separator. Two
38
- // separate tests (`lead !== undefined && lead !== null` vs `lead != null`)
39
- // agreed on null/undefined and diverged on a ReactNode that RENDERS NOTHING,
40
- // which produced an empty lead span while the first item still got its
41
- // leading dot — the rail opened with a stray `·`. React renders BOTH booleans
42
- // as nothing, so `true` is as empty as `false`; the typeof check covers the
43
- // pair rather than naming one of them.
44
- const hasLead = lead != null && lead !== '' && typeof lead !== 'boolean';
45
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)(
46
- // Recessed instrument strip: the page surface inside a hairline border
47
- // whose top edge runs one step darker — light-from-above recession
48
- // without any inner shadow.
49
- 'border-border border-t-foreground/10 bg-body-surface text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-lg border px-4 py-2 font-mono text-xs tabular-nums', className), children: [hasLead ? ((0, jsx_runtime_1.jsx)("span", { className: "text-foreground font-medium", children: lead })) : null, items.map((item, i) => ((0, jsx_runtime_1.jsx)(RailFragment, { hasLead: hasLead || i > 0, children: item.label != null ? ((0, jsx_runtime_1.jsxs)("span", { className: "flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-medium", children: item.label }), item.value] })) : ((0, jsx_runtime_1.jsx)("span", { className: "flex items-center gap-1.5", children: item.value })) }, item.id ?? i))), chips.length ? ((0, jsx_runtime_1.jsx)("span", { className: "ml-auto flex flex-wrap items-center gap-x-3 gap-y-1.5", children: chips.map((chip, i) => ((0, jsx_runtime_1.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [(0, jsx_runtime_1.jsx)("span", { className: "font-medium", children: chip.label }), (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)(
50
- // Tiny mono token: raised a hair off the sunken tape by the
51
- // card surface + whisper shadow.
52
- 'inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 shadow-sm', chip.alarm
53
- ? 'border-destructive/40 bg-destructive/10 text-system-error-h1a'
54
- : 'border-border bg-card text-foreground'), children: [chip.alarm ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.TriangleAlert, { "aria-hidden": true, className: "size-3" }), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: "(alarme)" })] })) : null, chip.value] })] }, chip.id ?? i))) })) : null] }));
55
- }
56
- /** A tape item preceded by a separator dot when it is not the first token. */
57
- function RailFragment({ children, hasLead }) {
58
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [hasLead ? (0, jsx_runtime_1.jsx)(Dot, {}) : null, children] }));
59
- }
60
- /** Decorative dot separator — muted, so the tape reads as punctuated, not broken. */
61
- function Dot() {
62
- return ((0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "text-muted-foreground/50", children: "\u00B7" }));
63
- }
64
- /**
65
- * The live auto-refresh pulse: a success dot with a reduced-motion-gated ping
66
- * ring. Place it inside a tape item value, e.g. `<><LivePulse /> Live</>`.
67
- *
68
- * The ring rides Tailwind's built-in `ping` keyframe under the `motion-safe:`
69
- * variant (`@media (prefers-reduced-motion: no-preference)`), so a
70
- * reduced-motion reader sees only the static dot — same gating as the
71
- * hand-rolled `status-rail-pulse` keyframe it replaces, with no stylesheet of
72
- * its own.
73
- */
74
- function LivePulse() {
75
- return ((0, jsx_runtime_1.jsxs)("span", { className: "relative flex size-2", "aria-hidden": true, children: [(0, jsx_runtime_1.jsx)("span", { className: "bg-system-success/60 absolute inline-flex size-2 rounded-full motion-safe:animate-ping" }), (0, jsx_runtime_1.jsx)("span", { className: "bg-system-success relative inline-flex size-2 rounded-full" })] }));
76
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.StatusRail=StatusRail;exports.Dot=Dot;exports.LivePulse=LivePulse;const jsx_runtime_1=require("react/jsx-runtime");const lucide_react_1=require("lucide-react");const utils_1=require("../../lib/utils");function StatusRail({lead:s,items:a=[],chips:n=[],className:t}){const l=s!=null&&s!==""&&typeof s!=="boolean";return(0,jsx_runtime_1.jsxs)("div",{className:(0,utils_1.cn)("border-border border-t-foreground/10 bg-body-surface text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-lg border px-4 py-2 font-mono text-xs tabular-nums",t),children:[l?(0,jsx_runtime_1.jsx)("span",{className:"text-foreground font-medium",children:s}):null,a.map((e,r)=>(0,jsx_runtime_1.jsx)(RailFragment,{hasLead:l||r>0,children:e.label!=null?(0,jsx_runtime_1.jsxs)("span",{className:"flex items-center gap-1.5",children:[(0,jsx_runtime_1.jsx)("span",{className:"font-medium",children:e.label}),e.value]}):(0,jsx_runtime_1.jsx)("span",{className:"flex items-center gap-1.5",children:e.value})},e.id??r)),n.length?(0,jsx_runtime_1.jsx)("span",{className:"ml-auto flex flex-wrap items-center gap-x-3 gap-y-1.5",children:n.map((e,r)=>(0,jsx_runtime_1.jsxs)("span",{className:"inline-flex items-center gap-1.5",children:[(0,jsx_runtime_1.jsx)("span",{className:"font-medium",children:e.label}),(0,jsx_runtime_1.jsxs)("span",{className:(0,utils_1.cn)("inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 shadow-sm",e.alarm?"border-destructive/40 bg-destructive/10 text-system-error-h1a":"border-border bg-card text-foreground"),children:[e.alarm?(0,jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment,{children:[(0,jsx_runtime_1.jsx)(lucide_react_1.TriangleAlert,{"aria-hidden":true,className:"size-3"}),(0,jsx_runtime_1.jsx)("span",{className:"sr-only",children:"(alarme)"})]}):null,e.value]})]},e.id??r))}):null]})}function RailFragment({children:s,hasLead:a}){return(0,jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment,{children:[a?(0,jsx_runtime_1.jsx)(Dot,{}):null,s]})}function Dot(){return(0,jsx_runtime_1.jsx)("span",{"aria-hidden":true,className:"text-muted-foreground/50",children:"\xB7"})}function LivePulse(){return(0,jsx_runtime_1.jsxs)("span",{className:"relative flex size-2","aria-hidden":true,children:[(0,jsx_runtime_1.jsx)("span",{className:"bg-system-success/60 absolute inline-flex size-2 rounded-full motion-safe:animate-ping"}),(0,jsx_runtime_1.jsx)("span",{className:"bg-system-success relative inline-flex size-2 rounded-full"})]})}
@@ -1,161 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.gaugeBand = gaugeBand;
4
- exports.ThresholdGauge = ThresholdGauge;
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- /**
7
- * ThresholdGauge — where a value sits across ordered, NAMED bands.
8
- *
9
- * A metric is rarely interesting in isolation; what matters is which band it has
10
- * crossed. A credit utilization of 95% is a breach; a liquidity coverage ratio
11
- * of 95% may be perfectly calm. So a gauge that paints a smooth red→green
12
- * gradient is lying by implication — it suggests a continuum where the business
13
- * has hard thresholds. This atom STATES the thresholds: it resolves the current
14
- * band (low / warn / breach), names it with a glyph + an sr-only word + a tint,
15
- * and marks the band edges on the bar so the reader sees the line the value
16
- * crossed, not a vibe.
17
- *
18
- * <ThresholdGauge value={0.92} max={1} warn={0.8} breach={0.9} format="percent"
19
- * direction="higher-is-worse" label="Utilização do limite" /> // breach
20
- * <ThresholdGauge value={1.18} max={2} warn={1} breach={0.9} format="ratio"
21
- * direction="lower-is-worse" label="Índice de cobertura" /> // low (calm)
22
- *
23
- * DIRECTION is mandatory because the same numbers mean opposite things:
24
- * - higher-is-worse: the value climbs INTO danger (warn < breach). Utilization,
25
- * concentration, error rate.
26
- * - lower-is-worse: the value FALLS into danger (breach < warn). Coverage,
27
- * liquidity, capital adequacy.
28
- *
29
- * INVARIANT (strict edges by DEFAULT): a band escalation requires the value to
30
- * be STRICTLY beyond the edge. A value sitting exactly ON a threshold belongs to
31
- * the calmer band, not the louder one — `gaugeBand` encodes this so an on-edge
32
- * utilization of exactly the breach line still reads as warn, never a surprise
33
- * breach. A consumer whose own enforcement is INCLUSIVE (a quota blocking at
34
- * `used >= limit`) opts out with `edges="inclusive"`, which escalates ON the
35
- * edge in both directions.
36
- *
37
- * The current band is the load-bearing signal and it never rides on color alone
38
- * (WCAG 1.4.1): a glyph leads, an sr-only word names it, the tint only
39
- * reinforces. The numeric position reads via a mono `Figure`, never inferred
40
- * from the bar geometry — and a consumer forced to clamp `value` to keep
41
- * `aria-valuenow` in range can still print the true figure via `displayValue`.
42
- *
43
- * Pure display: server-safe, no directive.
44
- */
45
- const lucide_react_1 = require("lucide-react");
46
- const typography_1 = require("../../lib/typography");
47
- const utils_1 = require("../../lib/utils");
48
- const figure_1 = require("../figure");
49
- const format_1 = require("../format");
50
- const money_text_1 = require("../money-text");
51
- /** Band → glyph + tint + accessible word. The glyph and sr-only word are the
52
- * load-bearing cue; the tint only reinforces, so the band survives grayscale
53
- * and color-vision deficiency. The words are pt-BR defaults — a consumer in
54
- * another locale overrides them via the `bandLabels` prop. */
55
- const BAND = {
56
- low: {
57
- Icon: lucide_react_1.ShieldCheck,
58
- tint: 'text-system-success-h1a',
59
- word: 'Dentro do limite'
60
- },
61
- warn: {
62
- Icon: lucide_react_1.TriangleAlert,
63
- tint: 'text-system-alert-h1a',
64
- word: 'Próximo do limite'
65
- },
66
- breach: {
67
- Icon: lucide_react_1.OctagonX,
68
- tint: 'text-system-error-h1a',
69
- word: 'Limite ultrapassado'
70
- }
71
- };
72
- /** Track fill tint per band, and the reason it is a SEPARATE map from the
73
- * tint above: these are the fill tokens, and a fill answers to no text floor.
74
- * The tint above is painted on the band glyph AND on the `Figure`, so it has
75
- * to be the ink family. Light `--system-alert` is #EAB308, about 1.9:1 on
76
- * white, and `--system-success` about 3.3:1 — both were readable only as a
77
- * bar wash, never as the number the reader is here to read. */
78
- const BAND_FILL = {
79
- low: 'bg-system-success',
80
- warn: 'bg-system-alert',
81
- breach: 'bg-destructive'
82
- };
83
- /**
84
- * Resolve which band a value occupies. Pure — the testable heart of the atom.
85
- *
86
- * STRICT edges by default: a value exactly ON a threshold stays in the CALMER
87
- * band; escalation needs the value strictly past.
88
- *
89
- * - higher-is-worse: `value > breach` → breach; `value > warn` → warn; else low.
90
- * - lower-is-worse: `value < breach` → breach; `value < warn` → warn; else low.
91
- *
92
- * `thresholds.edges = 'inclusive'` opts into `>=` / `<=` instead, for a consumer
93
- * whose enforcement is inclusive. Omitted or 'strict' → the behaviour above.
94
- *
95
- * Non-finite input degrades to 'low' rather than throwing — a missing reading is
96
- * not, by itself, an alarm.
97
- */
98
- function gaugeBand(value, thresholds, direction) {
99
- if (!Number.isFinite(value))
100
- return 'low';
101
- const { warn, breach, edges = 'strict' } = thresholds;
102
- const beyond = direction === 'higher-is-worse'
103
- ? (edge) => (edges === 'inclusive' ? value >= edge : value > edge)
104
- : (edge) => (edges === 'inclusive' ? value <= edge : value < edge);
105
- if (beyond(breach))
106
- return 'breach';
107
- if (beyond(warn))
108
- return 'warn';
109
- return 'low';
110
- }
111
- /**
112
- * An empty or whitespace-only string is not a name. `??` only skips null and
113
- * undefined, so `ariaLabel=""` or `bandLabels={{ breach: '' }}` won the fallback
114
- * chain and produced an EMPTY accessible name — worse than the missing one it
115
- * was meant to fix, because `aria-label=""` also suppresses the element's other
116
- * naming routes. Normalizing to undefined lets the chain fall through properly.
117
- */
118
- function nonEmpty(value) {
119
- return value != null && value.trim() !== '' ? value : undefined;
120
- }
121
- /** Clamp a value into [min, max] then normalize to a 0..1 fraction of the
122
- * track. A zero-width track (max <= min) collapses to 0 rather than dividing by
123
- * zero. */
124
- function trackFraction(value, min, max) {
125
- if (!Number.isFinite(value) || max <= min)
126
- return 0;
127
- const clamped = Math.max(min, Math.min(max, value));
128
- return (clamped - min) / (max - min);
129
- }
130
- /** Format the value for the mono readout per `format`. Money routes through
131
- * MoneyText (never a hand-rolled string); the rest through the format helpers. */
132
- function readout(value, format, currency, locale) {
133
- if (!Number.isFinite(value))
134
- return format_1.NO_VALUE;
135
- if (format === 'money') {
136
- return ((0, jsx_runtime_1.jsx)(money_text_1.MoneyText, { amount: value, currency: currency, signColor: false, locale: locale }));
137
- }
138
- if (format === 'percent')
139
- return (0, format_1.formatPercent)(value, { unit: 'percent', locale });
140
- if (format === 'ratio')
141
- return (0, format_1.formatPercent)(value, { unit: 'ratio', locale });
142
- return (0, format_1.formatCount)(value, locale);
143
- }
144
- function ThresholdGauge({ value, displayValue, min = 0, max, warn, breach, edges, direction, format = 'percent', currency, locale, label, ariaLabel, bandLabels, className }) {
145
- const band = gaugeBand(value, { warn, breach, edges }, direction);
146
- const { Icon, tint } = BAND[band];
147
- // The sr-only word is the band's only non-chromatic cue, so it is also the
148
- // string a trilingual consumer has to translate. pt-BR default, override wins.
149
- // Every rung of the naming chain is normalized: an empty override must fall
150
- // through to the next source rather than win with a blank string.
151
- const word = nonEmpty(bandLabels?.[band]) ?? BAND[band].word;
152
- const caption = nonEmpty(label);
153
- // A `role="meter"` with no accessible name is announced as a naked number.
154
- // The band word is always present and always meaningful, so the meter is named
155
- // even when a consumer renders the gauge without a visible caption.
156
- const meterName = nonEmpty(ariaLabel) ?? caption ?? word;
157
- const valuePct = trackFraction(value, min, max) * 100;
158
- const warnPct = trackFraction(warn, min, max) * 100;
159
- const breachPct = trackFraction(breach, min, max) * 100;
160
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex flex-col gap-2', className), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-baseline justify-between gap-3", children: [caption != null ? ((0, jsx_runtime_1.jsx)("span", { className: typography_1.LABEL_VOICE_CLASS, children: caption })) : ((0, jsx_runtime_1.jsx)("span", {})), (0, jsx_runtime_1.jsxs)("span", { className: (0, utils_1.cn)('inline-flex items-center gap-1.5', tint), children: [(0, jsx_runtime_1.jsx)(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), (0, jsx_runtime_1.jsxs)("span", { className: "sr-only", children: [word, ": "] }), (0, jsx_runtime_1.jsx)(figure_1.Figure, { size: "row", className: tint, children: readout(displayValue ?? value, format, currency, locale) })] })] }), (0, jsx_runtime_1.jsxs)("div", { role: "meter", "aria-valuenow": Number.isFinite(value) ? value : undefined, "aria-valuemin": min, "aria-valuemax": max, "aria-label": meterName, className: "border-border bg-muted relative h-2 w-full overflow-hidden rounded-full border", children: [(0, jsx_runtime_1.jsx)("div", { "aria-hidden": true, className: (0, utils_1.cn)('absolute inset-y-0 left-0 rounded-full', BAND_FILL[band]), style: { width: `${valuePct}%` } }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "bg-system-alert absolute inset-y-0 w-px", style: { left: `${warnPct}%` } }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": true, className: "bg-destructive absolute inset-y-0 w-px", style: { left: `${breachPct}%` } })] })] }));
161
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.gaugeBand=gaugeBand;exports.ThresholdGauge=ThresholdGauge;const jsx_runtime_1=require("react/jsx-runtime");const lucide_react_1=require("lucide-react");const typography_1=require("../../lib/typography");const utils_1=require("../../lib/utils");const figure_1=require("../figure");const format_1=require("../format");const money_text_1=require("../money-text");const BAND={low:{Icon:lucide_react_1.ShieldCheck,tint:"text-system-success-h1a",word:"Dentro do limite"},warn:{Icon:lucide_react_1.TriangleAlert,tint:"text-system-alert-h1a",word:"Pr\xF3ximo do limite"},breach:{Icon:lucide_react_1.OctagonX,tint:"text-system-error-h1a",word:"Limite ultrapassado"}};const BAND_FILL={low:"bg-system-success",warn:"bg-system-alert",breach:"bg-destructive"};function gaugeBand(e,r,s){if(!Number.isFinite(e))return"low";const{warn:t,breach:c,edges:i="strict"}=r;const o=s==="higher-is-worse"?n=>i==="inclusive"?e>=n:e>n:n=>i==="inclusive"?e<=n:e<n;if(o(c))return"breach";if(o(t))return"warn";return"low"}function nonEmpty(e){return e!=null&&e.trim()!==""?e:void 0}function trackFraction(e,r,s){if(!Number.isFinite(e)||s<=r)return 0;const t=Math.max(r,Math.min(s,e));return(t-r)/(s-r)}function readout(e,r,s,t){if(!Number.isFinite(e))return format_1.NO_VALUE;if(r==="money"){return(0,jsx_runtime_1.jsx)(money_text_1.MoneyText,{amount:e,currency:s,signColor:false,locale:t})}if(r==="percent")return(0,format_1.formatPercent)(e,{unit:"percent",locale:t});if(r==="ratio")return(0,format_1.formatPercent)(e,{unit:"ratio",locale:t});return(0,format_1.formatCount)(e,t)}function ThresholdGauge({value:e,displayValue:r,min:s=0,max:t,warn:c,breach:i,edges:o,direction:n,format:m="percent",currency:f,locale:h,label:b,ariaLabel:x,bandLabels:p,className:y}){const a=gaugeBand(e,{warn:c,breach:i,edges:o},n);const{Icon:g,tint:l}=BAND[a];const d=nonEmpty(p?.[a])??BAND[a].word;const u=nonEmpty(b);const w=nonEmpty(x)??u??d;const N=trackFraction(e,s,t)*100;const j=trackFraction(c,s,t)*100;const _=trackFraction(i,s,t)*100;return(0,jsx_runtime_1.jsxs)("div",{className:(0,utils_1.cn)("flex flex-col gap-2",y),children:[(0,jsx_runtime_1.jsxs)("div",{className:"flex items-baseline justify-between gap-3",children:[u!=null?(0,jsx_runtime_1.jsx)("span",{className:typography_1.LABEL_VOICE_CLASS,children:u}):(0,jsx_runtime_1.jsx)("span",{}),(0,jsx_runtime_1.jsxs)("span",{className:(0,utils_1.cn)("inline-flex items-center gap-1.5",l),children:[(0,jsx_runtime_1.jsx)(g,{"aria-hidden":true,className:"size-4 shrink-0"}),(0,jsx_runtime_1.jsxs)("span",{className:"sr-only",children:[d,": "]}),(0,jsx_runtime_1.jsx)(figure_1.Figure,{size:"row",className:l,children:readout(r??e,m,f,h)})]})]}),(0,jsx_runtime_1.jsxs)("div",{role:"meter","aria-valuenow":Number.isFinite(e)?e:void 0,"aria-valuemin":s,"aria-valuemax":t,"aria-label":w,className:"border-border bg-muted relative h-2 w-full overflow-hidden rounded-full border",children:[(0,jsx_runtime_1.jsx)("div",{"aria-hidden":true,className:(0,utils_1.cn)("absolute inset-y-0 left-0 rounded-full",BAND_FILL[a]),style:{width:`${N}%`}}),(0,jsx_runtime_1.jsx)("span",{"aria-hidden":true,className:"bg-system-alert absolute inset-y-0 w-px",style:{left:`${j}%`}}),(0,jsx_runtime_1.jsx)("span",{"aria-hidden":true,className:"bg-destructive absolute inset-y-0 w-px",style:{left:`${_}%`}})]})]})}
@@ -1,24 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AlertBanner = AlertBanner;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const utils_1 = require("../../lib/utils");
6
- /** Container tint + border per tone. The title color is applied separately so
7
- * the body copy stays high-contrast foreground. */
8
- const TONE_CONTAINER = {
9
- destructive: 'border-system-error-border bg-system-error-surface',
10
- warning: 'border-system-alert-border bg-system-alert-surface',
11
- info: 'border-system-info-border bg-system-info-surface',
12
- success: 'border-system-success-border bg-system-success-surface',
13
- neutral: 'border-border bg-muted/50'
14
- };
15
- const TONE_TITLE = {
16
- destructive: 'text-system-error-text',
17
- warning: 'text-system-alert-text',
18
- info: 'text-system-info-text',
19
- success: 'text-system-success-text',
20
- neutral: 'text-foreground'
21
- };
22
- function AlertBanner({ tone = 'neutral', title, children, detail, icon, className, ...props }) {
23
- return ((0, jsx_runtime_1.jsxs)("div", { ...props, role: "alert", "data-tone": tone, className: (0, utils_1.cn)('flex gap-3 rounded-md border px-4 py-3', TONE_CONTAINER[tone], className), children: [icon != null ? ((0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('mt-0.5 shrink-0', TONE_TITLE[tone]), "aria-hidden": true, children: icon })) : null, (0, jsx_runtime_1.jsxs)("div", { className: "min-w-0 flex-1 space-y-1", children: [title != null ? ((0, jsx_runtime_1.jsx)("p", { className: (0, utils_1.cn)('text-sm font-medium', TONE_TITLE[tone]), children: title })) : null, children != null ? ((0, jsx_runtime_1.jsx)("div", { className: "text-foreground text-xs leading-relaxed", children: children })) : null, detail != null ? ((0, jsx_runtime_1.jsx)("pre", { className: "text-muted-foreground overflow-x-auto font-mono text-xs break-words whitespace-pre-wrap", children: detail })) : null] })] }));
24
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.AlertBanner=AlertBanner;const jsx_runtime_1=require("react/jsx-runtime");const utils_1=require("../../lib/utils");const TONE_CONTAINER={destructive:"border-system-error-border bg-system-error-surface",warning:"border-system-alert-border bg-system-alert-surface",info:"border-system-info-border bg-system-info-surface",success:"border-system-success-border bg-system-success-surface",neutral:"border-border bg-muted/50"};const TONE_TITLE={destructive:"text-system-error-text",warning:"text-system-alert-text",info:"text-system-info-text",success:"text-system-success-text",neutral:"text-foreground"};function AlertBanner({tone:e="neutral",title:r,children:s,detail:t,icon:n,className:l,...u}){return(0,jsx_runtime_1.jsxs)("div",{...u,role:"alert","data-tone":e,className:(0,utils_1.cn)("flex gap-3 rounded-md border px-4 py-3",TONE_CONTAINER[e],l),children:[n!=null?(0,jsx_runtime_1.jsx)("span",{className:(0,utils_1.cn)("mt-0.5 shrink-0",TONE_TITLE[e]),"aria-hidden":true,children:n}):null,(0,jsx_runtime_1.jsxs)("div",{className:"min-w-0 flex-1 space-y-1",children:[r!=null?(0,jsx_runtime_1.jsx)("p",{className:(0,utils_1.cn)("text-sm font-medium",TONE_TITLE[e]),children:r}):null,s!=null?(0,jsx_runtime_1.jsx)("div",{className:"text-foreground text-xs leading-relaxed",children:s}):null,t!=null?(0,jsx_runtime_1.jsx)("pre",{className:"text-muted-foreground overflow-x-auto font-mono text-xs break-words whitespace-pre-wrap",children:t}):null]})]})}
@@ -1,87 +1 @@
1
- 'use client';
2
- "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || (function () {
20
- var ownKeys = function(o) {
21
- ownKeys = Object.getOwnPropertyNames || function (o) {
22
- var ar = [];
23
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
- return ar;
25
- };
26
- return ownKeys(o);
27
- };
28
- return function (mod) {
29
- if (mod && mod.__esModule) return mod;
30
- var result = {};
31
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
- __setModuleDefault(result, mod);
33
- return result;
34
- };
35
- })();
36
- Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.AppShell = void 0;
38
- const jsx_runtime_1 = require("react/jsx-runtime");
39
- /**
40
- * AppShell — the console frame: a sidebar rail, an optional sticky header row,
41
- * and a centered, scrollable content column. This is the whole screen, not a
42
- * fragment, so it deliberately OWNS the SidebarProvider — the consumer drops a
43
- * sindarian-ui sidebar (`SidebarRoot` + its parts) into `sidebar` and a
44
- * `SidebarExpandButton` into `header`, and the collapse behavior comes free,
45
- * no extra wrapper required.
46
- *
47
- * Landmark contract (the a11y-correct frame):
48
- * SidebarProvider
49
- * div (the shell ROW — carries `className`)
50
- * a.sr-only (skip link, if labelled) // FIRST focusable in the document,
51
- * // targets <main> — bypasses the nav
52
- * {sidebar}
53
- * div[data-slot=sidebar-inset] // the inset COLUMN — a plain div
54
- * header (banner, if given) // SIBLING of <main>, not nested
55
- * main#<id> tabIndex=-1 // the ONE main: skip-linkable + ref-able
56
- * div (centered content container) → {children}
57
- *
58
- * The skip link is the FIRST child inside the shell row — before the sidebar —
59
- * so a keyboard user's very first Tab lands on it and Enter jumps past the
60
- * entire nav to the content <main>. That is the whole point of WCAG 2.4.1
61
- * "Bypass Blocks": a skip link placed AFTER the nav would be reached only after
62
- * tabbing through every nav item, defeating its purpose. The inset column is a
63
- * <div>, not a <main>, so AppShell can own the single inner <main> for the
64
- * content. The page header passed via `header` becomes a top-level banner
65
- * SIBLING of <main> (one banner); a PageHeader rendered inside `children` lands
66
- * inside <main> and is content, not a top-level landmark.
67
- *
68
- * Client by construction: it calls React.useId() to wire the skip link to the
69
- * content <main>, and forwards a ref to that <main> so a consumer can focus it
70
- * on route change — both are client concerns, hence the "use client" directive.
71
- */
72
- const React = __importStar(require("react"));
73
- const sidebar_1 = require("../../components/ui/sidebar");
74
- const utils_1 = require("../../lib/utils");
75
- exports.AppShell = React.forwardRef(function AppShell({ sidebar, header, headerLabel, children, className, contentClassName, skipToContentLabel }, ref) {
76
- // The content <main> id — wires the skip link to its target and gives the
77
- // <main> a stable, focusable anchor. Internal: no consumer-facing id prop.
78
- const mainId = React.useId();
79
- // sindarian-ui's SidebarProvider is context-only (it renders no DOM and
80
- // takes no className), so the shell owns the flex row itself and `className`
81
- // lands on it — the same element the legacy provider's className reached.
82
- return ((0, jsx_runtime_1.jsx)(sidebar_1.SidebarProvider, { children: (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex h-svh w-full overflow-hidden', className), children: [skipToContentLabel ? ((0, jsx_runtime_1.jsx)("a", { href: `#${mainId}`, className: "focus:bg-background focus:text-foreground sr-only focus:not-sr-only focus:absolute focus:z-50 focus:m-2 focus:rounded focus:px-3 focus:py-2 focus:shadow", children: skipToContentLabel })) : null, sidebar, (0, jsx_runtime_1.jsxs)("div", { "data-slot": "sidebar-inset", className: "bg-background relative flex w-full min-w-0 flex-1 flex-col", children: [header ? ((0, jsx_runtime_1.jsx)("header", { "aria-label": headerLabel, className: "border-border bg-background sticky top-0 z-10 flex items-center gap-3 border-b px-6 py-3", children: header })) : null, (0, jsx_runtime_1.jsx)("main", { id: mainId, ref: ref, tabIndex: -1,
83
- // min-h-0 lets this flex child shrink below its content height —
84
- // without it `flex-1` keeps min-height:auto and nothing scrolls.
85
- className: "min-h-0 flex-1 overflow-y-auto outline-none", children: (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)('mx-auto w-full max-w-7xl px-6 py-8 lg:px-8', contentClassName), children: children }) })] })] }) }));
86
- });
87
- exports.AppShell.displayName = 'AppShell';
1
+ "use client";"use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(l,e,t,r){if(r===void 0)r=t;var n=Object.getOwnPropertyDescriptor(e,t);if(!n||("get"in n?!e.__esModule:n.writable||n.configurable)){n={enumerable:true,get:function(){return e[t]}}}Object.defineProperty(l,r,n)}):(function(l,e,t,r){if(r===void 0)r=t;l[r]=e[t]}));var __setModuleDefault=this&&this.__setModuleDefault||(Object.create?(function(l,e){Object.defineProperty(l,"default",{enumerable:true,value:e})}):function(l,e){l["default"]=e});var __importStar=this&&this.__importStar||(function(){var l=function(e){l=Object.getOwnPropertyNames||function(t){var r=[];for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n))r[r.length]=n;return r};return l(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null){for(var r=l(e),n=0;n<r.length;n++)if(r[n]!=="default")__createBinding(t,e,r[n])}__setModuleDefault(t,e);return t}})();Object.defineProperty(exports,"__esModule",{value:true});exports.AppShell=void 0;const jsx_runtime_1=require("react/jsx-runtime");const React=__importStar(require("react"));const sidebar_1=require("../../components/ui/sidebar");const utils_1=require("../../lib/utils");exports.AppShell=React.forwardRef(function l({sidebar:e,header:t,headerLabel:r,children:n,className:u,contentClassName:a,skipToContentLabel:s},o){const i=React.useId();return(0,jsx_runtime_1.jsx)(sidebar_1.SidebarProvider,{children:(0,jsx_runtime_1.jsxs)("div",{className:(0,utils_1.cn)("flex h-svh w-full overflow-hidden",u),children:[s?(0,jsx_runtime_1.jsx)("a",{href:`#${i}`,className:"focus:bg-background focus:text-foreground sr-only focus:not-sr-only focus:absolute focus:z-50 focus:m-2 focus:rounded focus:px-3 focus:py-2 focus:shadow",children:s}):null,e,(0,jsx_runtime_1.jsxs)("div",{"data-slot":"sidebar-inset",className:"bg-background relative flex w-full min-w-0 flex-1 flex-col",children:[t?(0,jsx_runtime_1.jsx)("header",{"aria-label":r,className:"border-border bg-background sticky top-0 z-10 flex items-center gap-3 border-b px-6 py-3",children:t}):null,(0,jsx_runtime_1.jsx)("main",{id:i,ref:o,tabIndex:-1,className:"min-h-0 flex-1 overflow-y-auto outline-none",children:(0,jsx_runtime_1.jsx)("div",{className:(0,utils_1.cn)("mx-auto w-full max-w-7xl px-6 py-8 lg:px-8",a),children:n})})]})]})})});exports.AppShell.displayName="AppShell";
@@ -1,26 +1 @@
1
- 'use client';
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.CursorPager = CursorPager;
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- /**
7
- * CursorPager drives the cursor-pagination envelope
8
- * { items, hasMore, nextCursor, prevCursor, limit }
9
- * shared by the console's cursor-paged list endpoints (do not use it on
10
- * offset-based endpoints).
11
- *
12
- * It is controlled: the parent owns the active cursor (the value it passes to
13
- * the list hook) and reacts to `onCursorChange`. Pass the page envelope's
14
- * `hasMore`, `nextCursor`, `prevCursor`. "Previous" is enabled when the page
15
- * reports a `prevCursor`; "Next" when `hasMore` and a `nextCursor` exist.
16
- *
17
- * `onCursorChange(undefined)` requests the first page (no cursor).
18
- */
19
- const lucide_react_1 = require("lucide-react");
20
- const button_1 = require("../../components/ui/button");
21
- const utils_1 = require("../../lib/utils");
22
- function CursorPager({ hasMore, nextCursor, prevCursor, onCursorChange, disabled = false, summary, previousLabel = 'Previous', nextLabel = 'Next', className }) {
23
- const canPrev = !disabled && !!prevCursor;
24
- const canNext = !disabled && !!hasMore && !!nextCursor;
25
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)('flex items-center justify-between gap-4 pt-3', className), children: [(0, jsx_runtime_1.jsx)("p", { className: "text-muted-foreground text-xs", children: summary ?? '' }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "outline", size: "small", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { "aria-hidden": true }), iconPlacement: "start", disabled: !canPrev, onClick: () => onCursorChange(prevCursor ?? undefined), children: previousLabel }), (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "outline", size: "small", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { "aria-hidden": true }), iconPlacement: "end", disabled: !canNext, onClick: () => onCursorChange(nextCursor ?? undefined), children: nextLabel })] })] }));
26
- }
1
+ "use client";"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.CursorPager=CursorPager;const jsx_runtime_1=require("react/jsx-runtime");const lucide_react_1=require("lucide-react");const button_1=require("../../components/ui/button");const utils_1=require("../../lib/utils");function CursorPager({hasMore:s,nextCursor:e,prevCursor:t,onCursorChange:n,disabled:i=false,summary:r,previousLabel:c="Previous",nextLabel:u="Next",className:a}){const l=!i&&!!t;const o=!i&&!!s&&!!e;return(0,jsx_runtime_1.jsxs)("div",{className:(0,utils_1.cn)("flex items-center justify-between gap-4 pt-3",a),children:[(0,jsx_runtime_1.jsx)("p",{className:"text-muted-foreground text-xs",children:r??""}),(0,jsx_runtime_1.jsxs)("div",{className:"flex items-center gap-2",children:[(0,jsx_runtime_1.jsx)(button_1.Button,{type:"button",variant:"outline",size:"small",icon:(0,jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft,{"aria-hidden":true}),iconPlacement:"start",disabled:!l,onClick:()=>n(t??void 0),children:c}),(0,jsx_runtime_1.jsx)(button_1.Button,{type:"button",variant:"outline",size:"small",icon:(0,jsx_runtime_1.jsx)(lucide_react_1.ChevronRight,{"aria-hidden":true}),iconPlacement:"end",disabled:!o,onClick:()=>n(e??void 0),children:u})]})]})}