@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,14 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { buttonVariants } from '../../ui/button/index.js';
4
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip/index.js';
5
- import { cn } from '../../../lib/utils.js';
6
- import { iconButtonVariants } from '../icon-button/index.js';
7
- import { useSidebarRouter } from './sidebar-router.js';
8
- export const SidebarItemIconButton = ({ className, title, icon, href, active, inactive, disabled, ...props }) => {
9
- const { Link } = useSidebarRouter();
10
- const sharedClassName = cn(buttonVariants({
11
- variant: active ? 'tertiary' : 'outline'
12
- }), iconButtonVariants(), inactive && 'hover:border-transparent', disabled && 'cursor-default opacity-30', className);
13
- return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { delayDuration: 0, children: [_jsx(TooltipTrigger, { asChild: true, children: disabled || inactive ? (_jsx("div", { "data-slot": "sidebar-item-icon-button", className: sharedClassName, children: icon })) : (_jsx(Link, { "data-slot": "sidebar-item-icon-button", href: href, className: sharedClassName, ...props, children: icon })) }), _jsx(TooltipContent, { side: "right", children: title })] }) }));
14
- };
1
+ "use client";import{jsx as t,jsxs as c}from"react/jsx-runtime";import{buttonVariants as u}from"../../ui/button/index.js";import{Tooltip as p,TooltipContent as h,TooltipProvider as f,TooltipTrigger as b}from"../../ui/tooltip/index.js";import{cn as x}from"../../../lib/utils.js";import{iconButtonVariants as T}from"../icon-button/index.js";import{useSidebarRouter as j}from"./sidebar-router.js";export const SidebarItemIconButton=({className:a,title:n,icon:r,href:s,active:l,inactive:o,disabled:i,...d})=>{const{Link:m}=j();const e=x(u({variant:l?"tertiary":"outline"}),T(),o&&"hover:border-transparent",i&&"cursor-default opacity-30",a);return t(f,{children:c(p,{delayDuration:0,children:[t(b,{asChild:true,children:i||o?t("div",{"data-slot":"sidebar-item-icon-button",className:e,children:r}):t(m,{"data-slot":"sidebar-item-icon-button",href:s,className:e,...d,children:r})}),t(h,{side:"right",children:n})]})})};
@@ -1,40 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { SidebarItemButton } from './sidebar-item-button.js';
4
- import { SidebarItemIconButton } from './sidebar-item-icon-button.js';
5
- import { useSidebar } from './sidebar-provider.js';
6
- import { useSidebarRouter } from './sidebar-router.js';
7
- export const SidebarItem = ({ active, href, children: _children, onClick, ...props }) => {
8
- const { usePathname } = useSidebarRouter();
9
- const pathname = usePathname();
10
- const { isCollapsed, isDrawer, setOpenMobile } = useSidebar();
11
- const isActive = (href) => pathname === href;
12
- /**
13
- * ⛔ ACTIVATING A DESTINATION CLOSES THE DRAWER. It is the whole point of the
14
- * drawer and it was the one interaction that left it open: Escape, the
15
- * backdrop and the X all dismissed it, a navigation link did not.
16
- *
17
- * The overlay is modal, so `document.body` carries `pointer-events: none`
18
- * while it is up, and a consumer's `SidebarItem` is a client-side `Link`
19
- * under a provider that survives the route change — so the reader landed on
20
- * the new page rendered INERT behind a drawer they had to dismiss a second
21
- * time, on a phone.
22
- *
23
- * Here rather than in `SidebarRoot`, because this is the component that knows
24
- * an activation happened; `SidebarBackButton` and every
25
- * `SidebarItemCollapsibleContent` leaf render through it, so they are covered
26
- * by construction. Guarded on `isDrawer` so an inline rail — where nothing is
27
- * covering the page — behaves exactly as before, and the consumer's own
28
- * handler still runs either way.
29
- */
30
- const handleClick = (event) => {
31
- onClick?.(event);
32
- if (isDrawer) {
33
- setOpenMobile(false);
34
- }
35
- };
36
- if (isCollapsed) {
37
- return (_jsx(SidebarItemIconButton, { "data-slot": "sidebar-item", href: href, active: isActive(href) || active, onClick: handleClick, ...props }));
38
- }
39
- return (_jsx(SidebarItemButton, { "data-slot": "sidebar-item", href: href, active: isActive(href) || active, onClick: handleClick, ...props }));
40
- };
1
+ "use client";import{jsx as a}from"react/jsx-runtime";import{SidebarItemButton as b}from"./sidebar-item-button.js";import{SidebarItemIconButton as f}from"./sidebar-item-icon-button.js";import{useSidebar as p}from"./sidebar-provider.js";import{useSidebarRouter as S}from"./sidebar-router.js";export const SidebarItem=({active:i,href:t,children:h,onClick:n,...o})=>{const{usePathname:m}=S();const c=m();const{isCollapsed:d,isDrawer:l,setOpenMobile:u}=p();const r=e=>c===e;const s=e=>{n?.(e);if(l){u(false)}};if(d){return a(f,{"data-slot":"sidebar-item",href:t,active:r(t)||i,onClick:s,...o})}return a(b,{"data-slot":"sidebar-item",href:t,active:r(t)||i,onClick:s,...o})};
@@ -1,193 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import React from 'react';
4
- import { getStorage, getStorageObject } from '../../../lib/storage/index.js';
5
- /**
6
- * The viewport below which the rail stops being a layout and becomes a drawer.
7
- *
8
- * ⛔ THE NEGATION OF THE TRIGGER'S QUERY, SPELLED AS A NEGATION.
9
- *
10
- * `SidebarTrigger` hides itself at `min-[768px]`, which is `width >= 768`. This
11
- * is its exact complement AT ANY PRECISION, which `(max-width: 767px)` was not:
12
- * that pair leaves the open interval (767, 768) matched by neither rule, and a
13
- * viewport there draws the rail AND a hamburger that opens nothing — with the
14
- * rail inline, `SidebarRoot` mounts no `Sheet`, so the control is dead. Chromium
15
- * snaps its layout viewport to a whole pixel and never lands there, measured at
16
- * four zoom levels; that is a rounding behaviour to rely on, not a boundary.
17
- *
18
- * ⚠️ THE PAIR HAS TO BE IN THE SAME UNIT. It used to be `md:hidden` over there,
19
- * and `md` is 48rem: rem in a media query follows the BROWSER'S default font
20
- * size, so at Chrome's "Small" setting that class hid the hamburger from 576px
21
- * while this query still asked for a drawer up to 767px — a band of viewports
22
- * with no navigation at all. Anything else that hides or shows a control at
23
- * this boundary states it in pixels for the same reason.
24
- *
25
- * Media Queries Level 4 boolean logic, which is not a new requirement here:
26
- * Tailwind v4 emits MQ4 RANGE syntax for everything this package ships —
27
- * `min-[768px]` on the trigger compiles to `@media (width >= 768px)` and
28
- * `max-sm:` on `SheetContent` to `@media (width < 40rem)` — and range syntax
29
- * and boolean `not` landed in the same browsers (Chrome 88, Firefox 64,
30
- * Safari 16.4). `(width < 768px)` is the equivalent range spelling of this
31
- * line, should a reader prefer the pair to match character for character.
32
- */
33
- export const SIDEBAR_MOBILE_QUERY = 'not (min-width: 768px)';
34
- /**
35
- * Where focus goes when the rail has to receive it. The rail's own content is
36
- * links and buttons, so this is deliberately the short list rather than the
37
- * full tabbable grammar: a `[tabindex]` sweep would have to exclude `-1`, and
38
- * nothing in a sidebar carries one.
39
- */
40
- const FOCUSABLE = 'a[href], button:not([disabled])';
41
- /**
42
- * Exported so `SidebarRoot` can re-provide it for the drawer's subtree. That
43
- * subtree is the only place `isCollapsed` and `isDrawer` differ from the
44
- * provider's own values, and scoping the override to it is what keeps a
45
- * consumer on `mobile="inline"` seeing exactly today's rail.
46
- */
47
- export const SidebarContext = React.createContext(undefined);
48
- export const useSidebar = () => {
49
- const context = React.useContext(SidebarContext);
50
- if (!context) {
51
- throw new Error('useSidebar must be used within a SidebarProvider');
52
- }
53
- return context;
54
- };
55
- export const SidebarProvider = ({ children }) => {
56
- const [hydrated, setHydrated] = React.useState(false);
57
- const [collapsed, setCollapsed] = React.useState(false);
58
- const [items, _setItems] = React.useState({});
59
- const [isMobile, setIsMobile] = React.useState(false);
60
- const [openMobile, _setOpenMobile] = React.useState(false);
61
- const sidebarId = React.useId();
62
- /**
63
- * ⛔ RADIX CANNOT RESTORE THIS FOCUS BY ITSELF. `DialogContent` preventDefaults
64
- * the focus scope's own restore and focuses `triggerRef.current` instead —
65
- * the ref a `SheetTrigger` would have filled. The drawer is opened from this
66
- * state rather than from a trigger inside the dialog, so that ref is null and
67
- * closing dropped focus onto `<body>`: a keyboard reader who opened the
68
- * navigation and pressed Escape was returned to the top of the document.
69
- *
70
- * Captured here rather than in `SidebarTrigger` so that a consumer opening
71
- * the drawer from its own control gets the same behaviour.
72
- */
73
- const opener = React.useRef(null);
74
- const setOpenMobile = React.useCallback((open) => {
75
- if (open && typeof document !== 'undefined') {
76
- opener.current = document.activeElement;
77
- }
78
- _setOpenMobile(open);
79
- }, []);
80
- /**
81
- * ⛔ THE VIEWPORT AT THE MOMENT FOCUS MOVES, NOT AT THE MOMENT IT OPENED.
82
- *
83
- * Radix calls `restoreDrawerFocus` from the focus scope's UNMOUNT handler,
84
- * which is the last thing in the commit to touch focus — later than any
85
- * effect in this provider, so the decision has to be made inside the handler
86
- * rather than beside it. By then `isMobile` has already flipped.
87
- */
88
- const isMobileRef = React.useRef(false);
89
- isMobileRef.current = isMobile;
90
- const restoreDrawerFocus = React.useCallback(() => {
91
- // `isConnected`: the control that opened the drawer may itself have been
92
- // unmounted by whatever the reader did inside it.
93
- //
94
- // ⛔ AND NOT AT ALL WHEN THE VIEWPORT IS THE ONE THAT DISMISSED IT. A
95
- // tablet rotated from portrait to landscape with the navigation open
96
- // crosses 768px, so the drawer is replaced by the rail and the opener is
97
- // `SidebarTrigger` — which the same breakpoint just hid.
98
- // `.focus()` on a `display: none` element is a silent no-op, and Radix's
99
- // own restore is already `preventDefault()`ed, so focus fell to `<body>`
100
- // and the reader lost their place (SC 2.4.3). Measured in Chromium at
101
- // 390 → 1280: `{"rails":1,"triggerDisplay":"none","focus":"BODY:"}`.
102
- if (isMobileRef.current && opener.current?.isConnected) {
103
- opener.current.focus();
104
- return;
105
- }
106
- // The rail is what the drawer became, so that is where the reader goes.
107
- // Below the breakpoint there is nothing here to find — a closed drawer
108
- // leaves no navigation in the DOM — and focus stays where Radix left it.
109
- document
110
- .getElementById(sidebarId)
111
- ?.querySelector(FOCUSABLE)
112
- ?.focus();
113
- }, [sidebarId]);
114
- const toggleSidebar = () => setCollapsed((collapsed) => !collapsed);
115
- const getItemCollapsed = (key) => {
116
- return items[key] || false;
117
- };
118
- const setItemCollapsed = (key, value) => {
119
- _setItems((items) => ({ ...items, [key]: value }));
120
- };
121
- // Read from localStorage after hydration to avoid SSR mismatch
122
- React.useEffect(() => {
123
- setCollapsed(getStorage('sidebar-collapsed', false) === 'true');
124
- _setItems(getStorageObject('sidebar-items', {}));
125
- setHydrated(true);
126
- }, []);
127
- /**
128
- * ⚠️ FALSE UNTIL THE CLIENT SAYS OTHERWISE. There is no viewport on the
129
- * server, so the first paint is always the rail and the drawer appears on
130
- * hydration; starting from a guess would make the markup differ between the
131
- * two renders. The `matchMedia` guard is the one `theme-provider.tsx` next
132
- * door already carries: jsdom and some embedded runtimes ship without it, and
133
- * a missing media API is a desktop, not a crash.
134
- */
135
- React.useEffect(() => {
136
- if (typeof window.matchMedia !== 'function') {
137
- return;
138
- }
139
- const media = window.matchMedia(SIDEBAR_MOBILE_QUERY);
140
- const sync = () => setIsMobile(media.matches);
141
- sync();
142
- media.addEventListener('change', sync);
143
- return () => media.removeEventListener('change', sync);
144
- }, []);
145
- /**
146
- * A drawer left open while the viewport grows back would keep an overlay and
147
- * a focus trap over a layout that is already showing its rail, with nothing
148
- * on screen to dismiss them.
149
- *
150
- * Where focus goes afterwards is `restoreDrawerFocus`'s decision, not this
151
- * effect's: Radix's unmount handler runs later than anything here.
152
- */
153
- React.useEffect(() => {
154
- if (!isMobile) {
155
- _setOpenMobile(false);
156
- }
157
- }, [isMobile]);
158
- // Only persist to localStorage after hydration to avoid overwriting stored values
159
- React.useEffect(() => {
160
- if (!hydrated) {
161
- return;
162
- }
163
- localStorage.setItem('sidebar-collapsed', JSON.stringify(collapsed));
164
- }, [collapsed, hydrated]);
165
- React.useEffect(() => {
166
- if (!hydrated) {
167
- return;
168
- }
169
- localStorage.setItem('sidebar-items', JSON.stringify(items));
170
- }, [items, hydrated]);
171
- return (_jsx(SidebarContext.Provider, { value: {
172
- /**
173
- * ⚠️ A NARROW VIEWPORT DOES NOT TOUCH THIS. It used to be forced false
174
- * whenever `isMobile`, which silently changed the rail for every
175
- * consumer — including the ones that never asked for a drawer.
176
- * `SidebarRoot` overrides it for the drawer's own subtree instead, so
177
- * the stored preference reaches an inline rail unchanged at every
178
- * viewport.
179
- */
180
- isCollapsed: collapsed,
181
- isDrawer: false,
182
- isMobile,
183
- openMobile,
184
- setOpenMobile,
185
- restoreDrawerFocus,
186
- sidebarId,
187
- items,
188
- setItems: _setItems,
189
- getItemCollapsed,
190
- setItemCollapsed,
191
- toggleSidebar
192
- }, children: children }));
193
- };
1
+ "use client";import{jsx as w}from"react/jsx-runtime";import e from"react";import{getStorage as y,getStorageObject as M}from"../../../lib/storage/index.js";export const SIDEBAR_MOBILE_QUERY="not (min-width: 768px)";const v="a[href], button:not([disabled])";export const SidebarContext=e.createContext(void 0);export const useSidebar=()=>{const r=e.useContext(SidebarContext);if(!r){throw new Error("useSidebar must be used within a SidebarProvider")}return r};export const SidebarProvider=({children:r})=>{const[o,b]=e.useState(false);const[c,l]=e.useState(false);const[n,i]=e.useState({});const[a,p]=e.useState(false);const[S,f]=e.useState(false);const u=e.useId();const d=e.useRef(null);const g=e.useCallback(t=>{if(t&&typeof document!=="undefined"){d.current=document.activeElement}f(t)},[]);const m=e.useRef(false);m.current=a;const E=e.useCallback(()=>{if(m.current&&d.current?.isConnected){d.current.focus();return}document.getElementById(u)?.querySelector(v)?.focus()},[u]);const I=()=>l(t=>!t);const h=t=>{return n[t]||false};const x=(t,s)=>{i(C=>({...C,[t]:s}))};e.useEffect(()=>{l(y("sidebar-collapsed",false)==="true");i(M("sidebar-items",{}));b(true)},[]);e.useEffect(()=>{if(typeof window.matchMedia!=="function"){return}const t=window.matchMedia(SIDEBAR_MOBILE_QUERY);const s=()=>p(t.matches);s();t.addEventListener("change",s);return()=>t.removeEventListener("change",s)},[]);e.useEffect(()=>{if(!a){f(false)}},[a]);e.useEffect(()=>{if(!o){return}localStorage.setItem("sidebar-collapsed",JSON.stringify(c))},[c,o]);e.useEffect(()=>{if(!o){return}localStorage.setItem("sidebar-items",JSON.stringify(n))},[n,o]);return w(SidebarContext.Provider,{value:{isCollapsed:c,isDrawer:false,isMobile:a,openMobile:S,setOpenMobile:g,restoreDrawerFocus:E,sidebarId:u,items:n,setItems:i,getItemCollapsed:h,setItemCollapsed:x,toggleSidebar:I},children:r})};
@@ -22,6 +22,8 @@ export type SidebarRootProps = React.ComponentProps<'nav'> & {
22
22
  * the drawer opens. Unused while `mobile` is `'inline'`.
23
23
  */
24
24
  mobileTitle?: string;
25
+ /** The drawer close button's accessible name. Override for localization. */
26
+ mobileCloseLabel?: string;
25
27
  };
26
28
  /**
27
29
  * ⛔ BELOW 768px A RAIL IS NOT A LAYOUT — once a consumer opts in.
@@ -36,5 +38,5 @@ export type SidebarRootProps = React.ComponentProps<'nav'> & {
36
38
  * focus to whatever opened it are Radix Dialog's, through the kit's own
37
39
  * `Sheet`; none of that is re-implemented here.
38
40
  */
39
- export declare const SidebarRoot: ({ className, id, mobile, mobileTitle, ...props }: SidebarRootProps) => React.JSX.Element;
41
+ export declare const SidebarRoot: ({ className, id, mobile, mobileTitle, mobileCloseLabel, ...props }: SidebarRootProps) => React.JSX.Element;
40
42
  //# sourceMappingURL=sidebar-root.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-root.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/sidebar/sidebar-root.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAqEzB,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC3D;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAI,kDAMzB,gBAAgB,sBAqHlB,CAAA"}
1
+ {"version":3,"file":"sidebar-root.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/sidebar/sidebar-root.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAqEzB,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC3D;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAI,oEAOzB,gBAAgB,sBAsHlB,CAAA"}
@@ -1,126 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cva } from 'class-variance-authority';
4
- import { SidebarContext, useSidebar } from './sidebar-provider.js';
5
- import { cn } from '../../../lib/utils.js';
6
- import { Sheet, SheetContent, SheetTitle } from '../sheet/index.js';
7
- /**
8
- * ⛔ THE WIDTHS ARE TOKENS, NOT LITERALS.
9
- *
10
- * They were `w-[72px]` and `w-[244px]`, which a consumer could only override by
11
- * winning a specificity argument with `cn`. `--sidebar-width` and
12
- * `--sidebar-width-collapsed` are declared in `tokens.css`, so the default
13
- * still ships with the stylesheet, and a consumer re-points either one with
14
- * `className="[--sidebar-width:280px]"` ON THE RAIL, which moves the rail and
15
- * the mobile drawer together (see `liftWidthOverrides` below), or with a rule
16
- * on `:root`/`html`.
17
- *
18
- * ⚠️ A DECLARATION ON A REACT-TREE ANCESTOR REACHES THE RAIL AND NOT THE
19
- * DRAWER. Custom properties inherit down the DOM tree, and the drawer is
20
- * portalled to `document.body`, so a layout wrapper is not an ancestor of it.
21
- * `:root` is, which is why it is named above and a wrapper is not.
22
- */
23
- const sidebarVariants = cva('group/sidebar shadow-sidebar relative flex flex-col transition-[width] duration-300 ease-in-out', {
24
- variants: {
25
- collapsed: {
26
- true: 'w-[var(--sidebar-width-collapsed)]',
27
- false: 'w-[var(--sidebar-width)]'
28
- }
29
- },
30
- defaultVariants: {
31
- collapsed: false
32
- }
33
- });
34
- /**
35
- * Tailwind arbitrary-property classes that re-point the sidebar geometry, e.g.
36
- * `[--sidebar-width:320px]` or `[--sidebar-width-collapsed:88px]`.
37
- *
38
- * ⚠️ ANCHORED TO A CLASS BOUNDARY, WHICH IS THE WHOLE POINT OF THE LOOKBEHIND.
39
- * Unanchored it also matched the tail of `md:[--sidebar-width:320px]` and
40
- * lifted it with the prefix stripped — an override a consumer scoped to
41
- * ≥768px, applied unconditionally to the drawer that only exists below it.
42
- */
43
- const WIDTH_OVERRIDE = /(?<=^|\s)\[--sidebar-width(?:-collapsed)?:[^\]]+\]/g;
44
- /**
45
- * ⛔ THE ONE PART OF THE CONSUMER'S className THAT HAS TO CROSS THE PORTAL.
46
- *
47
- * `SheetContent` mounts through `SheetPortal` into `document.body`, and custom
48
- * properties inherit down the DOM tree rather than the React tree. So the
49
- * documented override — a class on the rail — set `--sidebar-width` on an
50
- * element the drawer is not a descendant of, and the whole className that DOES
51
- * travel lands on the inner `<nav>`, which is BELOW the element that reads the
52
- * variable. Measured in Chromium: rail 320px, drawer 244px. Following the
53
- * instruction handed to product-console produced a 280px rail on desktop and a
54
- * 244px drawer on a phone, silently.
55
- *
56
- * ⚠️ ONLY THE GEOMETRY TOKENS. The rest of a rail className is rail-shaped —
57
- * `h-full`, and the `data-[collapsed=false]:min-w-70` all eight console
58
- * sidebars pass — and putting that on the sheet would reinstate the
59
- * 280px-inside-a-244px-sheet overflow from the other side.
60
- */
61
- function liftWidthOverrides(className) {
62
- return className?.match(WIDTH_OVERRIDE)?.join(' ');
63
- }
64
- /**
65
- * ⛔ BELOW 768px A RAIL IS NOT A LAYOUT — once a consumer opts in.
66
- *
67
- * The widths above are a fixed share of a flex row, so at 390px the expanded
68
- * rail took 63% of the screen and left the page 146px, and the only affordance
69
- * — `SidebarExpandButton` — shrinks it to 72px, which is still 18% and still
70
- * permanently on screen. There was nothing that removed it.
71
- *
72
- * With `mobile="drawer"` the rail is replaced below the breakpoint by an
73
- * overlay drawer. Escape, the backdrop click, the focus trap and returning
74
- * focus to whatever opened it are Radix Dialog's, through the kit's own
75
- * `Sheet`; none of that is re-implemented here.
76
- */
77
- export const SidebarRoot = ({ className, id, mobile = 'inline', mobileTitle = 'Navigation', ...props }) => {
78
- const context = useSidebar();
79
- const { isCollapsed, isMobile, openMobile, setOpenMobile, restoreDrawerFocus, sidebarId } = context;
80
- if (!isMobile || mobile === 'inline') {
81
- return (_jsx("nav", { "data-slot": "sidebar-root", className: cn(sidebarVariants({ collapsed: isCollapsed }), className), "data-collapsed": isCollapsed, ...props, id: mobile === 'drawer' ? sidebarId : id }));
82
- }
83
- return (_jsx(SidebarContext.Provider, { value: { ...context, isCollapsed: false, isDrawer: true }, children: _jsx(Sheet, { open: openMobile, onOpenChange: setOpenMobile, children: _jsxs(SheetContent, { side: "left",
84
- // The Sheet's own paddings are built for a form panel; a rail brings
85
- // its own. `max-w-full` so a consumer widening `--sidebar-width` past
86
- // the viewport still cannot push the drawer off screen. The lifted
87
- // override goes LAST so it re-points the variable this element reads.
88
- //
89
- // ⛔ THE `max-sm:` PAIR IS NOT A DUPLICATE. `SheetContent` grew a
90
- // phone step — `max-sm:w-full max-sm:px-4` — because a form panel at
91
- // two fifths of a 390px screen is unreadable. A NAVIGATION drawer is
92
- // the one panel that must not take it: 244px over a dimmed page is
93
- // the design, and full-bleed removes the tap-outside-to-close target
94
- // that every other way out of this drawer is an alternative to.
95
- // tailwind-merge drops a conflicting class only when the modifiers
96
- // match, so a bare `w-[…]` cannot reach `max-sm:w-full` and these two
97
- // tokens are what state the exemption. Measured: without them the
98
- // drawer is 390px wide with 16px of inset on a 390px phone.
99
- className: cn('w-[var(--sidebar-width)] max-w-full gap-0 p-0 max-sm:w-[var(--sidebar-width)] max-sm:p-0', liftWidthOverrides(className)), "aria-describedby": undefined,
100
- // ⛔ RADIX'S OWN RESTORE GOES NOWHERE HERE. `DialogContent`
101
- // preventDefaults the focus scope's restore and focuses the ref a
102
- // `SheetTrigger` would have filled; this drawer is opened from provider
103
- // state, so that ref is null and closing dropped focus onto `<body>`.
104
- // Running first means `composeEventHandlers` skips Radix's half.
105
- onCloseAutoFocus: (event) => {
106
- event.preventDefault();
107
- restoreDrawerFocus();
108
- }, children: [_jsx(SheetTitle, { className: "sr-only", children: mobileTitle }), _jsx("nav", { "data-slot": "sidebar-root", "data-mobile": "true",
109
- /* ⛔ NO `data-collapsed` HERE. The consumer className is forwarded
110
- verbatim, and all eight console sidebars pass
111
- `data-[collapsed=false]:min-w-70`; stamping the attribute armed
112
- it, giving the navigation a 280px min-width inside a 244px sheet.
113
- `min-width` resolves after `max-width`, so the sheet could not
114
- claw it back and the contents were 36px wider than the drawer.
115
- `data-mobile` already names this surface and a drawer is never
116
- collapsed, so the attribute had nothing left to say. */
117
- className: cn(sidebarVariants({ collapsed: false }), 'h-full w-full shadow-none', className), ...props,
118
- /* ⛔ AFTER THE SPREAD, AND NOT THE CALLER'S. This is the target of
119
- `SidebarTrigger`'s `aria-controls` and the handle the provider
120
- uses to put focus back into the navigation when the viewport
121
- grows. Spread first, a caller that set `id` replaced it and left
122
- a dangling `aria-controls` — which axe reports as a CRITICAL
123
- `aria-valid-attr-value` — and a focus restore that lands on
124
- `<body>`. Both silent. */
125
- id: sidebarId })] }) }) }));
126
- };
1
+ "use client";import{jsx as a,jsxs as w}from"react/jsx-runtime";import{cva as v}from"class-variance-authority";import{SidebarContext as x,useSidebar as C}from"./sidebar-provider.js";import{cn as s}from"../../../lib/utils.js";import{Sheet as S,SheetContent as g,SheetTitle as j}from"../sheet/index.js";const d=v("group/sidebar shadow-sidebar relative flex flex-col transition-[width] duration-300 ease-in-out",{variants:{collapsed:{true:"w-[var(--sidebar-width-collapsed)]",false:"w-[var(--sidebar-width)]"}},defaultVariants:{collapsed:false}});const D=/(?<=^|\s)\[--sidebar-width(?:-collapsed)?:[^\]]+\]/g;function O(e){return e?.match(D)?.join(" ")}export const SidebarRoot=({className:e,id:n,mobile:r="inline",mobileTitle:c="Navigation",mobileCloseLabel:p="Close",...i})=>{const t=C();const{isCollapsed:o,isMobile:u,openMobile:f,setOpenMobile:b,restoreDrawerFocus:h,sidebarId:l}=t;if(!u||r==="inline"){return a("nav",{"data-slot":"sidebar-root",className:s(d({collapsed:o}),e),"data-collapsed":o,...i,id:r==="drawer"?l:n})}return a(x.Provider,{value:{...t,isCollapsed:false,isDrawer:true},children:a(S,{open:f,onOpenChange:b,children:w(g,{side:"left",closeLabel:p,className:s("w-[var(--sidebar-width)] max-w-full gap-0 p-0 max-sm:w-[var(--sidebar-width)] max-sm:p-0",O(e)),"aria-describedby":void 0,onCloseAutoFocus:m=>{m.preventDefault();h()},children:[a(j,{className:"sr-only",children:c}),a("nav",{"data-slot":"sidebar-root","data-mobile":"true",className:s(d({collapsed:false}),"h-full w-full shadow-none",e),...i,id:l})]})})})};
@@ -1,89 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- /**
4
- * Router injection for the sidebar's links.
5
- *
6
- * The sidebar needs exactly two things from a router: a component that renders
7
- * a client-side-navigating link, and a way to read the current pathname (for
8
- * the active item). Nothing else.
9
- *
10
- * Resolution order, per render:
11
- * 1. a mounted <SidebarRouterProvider> — what a Vite/TanStack Router app uses
12
- * 2. next/link + next/navigation, when the app runs under Next.js
13
- * 3. a plain <a> (full page loads) + a dev-only warning
14
- *
15
- * Step 2 is why a Next.js app needs no provider and no code change: the default
16
- * still routes through next/link exactly as the hard import used to.
17
- */
18
- import * as React from 'react';
19
- import { loadNextRouter } from './next-router.cjs';
20
- const SidebarRouterContext = React.createContext(null);
21
- /**
22
- * Teaches the sidebar how to navigate. Mount it above any sidebar in an app
23
- * that is not Next.js:
24
- *
25
- * <SidebarRouterProvider router={{ Link: MyLink, usePathname: useMyPathname }}>
26
- *
27
- * Keep `router` referentially stable (module constant or useMemo): `usePathname`
28
- * is called as a hook, so swapping the object for a different implementation
29
- * mid-tree would change hook identity.
30
- */
31
- export function SidebarRouterProvider({ router, children }) {
32
- return (_jsx(SidebarRouterContext.Provider, { value: router, children: children }));
33
- }
34
- /**
35
- * Resolve Next's router once, at module load, so the returned object — and
36
- * therefore `usePathname`'s identity — is stable across renders.
37
- *
38
- * The resolution itself lives in `next-router.cjs`: it needs a literal
39
- * `require`, which exists in the CommonJS output but not in the ESM one. That
40
- * file is CommonJS in both builds, so a Next.js consumer keeps client-side
41
- * navigation whichever format its bundler picks. See the file for the details.
42
- */
43
- const NEXT_ROUTER = loadNextRouter();
44
- let warned = false;
45
- /**
46
- * The router-only props, as a runtime key set. Typed `Record<keyof
47
- * RouterOnlyLinkProps, true>` so it is exhaustive BY CONSTRUCTION: adding a
48
- * prop to the type without listing it here is a compile error, and the two can
49
- * never drift. Forwarding any of these to a DOM `<a>` earns a React
50
- * unknown-attribute warning.
51
- */
52
- const ROUTER_ONLY_PROPS = {
53
- as: true,
54
- replace: true,
55
- scroll: true,
56
- shallow: true,
57
- passHref: true,
58
- prefetch: true,
59
- unstable_dynamicOnHover: true,
60
- locale: true,
61
- legacyBehavior: true,
62
- onNavigate: true,
63
- transitionTypes: true
64
- };
65
- /** Last resort: a real link that costs a full page load. Warns once, in dev. */
66
- function PlainLink({ href, children, ...rest }) {
67
- if (!warned && process.env.NODE_ENV !== 'production') {
68
- warned = true;
69
- console.warn('sindarian-ui: sidebar links are falling back to plain <a>, so every ' +
70
- 'navigation reloads the page and no item will show as active. Mount ' +
71
- '<SidebarRouterProvider router={{ Link, usePathname }}> above the ' +
72
- "sidebar with your router's equivalents.");
73
- }
74
- const anchorProps = { ...rest };
75
- for (const key of Object.keys(ROUTER_ONLY_PROPS))
76
- delete anchorProps[key];
77
- return (_jsx("a", { href: href, ...anchorProps, children: children }));
78
- }
79
- const FALLBACK_ROUTER = {
80
- Link: PlainLink,
81
- // No router, no truth. Returning '' marks nothing active rather than
82
- // guessing from location.pathname, which would go stale on the first
83
- // client-side navigation anyway.
84
- usePathname: () => ''
85
- };
86
- /** The router the sidebar should use: injected, else Next, else plain anchors. */
87
- export function useSidebarRouter() {
88
- return (React.useContext(SidebarRouterContext) ?? NEXT_ROUTER ?? FALLBACK_ROUTER);
89
- }
1
+ "use client";import{jsx as o}from"react/jsx-runtime";import*as n from"react";import{loadNextRouter as l}from"./next-router.cjs";const a=n.createContext(null);export function SidebarRouterProvider({router:e,children:r}){return o(a.Provider,{value:e,children:r})}const c=l();let i=false;const d={as:true,replace:true,scroll:true,shallow:true,passHref:true,prefetch:true,unstable_dynamicOnHover:true,locale:true,legacyBehavior:true,onNavigate:true,transitionTypes:true};function f({href:e,children:r,...s}){if(!i&&process.env.NODE_ENV!=="production"){i=true;console.warn("sindarian-ui: sidebar links are falling back to plain <a>, so every navigation reloads the page and no item will show as active. Mount <SidebarRouterProvider router={{ Link, usePathname }}> above the sidebar with your router's equivalents.")}const t={...s};for(const u of Object.keys(d))delete t[u];return o("a",{href:e,...t,children:r})}const p={Link:f,usePathname:()=>""};export function useSidebarRouter(){return n.useContext(a)??c??p}
@@ -1,53 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { Menu } from 'lucide-react';
4
- import { cn } from '../../../lib/utils.js';
5
- import { IconButton } from '../icon-button/index.js';
6
- import { useSidebar } from './sidebar-provider.js';
7
- /**
8
- * The control that opens the mobile drawer.
9
- *
10
- * Hidden from 768px up by default, because above it the rail is already on
11
- * screen and a second way to reach it is a second thing to explain; a consumer
12
- * that wants it everywhere passes its own display class.
13
- *
14
- * ⛔ THE BREAKPOINT IS IN PIXELS, AND `md:hidden` IS NOT A SPELLING OF IT.
15
- *
16
- * Whether the rail became a drawer is decided by `SIDEBAR_MOBILE_QUERY`, which
17
- * is `not (min-width: 768px)` — pixels. `md:` is 48rem, and rem inside a MEDIA
18
- * QUERY resolves against the browser's default font size rather than anything
19
- * the page declares, so the two flip at different widths the moment a reader
20
- * changes that setting. At Chrome's "Small" (12px) `md:` turns over at 576px
21
- * while the drawer still turns over at 768px: every window between them showed
22
- * NO RAIL AND NO HAMBURGER, which is a console with no navigation at all.
23
- * Measured on product-console; the band is four of this package's own fixtures
24
- * in `scripts/measure-phone-shapes.mjs`. At "Very large" (20px) the same
25
- * mismatch runs the other way and 768–959px drew both.
26
- *
27
- * `min-[768px]:hidden` is the exact complement of that query, at every font
28
- * size AND at any sub-pixel precision — which is why the query next door is
29
- * spelled as a negation rather than as `(max-width: 767px)`: that pair leaves
30
- * the open interval (767, 768) matched by neither, and a viewport there draws
31
- * the rail plus a hamburger that opens nothing.
32
- *
33
- * ⚠️ THE PROPERTY IS ABOUT THE TWO MEDIA DECISIONS, NOT ABOUT THE FIRST PAINT.
34
- * The harness enforces one of the two and never neither or both, which holds
35
- * wherever `isMobile` has been read. `isMobile` starts false on purpose — there
36
- * is no viewport on the server — and is corrected in an effect, so on a phone
37
- * the first painted frame shows the inline rail while this control is already
38
- * on screen. That one hydration is the deliberate price of hydration safety,
39
- * documented on `SidebarProvider`'s own effect, and predates this class.
40
- *
41
- * ⚠️ `aria-controls` IS SET ONLY WHILE THE DRAWER EXISTS. Radix unmounts the
42
- * dialog content when closed, and a reference to an element that is not in the
43
- * DOM is what axe-core reports as a CRITICAL `aria-valid-attr-value` — the same
44
- * defect the Autocomplete panel was repaired for (console-sdk#150). A toggle
45
- * with `aria-expanded="false"` and no `aria-controls` is complete on its own.
46
- */
47
- export const SidebarTrigger = ({ className, onClick, 'aria-label': ariaLabel = 'Open navigation', ...props }) => {
48
- const { openMobile, setOpenMobile, sidebarId } = useSidebar();
49
- return (_jsx(IconButton, { type: "button", variant: "outline", "data-slot": "sidebar-trigger", "aria-label": ariaLabel, "aria-expanded": openMobile, "aria-controls": openMobile ? sidebarId : undefined, className: cn('min-[768px]:hidden', className), onClick: (event) => {
50
- onClick?.(event);
51
- setOpenMobile(!openMobile);
52
- }, ...props, children: _jsx(Menu, { "aria-hidden": true }) }));
53
- };
1
+ "use client";import{jsx as r}from"react/jsx-runtime";import{Menu as l}from"lucide-react";import{cn as m}from"../../../lib/utils.js";import{IconButton as p}from"../icon-button/index.js";import{useSidebar as b}from"./sidebar-provider.js";export const SidebarTrigger=({className:i,onClick:a,"aria-label":n="Open navigation",...o})=>{const{openMobile:e,setOpenMobile:t,sidebarId:d}=b();return r(p,{type:"button",variant:"outline","data-slot":"sidebar-trigger","aria-label":n,"aria-expanded":e,"aria-controls":e?d:void 0,className:m("min-[768px]:hidden",i),onClick:s=>{a?.(s);t(!e)},...o,children:r(l,{"aria-hidden":true})})};
@@ -1,6 +1 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cn } from '../../../lib/utils.js';
3
- function Skeleton({ className, ...props }) {
4
- return (_jsx("div", { "data-slot": "skeleton", className: cn('bg-muted rounded-md motion-safe:animate-pulse', className), ...props }));
5
- }
6
- export { Skeleton };
1
+ import{jsx as t}from"react/jsx-runtime";import{cn as m}from"../../../lib/utils.js";function n({className:e,...o}){return t("div",{"data-slot":"skeleton",className:m("bg-muted rounded-md motion-safe:animate-pulse",e),...o})}export{n as Skeleton};
@@ -1,20 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { cn } from '../../../lib/utils.js';
3
- import { CircleCheck } from 'lucide-react';
4
- import { Skeleton } from '../skeleton/index.js';
5
- export function Stepper({ className, ...props }) {
6
- return (_jsx("div", { "data-slot": "stepper", className: cn('stepper', className), ...props }));
7
- }
8
- export function StepperItem({ className, active = false, complete = false, ...props }) {
9
- return (_jsx("div", { "data-slot": "stepper-item", "data-active": active, "data-complete": complete, className: cn('stepper-item group', className), ...props }));
10
- }
11
- export function StepperItemNumber({ className, ...props }) {
12
- return (_jsx("div", { "data-slot": "stepper-item-number", className: cn('stepper-item-number', className), ...props }));
13
- }
14
- export function StepperItemText({ className, title, description, ...props }) {
15
- return (_jsxs("div", { "data-slot": "stepper-item-text", className: cn('stepper-item-text', className), ...props, children: [_jsxs("div", { className: "stepper-item-title", children: [_jsx("p", { children: title }), _jsx(CircleCheck, { className: "stepper-item-icon", width: 16, height: 16 })] }), description && _jsx("p", { className: "stepper-item-description", children: description })] }));
16
- }
17
- export const StepperContent = ({ active, children }) => {
18
- return active ? _jsx(_Fragment, { children: children }) : null;
19
- };
20
- export const StepperItemSkeleton = () => (_jsxs("div", { className: "flex flex-row items-center gap-3", children: [_jsx(Skeleton, { className: "bg-muted h-8 w-8 rounded-full" }), _jsx(Skeleton, { className: "bg-muted h-5 w-32" })] }));
1
+ import{jsx as r,jsxs as m,Fragment as n}from"react/jsx-runtime";import{cn as s}from"../../../lib/utils.js";import{CircleCheck as l}from"lucide-react";import{Skeleton as i}from"../skeleton/index.js";export function Stepper({className:e,...t}){return r("div",{"data-slot":"stepper",className:s("stepper",e),...t})}export function StepperItem({className:e,active:t=false,complete:p=false,...a}){return r("div",{"data-slot":"stepper-item","data-active":t,"data-complete":p,className:s("stepper-item group",e),...a})}export function StepperItemNumber({className:e,...t}){return r("div",{"data-slot":"stepper-item-number",className:s("stepper-item-number",e),...t})}export function StepperItemText({className:e,title:t,description:p,...a}){return m("div",{"data-slot":"stepper-item-text",className:s("stepper-item-text",e),...a,children:[m("div",{className:"stepper-item-title",children:[r("p",{children:t}),r(l,{className:"stepper-item-icon",width:16,height:16})]}),p&&r("p",{className:"stepper-item-description",children:p})]})}export const StepperContent=({active:e,children:t})=>{return e?r(n,{children:t}):null};export const StepperItemSkeleton=()=>m("div",{className:"flex flex-row items-center gap-3",children:[r(i,{className:"bg-muted h-8 w-8 rounded-full"}),r(i,{className:"bg-muted h-5 w-32"})]});
@@ -1,8 +1 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import * as SwitchPrimitives from '@radix-ui/react-switch';
4
- import { cn } from '../../../lib/utils.js';
5
- function Switch({ className, ...props }) {
6
- return (_jsx(SwitchPrimitives.Root, { "data-slot": "switch", className: cn('focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-muted peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: _jsx(SwitchPrimitives.Thumb, { "data-slot": "switch-thumb", className: cn('bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0') }) }));
7
- }
8
- export { Switch };
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import*as t from"@radix-ui/react-switch";import{cn as i}from"../../../lib/utils.js";function o({className:r,...s}){return e(t.Root,{"data-slot":"switch",className:i("focus-visible:ring-ring focus-visible:ring-offset-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-muted peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50",r),...s,children:e(t.Thumb,{"data-slot":"switch-thumb",className:i("bg-background pointer-events-none block h-5 w-5 rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0")})})}export{o as Switch};