@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,207 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VLQZANBF.mjs";
4
+
5
+ // src/components/ui/stepper.tsx
6
+ import * as React from "react";
7
+ import { Check } from "lucide-react";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ var StepperContext = React.createContext({
10
+ activeStep: 0,
11
+ orientation: "horizontal",
12
+ totalSteps: 0
13
+ });
14
+ var StepContext = React.createContext({
15
+ index: 0,
16
+ isActive: false,
17
+ isCompleted: false,
18
+ isFirst: true,
19
+ isLast: false
20
+ });
21
+ function Stepper({
22
+ activeStep = 0,
23
+ orientation = "horizontal",
24
+ className,
25
+ children
26
+ }) {
27
+ const totalSteps = React.Children.count(children);
28
+ return /* @__PURE__ */ jsx(StepperContext.Provider, { value: { activeStep, orientation, totalSteps }, children: /* @__PURE__ */ jsx(
29
+ "div",
30
+ {
31
+ "data-slot": "stepper",
32
+ className: cn(
33
+ "font-sans",
34
+ orientation === "horizontal" ? "flex w-full items-start" : "flex flex-col",
35
+ className
36
+ ),
37
+ children: React.Children.map(
38
+ children,
39
+ (step, index) => React.isValidElement(step) ? React.cloneElement(
40
+ step,
41
+ { _index: index }
42
+ ) : step
43
+ )
44
+ }
45
+ ) });
46
+ }
47
+ function Step({ _index = 0, error, className, children }) {
48
+ const { activeStep, orientation, totalSteps } = React.useContext(StepperContext);
49
+ const isActive = _index === activeStep;
50
+ const isCompleted = _index < activeStep;
51
+ const isFirst = _index === 0;
52
+ const isLast = _index === totalSteps - 1;
53
+ return /* @__PURE__ */ jsx(
54
+ StepContext.Provider,
55
+ {
56
+ value: { index: _index, isActive, isCompleted, isFirst, isLast },
57
+ children: /* @__PURE__ */ jsx(
58
+ "div",
59
+ {
60
+ "data-slot": "step",
61
+ "aria-current": isActive ? "step" : void 0,
62
+ "data-active": isActive || void 0,
63
+ "data-completed": isCompleted || void 0,
64
+ "data-error": error || void 0,
65
+ className: cn(
66
+ orientation === "horizontal" ? "flex flex-1 flex-col items-center" : "flex flex-row gap-3",
67
+ className
68
+ ),
69
+ children
70
+ }
71
+ )
72
+ }
73
+ );
74
+ }
75
+ function StepIndicator({ error, className }) {
76
+ const { orientation } = React.useContext(StepperContext);
77
+ const { index, isActive, isCompleted, isFirst, isLast } = React.useContext(StepContext);
78
+ const filled = isActive || isCompleted;
79
+ const circle = /* @__PURE__ */ jsx(
80
+ "div",
81
+ {
82
+ className: cn(
83
+ "relative z-10 flex size-8 shrink-0 items-center justify-center rounded-full text-sm font-medium transition-colors",
84
+ !filled && !error && "border-2 border-border bg-background text-muted-foreground",
85
+ isActive && !error && "border-2 border-primary bg-primary text-primary-foreground",
86
+ isCompleted && !error && "bg-primary text-primary-foreground",
87
+ error && "border-2 border-destructive bg-destructive text-destructive-foreground"
88
+ ),
89
+ children: isCompleted && !error ? /* @__PURE__ */ jsx(Check, { className: "size-4", strokeWidth: 2.5 }) : /* @__PURE__ */ jsx("span", { children: index + 1 })
90
+ }
91
+ );
92
+ if (orientation === "horizontal") {
93
+ return /* @__PURE__ */ jsxs(
94
+ "div",
95
+ {
96
+ "data-slot": "step-indicator",
97
+ className: cn("flex w-full items-center", className),
98
+ children: [
99
+ /* @__PURE__ */ jsx(
100
+ "div",
101
+ {
102
+ className: cn(
103
+ "h-[2px] flex-1 transition-colors",
104
+ isFirst ? "bg-transparent" : isActive || isCompleted ? "bg-primary" : "bg-border"
105
+ )
106
+ }
107
+ ),
108
+ circle,
109
+ /* @__PURE__ */ jsx(
110
+ "div",
111
+ {
112
+ className: cn(
113
+ "h-[2px] flex-1 transition-colors",
114
+ isLast ? "bg-transparent" : isCompleted ? "bg-primary" : "bg-border"
115
+ )
116
+ }
117
+ )
118
+ ]
119
+ }
120
+ );
121
+ }
122
+ return /* @__PURE__ */ jsxs(
123
+ "div",
124
+ {
125
+ "data-slot": "step-indicator",
126
+ className: cn("flex w-8 shrink-0 flex-col items-center", className),
127
+ children: [
128
+ circle,
129
+ !isLast && /* @__PURE__ */ jsx(
130
+ "div",
131
+ {
132
+ "data-slot": "step-connector",
133
+ className: cn(
134
+ "mt-1 w-[2px] flex-1 transition-colors",
135
+ isActive || isCompleted ? "bg-primary" : "bg-border"
136
+ )
137
+ }
138
+ )
139
+ ]
140
+ }
141
+ );
142
+ }
143
+ function StepLabel({
144
+ children,
145
+ description,
146
+ error,
147
+ className
148
+ }) {
149
+ const { orientation } = React.useContext(StepperContext);
150
+ const { isActive, isCompleted, isLast } = React.useContext(StepContext);
151
+ const subtext = typeof error === "string" ? error : description;
152
+ return /* @__PURE__ */ jsxs(
153
+ "div",
154
+ {
155
+ "data-slot": "step-label",
156
+ className: cn(
157
+ "flex flex-col",
158
+ orientation === "horizontal" ? "mt-2 items-center text-center" : cn("flex-1", !isLast && "pb-5"),
159
+ className
160
+ ),
161
+ children: [
162
+ /* @__PURE__ */ jsx(
163
+ "span",
164
+ {
165
+ className: cn(
166
+ "text-sm font-medium leading-tight transition-colors",
167
+ (isActive || isCompleted) && !error && "text-foreground",
168
+ !isActive && !isCompleted && !error && "text-muted-foreground",
169
+ error && "text-destructive"
170
+ ),
171
+ children
172
+ }
173
+ ),
174
+ subtext && /* @__PURE__ */ jsx(
175
+ "span",
176
+ {
177
+ className: cn(
178
+ "mt-0.5 text-xs",
179
+ error ? "text-destructive" : "text-muted-foreground"
180
+ ),
181
+ children: subtext
182
+ }
183
+ )
184
+ ]
185
+ }
186
+ );
187
+ }
188
+ function StepContent({ className, children }) {
189
+ const { isActive } = React.useContext(StepContext);
190
+ if (!isActive) return null;
191
+ return /* @__PURE__ */ jsx("div", { "data-slot": "step-content", className: cn("pb-4 pt-2", className), children });
192
+ }
193
+ function StepItem({ label, description, error }) {
194
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
195
+ /* @__PURE__ */ jsx(StepIndicator, { error: !!error }),
196
+ /* @__PURE__ */ jsx(StepLabel, { description, error, children: label })
197
+ ] });
198
+ }
199
+
200
+ export {
201
+ Stepper,
202
+ Step,
203
+ StepIndicator,
204
+ StepLabel,
205
+ StepContent,
206
+ StepItem
207
+ };
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  ToggleGroup,
6
6
  ToggleGroupItem
7
- } from "./chunk-PMB3A7V3.mjs";
7
+ } from "./chunk-EI5F6FMT.mjs";
8
8
  import {
9
9
  Label
10
10
  } from "./chunk-NSLMILBT.mjs";
@@ -0,0 +1,415 @@
1
+ import {
2
+ Tabs,
3
+ TabsContent,
4
+ TabsList,
5
+ TabsTrigger
6
+ } from "./chunk-JHJHG4GO.mjs";
7
+ import {
8
+ Avatar,
9
+ AvatarFallback
10
+ } from "./chunk-24FUO7TD.mjs";
11
+ import {
12
+ Badge
13
+ } from "./chunk-BKNFWEH2.mjs";
14
+ import {
15
+ Separator
16
+ } from "./chunk-FH6QVUVZ.mjs";
17
+ import {
18
+ Button
19
+ } from "./chunk-XREGSKX3.mjs";
20
+
21
+ // src/components/ui/appointment-calendar-view.tsx
22
+ import {
23
+ Check,
24
+ ChevronLeft,
25
+ ChevronRight,
26
+ RefreshCw,
27
+ X,
28
+ CalendarClock
29
+ } from "lucide-react";
30
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
31
+ var STATUS_COLORS = {
32
+ pending: "border-l-warning bg-warning/5",
33
+ confirmed: "border-l-success bg-success/5",
34
+ cancelled: "border-l-destructive bg-destructive/5",
35
+ rescheduled: "border-l-info bg-info/5"
36
+ };
37
+ var STATUS_CONFIG = {
38
+ pending: {
39
+ variant: "warning",
40
+ label: "Pending",
41
+ icon: /* @__PURE__ */ jsx(CalendarClock, { size: 12 })
42
+ },
43
+ confirmed: {
44
+ variant: "success",
45
+ label: "Confirmed",
46
+ icon: /* @__PURE__ */ jsx(Check, { size: 12 })
47
+ },
48
+ cancelled: {
49
+ variant: "destructive",
50
+ label: "Cancelled",
51
+ icon: /* @__PURE__ */ jsx(X, { size: 12 })
52
+ },
53
+ rescheduled: {
54
+ variant: "info",
55
+ label: "Rescheduled",
56
+ icon: /* @__PURE__ */ jsx(RefreshCw, { size: 12 })
57
+ }
58
+ };
59
+ function formatHour(h) {
60
+ if (h === 12) return "12 PM";
61
+ return h < 12 ? `${h} AM` : `${h - 12} PM`;
62
+ }
63
+ function getHourFromTime(time) {
64
+ const match = time.match(/^(\d+):/);
65
+ if (!match) return 0;
66
+ const h = parseInt(match[1], 10);
67
+ return time.includes("PM") && h !== 12 ? h + 12 : h;
68
+ }
69
+ var DEFAULT_HOURS = [9, 10, 11, 12, 13, 14, 15, 16, 17];
70
+ function DayView({
71
+ appointments,
72
+ date,
73
+ today,
74
+ hours,
75
+ onSelectAppointment
76
+ }) {
77
+ const d = /* @__PURE__ */ new Date(date + "T00:00:00");
78
+ const dayLabel = d.toLocaleDateString("en-AU", { weekday: "short" }).toUpperCase();
79
+ const dayShort = d.getDate();
80
+ const isToday = date === today;
81
+ const dayApts = appointments.filter((a) => a.date === date);
82
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
83
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[48px_1fr] border-b border-border", children: [
84
+ /* @__PURE__ */ jsx("div", { className: "border-r border-border" }),
85
+ /* @__PURE__ */ jsxs(
86
+ "div",
87
+ {
88
+ className: `flex flex-col items-center gap-1 py-3 ${isToday ? "bg-primary/5" : ""}`,
89
+ children: [
90
+ /* @__PURE__ */ jsx(
91
+ "span",
92
+ {
93
+ className: `text-xs font-medium tracking-wide ${isToday ? "font-semibold text-primary" : "text-muted-foreground"}`,
94
+ children: dayLabel
95
+ }
96
+ ),
97
+ /* @__PURE__ */ jsx(
98
+ "span",
99
+ {
100
+ className: `flex h-10 w-10 items-center justify-center text-xl font-semibold ${isToday ? "bg-primary text-primary-foreground" : ""}`,
101
+ children: dayShort
102
+ }
103
+ )
104
+ ]
105
+ }
106
+ )
107
+ ] }),
108
+ hours.map((hour) => {
109
+ const aptsAtHour = dayApts.filter(
110
+ (a) => getHourFromTime(a.timeStart) === hour
111
+ );
112
+ return /* @__PURE__ */ jsxs(
113
+ "div",
114
+ {
115
+ className: "grid min-h-[60px] grid-cols-[48px_1fr] border-b border-border/40 last:border-b-0",
116
+ children: [
117
+ /* @__PURE__ */ jsx(
118
+ "div",
119
+ {
120
+ className: `flex items-start justify-end border-r border-border pr-2 pt-1 ${isToday ? "bg-primary/5" : ""}`,
121
+ children: /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatHour(hour) })
122
+ }
123
+ ),
124
+ /* @__PURE__ */ jsx(
125
+ "div",
126
+ {
127
+ className: `flex flex-col gap-1.5 p-1.5 ${isToday ? "bg-primary/5" : ""}`,
128
+ children: aptsAtHour.map((apt) => /* @__PURE__ */ jsxs(
129
+ Button,
130
+ {
131
+ type: "button",
132
+ variant: "ghost",
133
+ onClick: () => onSelectAppointment == null ? void 0 : onSelectAppointment(apt),
134
+ className: `h-auto w-full justify-start gap-3 border-l-2 px-3 py-2 text-left hover:opacity-80 ${STATUS_COLORS[apt.status]}`,
135
+ children: [
136
+ /* @__PURE__ */ jsx(Avatar, { className: "h-7 w-7 shrink-0", children: /* @__PURE__ */ jsx(AvatarFallback, { className: "text-xs", children: apt.clientAvatarInitials }) }),
137
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
138
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: apt.clientName }),
139
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
140
+ apt.timeStart,
141
+ " \u2013 ",
142
+ apt.timeEnd
143
+ ] })
144
+ ] }),
145
+ /* @__PURE__ */ jsx(Badge, { variant: STATUS_CONFIG[apt.status].variant, children: STATUS_CONFIG[apt.status].label })
146
+ ]
147
+ },
148
+ apt.id
149
+ ))
150
+ }
151
+ )
152
+ ]
153
+ },
154
+ hour
155
+ );
156
+ })
157
+ ] });
158
+ }
159
+ function WeekView({
160
+ appointments,
161
+ weekDays,
162
+ today,
163
+ hours,
164
+ onSelectAppointment
165
+ }) {
166
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col overflow-x-auto", children: [
167
+ /* @__PURE__ */ jsxs(
168
+ "div",
169
+ {
170
+ className: "grid border-b border-border",
171
+ style: { gridTemplateColumns: `48px repeat(${weekDays.length}, 1fr)` },
172
+ children: [
173
+ /* @__PURE__ */ jsx("div", { className: "border-r border-border" }),
174
+ weekDays.map((day) => /* @__PURE__ */ jsxs(
175
+ "div",
176
+ {
177
+ className: `flex flex-col items-center border-r border-border py-2 last:border-r-0 ${day.date === today ? "bg-primary/5" : ""}`,
178
+ children: [
179
+ /* @__PURE__ */ jsx(
180
+ "span",
181
+ {
182
+ className: `text-xs font-medium ${day.date === today ? "font-semibold text-primary" : "text-muted-foreground"}`,
183
+ children: day.label
184
+ }
185
+ ),
186
+ /* @__PURE__ */ jsx(
187
+ "span",
188
+ {
189
+ className: `text-sm font-semibold ${day.date === today ? "text-primary" : ""}`,
190
+ children: day.short
191
+ }
192
+ )
193
+ ]
194
+ },
195
+ day.date
196
+ ))
197
+ ]
198
+ }
199
+ ),
200
+ hours.map((hour) => /* @__PURE__ */ jsxs(
201
+ "div",
202
+ {
203
+ className: "grid border-b border-border/40 last:border-b-0",
204
+ style: {
205
+ gridTemplateColumns: `48px repeat(${weekDays.length}, 1fr)`
206
+ },
207
+ children: [
208
+ /* @__PURE__ */ jsx("div", { className: "flex items-start justify-end border-r border-border pr-2 pt-1", children: /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: formatHour(hour) }) }),
209
+ weekDays.map((day) => {
210
+ const aptsAtCell = appointments.filter(
211
+ (a) => a.date === day.date && getHourFromTime(a.timeStart) === hour
212
+ );
213
+ return /* @__PURE__ */ jsx(
214
+ "div",
215
+ {
216
+ className: `min-h-[44px] overflow-hidden border-r border-border/40 p-0.5 last:border-r-0 ${day.date === today ? "bg-primary/5" : ""}`,
217
+ children: aptsAtCell.map((apt) => /* @__PURE__ */ jsxs(
218
+ Button,
219
+ {
220
+ type: "button",
221
+ variant: "ghost",
222
+ className: `h-auto w-full justify-start truncate border-l-2 px-1 py-1 text-left text-xs font-medium hover:opacity-80 ${STATUS_COLORS[apt.status]}`,
223
+ onClick: () => onSelectAppointment == null ? void 0 : onSelectAppointment(apt),
224
+ children: [
225
+ apt.timeStart,
226
+ " ",
227
+ apt.clientName
228
+ ]
229
+ },
230
+ apt.id
231
+ ))
232
+ },
233
+ day.date
234
+ );
235
+ })
236
+ ]
237
+ },
238
+ hour
239
+ ))
240
+ ] });
241
+ }
242
+ var MONTH_DAY_HEADERS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
243
+ function generateMonthGrid(year, month) {
244
+ const firstDay = new Date(year, month, 1);
245
+ const lastDay = new Date(year, month + 1, 0);
246
+ const startDow = firstDay.getDay();
247
+ const grid = [];
248
+ let week = Array.from({ length: startDow }, () => null);
249
+ for (let day = 1; day <= lastDay.getDate(); day++) {
250
+ week.push(new Date(year, month, day));
251
+ if (week.length === 7) {
252
+ grid.push(week);
253
+ week = [];
254
+ }
255
+ }
256
+ if (week.length > 0) {
257
+ while (week.length < 7) week.push(null);
258
+ grid.push(week);
259
+ }
260
+ return grid;
261
+ }
262
+ function MonthView({
263
+ appointments,
264
+ today,
265
+ onSelectAppointment
266
+ }) {
267
+ const todayDate = /* @__PURE__ */ new Date(today + "T00:00:00");
268
+ const grid = generateMonthGrid(todayDate.getFullYear(), todayDate.getMonth());
269
+ const toIso = (d) => d.toISOString().slice(0, 10);
270
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
271
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 border-b border-border", children: MONTH_DAY_HEADERS.map((d) => /* @__PURE__ */ jsx(
272
+ "div",
273
+ {
274
+ className: "flex items-center justify-center border-r border-border/40 py-2 last:border-r-0",
275
+ children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: d })
276
+ },
277
+ d
278
+ )) }),
279
+ grid.map((week, wi) => /* @__PURE__ */ jsx(
280
+ "div",
281
+ {
282
+ className: "grid grid-cols-7 border-b border-border last:border-b-0",
283
+ children: week.map((day, di) => {
284
+ const iso = day ? toIso(day) : null;
285
+ const dayApts = iso ? appointments.filter((a) => a.date === iso) : [];
286
+ const isToday = iso === today;
287
+ return /* @__PURE__ */ jsx(
288
+ "div",
289
+ {
290
+ className: `min-h-[80px] border-r border-border/40 p-1 last:border-r-0 ${!day ? "bg-muted/20" : ""} ${isToday ? "bg-primary/5" : ""}`,
291
+ children: day && /* @__PURE__ */ jsxs(Fragment, { children: [
292
+ /* @__PURE__ */ jsx(
293
+ "div",
294
+ {
295
+ className: `mb-1 flex h-6 w-6 items-center justify-center text-xs font-semibold ${isToday ? "bg-primary text-primary-foreground" : "text-foreground"}`,
296
+ children: day.getDate()
297
+ }
298
+ ),
299
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
300
+ dayApts.slice(0, 2).map((apt) => /* @__PURE__ */ jsxs(
301
+ Button,
302
+ {
303
+ type: "button",
304
+ variant: "ghost",
305
+ onClick: () => onSelectAppointment == null ? void 0 : onSelectAppointment(apt),
306
+ className: `h-auto w-full justify-start truncate border-l-2 px-1 py-0.5 text-left text-[10px] font-medium hover:opacity-80 ${STATUS_COLORS[apt.status]}`,
307
+ children: [
308
+ apt.timeStart,
309
+ " ",
310
+ apt.clientName
311
+ ]
312
+ },
313
+ apt.id
314
+ )),
315
+ dayApts.length > 2 && /* @__PURE__ */ jsxs("p", { className: "px-1 text-[10px] text-muted-foreground", children: [
316
+ "+",
317
+ dayApts.length - 2,
318
+ " more"
319
+ ] })
320
+ ] })
321
+ ] })
322
+ },
323
+ di
324
+ );
325
+ })
326
+ },
327
+ wi
328
+ ))
329
+ ] });
330
+ }
331
+ function AppointmentCalendarView({
332
+ appointments,
333
+ today,
334
+ periodLabel,
335
+ weekDays,
336
+ hours = DEFAULT_HOURS,
337
+ dayViewDate,
338
+ defaultView = "week",
339
+ onPrev,
340
+ onNext,
341
+ onToday,
342
+ onSelectAppointment,
343
+ toolbarActions
344
+ }) {
345
+ const dayDate = dayViewDate != null ? dayViewDate : today;
346
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col border border-border bg-card", children: [
347
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 px-4 py-3", children: [
348
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
349
+ /* @__PURE__ */ jsx(
350
+ Button,
351
+ {
352
+ variant: "outline",
353
+ size: "sm",
354
+ className: "gap-1",
355
+ onClick: onPrev,
356
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5" })
357
+ }
358
+ ),
359
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: periodLabel }),
360
+ /* @__PURE__ */ jsx(
361
+ Button,
362
+ {
363
+ variant: "outline",
364
+ size: "sm",
365
+ className: "gap-1",
366
+ onClick: onNext,
367
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" })
368
+ }
369
+ ),
370
+ /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: onToday, children: "Today" })
371
+ ] }),
372
+ toolbarActions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: toolbarActions })
373
+ ] }),
374
+ /* @__PURE__ */ jsx(Separator, {}),
375
+ /* @__PURE__ */ jsxs(Tabs, { defaultValue: defaultView, className: "flex flex-col", children: [
376
+ /* @__PURE__ */ jsx("div", { className: "px-4 pt-3", children: /* @__PURE__ */ jsxs(TabsList, { children: [
377
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "day", children: "Day" }),
378
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "week", children: "Week" }),
379
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "month", children: "Month" })
380
+ ] }) }),
381
+ /* @__PURE__ */ jsx(TabsContent, { value: "day", className: "mt-0", children: /* @__PURE__ */ jsx(
382
+ DayView,
383
+ {
384
+ appointments,
385
+ date: dayDate,
386
+ today,
387
+ hours,
388
+ onSelectAppointment
389
+ }
390
+ ) }),
391
+ /* @__PURE__ */ jsx(TabsContent, { value: "week", className: "mt-0", children: /* @__PURE__ */ jsx(
392
+ WeekView,
393
+ {
394
+ appointments,
395
+ weekDays,
396
+ today,
397
+ hours,
398
+ onSelectAppointment
399
+ }
400
+ ) }),
401
+ /* @__PURE__ */ jsx(TabsContent, { value: "month", className: "mt-0", children: /* @__PURE__ */ jsx(
402
+ MonthView,
403
+ {
404
+ appointments,
405
+ today,
406
+ onSelectAppointment
407
+ }
408
+ ) })
409
+ ] })
410
+ ] });
411
+ }
412
+
413
+ export {
414
+ AppointmentCalendarView
415
+ };
@@ -8,10 +8,12 @@ import {
8
8
  FALLBACK_PRIMARY,
9
9
  FALLBACK_SECONDARY,
10
10
  FALLBACK_TICK,
11
- formatAbbrev,
12
11
  formatMonthLabel,
13
12
  formatTooltipDate
14
- } from "./chunk-FZIXGLMV.mjs";
13
+ } from "./chunk-M3FV7LOK.mjs";
14
+ import {
15
+ formatCurrencyAbbrev
16
+ } from "./chunk-MN5NYQCL.mjs";
15
17
  import {
16
18
  Empty,
17
19
  EmptyDescription
@@ -22,7 +24,7 @@ import {
22
24
  CardContent,
23
25
  CardHeader,
24
26
  CardTitle
25
- } from "./chunk-CLIN5525.mjs";
27
+ } from "./chunk-C7CQJNMR.mjs";
26
28
  import {
27
29
  useThemeVars
28
30
  } from "./chunk-FEZKMUCF.mjs";
@@ -225,7 +227,7 @@ function PropertyMobileEstimateLineChart({
225
227
  label: (ctx) => {
226
228
  const val = ctx.raw;
227
229
  if (val === 0) return;
228
- return ` ${ctx.dataset.label}: ${formatAbbrev(val)}`;
230
+ return ` ${ctx.dataset.label}: ${formatCurrencyAbbrev(val)}`;
229
231
  }
230
232
  }
231
233
  }
@@ -253,7 +255,7 @@ function PropertyMobileEstimateLineChart({
253
255
  maxTicksLimit: 5,
254
256
  color: FALLBACK_TICK,
255
257
  font: { size: 10 },
256
- callback: (v) => formatAbbrev(Number(v))
258
+ callback: (v) => formatCurrencyAbbrev(Number(v))
257
259
  }
258
260
  }
259
261
  }
@@ -267,7 +269,7 @@ function PropertyMobileEstimateLineChart({
267
269
  style: { maxWidth: width, fontFamily },
268
270
  children: [
269
271
  /* @__PURE__ */ jsxs(CardHeader, { className: "px-3 sm:px-6", children: [
270
- /* @__PURE__ */ jsx(CardTitle, { className: "text-sm sm:text-base", children: title }),
272
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-xs font-semibold uppercase tracking-wide", children: title }),
271
273
  showPeriodSelector && /* @__PURE__ */ jsx(CardAction, { children: /* @__PURE__ */ jsx("div", { className: "flex gap-0.5 sm:gap-1", children: PROPERTY_PERIODS.map((p) => /* @__PURE__ */ jsx(
272
274
  ChartPeriodButton,
273
275
  {
@@ -23,10 +23,10 @@ var buttonVariants = cva(
23
23
  default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
24
24
  secondary: "bg-brand-secondary text-brand-secondary-foreground shadow-xs hover:bg-brand-secondary/80 focus-visible:ring-brand-secondary/30",
25
25
  destructive: "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
26
- outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
26
+ outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground focus-visible:ring-border/50 dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
27
27
  "outline-primary": "border border-primary text-foreground bg-transparent shadow-xs hover:bg-primary/5 focus-visible:ring-primary/50",
28
28
  "outline-secondary": "border border-brand-secondary text-brand-secondary bg-transparent shadow-xs hover:bg-brand-secondary/10 focus-visible:ring-brand-secondary/30",
29
- ghost: "hover:bg-accent hover:text-accent-foreground hover:shadow-xs dark:hover:bg-accent/50",
29
+ ghost: "hover:bg-accent hover:text-accent-foreground hover:shadow-xs focus-visible:ring-border/50 dark:hover:bg-accent/50",
30
30
  link: "text-primary underline-offset-4 hover:underline"
31
31
  },
32
32
  size: {