@lerianstudio/sindarian-ui 2.0.0-beta.25 → 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 (305) 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.js +1 -96
  11. package/dist/components/dialog/confirmation-dialog/use-confirm-dialog.js +1 -55
  12. package/dist/components/dialog/index.js +1 -19
  13. package/dist/components/dialog/large-dialog/index.js +1 -21
  14. package/dist/components/entity-box/index.js +1 -67
  15. package/dist/components/entity-data-table/index.js +1 -20
  16. package/dist/components/form/combo-box-field/index.js +1 -35
  17. package/dist/components/form/country-field/index.js +1 -11
  18. package/dist/components/form/date-picker-field/index.js +1 -83
  19. package/dist/components/form/date-range-field/index.js +1 -58
  20. package/dist/components/form/date-time-picker-field/index.js +1 -114
  21. package/dist/components/form/file-upload-field/index.js +1 -69
  22. package/dist/components/form/index.js +1 -31
  23. package/dist/components/form/input-field/index.js +1 -96
  24. package/dist/components/form/otp-field/index.js +1 -19
  25. package/dist/components/form/pagination-limit-field/index.js +1 -10
  26. package/dist/components/form/password-field/index.js +1 -16
  27. package/dist/components/form/radio-group-field/index.js +1 -36
  28. package/dist/components/form/renderable-label.js +1 -57
  29. package/dist/components/form/select-field/index.js +1 -68
  30. package/dist/components/form/state-field/index.js +1 -42
  31. package/dist/components/form/switch-field/index.js +1 -16
  32. package/dist/components/form/textarea-field/index.js +1 -23
  33. package/dist/components/page/index.js +1 -20
  34. package/dist/components/page-header/index.js +1 -80
  35. package/dist/components/pagination/index.js +1 -10
  36. package/dist/components/table/id-table-cell.js +1 -109
  37. package/dist/components/table/index.js +1 -19
  38. package/dist/components/table/locked-table-actions.js +1 -41
  39. package/dist/components/table/name-table-cell.js +1 -58
  40. package/dist/components/ui/accordion/index.js +1 -62
  41. package/dist/components/ui/alert/index.js +1 -45
  42. package/dist/components/ui/alert-dialog/index.js +1 -84
  43. package/dist/components/ui/autocomplete/index.js +1 -440
  44. package/dist/components/ui/autosize-textarea/index.js +1 -89
  45. package/dist/components/ui/avatar/index.js +1 -51
  46. package/dist/components/ui/badge/index.js +1 -83
  47. package/dist/components/ui/breadcrumb/index.js +1 -35
  48. package/dist/components/ui/button/index.js +1 -65
  49. package/dist/components/ui/calendar/index.js +1 -118
  50. package/dist/components/ui/card/index.js +1 -32
  51. package/dist/components/ui/checkbox/index.js +1 -44
  52. package/dist/components/ui/collapsible/index.js +1 -50
  53. package/dist/components/ui/command/index.js +1 -95
  54. package/dist/components/ui/copy-field/index.js +1 -163
  55. package/dist/components/ui/dialog/index.js +1 -80
  56. package/dist/components/ui/dropdown-menu/index.js +1 -110
  57. package/dist/components/ui/field/index.js +1 -82
  58. package/dist/components/ui/file-upload/index.js +1 -574
  59. package/dist/components/ui/form.js +1 -162
  60. package/dist/components/ui/hover-card/index.js +1 -51
  61. package/dist/components/ui/icon-button/index.js +1 -35
  62. package/dist/components/ui/input/adornment.js +1 -21
  63. package/dist/components/ui/input/index.js +1 -99
  64. package/dist/components/ui/label/index.js +1 -45
  65. package/dist/components/ui/lerian-wordmark/index.js +1 -7
  66. package/dist/components/ui/loading-button/index.js +1 -9
  67. package/dist/components/ui/multiple-select/index.js +1 -235
  68. package/dist/components/ui/otp-input/index.js +1 -62
  69. package/dist/components/ui/paper/index.js +1 -8
  70. package/dist/components/ui/paper-collapsible/index.js +1 -24
  71. package/dist/components/ui/popover/index.js +1 -55
  72. package/dist/components/ui/progress/index.js +1 -66
  73. package/dist/components/ui/qr-code/index.js +1 -27
  74. package/dist/components/ui/radio-group/index.js +1 -48
  75. package/dist/components/ui/scroll-area/index.js +1 -49
  76. package/dist/components/ui/select/index.js +1 -119
  77. package/dist/components/ui/separator/index.js +1 -43
  78. package/dist/components/ui/sheet/index.js +1 -136
  79. package/dist/components/ui/sidebar/index.js +1 -27
  80. package/dist/components/ui/sidebar/next-router.cjs +1 -119
  81. package/dist/components/ui/sidebar/sidebar-back-button.js +1 -8
  82. package/dist/components/ui/sidebar/sidebar-components.js +1 -23
  83. package/dist/components/ui/sidebar/sidebar-expand-button.js +1 -49
  84. package/dist/components/ui/sidebar/sidebar-item-button.js +1 -21
  85. package/dist/components/ui/sidebar/sidebar-item-collapsible.js +1 -52
  86. package/dist/components/ui/sidebar/sidebar-item-icon-button.js +1 -18
  87. package/dist/components/ui/sidebar/sidebar-item.js +1 -44
  88. package/dist/components/ui/sidebar/sidebar-provider.js +1 -201
  89. package/dist/components/ui/sidebar/sidebar-root.js +1 -130
  90. package/dist/components/ui/sidebar/sidebar-router.js +1 -126
  91. package/dist/components/ui/sidebar/sidebar-trigger.js +1 -57
  92. package/dist/components/ui/skeleton/index.js +1 -8
  93. package/dist/components/ui/stepper/index.js +1 -29
  94. package/dist/components/ui/switch/index.js +1 -43
  95. package/dist/components/ui/table/index.js +1 -56
  96. package/dist/components/ui/tabs/index.js +1 -55
  97. package/dist/components/ui/textarea/index.js +1 -8
  98. package/dist/components/ui/time-picker/index.js +1 -85
  99. package/dist/components/ui/toast/index.js +1 -3
  100. package/dist/components/ui/toast/toaster.js +1 -16
  101. package/dist/components/ui/toggle-group/index.js +1 -156
  102. package/dist/components/ui/tooltip/index.js +1 -81
  103. package/dist/domain/blotter/index.js +1 -20
  104. package/dist/domain/delinquency-aging/aging-buckets.js +1 -120
  105. package/dist/domain/delinquency-aging/index.js +1 -222
  106. package/dist/domain/figure/index.js +1 -19
  107. package/dist/domain/format.js +1 -137
  108. package/dist/domain/index.js +1 -43
  109. package/dist/domain/key-id/index.js +1 -174
  110. package/dist/domain/ledger-sheet/index.js +1 -28
  111. package/dist/domain/money-diff.js +1 -48
  112. package/dist/domain/money-math.js +1 -104
  113. package/dist/domain/money-text/index.js +1 -123
  114. package/dist/domain/section-label/index.js +1 -17
  115. package/dist/domain/status-rail/index.js +1 -76
  116. package/dist/domain/threshold-gauge/index.js +1 -161
  117. package/dist/enterprise/alert-banner/index.js +1 -24
  118. package/dist/enterprise/app-shell/index.js +1 -87
  119. package/dist/enterprise/cursor-pager/index.js +1 -26
  120. package/dist/enterprise/data-table/column-size.js +1 -103
  121. package/dist/enterprise/data-table/index.js +1 -345
  122. package/dist/enterprise/date-range-picker/index.js +1 -115
  123. package/dist/enterprise/detail-panel/index.js +1 -20
  124. package/dist/enterprise/empty-state/index.js +1 -14
  125. package/dist/enterprise/index.js +1 -39
  126. package/dist/enterprise/number-input/index.js +1 -252
  127. package/dist/enterprise/search-input/index.js +1 -121
  128. package/dist/enterprise/stat-card/index.js +1 -75
  129. package/dist/enterprise/status-badge/index.js +1 -120
  130. package/dist/enterprise/use-is-mobile.js +1 -68
  131. package/dist/enterprise/virtualized-table/index.js +1 -141
  132. package/dist/esm/charts/chart.js +4 -190
  133. package/dist/esm/charts/index.js +1 -3
  134. package/dist/esm/components/breadcrumb/get-breadcrumb-paths.js +1 -12
  135. package/dist/esm/components/breadcrumb/index.js +1 -30
  136. package/dist/esm/components/card/account-card/index.js +1 -53
  137. package/dist/esm/components/card/basic-card/index.js +1 -14
  138. package/dist/esm/components/card/dashboard-card/index.js +1 -14
  139. package/dist/esm/components/card/entity-card/index.js +1 -52
  140. package/dist/esm/components/card/index.js +1 -4
  141. package/dist/esm/components/dialog/confirmation-dialog/index.js +1 -60
  142. package/dist/esm/components/dialog/confirmation-dialog/use-confirm-dialog.js +1 -49
  143. package/dist/esm/components/dialog/index.js +1 -3
  144. package/dist/esm/components/dialog/large-dialog/index.js +1 -16
  145. package/dist/esm/components/entity-box/index.js +1 -56
  146. package/dist/esm/components/entity-data-table/index.js +1 -17
  147. package/dist/esm/components/form/combo-box-field/index.js +1 -28
  148. package/dist/esm/components/form/country-field/index.js +1 -7
  149. package/dist/esm/components/form/date-picker-field/index.js +1 -43
  150. package/dist/esm/components/form/date-range-field/index.js +1 -18
  151. package/dist/esm/components/form/date-time-picker-field/index.js +1 -74
  152. package/dist/esm/components/form/file-upload-field/index.js +1 -65
  153. package/dist/esm/components/form/index.js +1 -15
  154. package/dist/esm/components/form/input-field/index.js +1 -92
  155. package/dist/esm/components/form/otp-field/index.js +1 -15
  156. package/dist/esm/components/form/pagination-limit-field/index.js +1 -6
  157. package/dist/esm/components/form/password-field/index.js +1 -10
  158. package/dist/esm/components/form/radio-group-field/index.js +1 -32
  159. package/dist/esm/components/form/renderable-label.js +1 -54
  160. package/dist/esm/components/form/select-field/index.js +1 -64
  161. package/dist/esm/components/form/state-field/index.js +1 -35
  162. package/dist/esm/components/form/switch-field/index.js +1 -12
  163. package/dist/esm/components/form/textarea-field/index.js +1 -19
  164. package/dist/esm/components/page/index.js +1 -15
  165. package/dist/esm/components/page-header/index.js +1 -71
  166. package/dist/esm/components/pagination/index.js +1 -6
  167. package/dist/esm/components/table/id-table-cell.js +1 -105
  168. package/dist/esm/components/table/index.js +1 -3
  169. package/dist/esm/components/table/locked-table-actions.js +1 -37
  170. package/dist/esm/components/table/name-table-cell.js +1 -54
  171. package/dist/esm/components/ui/accordion/index.js +1 -24
  172. package/dist/esm/components/ui/alert/index.js +1 -38
  173. package/dist/esm/components/ui/alert-dialog/index.js +1 -39
  174. package/dist/esm/components/ui/autocomplete/index.js +1 -392
  175. package/dist/esm/components/ui/autosize-textarea/index.js +1 -51
  176. package/dist/esm/components/ui/avatar/index.js +1 -14
  177. package/dist/esm/components/ui/badge/index.js +1 -79
  178. package/dist/esm/components/ui/breadcrumb/index.js +1 -27
  179. package/dist/esm/components/ui/button/index.js +1 -60
  180. package/dist/esm/components/ui/calendar/index.js +1 -82
  181. package/dist/esm/components/ui/card/index.js +1 -24
  182. package/dist/esm/components/ui/checkbox/index.js +1 -9
  183. package/dist/esm/components/ui/collapsible/index.js +1 -13
  184. package/dist/esm/components/ui/command/index.js +1 -51
  185. package/dist/esm/components/ui/copy-field/index.js +1 -127
  186. package/dist/esm/components/ui/dialog/index.js +1 -36
  187. package/dist/esm/components/ui/dropdown-menu/index.js +1 -60
  188. package/dist/esm/components/ui/field/index.js +1 -71
  189. package/dist/esm/components/ui/file-upload/index.js +1 -536
  190. package/dist/esm/components/ui/form.js +1 -118
  191. package/dist/esm/components/ui/hover-card/index.js +1 -14
  192. package/dist/esm/components/ui/icon-button/index.js +1 -31
  193. package/dist/esm/components/ui/input/adornment.js +1 -17
  194. package/dist/esm/components/ui/input/index.js +1 -60
  195. package/dist/esm/components/ui/label/index.js +1 -10
  196. package/dist/esm/components/ui/lerian-wordmark/index.js +1 -4
  197. package/dist/esm/components/ui/loading-button/index.js +1 -7
  198. package/dist/esm/components/ui/multiple-select/index.js +1 -196
  199. package/dist/esm/components/ui/otp-input/index.js +1 -21
  200. package/dist/esm/components/ui/paper/index.js +1 -5
  201. package/dist/esm/components/ui/paper-collapsible/index.js +1 -19
  202. package/dist/esm/components/ui/popover/index.js +1 -17
  203. package/dist/esm/components/ui/progress/index.js +1 -31
  204. package/dist/esm/components/ui/qr-code/index.js +1 -24
  205. package/dist/esm/components/ui/radio-group/index.js +1 -12
  206. package/dist/esm/components/ui/scroll-area/index.js +1 -13
  207. package/dist/esm/components/ui/select/index.js +1 -74
  208. package/dist/esm/components/ui/separator/index.js +1 -8
  209. package/dist/esm/components/ui/sheet/index.js +1 -92
  210. package/dist/esm/components/ui/sidebar/index.js +1 -11
  211. package/dist/esm/components/ui/sidebar/next-router.cjs +1 -119
  212. package/dist/esm/components/ui/sidebar/sidebar-back-button.js +1 -5
  213. package/dist/esm/components/ui/sidebar/sidebar-components.js +1 -15
  214. package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +1 -42
  215. package/dist/esm/components/ui/sidebar/sidebar-item-button.js +1 -18
  216. package/dist/esm/components/ui/sidebar/sidebar-item-collapsible.js +1 -44
  217. package/dist/esm/components/ui/sidebar/sidebar-item-icon-button.js +1 -14
  218. package/dist/esm/components/ui/sidebar/sidebar-item.js +1 -40
  219. package/dist/esm/components/ui/sidebar/sidebar-provider.js +1 -193
  220. package/dist/esm/components/ui/sidebar/sidebar-root.js +1 -126
  221. package/dist/esm/components/ui/sidebar/sidebar-router.js +1 -89
  222. package/dist/esm/components/ui/sidebar/sidebar-trigger.js +1 -53
  223. package/dist/esm/components/ui/skeleton/index.js +1 -6
  224. package/dist/esm/components/ui/stepper/index.js +1 -20
  225. package/dist/esm/components/ui/switch/index.js +1 -8
  226. package/dist/esm/components/ui/table/index.js +1 -44
  227. package/dist/esm/components/ui/tabs/index.js +1 -17
  228. package/dist/esm/components/ui/textarea/index.js +1 -6
  229. package/dist/esm/components/ui/time-picker/index.js +1 -49
  230. package/dist/esm/components/ui/toast/index.js +1 -2
  231. package/dist/esm/components/ui/toast/toaster.js +1 -13
  232. package/dist/esm/components/ui/toggle-group/index.js +1 -120
  233. package/dist/esm/components/ui/tooltip/index.js +1 -43
  234. package/dist/esm/domain/blotter/index.js +1 -16
  235. package/dist/esm/domain/delinquency-aging/aging-buckets.js +1 -115
  236. package/dist/esm/domain/delinquency-aging/index.js +1 -218
  237. package/dist/esm/domain/figure/index.js +1 -15
  238. package/dist/esm/domain/format.js +1 -128
  239. package/dist/esm/domain/index.js +1 -19
  240. package/dist/esm/domain/key-id/index.js +1 -169
  241. package/dist/esm/domain/ledger-sheet/index.js +1 -24
  242. package/dist/esm/domain/money-diff.js +1 -45
  243. package/dist/esm/domain/money-math.js +1 -98
  244. package/dist/esm/domain/money-text/index.js +1 -118
  245. package/dist/esm/domain/section-label/index.js +1 -14
  246. package/dist/esm/domain/status-rail/index.js +1 -71
  247. package/dist/esm/domain/threshold-gauge/index.js +1 -157
  248. package/dist/esm/enterprise/alert-banner/index.js +1 -21
  249. package/dist/esm/enterprise/app-shell/index.js +1 -51
  250. package/dist/esm/enterprise/cursor-pager/index.js +1 -23
  251. package/dist/esm/enterprise/data-table/column-size.js +1 -97
  252. package/dist/esm/enterprise/data-table/index.js +1 -342
  253. package/dist/esm/enterprise/date-range-picker/index.js +1 -112
  254. package/dist/esm/enterprise/detail-panel/index.js +1 -17
  255. package/dist/esm/enterprise/empty-state/index.js +1 -11
  256. package/dist/esm/enterprise/index.js +1 -22
  257. package/dist/esm/enterprise/number-input/index.js +1 -214
  258. package/dist/esm/enterprise/search-input/index.js +1 -85
  259. package/dist/esm/enterprise/stat-card/index.js +1 -72
  260. package/dist/esm/enterprise/status-badge/index.js +1 -116
  261. package/dist/esm/enterprise/use-is-mobile.js +1 -31
  262. package/dist/esm/enterprise/virtualized-table/index.js +1 -138
  263. package/dist/esm/hooks/use-click-away.js +1 -22
  264. package/dist/esm/hooks/use-pagination.js +1 -38
  265. package/dist/esm/hooks/use-stepper.js +1 -22
  266. package/dist/esm/hooks/use-time.js +1 -13
  267. package/dist/esm/hooks/use-toast.js +1 -107
  268. package/dist/esm/index.js +1 -77
  269. package/dist/esm/lib/storage/get-storage-object.js +1 -17
  270. package/dist/esm/lib/storage/get-storage.js +1 -14
  271. package/dist/esm/lib/storage/index.js +1 -2
  272. package/dist/esm/lib/typography.js +1 -31
  273. package/dist/esm/lib/utils.js +1 -41
  274. package/dist/esm/theme/get-theme-script.js +1 -41
  275. package/dist/esm/theme/index.js +1 -4
  276. package/dist/esm/theme/mode-toggle.js +1 -45
  277. package/dist/esm/theme/theme-provider.js +1 -122
  278. package/dist/esm/toast/helpers.js +1 -36
  279. package/dist/esm/toast/index.js +1 -4
  280. package/dist/esm/types/metadata-type.js +1 -1
  281. package/dist/esm/utils/countries.cjs +1 -17
  282. package/dist/esm/utils/country-utils.js +1 -18
  283. package/dist/esm/utils/currency-codes.js +1 -181
  284. package/dist/hooks/use-click-away.js +1 -29
  285. package/dist/hooks/use-pagination.js +1 -41
  286. package/dist/hooks/use-stepper.js +1 -26
  287. package/dist/hooks/use-time.js +1 -20
  288. package/dist/hooks/use-toast.js +1 -111
  289. package/dist/index.js +1 -96
  290. package/dist/lib/storage/get-storage-object.js +1 -23
  291. package/dist/lib/storage/get-storage.js +1 -17
  292. package/dist/lib/storage/index.js +1 -18
  293. package/dist/lib/typography.js +1 -34
  294. package/dist/lib/utils.js +1 -45
  295. package/dist/theme/get-theme-script.js +1 -44
  296. package/dist/theme/index.js +1 -11
  297. package/dist/theme/mode-toggle.js +1 -48
  298. package/dist/theme/theme-provider.js +1 -160
  299. package/dist/toast/helpers.js +1 -41
  300. package/dist/toast/index.js +1 -10
  301. package/dist/types/metadata-type.js +1 -2
  302. package/dist/utils/countries.cjs +1 -17
  303. package/dist/utils/country-utils.js +1 -25
  304. package/dist/utils/currency-codes.js +1 -184
  305. package/package.json +4 -3
@@ -1,138 +1 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- /**
4
- * VirtualizedTable — a windowed table for very large, flat datasets.
5
- *
6
- * Mirrors DataTable's column/data API (standard TanStack `ColumnDef<T>`, cells
7
- * receive the row's `original`), so screens reuse the exact same column
8
- * definitions. The difference is the rendering strategy: where DataTable
9
- * renders every row, VirtualizedTable renders only the rows inside (and just
10
- * past) the scroll viewport via `@tanstack/react-virtual`. Tens of thousands of
11
- * rows stay scroll-smooth because the DOM only ever holds the visible window.
12
- *
13
- * Layout is div-based (role="table"/"row"/"cell"), not a real `<table>`:
14
- * absolute positioning by `virtualItem.start` is incompatible with table
15
- * layout, so a windowed table cannot use `<tbody>`. The header is a sibling
16
- * above the scroll region: it stays put by layout (it simply sits above an
17
- * overflow box), not via `position: sticky`. Inside the scroll container an
18
- * inner spacer sized to `getTotalSize()` reserves the full scroll height, and
19
- * each virtual row is absolutely positioned within that spacer.
20
- *
21
- * Rows are fixed-height (= `rowHeight`): cell content taller than `rowHeight`
22
- * will clip — cells use `truncate`. This component is for flat, single-line
23
- * datasets only; it does NOT measure rows, so it is not suitable for
24
- * variable-height content.
25
- *
26
- * This is deliberately leaner than DataTable: no pagination, selection,
27
- * keyboard nav, loading or empty affordances — it is the right tool only when
28
- * the whole dataset is already in memory and the row count is the problem.
29
- * For server-paged lists, reach for DataTable + CursorPager instead.
30
- */
31
- import { useEffect, useRef, useState } from 'react';
32
- import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
33
- import { useVirtualizer } from '@tanstack/react-virtual';
34
- import { LABEL_VOICE_CLASS } from '../../lib/typography.js';
35
- import { cn } from '../../lib/utils.js';
36
- import { readDeclaredColumnSize, readDeclaredGroupSize, UNSIZED_DEFAULT_COLUMN } from '../data-table/column-size.js';
37
- /** Rows rendered just outside the viewport to keep fast scrolls smooth. */
38
- const OVERSCAN = 8;
39
- export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 480, scrollAreaLabel = 'Scrollable table rows', className, headClassName }) {
40
- const scrollRef = useRef(null);
41
- const [isScrollable, setIsScrollable] = useState(false);
42
- // A number is px; a string is used verbatim (e.g. '60vh').
43
- const viewportMaxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight;
44
- const table = useReactTable({
45
- data,
46
- columns,
47
- // Keeps `columnDef.size`/`minSize`/`maxSize` meaning "declared" — see
48
- // ../data-table/column-size. `getSize()` is unaffected; it falls back to
49
- // the library defaults itself.
50
- defaultColumn: UNSIZED_DEFAULT_COLUMN,
51
- getCoreRowModel: getCoreRowModel()
52
- });
53
- const rows = table.getRowModel().rows;
54
- // Grouped columns (a ColumnDef with nested `columns`) render one header row
55
- // per depth level, so the header is not always a single row.
56
- const headerGroups = table.getHeaderGroups();
57
- const headerRowCount = headerGroups.length;
58
- // The table's real column geometry is its LEAF columns: a grouped ColumnDef
59
- // contributes one spanning header cell but no column of its own, so counting
60
- // top-level defs both under-reports aria-colcount and misplaces every
61
- // aria-colindex to its right.
62
- const leafColumns = table.getVisibleLeafColumns();
63
- const leafPosition = new Map(leafColumns.map((column, i) => [column.id, i]));
64
- const virtualizer = useVirtualizer({
65
- count: rows.length,
66
- getScrollElement: () => scrollRef.current,
67
- estimateSize: () => rowHeight,
68
- overscan: OVERSCAN
69
- });
70
- const virtualRows = virtualizer.getVirtualItems();
71
- const totalSize = virtualizer.getTotalSize();
72
- // `estimateSize` is read through a closure the virtualizer caches per item, so
73
- // changing rowHeight leaves every already-measured row at its old size until
74
- // the cache is dropped explicitly.
75
- useEffect(() => {
76
- virtualizer.measure();
77
- }, [rowHeight, virtualizer]);
78
- useEffect(() => {
79
- const viewport = scrollRef.current;
80
- if (!viewport)
81
- return;
82
- const updateScrollability = () => {
83
- const nextIsScrollable = viewport.scrollHeight > viewport.clientHeight ||
84
- viewport.scrollWidth > viewport.clientWidth;
85
- setIsScrollable((current) => current === nextIsScrollable ? current : nextIsScrollable);
86
- };
87
- updateScrollability();
88
- if (typeof ResizeObserver === 'undefined')
89
- return;
90
- const observer = new ResizeObserver(updateScrollability);
91
- observer.observe(viewport);
92
- const content = viewport.firstElementChild;
93
- if (content)
94
- observer.observe(content);
95
- return () => observer.disconnect();
96
- }, [totalSize, viewportMaxHeight]);
97
- return (_jsx("div", { className: cn('border-border bg-card text-card-foreground rounded-lg border', className), children: _jsxs("div", { role: "table", "aria-rowcount": rows.length + headerRowCount, "aria-colcount": leafColumns.length, children: [_jsx("div", { role: "rowgroup", className: "bg-card z-10", children: headerGroups.map((headerGroup, groupIndex) => (_jsx("div", { role: "row", "aria-rowindex": groupIndex + 1, className: "border-border flex border-b", children: headerGroup.headers.map((header) => {
98
- // Anchor the cell on its leftmost leaf column, so a spanning
99
- // group reports the column it actually starts at rather than
100
- // its position among its siblings.
101
- const firstLeaf = header.column.getLeafColumns()[0];
102
- const start = leafPosition.get(firstLeaf?.id ?? header.column.id);
103
- // A group header spans leaf columns whose body cells carry
104
- // their own widths, so its size comes from those leaves, not
105
- // from the group def (which declares nothing). A leaf header
106
- // reads its own column, as before.
107
- const size = header.subHeaders.length > 0
108
- ? readDeclaredGroupSize(header.column.getLeafColumns())
109
- : readDeclaredColumnSize(header.column);
110
- return (_jsx("div", { role: "columnheader", "aria-colindex": (start ?? 0) + 1, "aria-colspan": header.colSpan > 1 ? header.colSpan : undefined,
111
- // A declared width must not be flexed away; without one the
112
- // cell keeps its colSpan share of the row, as before.
113
- style: size?.width === undefined
114
- ? { flex: `${header.colSpan} 1 0%`, ...size }
115
- : { flex: '0 0 auto', ...size },
116
- // Header height is independent of rowHeight: pinning it to a
117
- // small rowHeight (32) clipped the uppercase label against its
118
- // own padding. Padding sizes it; min-h keeps a stable rule.
119
- className: cn('min-h-10 px-4 py-2.5 text-left', LABEL_VOICE_CLASS, headClassName), children: header.isPlaceholder
120
- ? null
121
- : flexRender(header.column.columnDef.header, header.getContext()) }, header.id));
122
- }) }, headerGroup.id))) }), _jsx("div", { ref: scrollRef, role: "rowgroup", "data-testid": "virtualized-table-viewport", "aria-label": isScrollable ? scrollAreaLabel : undefined, tabIndex: isScrollable ? 0 : undefined, className: "focus-visible:ring-ring relative overflow-auto focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none", style: { maxHeight: viewportMaxHeight }, children: _jsx("div", { role: "presentation", className: "relative w-full", style: { height: totalSize }, children: virtualRows.map((virtualItem) => {
123
- const row = rows[virtualItem.index];
124
- return (_jsx("div", { role: "row", "aria-rowindex": virtualItem.index + headerRowCount + 1, "data-index": virtualItem.index, className: "border-border absolute left-0 flex w-full items-center border-b text-sm", style: {
125
- height: virtualItem.size,
126
- transform: `translateY(${virtualItem.start}px)`
127
- }, children: row.getVisibleCells().map((cell, i) => {
128
- const size = readDeclaredColumnSize(cell.column);
129
- return (_jsx("div", { role: "cell", "aria-colindex": i + 1,
130
- // An inline `flex` beats the class, so a sized column
131
- // stops flexing while every other column renders
132
- // exactly as it did before.
133
- style: size?.width === undefined
134
- ? size
135
- : { flex: '0 0 auto', ...size }, className: "flex-1 truncate px-4", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
136
- }) }, row.id));
137
- }) }) })] }) }));
138
- }
1
+ "use client";import{jsx as l,jsxs as M}from"react/jsx-runtime";import{useEffect as v,useRef as _,useState as O}from"react";import{flexRender as h,getCoreRowModel as j,useReactTable as A}from"@tanstack/react-table";import{useVirtualizer as T}from"@tanstack/react-virtual";import{LABEL_VOICE_CLASS as H}from"../../lib/typography.js";import{cn as S}from"../../lib/utils.js";import{readDeclaredColumnSize as C,readDeclaredGroupSize as U,UNSIZED_DEFAULT_COLUMN as $}from"../data-table/column-size.js";const G=8;export function VirtualizedTable({columns:z,data:R,rowHeight:f=40,maxHeight:a=480,scrollAreaLabel:N="Scrollable table rows",className:y,headClassName:L}){const c=_(null);const[m,E]=O(false);const b=typeof a==="number"?`${a}px`:a;const d=A({data:R,columns:z,defaultColumn:$,getCoreRowModel:j()});const u=d.getRowModel().rows;const p=d.getHeaderGroups();const g=p.length;const x=d.getVisibleLeafColumns();const V=new Map(x.map((o,t)=>[o.id,t]));const s=T({count:u.length,getScrollElement:()=>c.current,estimateSize:()=>f,overscan:G});const D=s.getVirtualItems();const w=s.getTotalSize();v(()=>{s.measure()},[f,s]);v(()=>{const o=c.current;if(!o)return;const t=()=>{const r=o.scrollHeight>o.clientHeight||o.scrollWidth>o.clientWidth;E(i=>i===r?i:r)};t();if(typeof ResizeObserver==="undefined")return;const e=new ResizeObserver(t);e.observe(o);const n=o.firstElementChild;if(n)e.observe(n);return()=>e.disconnect()},[w,b]);return l("div",{className:S("border-border bg-card text-card-foreground rounded-lg border",y),children:M("div",{role:"table","aria-rowcount":u.length+g,"aria-colcount":x.length,children:[l("div",{role:"rowgroup",className:"bg-card z-10",children:p.map((o,t)=>l("div",{role:"row","aria-rowindex":t+1,className:"border-border flex border-b",children:o.headers.map(e=>{const n=e.column.getLeafColumns()[0];const r=V.get(n?.id??e.column.id);const i=e.subHeaders.length>0?U(e.column.getLeafColumns()):C(e.column);return l("div",{role:"columnheader","aria-colindex":(r??0)+1,"aria-colspan":e.colSpan>1?e.colSpan:void 0,style:i?.width===void 0?{flex:`${e.colSpan} 1 0%`,...i}:{flex:"0 0 auto",...i},className:S("min-h-10 px-4 py-2.5 text-left",H,L),children:e.isPlaceholder?null:h(e.column.columnDef.header,e.getContext())},e.id)})},o.id))}),l("div",{ref:c,role:"rowgroup","data-testid":"virtualized-table-viewport","aria-label":m?N:void 0,tabIndex:m?0:void 0,className:"focus-visible:ring-ring relative overflow-auto focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",style:{maxHeight:b},children:l("div",{role:"presentation",className:"relative w-full",style:{height:w},children:D.map(o=>{const t=u[o.index];return l("div",{role:"row","aria-rowindex":o.index+g+1,"data-index":o.index,className:"border-border absolute left-0 flex w-full items-center border-b text-sm",style:{height:o.size,transform:`translateY(${o.start}px)`},children:t.getVisibleCells().map((e,n)=>{const r=C(e.column);return l("div",{role:"cell","aria-colindex":n+1,style:r?.width===void 0?r:{flex:"0 0 auto",...r},className:"flex-1 truncate px-4",children:h(e.column.columnDef.cell,e.getContext())},e.id)})},t.id)})})})]})})}
@@ -1,22 +1 @@
1
- import React from 'react';
2
- /**
3
- * Detects clicks outside of a specified component and triggers a callback function.
4
- *
5
- * @param ref Component reference
6
- * @param onClickAway Callback function to be called when a click is detected outside the component
7
- */
8
- export const useClickAway = (ref, onClickAway) => {
9
- const handleClick = React.useCallback((event) => {
10
- if (ref.current && !ref.current.contains(event.target)) {
11
- onClickAway(event);
12
- }
13
- }, [ref, onClickAway]);
14
- React.useEffect(() => {
15
- document.addEventListener('mousedown', handleClick);
16
- document.addEventListener('touchend', handleClick);
17
- return () => {
18
- document.removeEventListener('mousedown', handleClick);
19
- document.removeEventListener('touchend', handleClick);
20
- };
21
- }, [ref, handleClick]);
22
- };
1
+ import c from"react";export const useClickAway=(t,n)=>{const e=c.useCallback(o=>{if(t.current&&!t.current.contains(o.target)){n(o)}},[t,n]);c.useEffect(()=>{document.addEventListener("mousedown",e);document.addEventListener("touchend",e);return()=>{document.removeEventListener("mousedown",e);document.removeEventListener("touchend",e)}},[t,e])};
@@ -1,38 +1 @@
1
- import { useState } from 'react';
2
- export function usePagination({ total = 1 }) {
3
- const [page, _setPage] = useState(1);
4
- const [limit, _setLimit] = useState(10);
5
- const totalPages = Math.ceil(total / limit);
6
- const nextPage = () => {
7
- if (page + 1 > totalPages) {
8
- return;
9
- }
10
- _setPage((page) => page + 1);
11
- };
12
- const previousPage = () => {
13
- if (page - 1 < 1) {
14
- return;
15
- }
16
- _setPage((page) => page - 1);
17
- };
18
- const setPage = (page) => {
19
- if (page < 1 || page > totalPages) {
20
- return;
21
- }
22
- _setPage(page);
23
- };
24
- const setLimit = (limit) => {
25
- if (limit < 1) {
26
- return;
27
- }
28
- _setLimit(limit);
29
- };
30
- return {
31
- page,
32
- limit,
33
- setLimit,
34
- setPage,
35
- nextPage,
36
- previousPage
37
- };
38
- }
1
+ import{useState as o}from"react";export function usePagination({total:r=1}){const[e,n]=o(1);const[s,a]=o(10);const i=Math.ceil(r/s);const c=()=>{if(e+1>i){return}n(t=>t+1)};const u=()=>{if(e-1<1){return}n(t=>t-1)};const f=t=>{if(t<1||t>i){return}n(t)};const P=t=>{if(t<1){return}a(t)};return{page:e,limit:s,setLimit:P,setPage:f,nextPage:c,previousPage:u}}
@@ -1,22 +1 @@
1
- import { useState } from 'react';
2
- export const useStepper = ({ defaultStep = 0, maxSteps = 2 }) => {
3
- const [step, setStep] = useState(defaultStep);
4
- const handleNext = () => {
5
- if (maxSteps && step >= maxSteps - 1) {
6
- return;
7
- }
8
- setStep((prev) => prev + 1);
9
- };
10
- const handlePrevious = () => {
11
- if (step <= 0) {
12
- return;
13
- }
14
- setStep((prev) => prev - 1);
15
- };
16
- return {
17
- step,
18
- setStep,
19
- handleNext,
20
- handlePrevious
21
- };
22
- };
1
+ import{useState as p}from"react";export const useStepper=({defaultStep:o=0,maxSteps:n=2})=>{const[e,t]=p(o);const s=()=>{if(n&&e>=n-1){return}t(r=>r+1)};const u=()=>{if(e<=0){return}t(r=>r-1)};return{step:e,setStep:t,handleNext:s,handlePrevious:u}};
@@ -1,13 +1 @@
1
- import React from 'react';
2
- export const useTime = ({ interval = 1000, onUpdate }) => {
3
- const [time, setTime] = React.useState(new Date());
4
- React.useEffect(() => {
5
- const timer = setInterval(() => {
6
- const newTime = new Date();
7
- setTime(newTime);
8
- onUpdate?.(newTime);
9
- }, interval);
10
- return () => clearInterval(timer);
11
- }, [interval, onUpdate]);
12
- return time;
13
- };
1
+ import n from"react";export const useTime=({interval:e=1e3,onUpdate:t})=>{const[s,c]=n.useState(new Date);n.useEffect(()=>{const m=setInterval(()=>{const r=new Date;c(r);t?.(r)},e);return()=>clearInterval(m)},[e,t]);return s};
@@ -1,107 +1 @@
1
- 'use client';
2
- import { toast as sonnerToast } from 'sonner';
3
- /**
4
- * Lifetime of every non-destructive toast, and the `<Toaster />` fallback for
5
- * anything raised without one. The two must not drift apart, so the Toaster
6
- * imports this rather than repeating the literal.
7
- */
8
- export const DEFAULT_DURATION = 10000;
9
- /**
10
- * A destructive toast reports something the operator has to read -- a refused
11
- * money operation, a failed copy of a show-once secret, a language switch that
12
- * did not take. It stays up until dismissed instead of auto-closing.
13
- *
14
- * `Infinity` is how sonner disables the auto-close timer (it short-circuits the
15
- * timer effect rather than calling `setTimeout(fn, Infinity)`, which would fire
16
- * immediately). `<Toaster />` already passes `closeButton`, and sonner gates the
17
- * close button on that flag alone, never on the duration -- so a persistent
18
- * toast still renders its dismiss affordance.
19
- */
20
- const PERSIST_UNTIL_DISMISSED = Infinity;
21
- const isPlainText = (value) => value === undefined || typeof value === 'string';
22
- /**
23
- * Two identical errors share one toast instead of stacking: same variant, same
24
- * text -- same id, and sonner updates the one already on screen.
25
- *
26
- * Unbounded stacking is worse for a persistent toast than for a transient one.
27
- * `<Toaster />` shows three at a time and renders the rest `opacity: 0;
28
- * pointer-events: none`, so a fourth error nobody can read is also a fourth
29
- * error nobody can close -- and without an auto-dismiss, nothing ahead of it
30
- * clears on its own.
31
- *
32
- * Only plain-text toasts collapse. A `ReactNode` has no stable key and
33
- * `String(node)` would fold unrelated errors onto one id.
34
- *
35
- * ponytail: the ceiling is still three. Distinct persistent errors past the
36
- * third queue behind the front three until one is dismissed; lifting that means
37
- * raising `visibleToasts`, not more work here.
38
- */
39
- function collapseKey(title, description) {
40
- if (!isPlainText(title) || !isPlainText(description)) {
41
- return undefined;
42
- }
43
- return `destructive:${JSON.stringify([title ?? null, description ?? null])}`;
44
- }
45
- function toast({ title, description, variant, duration, id, ...rest }) {
46
- const message = title ?? '';
47
- const toastId = variant === 'destructive' && id === undefined
48
- ? collapseKey(title, description)
49
- : id;
50
- const options = {
51
- description,
52
- ...rest,
53
- ...(toastId !== undefined && { id: toastId }),
54
- duration: duration ??
55
- (variant === 'destructive' ? PERSIST_UNTIL_DISMISSED : DEFAULT_DURATION)
56
- };
57
- let raisedId;
58
- switch (variant) {
59
- case 'success':
60
- raisedId = sonnerToast.success(message, options);
61
- break;
62
- case 'warning':
63
- raisedId = sonnerToast.warning(message, options);
64
- break;
65
- case 'destructive':
66
- raisedId = sonnerToast.error(message, options);
67
- break;
68
- default:
69
- raisedId = sonnerToast(message, options);
70
- break;
71
- }
72
- return {
73
- id: raisedId,
74
- dismiss: () => sonnerToast.dismiss(raisedId),
75
- update: (props) => {
76
- sonnerToast(props.title ?? message, {
77
- ...rest,
78
- id: raisedId,
79
- description: props.description ?? description,
80
- duration: props.duration ?? options.duration
81
- });
82
- }
83
- };
84
- }
85
- /**
86
- * Backward-compatible hook that wraps Sonner's toast API.
87
- *
88
- * Returns the same shape as the original Radix-based useToast:
89
- * - `toast()` to create a toast
90
- * - `dismiss()` to dismiss a toast by id (or all if no id)
91
- * - `toasts` array (always empty -- Sonner manages its own state internally)
92
- */
93
- function useToast() {
94
- return {
95
- toast,
96
- dismiss: (toastId) => {
97
- if (toastId !== undefined) {
98
- sonnerToast.dismiss(toastId);
99
- }
100
- else {
101
- sonnerToast.dismiss();
102
- }
103
- },
104
- toasts: []
105
- };
106
- }
107
- export { useToast, toast };
1
+ "use client";import{toast as e}from"sonner";export const DEFAULT_DURATION=1e4;const I=Infinity;const f=s=>s===void 0||typeof s==="string";function T(s,t){if(!f(s)||!f(t)){return void 0}return`destructive:${JSON.stringify([s??null,t??null])}`}function l({title:s,description:t,variant:r,duration:m,id:o,...c}){const i=s??"";const a=r==="destructive"&&o===void 0?T(s,t):o;const d={description:t,...c,...a!==void 0&&{id:a},duration:m??(r==="destructive"?I:DEFAULT_DURATION)};let n;switch(r){case"success":n=e.success(i,d);break;case"warning":n=e.warning(i,d);break;case"destructive":n=e.error(i,d);break;default:n=e(i,d);break}return{id:n,dismiss:()=>e.dismiss(n),update:u=>{e(u.title??i,{...c,id:n,description:u.description??t,duration:u.duration??d.duration})}}}function S(){return{toast:l,dismiss:s=>{if(s!==void 0){e.dismiss(s)}else{e.dismiss()}},toasts:[]}}export{S as useToast,l as toast};
package/dist/esm/index.js CHANGED
@@ -1,77 +1 @@
1
- 'use client';
2
- // Primitives
3
- export * from './components/ui/alert/index.js';
4
- export * from './components/ui/autocomplete/index.js';
5
- export * from './hooks/use-click-away.js';
6
- export * from './components/ui/autosize-textarea/index.js';
7
- export * from './components/ui/avatar/index.js';
8
- export * from './components/ui/badge/index.js';
9
- export * from './components/ui/breadcrumb/index.js';
10
- export * from './components/ui/button/index.js';
11
- export * from './components/ui/icon-button/index.js';
12
- export * from './components/ui/calendar/index.js';
13
- export * from './components/ui/card/index.js';
14
- export * from './components/ui/checkbox/index.js';
15
- export * from './components/ui/collapsible/index.js';
16
- export * from './components/ui/command/index.js';
17
- export * from './components/ui/copy-field/index.js';
18
- export * from './components/ui/dialog/index.js';
19
- export * from './components/ui/dropdown-menu/index.js';
20
- export * from './components/ui/input/index.js';
21
- export * from './components/ui/otp-input/index.js';
22
- export * from './components/ui/label/index.js';
23
- export * from './components/ui/lerian-wordmark/index.js';
24
- export * from './components/ui/loading-button/index.js';
25
- export * from './components/ui/multiple-select/index.js';
26
- export * from './components/ui/paper/index.js';
27
- export * from './components/ui/paper-collapsible/index.js';
28
- export * from './components/ui/popover/index.js';
29
- export * from './components/ui/progress/index.js';
30
- export * from './components/ui/qr-code/index.js';
31
- export * from './components/ui/select/index.js';
32
- export * from './components/ui/separator/index.js';
33
- export * from './components/ui/sheet/index.js';
34
- export * from './components/ui/sidebar/index.js';
35
- export * from './components/ui/skeleton/index.js';
36
- export * from './components/ui/stepper/index.js';
37
- export * from './hooks/use-stepper.js';
38
- export * from './components/ui/switch/index.js';
39
- export * from './components/ui/table/index.js';
40
- export * from './components/ui/tabs/index.js';
41
- export * from './components/ui/textarea/index.js';
42
- export * from './components/ui/toast/index.js';
43
- export * from './components/ui/toast/toaster.js';
44
- export * from './hooks/use-toast.js';
45
- export * from './components/ui/time-picker/index.js';
46
- export * from './hooks/use-time.js';
47
- export * from './components/ui/tooltip/index.js';
48
- export * from './components/ui/form.js';
49
- // Components
50
- export { Breadcrumb as ApplicationBreadcrumb } from './components/breadcrumb/index.js';
51
- export * from './components/breadcrumb/get-breadcrumb-paths.js';
52
- export * from './components/card/index.js';
53
- export * from './components/dialog/index.js';
54
- export * from './components/entity-box/index.js';
55
- export * from './components/entity-data-table/index.js';
56
- export * from './components/form/index.js';
57
- export * from './components/page/index.js';
58
- export * from './components/page-header/index.js';
59
- export * from './components/pagination/index.js';
60
- export * from './components/table/index.js';
61
- // Enterprise surface (sindarian-x absorption — see docs/plans/2026-08-26-sindarian-x-retirement/)
62
- export * from './enterprise/index.js';
63
- export * from './theme/index.js';
64
- export * from './toast/index.js';
65
- export * from './charts/index.js';
66
- export * from './domain/index.js';
67
- // Primitives absorbed from sindarian-x (see docs/plans/2026-08-26-sindarian-x-retirement/)
68
- export * from './components/ui/accordion/index.js';
69
- export * from './components/ui/alert-dialog/index.js';
70
- export * from './components/ui/file-upload/index.js';
71
- export * from './components/ui/hover-card/index.js';
72
- export * from './components/ui/radio-group/index.js';
73
- export * from './components/ui/scroll-area/index.js';
74
- export * from './components/ui/toggle-group/index.js';
75
- // Utilities
76
- export { cn } from './lib/utils.js';
77
- export * from './lib/typography.js';
1
+ "use client";export*from"./components/ui/alert/index.js";export*from"./components/ui/autocomplete/index.js";export*from"./hooks/use-click-away.js";export*from"./components/ui/autosize-textarea/index.js";export*from"./components/ui/avatar/index.js";export*from"./components/ui/badge/index.js";export*from"./components/ui/breadcrumb/index.js";export*from"./components/ui/button/index.js";export*from"./components/ui/icon-button/index.js";export*from"./components/ui/calendar/index.js";export*from"./components/ui/card/index.js";export*from"./components/ui/checkbox/index.js";export*from"./components/ui/collapsible/index.js";export*from"./components/ui/command/index.js";export*from"./components/ui/copy-field/index.js";export*from"./components/ui/dialog/index.js";export*from"./components/ui/dropdown-menu/index.js";export*from"./components/ui/input/index.js";export*from"./components/ui/otp-input/index.js";export*from"./components/ui/label/index.js";export*from"./components/ui/lerian-wordmark/index.js";export*from"./components/ui/loading-button/index.js";export*from"./components/ui/multiple-select/index.js";export*from"./components/ui/paper/index.js";export*from"./components/ui/paper-collapsible/index.js";export*from"./components/ui/popover/index.js";export*from"./components/ui/progress/index.js";export*from"./components/ui/qr-code/index.js";export*from"./components/ui/select/index.js";export*from"./components/ui/separator/index.js";export*from"./components/ui/sheet/index.js";export*from"./components/ui/sidebar/index.js";export*from"./components/ui/skeleton/index.js";export*from"./components/ui/stepper/index.js";export*from"./hooks/use-stepper.js";export*from"./components/ui/switch/index.js";export*from"./components/ui/table/index.js";export*from"./components/ui/tabs/index.js";export*from"./components/ui/textarea/index.js";export*from"./components/ui/toast/index.js";export*from"./components/ui/toast/toaster.js";export*from"./hooks/use-toast.js";export*from"./components/ui/time-picker/index.js";export*from"./hooks/use-time.js";export*from"./components/ui/tooltip/index.js";export*from"./components/ui/form.js";export{Breadcrumb as ApplicationBreadcrumb}from"./components/breadcrumb/index.js";export*from"./components/breadcrumb/get-breadcrumb-paths.js";export*from"./components/card/index.js";export*from"./components/dialog/index.js";export*from"./components/entity-box/index.js";export*from"./components/entity-data-table/index.js";export*from"./components/form/index.js";export*from"./components/page/index.js";export*from"./components/page-header/index.js";export*from"./components/pagination/index.js";export*from"./components/table/index.js";export*from"./enterprise/index.js";export*from"./theme/index.js";export*from"./toast/index.js";export*from"./charts/index.js";export*from"./domain/index.js";export*from"./components/ui/accordion/index.js";export*from"./components/ui/alert-dialog/index.js";export*from"./components/ui/file-upload/index.js";export*from"./components/ui/hover-card/index.js";export*from"./components/ui/radio-group/index.js";export*from"./components/ui/scroll-area/index.js";export*from"./components/ui/toggle-group/index.js";export{cn}from"./lib/utils.js";export*from"./lib/typography.js";
@@ -1,17 +1 @@
1
- import { getStorage } from './get-storage.js';
2
- import isEmpty from 'lodash/isEmpty.js';
3
- import isNil from 'lodash/isNil.js';
4
- export function getStorageObject(key, defaultValue) {
5
- try {
6
- const dataString = getStorage(key, defaultValue);
7
- const isNilOrEmpty = isNil(dataString) || isEmpty(dataString);
8
- return isNilOrEmpty ? {} : JSON.parse(dataString);
9
- }
10
- catch (error) {
11
- // Only log errors when not in test environment
12
- if (process.env.NODE_ENV !== 'test') {
13
- console.error(error);
14
- }
15
- return defaultValue;
16
- }
17
- }
1
+ import{getStorage as i}from"./get-storage.js";import s from"lodash/isEmpty.js";import n from"lodash/isNil.js";export function getStorageObject(o,t){try{const r=i(o,t);const e=n(r)||s(r);return e?{}:JSON.parse(r)}catch(r){if(process.env.NODE_ENV!=="test"){console.error(r)}return t}}
@@ -1,14 +1 @@
1
- const isServer = typeof window === 'undefined';
2
- export function getStorage(key, defaultValue) {
3
- if (isServer) {
4
- return defaultValue;
5
- }
6
- let value;
7
- try {
8
- value = localStorage.getItem(key) || undefined;
9
- }
10
- catch (_e) {
11
- // Unsupported
12
- }
13
- return value || defaultValue;
14
- }
1
+ const r=typeof window==="undefined";export function getStorage(n,e){if(r){return e}let t;try{t=localStorage.getItem(n)||void 0}catch(o){}return t||e}
@@ -1,2 +1 @@
1
- export * from './get-storage.js';
2
- export * from './get-storage-object.js';
1
+ export*from"./get-storage.js";export*from"./get-storage-object.js";
@@ -1,31 +1 @@
1
- /**
2
- * THE canonical quiet-label voice: sentence-case, one step down in size,
3
- * medium weight, muted ink. Used by column heads, panel headings, key/value
4
- * labels, captions — anywhere the console needs a quiet label.
5
- *
6
- * This is product-console's table-head voice, copied rather than invented. The
7
- * kit's own `TableHead` paints `text-muted-foreground … font-medium` inside a
8
- * `text-sm` `Table` (`components/ui/table/index.tsx:20,90`), and
9
- * product-console renders every data table through that primitive
10
- * (`src/components/table/data-table.tsx:14`). It replaced the retired "Ledger"
11
- * voice — `text-[11px] uppercase tracking-[0.08em]` — which shouted a register
12
- * no sibling console speaks.
13
- *
14
- * Do NOT re-state the cluster by hand; compose extra classes via
15
- * `cn(LABEL_VOICE_CLASS, ...)`.
16
- */
17
- export const LABEL_VOICE_CLASS = 'text-sm font-medium text-muted-foreground';
18
- /**
19
- * Alias of {@link LABEL_VOICE_CLASS} for section headings. Kept as a distinct
20
- * name so section-level headings can diverge later without touching every
21
- * quiet-label call site.
22
- *
23
- * It stays an alias on purpose. product-console's panel/section TITLE voice is
24
- * `text-muted-foreground text-lg font-medium` (`EntityBoxHeaderTitle`,
25
- * `components/entity-box/index.tsx:108`) — but that voice already ships as a
26
- * component, and every live `SectionLabel` call site is a caption or a small
27
- * heading (a stat-card label, an inline rate label), not an EntityBox-scale
28
- * panel title. Promoting this constant to `text-lg` would duplicate a voice the
29
- * kit already owns and inflate those captions.
30
- */
31
- export const SECTION_LABEL_CLASS = LABEL_VOICE_CLASS;
1
+ export const LABEL_VOICE_CLASS="text-sm font-medium text-muted-foreground";export const SECTION_LABEL_CLASS=LABEL_VOICE_CLASS;
@@ -1,41 +1 @@
1
- import { clsx } from 'clsx';
2
- import { extendTailwindMerge } from 'tailwind-merge';
3
- /**
4
- * The kit's button variants are component classes in `@layer components`, not
5
- * Tailwind utilities, so stock tailwind-merge has no group for them: it kept
6
- * `button-primary button-destructive` together and let stylesheet source order
7
- * pick the winner. Declaring the group makes the last one win, like every other
8
- * conflict `cn` resolves.
9
- *
10
- * Variant classes only. `button-base`, `button-disabled`, `button-read-only`
11
- * and `button-small` compose with a variant instead of conflicting with it, so
12
- * they stay out of the group and are never merged away.
13
- */
14
- const twMerge = extendTailwindMerge({
15
- extend: {
16
- classGroups: {
17
- 'sindarian-button-variant': [
18
- 'button-plain',
19
- 'button-primary',
20
- 'button-secondary',
21
- 'button-tertiary',
22
- 'button-outline',
23
- 'button-link',
24
- 'button-destructive'
25
- ]
26
- }
27
- }
28
- });
29
- export function cn(...inputs) {
30
- return twMerge(clsx(inputs));
31
- }
32
- /** Wraps a Radix `onInteractOutside` so a press on a toast never dismisses the layer under it. */
33
- export function keepOpenOnToast(onInteractOutside) {
34
- return (event) => {
35
- if (event.target?.closest('[data-sonner-toaster]')) {
36
- event.preventDefault();
37
- return;
38
- }
39
- onInteractOutside?.(event);
40
- };
41
- }
1
+ import{clsx as r}from"clsx";import{extendTailwindMerge as e}from"tailwind-merge";const o=e({extend:{classGroups:{"sindarian-button-variant":["button-plain","button-primary","button-secondary","button-tertiary","button-outline","button-link","button-destructive"]}}});export function cn(...t){return o(r(t))}export function keepOpenOnToast(t){return n=>{if(n.target?.closest("[data-sonner-toaster]")){n.preventDefault();return}t?.(n)}}
@@ -1,41 +1 @@
1
- /**
2
- * Pre-paint theme script (FOUC guard). Returns a minified IIFE string that
3
- * reads the persisted preference from localStorage, resolves it the way
4
- * ThemeProvider does, and toggles the `.dark` class on the page root element
5
- * before first paint — so the page never flashes the wrong theme while React
6
- * hydrates. ThemeProvider owns the class from mount onward.
7
- *
8
- * The resolution mirrors ThemeProvider's exactly: an exact "dark"/"light"/
9
- * "system" stored value wins; anything else — absent or corrupted — falls back
10
- * to `defaultTheme`, which is then resolved ("dark" → dark, "light" → light,
11
- * "system" → the media query). Pass the SAME `defaultTheme` you give
12
- * ThemeProvider, or the two disagree on a first visit.
13
- * `get-theme-script.test.tsx` pins that agreement case by case.
14
- *
15
- * Server-safe: this module references no browser globals at module scope; the
16
- * returned string runs in the browser only, inside a try/catch.
17
- *
18
- * Consumer usage — inject in the page <head>, ideally as the first script:
19
- *
20
- * <script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />
21
- *
22
- * A dark-by-default app passes both arguments:
23
- *
24
- * <script dangerouslySetInnerHTML={{ __html: getThemeScript('app.theme', 'dark') }} />
25
- */
26
- /**
27
- * JSON string literal with `<` escaped, so no embedded value can close the
28
- * inline <script> element it is written into. `<` is `<` to the JS parser,
29
- * so the emitted script still compares against the original text.
30
- */
31
- function jsString(value) {
32
- return JSON.stringify(value).replace(/</g, '\\u003C');
33
- }
34
- export function getThemeScript(storageKey = 'sindarian.theme', defaultTheme = 'system') {
35
- // The storage read gets its OWN try/catch, mirroring ThemeProvider, which
36
- // isolates the same read. A browser with site data blocked throws on
37
- // getItem; if that escaped to the outer catch the class would never be
38
- // applied at all and a dark user would flash light before hydration.
39
- // Resolution starts from defaultTheme and storage only narrows it.
40
- return `(function(){try{var r=${jsString(defaultTheme)};try{var t=localStorage.getItem(${jsString(storageKey)});if(t==="dark"||t==="light"||t==="system")r=t}catch(e){}var d=r==="dark"||(r==="system"&&matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.classList.toggle("dark",d)}catch(e){}})()`;
41
- }
1
+ function e(t){return JSON.stringify(t).replace(/</g,"\\u003C")}export function getThemeScript(t="sindarian.theme",r="system"){return`(function(){try{var r=${e(r)};try{var t=localStorage.getItem(${e(t)});if(t==="dark"||t==="light"||t==="system")r=t}catch(e){}var d=r==="dark"||(r==="system"&&matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.classList.toggle("dark",d)}catch(e){}})()`}
@@ -1,4 +1 @@
1
- // Owned by lane theme-toasts-charts — see docs/plans/2026-08-26-sindarian-x-retirement/
2
- export { ThemeProvider, useTheme } from './theme-provider.js';
3
- export { getThemeScript } from './get-theme-script.js';
4
- export { ModeToggle } from './mode-toggle.js';
1
+ export{ThemeProvider,useTheme}from"./theme-provider.js";export{getThemeScript}from"./get-theme-script.js";export{ModeToggle}from"./mode-toggle.js";