@wealthx/shadcn 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/.turbo/turbo-build.log +203 -150
  2. package/CHANGELOG.md +29 -0
  3. package/dist/{chunk-4Y6R4WEC.mjs → chunk-2A5RRQGG.mjs} +9 -22
  4. package/dist/{chunk-TS2ZX2VS.mjs → chunk-2UM72RJ7.mjs} +11 -15
  5. package/dist/{chunk-A56YQQHG.mjs → chunk-3NCUZIFP.mjs} +2 -2
  6. package/dist/chunk-3OYFOX3X.mjs +79 -0
  7. package/dist/{chunk-RP3SQYA3.mjs → chunk-3TTACBDP.mjs} +9 -4
  8. package/dist/chunk-4GAWMKMI.mjs +710 -0
  9. package/dist/{chunk-SYOD63OZ.mjs → chunk-5FQIKDKP.mjs} +6 -6
  10. package/dist/{chunk-K3JYD4IU.mjs → chunk-5IS7G74I.mjs} +11 -4
  11. package/dist/chunk-6AW4KJHE.mjs +235 -0
  12. package/dist/chunk-6CR5N2JW.mjs +302 -0
  13. package/dist/{chunk-XIRTEFKH.mjs → chunk-6DZEXFNB.mjs} +36 -8
  14. package/dist/chunk-6O6KD7CE.mjs +271 -0
  15. package/dist/chunk-7PV3IWCN.mjs +33 -0
  16. package/dist/{chunk-SPJ5KXW7.mjs → chunk-7S5AESZO.mjs} +5 -5
  17. package/dist/{chunk-RYCLWMZ7.mjs → chunk-ABFDMHOR.mjs} +9 -7
  18. package/dist/{chunk-SWGT756Z.mjs → chunk-AMQZRHEZ.mjs} +10 -4
  19. package/dist/{chunk-WOEHFRGB.mjs → chunk-BDYZCBRT.mjs} +4 -4
  20. package/dist/{chunk-WAZD7NFU.mjs → chunk-BKNFWEH2.mjs} +6 -6
  21. package/dist/{chunk-CLIN5525.mjs → chunk-C7CQJNMR.mjs} +1 -1
  22. package/dist/{chunk-D4ILTPOG.mjs → chunk-CFMQP5QS.mjs} +5 -4
  23. package/dist/{chunk-VPBN3WOO.mjs → chunk-DGHAXJBN.mjs} +9 -7
  24. package/dist/chunk-DOEO3CDL.mjs +27 -0
  25. package/dist/{chunk-KUDCQ4FI.mjs → chunk-DUJTAXMH.mjs} +9 -4
  26. package/dist/{chunk-GGM2UYGG.mjs → chunk-EBXQWIYG.mjs} +10 -4
  27. package/dist/{chunk-PMB3A7V3.mjs → chunk-EI5F6FMT.mjs} +1 -1
  28. package/dist/chunk-EWRB4PAD.mjs +468 -0
  29. package/dist/chunk-FAKPBKLT.mjs +253 -0
  30. package/dist/chunk-FNQXOAYJ.mjs +169 -0
  31. package/dist/{chunk-4CX4SBRO.mjs → chunk-GHC7LLUX.mjs} +14 -5
  32. package/dist/chunk-HBZLGDIN.mjs +507 -0
  33. package/dist/{chunk-SIZMLSRU.mjs → chunk-HISNT2MG.mjs} +8 -6
  34. package/dist/{chunk-PR6V5XKM.mjs → chunk-HVY6KCCF.mjs} +7 -4
  35. package/dist/chunk-I3RZS7V2.mjs +136 -0
  36. package/dist/chunk-IAE3F7DR.mjs +1962 -0
  37. package/dist/{chunk-ZRO5JO3H.mjs → chunk-IHMFS7NZ.mjs} +81 -84
  38. package/dist/{chunk-PCPLO5HT.mjs → chunk-IOJRDS6V.mjs} +96 -14
  39. package/dist/{chunk-LHYCMLVA.mjs → chunk-JKGDCQTZ.mjs} +11 -4
  40. package/dist/{chunk-H45TKD34.mjs → chunk-JMHR3YGZ.mjs} +1 -1
  41. package/dist/{chunk-4MN6UQHG.mjs → chunk-K5A5L6T2.mjs} +17 -39
  42. package/dist/{chunk-CSDO6VBW.mjs → chunk-LBMRIB3G.mjs} +10 -10
  43. package/dist/chunk-LV35NGVG.mjs +272 -0
  44. package/dist/{chunk-FZIXGLMV.mjs → chunk-M3FV7LOK.mjs} +5 -12
  45. package/dist/{chunk-FMAXJ2SI.mjs → chunk-MBON7YRJ.mjs} +1 -1
  46. package/dist/chunk-MIZQHHUO.mjs +441 -0
  47. package/dist/chunk-MN5NYQCL.mjs +29 -0
  48. package/dist/chunk-NL3ZO62D.mjs +31 -0
  49. package/dist/{chunk-Q76O3RIQ.mjs → chunk-NMOI6CQD.mjs} +1 -1
  50. package/dist/{chunk-P6AM5V7O.mjs → chunk-OODBHKG7.mjs} +1 -1
  51. package/dist/chunk-PBL4OQV2.mjs +283 -0
  52. package/dist/{chunk-3WMX6KWS.mjs → chunk-PU4YZQXV.mjs} +11 -12
  53. package/dist/chunk-QMY3AZJH.mjs +80 -0
  54. package/dist/{chunk-BL3DXM2X.mjs → chunk-QZ4RE6NA.mjs} +11 -4
  55. package/dist/{chunk-VACKZOMY.mjs → chunk-R3VSPKNP.mjs} +3 -3
  56. package/dist/{chunk-OPNQAVVH.mjs → chunk-RJI6GKVF.mjs} +8 -6
  57. package/dist/{chunk-WG6JGJXB.mjs → chunk-T4BJLT57.mjs} +1 -1
  58. package/dist/chunk-U4NDAF2P.mjs +207 -0
  59. package/dist/{chunk-DOH3EHX7.mjs → chunk-U5X52X37.mjs} +1 -1
  60. package/dist/chunk-UMTOX62O.mjs +415 -0
  61. package/dist/{chunk-7MMXNK3C.mjs → chunk-VLARHE5V.mjs} +8 -6
  62. package/dist/{chunk-2I5S2AMY.mjs → chunk-XREGSKX3.mjs} +2 -2
  63. package/dist/{chunk-JNQORUPP.mjs → chunk-YJG55G2H.mjs} +14 -11
  64. package/dist/chunk-ZC45IGZO.mjs +388 -0
  65. package/dist/components/ui/add-column-modal.js +42 -14
  66. package/dist/components/ui/add-column-modal.mjs +4 -4
  67. package/dist/components/ui/add-lead-modal.js +42 -11
  68. package/dist/components/ui/add-lead-modal.mjs +3 -3
  69. package/dist/components/ui/advisor-card.js +497 -0
  70. package/dist/components/ui/advisor-card.mjs +13 -0
  71. package/dist/components/ui/ai-assistant-drawer.js +11 -10
  72. package/dist/components/ui/ai-assistant-drawer.mjs +3 -3
  73. package/dist/components/ui/alert-dialog.js +2 -2
  74. package/dist/components/ui/alert-dialog.mjs +2 -2
  75. package/dist/components/ui/appointment-action-dialogs.js +1160 -0
  76. package/dist/components/ui/appointment-action-dialogs.mjs +23 -0
  77. package/dist/components/ui/appointment-availability-settings.js +1590 -0
  78. package/dist/components/ui/appointment-availability-settings.mjs +23 -0
  79. package/dist/components/ui/appointment-book-dialog.js +1744 -0
  80. package/dist/components/ui/appointment-book-dialog.mjs +27 -0
  81. package/dist/components/ui/appointment-calendar-view.js +833 -0
  82. package/dist/components/ui/appointment-calendar-view.mjs +14 -0
  83. package/dist/components/ui/appointment-detail-sheet.js +1517 -0
  84. package/dist/components/ui/appointment-detail-sheet.mjs +24 -0
  85. package/dist/components/ui/appointment-gmail-connect.js +467 -0
  86. package/dist/components/ui/appointment-gmail-connect.mjs +14 -0
  87. package/dist/components/ui/appointment-mini-card.js +345 -0
  88. package/dist/components/ui/appointment-mini-card.mjs +11 -0
  89. package/dist/components/ui/appointment-time-slot-picker.js +311 -0
  90. package/dist/components/ui/appointment-time-slot-picker.mjs +13 -0
  91. package/dist/components/ui/appointment-upcoming-card.js +1268 -0
  92. package/dist/components/ui/appointment-upcoming-card.mjs +21 -0
  93. package/dist/components/ui/backoffice-alert-history-chart.js +11 -5
  94. package/dist/components/ui/backoffice-alert-history-chart.mjs +5 -4
  95. package/dist/components/ui/backoffice-alerts-chart.js +786 -0
  96. package/dist/components/ui/backoffice-alerts-chart.mjs +19 -0
  97. package/dist/components/ui/backoffice-connections-chart.js +817 -0
  98. package/dist/components/ui/backoffice-connections-chart.mjs +19 -0
  99. package/dist/components/ui/backoffice-contact-history-chart.js +11 -5
  100. package/dist/components/ui/backoffice-contact-history-chart.mjs +5 -4
  101. package/dist/components/ui/badge.js +6 -6
  102. package/dist/components/ui/badge.mjs +1 -1
  103. package/dist/components/ui/borrowing-capacity-line-chart.js +30 -21
  104. package/dist/components/ui/borrowing-capacity-line-chart.mjs +5 -4
  105. package/dist/components/ui/button.js +2 -2
  106. package/dist/components/ui/button.mjs +1 -1
  107. package/dist/components/ui/calendar.js +2 -2
  108. package/dist/components/ui/calendar.mjs +2 -2
  109. package/dist/components/ui/card.js +1 -1
  110. package/dist/components/ui/card.mjs +1 -1
  111. package/dist/components/ui/cash-balance-line-chart.js +31 -23
  112. package/dist/components/ui/cash-balance-line-chart.mjs +5 -4
  113. package/dist/components/ui/cashflow-bar-chart.js +12 -5
  114. package/dist/components/ui/cashflow-bar-chart.mjs +5 -4
  115. package/dist/components/ui/chip.js +97 -18
  116. package/dist/components/ui/chip.mjs +3 -2
  117. package/dist/components/ui/color-picker.js +547 -0
  118. package/dist/components/ui/color-picker.mjs +24 -0
  119. package/dist/components/ui/data-table.js +182 -129
  120. package/dist/components/ui/data-table.mjs +3 -2
  121. package/dist/components/ui/date-picker.js +48 -27
  122. package/dist/components/ui/date-picker.mjs +4 -3
  123. package/dist/components/ui/dialog.js +37 -9
  124. package/dist/components/ui/dialog.mjs +2 -2
  125. package/dist/components/ui/expense-bar-chart.js +12 -5
  126. package/dist/components/ui/expense-bar-chart.mjs +5 -4
  127. package/dist/components/ui/field.mjs +2 -2
  128. package/dist/components/ui/financial-cards.js +322 -155
  129. package/dist/components/ui/financial-cards.mjs +5 -3
  130. package/dist/components/ui/financial-drawers.js +2 -2
  131. package/dist/components/ui/financial-drawers.mjs +3 -3
  132. package/dist/components/ui/financial-sections.js +14 -10
  133. package/dist/components/ui/financial-sections.mjs +6 -5
  134. package/dist/components/ui/form-primitives.js +4 -4
  135. package/dist/components/ui/form-primitives.mjs +3 -3
  136. package/dist/components/ui/income-bar-chart.js +12 -5
  137. package/dist/components/ui/income-bar-chart.mjs +5 -4
  138. package/dist/components/ui/input-group.js +2 -2
  139. package/dist/components/ui/input-group.mjs +2 -2
  140. package/dist/components/ui/kanban-column.js +52 -44
  141. package/dist/components/ui/kanban-column.mjs +7 -5
  142. package/dist/components/ui/opportunity-card.js +52 -44
  143. package/dist/components/ui/opportunity-card.mjs +6 -4
  144. package/dist/components/ui/opportunity-edit-modals.js +1371 -1267
  145. package/dist/components/ui/opportunity-edit-modals.mjs +10 -10
  146. package/dist/components/ui/opportunity-summary-tab.js +2748 -2161
  147. package/dist/components/ui/opportunity-summary-tab.mjs +16 -16
  148. package/dist/components/ui/page-header.js +92 -0
  149. package/dist/components/ui/page-header.mjs +8 -0
  150. package/dist/components/ui/page-top-bar.js +88 -0
  151. package/dist/components/ui/page-top-bar.mjs +8 -0
  152. package/dist/components/ui/pagination.js +303 -19
  153. package/dist/components/ui/pagination.mjs +11 -4
  154. package/dist/components/ui/pipeline-board.js +209 -195
  155. package/dist/components/ui/pipeline-board.mjs +10 -8
  156. package/dist/components/ui/pipeline-dialogs.js +118 -69
  157. package/dist/components/ui/pipeline-dialogs.mjs +8 -7
  158. package/dist/components/ui/pipeline-primitives.js +6 -6
  159. package/dist/components/ui/pipeline-primitives.mjs +2 -2
  160. package/dist/components/ui/property-cashflow-doughnut-chart.js +14 -12
  161. package/dist/components/ui/property-cashflow-doughnut-chart.mjs +5 -4
  162. package/dist/components/ui/property-debt-equity-doughnut-chart.js +14 -12
  163. package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +5 -4
  164. package/dist/components/ui/property-mobile-estimate-line-chart.js +16 -14
  165. package/dist/components/ui/property-mobile-estimate-line-chart.mjs +5 -4
  166. package/dist/components/ui/sidebar-nav.js +679 -0
  167. package/dist/components/ui/sidebar-nav.mjs +14 -0
  168. package/dist/components/ui/stage-timeline.js +6 -6
  169. package/dist/components/ui/stage-timeline.mjs +3 -3
  170. package/dist/components/ui/stepper.js +283 -0
  171. package/dist/components/ui/stepper.mjs +18 -0
  172. package/dist/components/ui/toggle-group.js +4 -4
  173. package/dist/components/ui/toggle-group.mjs +2 -2
  174. package/dist/components/ui/toggle.js +4 -4
  175. package/dist/components/ui/toggle.mjs +1 -1
  176. package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +18 -16
  177. package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +5 -4
  178. package/dist/components/ui/transactions-income-expense-bar-chart.js +28 -12
  179. package/dist/components/ui/transactions-income-expense-bar-chart.mjs +5 -4
  180. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +18 -16
  181. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +5 -4
  182. package/dist/index.js +12927 -8522
  183. package/dist/index.mjs +288 -190
  184. package/dist/lib/typography.js +10 -10
  185. package/dist/lib/typography.mjs +1 -1
  186. package/dist/styles.css +1 -1
  187. package/package.json +86 -1
  188. package/src/components/index.tsx +146 -0
  189. package/src/components/ui/add-column-modal.tsx +7 -7
  190. package/src/components/ui/add-lead-modal.tsx +6 -3
  191. package/src/components/ui/advisor-card.tsx +227 -0
  192. package/src/components/ui/ai-assistant-drawer.tsx +4 -3
  193. package/src/components/ui/appointment-action-dialogs.tsx +297 -0
  194. package/src/components/ui/appointment-availability-settings.tsx +645 -0
  195. package/src/components/ui/appointment-book-dialog.tsx +618 -0
  196. package/src/components/ui/appointment-calendar-view.tsx +510 -0
  197. package/src/components/ui/appointment-detail-sheet.tsx +415 -0
  198. package/src/components/ui/appointment-gmail-connect.tsx +188 -0
  199. package/src/components/ui/appointment-mini-card.tsx +104 -0
  200. package/src/components/ui/appointment-time-slot-picker.tsx +123 -0
  201. package/src/components/ui/appointment-upcoming-card.tsx +635 -0
  202. package/src/components/ui/backoffice-alert-history-chart.tsx +10 -2
  203. package/src/components/ui/backoffice-alerts-chart.tsx +312 -0
  204. package/src/components/ui/backoffice-connections-chart.tsx +339 -0
  205. package/src/components/ui/backoffice-contact-history-chart.tsx +10 -2
  206. package/src/components/ui/badge.tsx +12 -6
  207. package/src/components/ui/borrowing-capacity-line-chart.tsx +4 -11
  208. package/src/components/ui/button.tsx +2 -2
  209. package/src/components/ui/card.tsx +1 -1
  210. package/src/components/ui/cash-balance-line-chart.tsx +4 -23
  211. package/src/components/ui/cashflow-bar-chart.tsx +9 -2
  212. package/src/components/ui/chart-shared.tsx +4 -11
  213. package/src/components/ui/chip.tsx +23 -19
  214. package/src/components/ui/color-picker.tsx +309 -0
  215. package/src/components/ui/data-table.tsx +117 -83
  216. package/src/components/ui/date-picker.tsx +42 -37
  217. package/src/components/ui/dialog.tsx +72 -6
  218. package/src/components/ui/expense-bar-chart.tsx +11 -2
  219. package/src/components/ui/financial-cards.tsx +99 -10
  220. package/src/components/ui/income-bar-chart.tsx +11 -2
  221. package/src/components/ui/opportunity-card.tsx +10 -39
  222. package/src/components/ui/opportunity-edit-modals.tsx +98 -36
  223. package/src/components/ui/opportunity-summary-tab.tsx +548 -232
  224. package/src/components/ui/page-header.tsx +57 -0
  225. package/src/components/ui/page-top-bar.tsx +48 -0
  226. package/src/components/ui/pagination.tsx +171 -22
  227. package/src/components/ui/pipeline-board.tsx +12 -5
  228. package/src/components/ui/property-cashflow-doughnut-chart.tsx +3 -1
  229. package/src/components/ui/property-debt-equity-doughnut-chart.tsx +3 -1
  230. package/src/components/ui/property-mobile-estimate-line-chart.tsx +3 -1
  231. package/src/components/ui/sidebar-nav.tsx +516 -0
  232. package/src/components/ui/stepper.tsx +347 -0
  233. package/src/components/ui/toggle.tsx +4 -4
  234. package/src/components/ui/transactions-expense-categories-doughnut-chart.tsx +3 -1
  235. package/src/components/ui/transactions-income-expense-bar-chart.tsx +12 -9
  236. package/src/components/ui/transactions-liabilities-breakdown-doughnut-chart.tsx +3 -1
  237. package/src/lib/format-currency.ts +44 -0
  238. package/src/lib/format-date.ts +50 -0
  239. package/src/lib/opportunity-constants.ts +12 -0
  240. package/src/lib/typography.ts +11 -11
  241. package/src/styles/globals.css +36 -34
  242. package/src/styles/styles-css.ts +1 -1
  243. package/tsup.config.ts +17 -0
  244. package/dist/chunk-PG6K5XEC.mjs +0 -475
  245. package/dist/chunk-WA6O6EUR.mjs +0 -1885
  246. package/dist/chunk-WNGWBVLV.mjs +0 -148
  247. package/dist/{chunk-LLVQKSU3.mjs → chunk-GD4BJDJR.mjs} +3 -3
@@ -0,0 +1,57 @@
1
+ import * as React from "react";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ /**
5
+ * PageHeader — WealthX Design System
6
+ *
7
+ * In-page heading block. Renders inside scrollable content — not part of
8
+ * the layout shell. Use for sections that need a visible title and optional
9
+ * description (e.g. "My Advisors", "How can we help?").
10
+ *
11
+ * For a sticky top-of-page bar with action buttons, use PageTopBar instead.
12
+ */
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Types
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export interface PageHeaderProps {
19
+ /** Main page / section title */
20
+ title: string;
21
+ /** Optional subtitle shown below the title */
22
+ description?: string;
23
+ /** Optional action elements rendered to the right of the title block */
24
+ actions?: React.ReactNode;
25
+ className?: string;
26
+ }
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Component
30
+ // ---------------------------------------------------------------------------
31
+
32
+ export function PageHeader({
33
+ title,
34
+ description,
35
+ actions,
36
+ className,
37
+ }: PageHeaderProps) {
38
+ return (
39
+ <div
40
+ data-slot="page-header"
41
+ className={cn("flex items-start justify-between gap-4", className)}
42
+ >
43
+ {/* Title + description */}
44
+ <div className="flex flex-col gap-0.5">
45
+ <h1 className="text-xl font-bold leading-tight">{title}</h1>
46
+ {description && (
47
+ <p className="text-sm text-muted-foreground">{description}</p>
48
+ )}
49
+ </div>
50
+
51
+ {/* Optional actions */}
52
+ {actions && (
53
+ <div className="flex shrink-0 items-center gap-2">{actions}</div>
54
+ )}
55
+ </div>
56
+ );
57
+ }
@@ -0,0 +1,48 @@
1
+ import * as React from "react";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ /**
5
+ * PageTopBar — WealthX Design System
6
+ *
7
+ * Sticky top-of-page bar. Sits at the top of the main content area,
8
+ * separated from the content by a bottom border. Holds the page title
9
+ * and action buttons.
10
+ *
11
+ * Used by: Loan CRM, Contact, AI Builder, and other data-heavy pages.
12
+ * For an in-page title block with a description, use PageHeader instead.
13
+ */
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Types
17
+ // ---------------------------------------------------------------------------
18
+
19
+ export interface PageTopBarProps {
20
+ /** Page title shown on the left */
21
+ title: string;
22
+ /** Optional action elements rendered to the right */
23
+ actions?: React.ReactNode;
24
+ className?: string;
25
+ }
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Component
29
+ // ---------------------------------------------------------------------------
30
+
31
+ export function PageTopBar({ title, actions, className }: PageTopBarProps) {
32
+ return (
33
+ <div
34
+ data-slot="page-top-bar"
35
+ className={cn(
36
+ "flex shrink-0 items-center justify-between gap-4",
37
+ "border-b border-border bg-background px-6 py-3",
38
+ className,
39
+ )}
40
+ >
41
+ {/* Title */}
42
+ <h1 className="text-lg font-semibold leading-tight">{title}</h1>
43
+
44
+ {/* Optional actions */}
45
+ {actions && <div className="flex items-center gap-2">{actions}</div>}
46
+ </div>
47
+ );
48
+ }
@@ -1,12 +1,21 @@
1
- import { type ReactElement } from "react"
2
- import * as React from "react"
1
+ import { type ReactElement } from "react";
2
+ import * as React from "react";
3
3
  import {
4
4
  ChevronLeftIcon,
5
5
  ChevronRightIcon,
6
+ ChevronsLeftIcon,
7
+ ChevronsRightIcon,
6
8
  MoreHorizontalIcon,
7
- } from "lucide-react"
8
- import { cn } from "@/lib/utils"
9
- import { buttonVariants, type Button } from "@/components/ui/button"
9
+ } from "lucide-react";
10
+ import { cn } from "@/lib/utils";
11
+ import { buttonVariants, Button } from "@/components/ui/button";
12
+ import {
13
+ Select,
14
+ SelectContent,
15
+ SelectItem,
16
+ SelectTrigger,
17
+ SelectValue,
18
+ } from "@/components/ui/select";
10
19
 
11
20
  /**
12
21
  * Pagination — WealthX Design System
@@ -16,7 +25,7 @@ import { buttonVariants, type Button } from "@/components/ui/button"
16
25
  * WealthX overrides: none — ghost/outline variants match design system
17
26
  */
18
27
 
19
- export type PaginationProps = React.ComponentProps<"nav">
28
+ export type PaginationProps = React.ComponentProps<"nav">;
20
29
 
21
30
  function Pagination({ className, ...props }: PaginationProps): ReactElement {
22
31
  return (
@@ -27,10 +36,10 @@ function Pagination({ className, ...props }: PaginationProps): ReactElement {
27
36
  role="navigation"
28
37
  {...props}
29
38
  />
30
- )
39
+ );
31
40
  }
32
41
 
33
- export type PaginationContentProps = React.ComponentProps<"ul">
42
+ export type PaginationContentProps = React.ComponentProps<"ul">;
34
43
 
35
44
  function PaginationContent({
36
45
  className,
@@ -42,19 +51,19 @@ function PaginationContent({
42
51
  data-slot="pagination-content"
43
52
  {...props}
44
53
  />
45
- )
54
+ );
46
55
  }
47
56
 
48
- export type PaginationItemProps = React.ComponentProps<"li">
57
+ export type PaginationItemProps = React.ComponentProps<"li">;
49
58
 
50
59
  function PaginationItem({ ...props }: PaginationItemProps): ReactElement {
51
- return <li data-slot="pagination-item" {...props} />
60
+ return <li data-slot="pagination-item" {...props} />;
52
61
  }
53
62
 
54
63
  export type PaginationLinkProps = {
55
- isActive?: boolean
64
+ isActive?: boolean;
56
65
  } & Pick<React.ComponentProps<typeof Button>, "size"> &
57
- React.ComponentProps<"a">
66
+ React.ComponentProps<"a">;
58
67
 
59
68
  function PaginationLink({
60
69
  className,
@@ -71,16 +80,18 @@ function PaginationLink({
71
80
  variant: isActive ? "outline" : "ghost",
72
81
  size,
73
82
  }),
74
- className
83
+ className,
75
84
  )}
76
85
  data-active={isActive}
77
86
  data-slot="pagination-link"
78
87
  {...props}
79
88
  />
80
- )
89
+ );
81
90
  }
82
91
 
83
- export type PaginationPreviousProps = React.ComponentProps<typeof PaginationLink>
92
+ export type PaginationPreviousProps = React.ComponentProps<
93
+ typeof PaginationLink
94
+ >;
84
95
 
85
96
  function PaginationPrevious({
86
97
  className,
@@ -96,10 +107,10 @@ function PaginationPrevious({
96
107
  <ChevronLeftIcon />
97
108
  <span className="hidden sm:block">Previous</span>
98
109
  </PaginationLink>
99
- )
110
+ );
100
111
  }
101
112
 
102
- export type PaginationNextProps = React.ComponentProps<typeof PaginationLink>
113
+ export type PaginationNextProps = React.ComponentProps<typeof PaginationLink>;
103
114
 
104
115
  function PaginationNext({
105
116
  className,
@@ -115,10 +126,10 @@ function PaginationNext({
115
126
  <span className="hidden sm:block">Next</span>
116
127
  <ChevronRightIcon />
117
128
  </PaginationLink>
118
- )
129
+ );
119
130
  }
120
131
 
121
- export type PaginationEllipsisProps = React.ComponentProps<"span">
132
+ export type PaginationEllipsisProps = React.ComponentProps<"span">;
122
133
 
123
134
  function PaginationEllipsis({
124
135
  className,
@@ -134,7 +145,143 @@ function PaginationEllipsis({
134
145
  <MoreHorizontalIcon className="size-4" />
135
146
  <span className="sr-only">More pages</span>
136
147
  </span>
137
- )
148
+ );
149
+ }
150
+
151
+ export type PaginationNavButtonsProps = {
152
+ hasPrev: boolean;
153
+ hasNext: boolean;
154
+ onFirst: () => void;
155
+ onPrev: () => void;
156
+ onNext: () => void;
157
+ onLast: () => void;
158
+ };
159
+
160
+ function PaginationNavButtons({
161
+ hasPrev,
162
+ hasNext,
163
+ onFirst,
164
+ onPrev,
165
+ onNext,
166
+ onLast,
167
+ }: PaginationNavButtonsProps): ReactElement {
168
+ return (
169
+ <div className="flex items-center gap-1">
170
+ <Button
171
+ aria-label="Go to first page"
172
+ disabled={!hasPrev}
173
+ onClick={onFirst}
174
+ size="icon-sm"
175
+ variant="outline"
176
+ >
177
+ <ChevronsLeftIcon className="size-4" />
178
+ </Button>
179
+ <Button
180
+ aria-label="Go to previous page"
181
+ disabled={!hasPrev}
182
+ onClick={onPrev}
183
+ size="icon-sm"
184
+ variant="outline"
185
+ >
186
+ <ChevronLeftIcon className="size-4" />
187
+ </Button>
188
+ <Button
189
+ aria-label="Go to next page"
190
+ disabled={!hasNext}
191
+ onClick={onNext}
192
+ size="icon-sm"
193
+ variant="outline"
194
+ >
195
+ <ChevronRightIcon className="size-4" />
196
+ </Button>
197
+ <Button
198
+ aria-label="Go to last page"
199
+ disabled={!hasNext}
200
+ onClick={onLast}
201
+ size="icon-sm"
202
+ variant="outline"
203
+ >
204
+ <ChevronsRightIcon className="size-4" />
205
+ </Button>
206
+ </div>
207
+ );
208
+ }
209
+
210
+ export type TablePaginationProps = {
211
+ page: number;
212
+ pageCount: number;
213
+ pageSize: number;
214
+ pageSizeOptions?: number[];
215
+ onPageChange: (page: number) => void;
216
+ onPageSizeChange: (pageSize: number) => void;
217
+ selectedCount?: number;
218
+ totalCount?: number;
219
+ className?: string;
220
+ };
221
+
222
+ function TablePagination({
223
+ page,
224
+ pageCount,
225
+ pageSize,
226
+ pageSizeOptions = [10, 20, 30, 50],
227
+ onPageChange,
228
+ onPageSizeChange,
229
+ selectedCount,
230
+ totalCount,
231
+ className,
232
+ }: TablePaginationProps): ReactElement {
233
+ return (
234
+ <div
235
+ className={cn("flex items-center gap-4 py-4", className)}
236
+ data-slot="table-pagination"
237
+ >
238
+ {selectedCount != null && selectedCount > 0 && totalCount != null && (
239
+ <span className="text-body-small text-muted-foreground">
240
+ {selectedCount} of {totalCount} row(s) selected.
241
+ </span>
242
+ )}
243
+
244
+ <div className="ml-auto flex items-center gap-6">
245
+ <div className="flex items-center gap-2">
246
+ <span className="text-body-small text-muted-foreground whitespace-nowrap">
247
+ Rows per page
248
+ </span>
249
+ <Select
250
+ onValueChange={(value) => onPageSizeChange(Number(value))}
251
+ value={`${pageSize}`}
252
+ >
253
+ <SelectTrigger
254
+ aria-label="Rows per page"
255
+ className="w-[70px]"
256
+ size="sm"
257
+ >
258
+ <SelectValue />
259
+ </SelectTrigger>
260
+ <SelectContent>
261
+ {pageSizeOptions.map((size) => (
262
+ <SelectItem key={size} value={`${size}`}>
263
+ {size}
264
+ </SelectItem>
265
+ ))}
266
+ </SelectContent>
267
+ </Select>
268
+ </div>
269
+
270
+ <span className="text-body-small text-muted-foreground whitespace-nowrap">
271
+ Page {page} of {pageCount}
272
+ </span>
273
+
274
+ <PaginationNavButtons
275
+ hasNext={page < pageCount}
276
+ hasPrev={page > 1}
277
+ onFirst={() => onPageChange(1)}
278
+ onLast={() => onPageChange(pageCount)}
279
+ onNext={() => onPageChange(page + 1)}
280
+ onPrev={() => onPageChange(page - 1)}
281
+ />
282
+ </div>
283
+ </div>
284
+ );
138
285
  }
139
286
 
140
287
  export {
@@ -145,4 +292,6 @@ export {
145
292
  PaginationPrevious,
146
293
  PaginationNext,
147
294
  PaginationEllipsis,
148
- }
295
+ PaginationNavButtons,
296
+ TablePagination,
297
+ };
@@ -1,5 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { RefreshCw, Search, X } from "lucide-react";
3
+ import { Button } from "@/components/ui/button";
3
4
  import { cn } from "@/lib/utils";
4
5
  import { Input } from "@/components/ui/input";
5
6
  import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
@@ -128,13 +129,16 @@ function Toolbar({
128
129
  className="h-8 pl-8 text-sm"
129
130
  />
130
131
  {searchValue && (
131
- <button
132
+ <Button
133
+ type="button"
134
+ variant="ghost"
135
+ size="icon"
132
136
  onClick={() => onSearchChange("")}
133
- className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
137
+ className="absolute right-2 top-1/2 size-6 -translate-y-1/2 text-muted-foreground hover:text-foreground"
134
138
  aria-label="Clear search"
135
139
  >
136
140
  <X className="size-3.5" />
137
- </button>
141
+ </Button>
138
142
  )}
139
143
  </div>
140
144
 
@@ -163,13 +167,16 @@ function Toolbar({
163
167
 
164
168
  {/* Refresh */}
165
169
  {onRefresh && (
166
- <button
170
+ <Button
171
+ type="button"
172
+ variant="ghost"
173
+ size="icon"
167
174
  onClick={onRefresh}
168
175
  className="ml-auto text-muted-foreground hover:text-foreground"
169
176
  aria-label="Refresh board"
170
177
  >
171
178
  <RefreshCw className="size-4" />
172
- </button>
179
+ </Button>
173
180
  )}
174
181
  </div>
175
182
  );
@@ -127,7 +127,9 @@ export function PropertyCashflowDoughnutChart({
127
127
  style={{ maxWidth: width, fontFamily }}
128
128
  >
129
129
  <CardHeader className="px-3 sm:px-6">
130
- <CardTitle className="text-sm sm:text-base">{title}</CardTitle>
130
+ <CardTitle className="text-xs font-semibold uppercase tracking-wide">
131
+ {title}
132
+ </CardTitle>
131
133
  </CardHeader>
132
134
 
133
135
  <CardContent className="px-3 sm:px-6">
@@ -124,7 +124,9 @@ export function PropertyDebtEquityDoughnutChart({
124
124
  style={{ maxWidth: width, fontFamily }}
125
125
  >
126
126
  <CardHeader className="px-3 sm:px-6">
127
- <CardTitle className="text-sm sm:text-base">{title}</CardTitle>
127
+ <CardTitle className="text-xs font-semibold uppercase tracking-wide">
128
+ {title}
129
+ </CardTitle>
128
130
  </CardHeader>
129
131
 
130
132
  <CardContent className="px-3 sm:px-6">
@@ -337,7 +337,9 @@ export function PropertyMobileEstimateLineChart({
337
337
  style={{ maxWidth: width, fontFamily }}
338
338
  >
339
339
  <CardHeader className="px-3 sm:px-6">
340
- <CardTitle className="text-sm sm:text-base">{title}</CardTitle>
340
+ <CardTitle className="text-xs font-semibold uppercase tracking-wide">
341
+ {title}
342
+ </CardTitle>
341
343
  {showPeriodSelector && (
342
344
  <CardAction>
343
345
  <div className="flex gap-0.5 sm:gap-1">