@wealthx/shadcn 1.5.12 → 1.5.13

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 (32) hide show
  1. package/.turbo/turbo-build.log +74 -74
  2. package/CHANGELOG.md +6 -0
  3. package/dist/{chunk-CPM6P63C.mjs → chunk-BF5FKUF6.mjs} +53 -24
  4. package/dist/chunk-KICT4VQL.mjs +508 -0
  5. package/dist/chunk-V23CBULF.mjs +432 -0
  6. package/dist/components/ui/appointment-calendar-view.js +177 -176
  7. package/dist/components/ui/appointment-calendar-view.mjs +1 -1
  8. package/dist/components/ui/bank-statement-generate-dialog.js +163 -76
  9. package/dist/components/ui/bank-statement-generate-dialog.mjs +2 -1
  10. package/dist/components/ui/resource-center/index.js +1030 -0
  11. package/dist/components/ui/resource-center/index.mjs +29 -0
  12. package/dist/index.js +540 -364
  13. package/dist/index.mjs +15 -13
  14. package/dist/styles.css +1 -1
  15. package/package.json +4 -4
  16. package/src/components/index.tsx +2 -0
  17. package/src/components/ui/appointment-calendar-view.tsx +211 -199
  18. package/src/components/ui/bank-statement-generate-dialog.tsx +125 -97
  19. package/src/components/ui/resource-center/index.tsx +35 -0
  20. package/src/components/ui/resource-center/resource-cards.tsx +218 -0
  21. package/src/components/ui/resource-center/resource-carousel.tsx +122 -0
  22. package/src/components/ui/resource-center/resource-center-header.tsx +95 -0
  23. package/src/components/ui/resource-center/resource-email-editor-dialog.tsx +131 -0
  24. package/src/components/ui/resource-center/resource-modal.tsx +76 -0
  25. package/src/components/ui/resource-center/types.ts +81 -0
  26. package/src/styles/styles-css.ts +1 -1
  27. package/tsup.config.ts +1 -1
  28. package/dist/chunk-IODGRCQG.mjs +0 -438
  29. package/dist/chunk-XYWEGBAA.mjs +0 -348
  30. package/dist/components/ui/resource-center.js +0 -748
  31. package/dist/components/ui/resource-center.mjs +0 -24
  32. package/src/components/ui/resource-center.tsx +0 -539
@@ -0,0 +1,432 @@
1
+ import {
2
+ Tabs,
3
+ TabsContent,
4
+ TabsList,
5
+ TabsTrigger
6
+ } from "./chunk-WE4YKBDE.mjs";
7
+ import {
8
+ Separator
9
+ } from "./chunk-2GIYVERS.mjs";
10
+ import {
11
+ Avatar,
12
+ AvatarFallback
13
+ } from "./chunk-H6NQTIF4.mjs";
14
+ import {
15
+ Badge
16
+ } from "./chunk-X6RC5UWB.mjs";
17
+ import {
18
+ formatWeekdayShort
19
+ } from "./chunk-LHWJQNLG.mjs";
20
+ import {
21
+ Button
22
+ } from "./chunk-NOOEKOWY.mjs";
23
+
24
+ // src/components/ui/appointment-calendar-view.tsx
25
+ import { ChevronLeft, ChevronRight } from "lucide-react";
26
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
27
+ var STATUS = {
28
+ pending: {
29
+ card: "border-l-warning bg-warning/[0.06]",
30
+ badge: "warning",
31
+ label: "Pending"
32
+ },
33
+ confirmed: {
34
+ card: "border-l-success bg-success/[0.06]",
35
+ badge: "success",
36
+ label: "Confirmed"
37
+ },
38
+ cancelled: {
39
+ card: "border-l-destructive bg-destructive/[0.06]",
40
+ badge: "destructive",
41
+ label: "Cancelled"
42
+ },
43
+ rescheduled: {
44
+ card: "border-l-info bg-info/[0.06]",
45
+ badge: "info",
46
+ label: "Rescheduled"
47
+ }
48
+ };
49
+ function formatHour(h) {
50
+ if (h === 12) return "12 PM";
51
+ return h < 12 ? `${h} AM` : `${h - 12} PM`;
52
+ }
53
+ function getHourFromTime(time) {
54
+ const match = time.match(/^(\d+):/);
55
+ if (!match) return 0;
56
+ const h = parseInt(match[1], 10);
57
+ return time.includes("PM") && h !== 12 ? h + 12 : h;
58
+ }
59
+ var DEFAULT_HOURS = [9, 10, 11, 12, 13, 14, 15, 16, 17];
60
+ function TimeGutter({ hour }) {
61
+ return /* @__PURE__ */ jsx("div", { className: "flex w-16 shrink-0 items-start justify-end border-r border-border pr-3 pt-2", children: /* @__PURE__ */ jsx("span", { className: "text-caption text-muted-foreground", children: formatHour(hour) }) });
62
+ }
63
+ function DayCard({
64
+ apt,
65
+ onSelect
66
+ }) {
67
+ return /* @__PURE__ */ jsxs(
68
+ Button,
69
+ {
70
+ type: "button",
71
+ variant: "ghost",
72
+ onClick: () => onSelect == null ? void 0 : onSelect(apt),
73
+ className: `h-auto w-full justify-start gap-3 border-l-2 px-3 py-3 text-left hover:opacity-80 ${STATUS[apt.status].card}`,
74
+ children: [
75
+ /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: /* @__PURE__ */ jsx(AvatarFallback, { className: "text-caption", children: apt.clientAvatarInitials }) }),
76
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
77
+ /* @__PURE__ */ jsx("span", { className: "text-body-small font-semibold", children: apt.clientName }),
78
+ /* @__PURE__ */ jsxs("span", { className: "text-caption text-muted-foreground", children: [
79
+ apt.timeStart,
80
+ " \u2013 ",
81
+ apt.timeEnd
82
+ ] })
83
+ ] }),
84
+ /* @__PURE__ */ jsx(Badge, { variant: STATUS[apt.status].badge, children: STATUS[apt.status].label })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ function AptChip({
90
+ apt,
91
+ onSelect,
92
+ className
93
+ }) {
94
+ return /* @__PURE__ */ jsx(
95
+ Button,
96
+ {
97
+ type: "button",
98
+ variant: "ghost",
99
+ onClick: () => onSelect == null ? void 0 : onSelect(apt),
100
+ className: `h-auto w-full justify-start truncate border-l-2 text-left hover:opacity-80 ${STATUS[apt.status].card} ${className != null ? className : ""}`,
101
+ children: /* @__PURE__ */ jsxs("span", { className: "truncate text-caption font-medium", children: [
102
+ apt.timeStart,
103
+ " ",
104
+ apt.clientName
105
+ ] })
106
+ }
107
+ );
108
+ }
109
+ function DayView({
110
+ appointments,
111
+ date,
112
+ today,
113
+ hours,
114
+ onSelectAppointment
115
+ }) {
116
+ const d = /* @__PURE__ */ new Date(date + "T00:00:00");
117
+ const isToday = date === today;
118
+ const dayApts = appointments.filter((a) => a.date === date);
119
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
120
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 border-b border-border", children: [
121
+ /* @__PURE__ */ jsx("div", { className: "w-16 shrink-0 border-r border-border" }),
122
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center gap-1 py-4", children: [
123
+ /* @__PURE__ */ jsx(
124
+ "span",
125
+ {
126
+ className: `text-caption tracking-wide ${isToday ? "font-semibold text-primary" : "text-muted-foreground"}`,
127
+ children: formatWeekdayShort(d)
128
+ }
129
+ ),
130
+ /* @__PURE__ */ jsx(
131
+ "span",
132
+ {
133
+ className: `flex h-10 w-10 items-center justify-center text-xl font-semibold ${isToday ? "text-primary" : ""}`,
134
+ children: d.getDate()
135
+ }
136
+ )
137
+ ] })
138
+ ] }),
139
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col", children: hours.map((hour) => {
140
+ const aptsAtHour = dayApts.filter(
141
+ (a) => getHourFromTime(a.timeStart) === hour
142
+ );
143
+ return /* @__PURE__ */ jsxs(
144
+ "div",
145
+ {
146
+ className: "flex flex-1 border-b border-border/40 last:border-b-0",
147
+ children: [
148
+ /* @__PURE__ */ jsx(TimeGutter, { hour }),
149
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col gap-2 p-2", children: aptsAtHour.map((apt) => /* @__PURE__ */ jsx(
150
+ DayCard,
151
+ {
152
+ apt,
153
+ onSelect: onSelectAppointment
154
+ },
155
+ apt.id
156
+ )) })
157
+ ]
158
+ },
159
+ hour
160
+ );
161
+ }) })
162
+ ] });
163
+ }
164
+ function WeekView({
165
+ appointments,
166
+ weekDays,
167
+ today,
168
+ hours,
169
+ onSelectAppointment
170
+ }) {
171
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-x-auto", children: [
172
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 border-b border-border", children: [
173
+ /* @__PURE__ */ jsx("div", { className: "w-16 shrink-0 border-r border-border" }),
174
+ weekDays.map((day) => /* @__PURE__ */ jsxs(
175
+ "div",
176
+ {
177
+ className: "flex flex-1 flex-col items-center border-r border-border py-3 last:border-r-0",
178
+ children: [
179
+ /* @__PURE__ */ jsx(
180
+ "span",
181
+ {
182
+ className: `text-caption ${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-body-small font-semibold ${day.date === today ? "text-primary" : ""}`,
190
+ children: day.short
191
+ }
192
+ )
193
+ ]
194
+ },
195
+ day.date
196
+ ))
197
+ ] }),
198
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col", children: hours.map((hour) => /* @__PURE__ */ jsxs(
199
+ "div",
200
+ {
201
+ className: "flex flex-1 border-b border-border/40 last:border-b-0",
202
+ children: [
203
+ /* @__PURE__ */ jsx(TimeGutter, { hour }),
204
+ weekDays.map((day) => {
205
+ const aptsAtCell = appointments.filter(
206
+ (a) => a.date === day.date && getHourFromTime(a.timeStart) === hour
207
+ );
208
+ return /* @__PURE__ */ jsx(
209
+ "div",
210
+ {
211
+ className: "flex flex-1 flex-col overflow-hidden border-r border-border/40 p-1 last:border-r-0",
212
+ children: aptsAtCell.map((apt) => /* @__PURE__ */ jsx(
213
+ AptChip,
214
+ {
215
+ apt,
216
+ onSelect: onSelectAppointment,
217
+ className: "px-2 py-1.5"
218
+ },
219
+ apt.id
220
+ ))
221
+ },
222
+ day.date
223
+ );
224
+ })
225
+ ]
226
+ },
227
+ hour
228
+ )) })
229
+ ] });
230
+ }
231
+ var MONTH_DAY_HEADERS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
232
+ function generateMonthGrid(year, month) {
233
+ const firstDay = new Date(year, month, 1);
234
+ const lastDay = new Date(year, month + 1, 0);
235
+ const startDow = firstDay.getDay();
236
+ const grid = [];
237
+ let week = Array.from({ length: startDow }, () => null);
238
+ for (let day = 1; day <= lastDay.getDate(); day++) {
239
+ week.push(new Date(year, month, day));
240
+ if (week.length === 7) {
241
+ grid.push(week);
242
+ week = [];
243
+ }
244
+ }
245
+ if (week.length > 0) {
246
+ while (week.length < 7) week.push(null);
247
+ grid.push(week);
248
+ }
249
+ return grid;
250
+ }
251
+ function MonthView({
252
+ appointments,
253
+ viewDate,
254
+ today,
255
+ onSelectAppointment
256
+ }) {
257
+ const vd = /* @__PURE__ */ new Date(viewDate + "T00:00:00");
258
+ const grid = generateMonthGrid(vd.getFullYear(), vd.getMonth());
259
+ const toIso = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
260
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
261
+ /* @__PURE__ */ jsx("div", { className: "grid shrink-0 grid-cols-7 border-b border-border", children: MONTH_DAY_HEADERS.map((d) => /* @__PURE__ */ jsx(
262
+ "div",
263
+ {
264
+ className: "flex items-center justify-center border-r border-border/40 py-2 last:border-r-0",
265
+ children: /* @__PURE__ */ jsx("span", { className: "text-caption font-medium text-muted-foreground", children: d })
266
+ },
267
+ d
268
+ )) }),
269
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col", children: grid.map((week, wi) => /* @__PURE__ */ jsx(
270
+ "div",
271
+ {
272
+ className: "flex flex-1 border-b border-border last:border-b-0",
273
+ children: week.map((day, di) => {
274
+ const iso = day ? toIso(day) : null;
275
+ const dayApts = iso ? appointments.filter((a) => a.date === iso) : [];
276
+ const isToday = iso === today;
277
+ return /* @__PURE__ */ jsx(
278
+ "div",
279
+ {
280
+ className: `min-w-0 flex-1 border-r border-border/40 p-1.5 last:border-r-0 ${!day ? "bg-muted/20" : ""}`,
281
+ children: day && /* @__PURE__ */ jsxs(Fragment, { children: [
282
+ /* @__PURE__ */ jsx(
283
+ "div",
284
+ {
285
+ className: `mb-1 flex h-6 w-6 items-center justify-center text-xs font-semibold ${isToday ? "text-primary" : "text-foreground"}`,
286
+ children: day.getDate()
287
+ }
288
+ ),
289
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
290
+ dayApts.slice(0, 2).map((apt) => /* @__PURE__ */ jsx(
291
+ AptChip,
292
+ {
293
+ apt,
294
+ onSelect: onSelectAppointment,
295
+ className: "px-1.5 py-1"
296
+ },
297
+ apt.id
298
+ )),
299
+ dayApts.length > 2 && /* @__PURE__ */ jsxs("p", { className: "px-1 text-caption text-muted-foreground", children: [
300
+ "+",
301
+ dayApts.length - 2,
302
+ " more"
303
+ ] })
304
+ ] })
305
+ ] })
306
+ },
307
+ di
308
+ );
309
+ })
310
+ },
311
+ wi
312
+ )) })
313
+ ] });
314
+ }
315
+ function AppointmentCalendarView({
316
+ appointments,
317
+ today,
318
+ periodLabel,
319
+ weekDays,
320
+ hours = DEFAULT_HOURS,
321
+ viewDate,
322
+ dayViewDate,
323
+ defaultView = "week",
324
+ onPrev,
325
+ onNext,
326
+ onToday,
327
+ onViewChange,
328
+ onSelectAppointment,
329
+ toolbarActions
330
+ }) {
331
+ var _a;
332
+ const effectiveViewDate = (_a = viewDate != null ? viewDate : dayViewDate) != null ? _a : today;
333
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col min-h-0 border border-border bg-card", children: [
334
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 px-4 py-3", children: [
335
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
336
+ /* @__PURE__ */ jsx(
337
+ Button,
338
+ {
339
+ variant: "outline",
340
+ size: "sm",
341
+ className: "gap-1",
342
+ onClick: onPrev,
343
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5" })
344
+ }
345
+ ),
346
+ /* @__PURE__ */ jsx("p", { className: "text-label-medium", children: periodLabel }),
347
+ /* @__PURE__ */ jsx(
348
+ Button,
349
+ {
350
+ variant: "outline",
351
+ size: "sm",
352
+ className: "gap-1",
353
+ onClick: onNext,
354
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" })
355
+ }
356
+ ),
357
+ /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: onToday, children: "Today" })
358
+ ] }),
359
+ toolbarActions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: toolbarActions })
360
+ ] }),
361
+ /* @__PURE__ */ jsx(Separator, {}),
362
+ /* @__PURE__ */ jsxs(
363
+ Tabs,
364
+ {
365
+ defaultValue: defaultView,
366
+ onValueChange: (v) => onViewChange == null ? void 0 : onViewChange(v),
367
+ className: "flex flex-col flex-1 min-h-0",
368
+ children: [
369
+ /* @__PURE__ */ jsx("div", { className: "px-4 pt-3", children: /* @__PURE__ */ jsxs(TabsList, { children: [
370
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "day", children: "Day" }),
371
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "week", children: "Week" }),
372
+ /* @__PURE__ */ jsx(TabsTrigger, { value: "month", children: "Month" })
373
+ ] }) }),
374
+ /* @__PURE__ */ jsx(
375
+ TabsContent,
376
+ {
377
+ value: "day",
378
+ className: "mt-0 min-h-0 flex-1 flex flex-col overflow-y-auto",
379
+ children: /* @__PURE__ */ jsx(
380
+ DayView,
381
+ {
382
+ appointments,
383
+ date: effectiveViewDate,
384
+ today,
385
+ hours,
386
+ onSelectAppointment
387
+ }
388
+ )
389
+ }
390
+ ),
391
+ /* @__PURE__ */ jsx(
392
+ TabsContent,
393
+ {
394
+ value: "week",
395
+ className: "mt-0 min-h-0 flex-1 flex flex-col overflow-y-auto",
396
+ children: /* @__PURE__ */ jsx(
397
+ WeekView,
398
+ {
399
+ appointments,
400
+ weekDays,
401
+ today,
402
+ hours,
403
+ onSelectAppointment
404
+ }
405
+ )
406
+ }
407
+ ),
408
+ /* @__PURE__ */ jsx(
409
+ TabsContent,
410
+ {
411
+ value: "month",
412
+ className: "mt-0 min-h-0 flex-1 flex flex-col overflow-y-auto",
413
+ children: /* @__PURE__ */ jsx(
414
+ MonthView,
415
+ {
416
+ appointments,
417
+ viewDate: effectiveViewDate,
418
+ today,
419
+ onSelectAppointment
420
+ }
421
+ )
422
+ }
423
+ )
424
+ ]
425
+ }
426
+ )
427
+ ] });
428
+ }
429
+
430
+ export {
431
+ AppointmentCalendarView
432
+ };