@wealthx/shadcn 1.5.32 → 1.5.34

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 (62) hide show
  1. package/.turbo/turbo-build.log +114 -114
  2. package/CHANGELOG.md +12 -0
  3. package/dist/{chunk-SYJ6LVJ6.mjs → chunk-3ZU5BH6X.mjs} +1 -1
  4. package/dist/{chunk-FTQ2AKZ2.mjs → chunk-4QTHK7ML.mjs} +1 -1
  5. package/dist/{chunk-T5HU4S4X.mjs → chunk-C7ZTZTEW.mjs} +1 -1
  6. package/dist/{chunk-KI57CBJR.mjs → chunk-DQNNP6I4.mjs} +33 -24
  7. package/dist/{chunk-RSEVIQEO.mjs → chunk-E432NK23.mjs} +41 -36
  8. package/dist/{chunk-AE4JKISB.mjs → chunk-EEI4FLEE.mjs} +1 -1
  9. package/dist/{chunk-IEQX4UVP.mjs → chunk-EY36WDCF.mjs} +1 -1
  10. package/dist/{chunk-HB5BKRMH.mjs → chunk-F3CU6KEI.mjs} +11 -1
  11. package/dist/chunk-H65NB7KI.mjs +182 -0
  12. package/dist/{chunk-TRM3KIHT.mjs → chunk-ICCPK3J2.mjs} +1 -1
  13. package/dist/{chunk-KGVVK6OS.mjs → chunk-ORMC3TV3.mjs} +3 -1
  14. package/dist/{chunk-HSXMTFIM.mjs → chunk-UD5UF5OC.mjs} +1 -1
  15. package/dist/{chunk-IW33VLL5.mjs → chunk-X3VEDQPO.mjs} +7 -3
  16. package/dist/{chunk-AAZSLTER.mjs → chunk-XGRSPFFC.mjs} +16 -7
  17. package/dist/components/ui/about-you-form.js +9 -6
  18. package/dist/components/ui/about-you-form.mjs +2 -2
  19. package/dist/components/ui/ai-conversations/index.js +4 -1
  20. package/dist/components/ui/ai-conversations/index.mjs +2 -2
  21. package/dist/components/ui/appointment-availability-settings.js +24 -12
  22. package/dist/components/ui/appointment-availability-settings.mjs +3 -3
  23. package/dist/components/ui/appointment-book-dialog.js +33 -24
  24. package/dist/components/ui/appointment-book-dialog.mjs +1 -1
  25. package/dist/components/ui/appointment-detail-sheet.js +3 -1
  26. package/dist/components/ui/appointment-detail-sheet.mjs +1 -1
  27. package/dist/components/ui/appointment-gmail-connect.js +127 -70
  28. package/dist/components/ui/appointment-gmail-connect.mjs +1 -1
  29. package/dist/components/ui/backoffice-signup-steps.js +23 -16
  30. package/dist/components/ui/backoffice-signup-steps.mjs +3 -3
  31. package/dist/components/ui/bank-statement-generate-dialog.js +12 -9
  32. package/dist/components/ui/bank-statement-generate-dialog.mjs +3 -3
  33. package/dist/components/ui/color-picker.js +21 -14
  34. package/dist/components/ui/color-picker.mjs +2 -2
  35. package/dist/components/ui/date-picker.js +6 -3
  36. package/dist/components/ui/date-picker.mjs +2 -2
  37. package/dist/components/ui/opportunity-edit-modals.js +45 -42
  38. package/dist/components/ui/opportunity-edit-modals.mjs +3 -3
  39. package/dist/components/ui/opportunity-summary-tab.js +48 -45
  40. package/dist/components/ui/opportunity-summary-tab.mjs +4 -4
  41. package/dist/components/ui/pipeline-dialogs.js +12 -9
  42. package/dist/components/ui/pipeline-dialogs.mjs +3 -3
  43. package/dist/components/ui/popover.js +22 -1
  44. package/dist/components/ui/popover.mjs +3 -1
  45. package/dist/components/ui/savings-goal-modal.js +11 -8
  46. package/dist/components/ui/savings-goal-modal.mjs +2 -2
  47. package/dist/components/ui/sidebar-nav.js +39 -34
  48. package/dist/components/ui/sidebar-nav.mjs +1 -1
  49. package/dist/index.js +388 -291
  50. package/dist/index.mjs +16 -14
  51. package/dist/styles.css +1 -1
  52. package/package.json +1 -1
  53. package/src/components/index.tsx +4 -0
  54. package/src/components/ui/appointment-availability-settings.tsx +32 -19
  55. package/src/components/ui/appointment-book-dialog.tsx +52 -73
  56. package/src/components/ui/appointment-detail-sheet.tsx +3 -1
  57. package/src/components/ui/appointment-gmail-connect.tsx +89 -29
  58. package/src/components/ui/color-picker.tsx +12 -4
  59. package/src/components/ui/popover.tsx +33 -2
  60. package/src/components/ui/sidebar-nav.tsx +96 -75
  61. package/src/styles/styles-css.ts +1 -1
  62. package/dist/chunk-7TMPOZDE.mjs +0 -122
@@ -131,31 +131,40 @@ function ClientSearch({
131
131
  ] }) })
132
132
  ] });
133
133
  }
134
+ var FMT_CALL = {
135
+ value: "call",
136
+ label: "Call",
137
+ icon: /* @__PURE__ */ jsx(Phone, { className: "h-4 w-4" })
138
+ };
139
+ var FMT_ONLINE = {
140
+ value: "online",
141
+ label: "Online Meeting",
142
+ icon: /* @__PURE__ */ jsx(Video, { className: "h-4 w-4" })
143
+ };
144
+ var FMT_GOOGLE_MEET = {
145
+ value: "google-meet",
146
+ label: "Google Meet",
147
+ icon: /* @__PURE__ */ jsx(Video, { className: "h-4 w-4" })
148
+ };
149
+ var FMT_MS_TEAMS = {
150
+ value: "microsoft-teams",
151
+ label: "MS Teams",
152
+ icon: /* @__PURE__ */ jsx(Users, { className: "h-4 w-4" })
153
+ };
154
+ var FMT_OFFLINE = {
155
+ value: "offline",
156
+ label: "Offline Meeting",
157
+ icon: /* @__PURE__ */ jsx(MapPin, { className: "h-4 w-4" })
158
+ };
134
159
  function getFormatOptions(platform) {
135
- const call = {
136
- value: "call",
137
- label: "Call",
138
- icon: /* @__PURE__ */ jsx(Phone, { className: "h-4 w-4" })
139
- };
140
- const googleMeet = {
141
- value: "google-meet",
142
- label: "Google Meet",
143
- icon: /* @__PURE__ */ jsx(Video, { className: "h-4 w-4" })
144
- };
145
- const msTeams = {
146
- value: "microsoft-teams",
147
- label: "MS Teams",
148
- icon: /* @__PURE__ */ jsx(Users, { className: "h-4 w-4" })
149
- };
150
- const offline = {
151
- value: "offline",
152
- label: "Offline Meeting",
153
- icon: /* @__PURE__ */ jsx(MapPin, { className: "h-4 w-4" })
154
- };
155
- if (platform === "google-meet") return [call, googleMeet, offline];
156
- if (platform === "microsoft-teams") return [call, msTeams, offline];
157
- if (platform === "any") return [call, googleMeet, msTeams, offline];
158
- return [call, offline];
160
+ if (platform === "online") return [FMT_CALL, FMT_ONLINE, FMT_OFFLINE];
161
+ if (platform === "google-meet")
162
+ return [FMT_CALL, FMT_GOOGLE_MEET, FMT_OFFLINE];
163
+ if (platform === "microsoft-teams")
164
+ return [FMT_CALL, FMT_MS_TEAMS, FMT_OFFLINE];
165
+ if (platform === "any")
166
+ return [FMT_CALL, FMT_GOOGLE_MEET, FMT_MS_TEAMS, FMT_OFFLINE];
167
+ return [FMT_CALL, FMT_OFFLINE];
159
168
  }
160
169
  function MeetingFormatSection({
161
170
  format,
@@ -27,8 +27,8 @@ import {
27
27
  ChevronRight,
28
28
  Info,
29
29
  LogOut,
30
- PanelLeftClose,
31
- PanelLeftOpen
30
+ Pin,
31
+ PinOff
32
32
  } from "lucide-react";
33
33
  import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
34
34
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -230,42 +230,53 @@ function CollapsibleNavItem({
230
230
  function SidebarNav({
231
231
  items,
232
232
  userName = "Anonymous User",
233
- collapsed = false,
234
233
  logo,
235
234
  logoCollapsed,
236
235
  metricsGroups,
237
236
  onNavigate,
238
237
  onLogout,
239
- onCollapsedChange,
238
+ defaultLocked = false,
239
+ onLockedChange,
240
240
  className
241
241
  }) {
242
+ const [isLocked, setIsLocked] = React.useState(defaultLocked);
243
+ const [isHovered, setIsHovered] = React.useState(false);
244
+ const isExpanded = isLocked || isHovered;
242
245
  const [userMenuOpen, setUserMenuOpen] = React.useState(false);
243
246
  const navScrollRef = React.useRef(null);
244
247
  const expandedScrollRef = React.useRef(0);
248
+ const handleLockToggle = () => {
249
+ const next = !isLocked;
250
+ setIsLocked(next);
251
+ onLockedChange == null ? void 0 : onLockedChange(next);
252
+ };
245
253
  React.useEffect(() => {
246
- if (collapsed) setUserMenuOpen(false);
247
- }, [collapsed]);
254
+ if (!isExpanded) setUserMenuOpen(false);
255
+ }, [isExpanded]);
248
256
  React.useLayoutEffect(() => {
249
257
  const nav = navScrollRef.current;
250
258
  if (!nav) return;
251
- if (!collapsed) {
259
+ if (isExpanded) {
252
260
  nav.scrollTop = expandedScrollRef.current;
253
261
  }
254
262
  return () => {
255
- if (!collapsed && nav) {
263
+ if (isExpanded && nav) {
256
264
  expandedScrollRef.current = nav.scrollTop;
257
265
  }
258
266
  };
259
- }, [collapsed]);
267
+ }, [isExpanded]);
260
268
  return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(
261
269
  "nav",
262
270
  {
263
271
  "data-slot": "sidebar-nav",
264
- "data-collapsed": collapsed,
272
+ "data-expanded": isExpanded,
273
+ "data-locked": isLocked,
274
+ onMouseEnter: () => setIsHovered(true),
275
+ onMouseLeave: () => setIsHovered(false),
265
276
  className: cn(
266
277
  "flex h-full flex-col bg-brand-secondary text-brand-secondary-foreground",
267
278
  "transition-all duration-200 ease-in-out",
268
- collapsed ? "w-14" : "w-[279px]",
279
+ isExpanded ? "w-[279px]" : "w-14",
269
280
  className
270
281
  ),
271
282
  children: [
@@ -277,7 +288,7 @@ function SidebarNav({
277
288
  alt: "Logo",
278
289
  className: cn(
279
290
  "h-8 w-auto object-contain object-left px-5 transition-opacity duration-200",
280
- collapsed ? "opacity-0" : "opacity-100"
291
+ !isExpanded ? "opacity-0" : "opacity-100"
281
292
  )
282
293
  }
283
294
  ),
@@ -288,7 +299,7 @@ function SidebarNav({
288
299
  alt: "Logo",
289
300
  className: cn(
290
301
  "absolute inset-y-0 left-0 right-0 m-auto h-8 w-8 object-contain transition-opacity duration-200",
291
- collapsed ? "opacity-100" : "opacity-0"
302
+ !isExpanded ? "opacity-100" : "opacity-0"
292
303
  )
293
304
  }
294
305
  )
@@ -298,7 +309,7 @@ function SidebarNav({
298
309
  "div",
299
310
  {
300
311
  className: cn(
301
- collapsed ? "opacity-0 pointer-events-none" : "opacity-100"
312
+ !isExpanded ? "opacity-0 pointer-events-none" : "opacity-100"
302
313
  ),
303
314
  children: /* @__PURE__ */ jsx(
304
315
  Accordion,
@@ -355,12 +366,12 @@ function SidebarNav({
355
366
  )
356
367
  }
357
368
  ),
358
- /* @__PURE__ */ jsx(NavTooltip, { label: userName, collapsed, children: /* @__PURE__ */ jsx(
369
+ /* @__PURE__ */ jsx(NavTooltip, { label: userName, collapsed: !isExpanded, children: /* @__PURE__ */ jsx(
359
370
  "div",
360
371
  {
361
372
  className: cn(
362
373
  "absolute inset-0 flex items-center justify-center transition-opacity duration-200",
363
- collapsed ? "opacity-100" : "opacity-0 pointer-events-none"
374
+ !isExpanded ? "opacity-100" : "opacity-0 pointer-events-none"
364
375
  ),
365
376
  children: /* @__PURE__ */ jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center font-semibold text-xs bg-primary text-primary-foreground", children: getInitials(userName) })
366
377
  }
@@ -369,7 +380,7 @@ function SidebarNav({
369
380
  !!(metricsGroups == null ? void 0 : metricsGroups.length) && /* @__PURE__ */ jsx(
370
381
  Accordion,
371
382
  {
372
- value: !collapsed ? ["metrics"] : [],
383
+ value: isExpanded ? ["metrics"] : [],
373
384
  onValueChange: () => {
374
385
  },
375
386
  children: /* @__PURE__ */ jsx(AccordionItem, { className: "border-none", value: "metrics", children: /* @__PURE__ */ jsx(AccordionContent, { className: "p-0 text-inherit", children: metricsGroups.map((group, i) => /* @__PURE__ */ jsx(MetricsGroup, { group }, i)) }) })
@@ -380,7 +391,7 @@ function SidebarNav({
380
391
  CollapsibleNavItem,
381
392
  {
382
393
  item,
383
- collapsed,
394
+ collapsed: !isExpanded,
384
395
  onNavigate
385
396
  },
386
397
  item.href
@@ -388,45 +399,39 @@ function SidebarNav({
388
399
  SidebarNavItemView,
389
400
  {
390
401
  item,
391
- collapsed,
402
+ collapsed: !isExpanded,
392
403
  onNavigate
393
404
  },
394
405
  item.href
395
406
  )
396
407
  ) }),
397
- onCollapsedChange && /* @__PURE__ */ jsx("div", { className: "mt-auto border-t border-white/15 bg-white/8", children: /* @__PURE__ */ jsx(
408
+ /* @__PURE__ */ jsx("div", { className: "mt-auto border-t border-white/15 bg-white/10", children: /* @__PURE__ */ jsx(
398
409
  NavTooltip,
399
410
  {
400
- label: collapsed ? "Expand" : "Collapse",
401
- collapsed,
411
+ label: isLocked ? "Unpin sidebar" : "Pin sidebar open",
412
+ collapsed: !isExpanded,
402
413
  children: /* @__PURE__ */ jsxs(
403
414
  Button,
404
415
  {
405
416
  type: "button",
406
417
  variant: "ghost",
407
- onClick: () => onCollapsedChange(!collapsed),
418
+ onClick: handleLockToggle,
408
419
  className: cn(
409
- "h-12 w-full justify-start gap-3 px-3 py-3 transition-colors",
420
+ "h-12 w-full items-center gap-3 py-3 transition-colors",
410
421
  "text-brand-secondary-foreground/80 hover:bg-white/10 hover:text-brand-secondary-foreground",
411
- collapsed && "justify-center px-2"
422
+ isExpanded ? "justify-start px-3" : "justify-center px-2",
423
+ isLocked && "text-primary"
412
424
  ),
413
425
  children: [
414
- collapsed ? /* @__PURE__ */ jsx(
415
- PanelLeftOpen,
426
+ isLocked ? /* @__PURE__ */ jsx(Pin, { size: 24, strokeWidth: 1.75, className: "shrink-0" }) : /* @__PURE__ */ jsx(
427
+ PinOff,
416
428
  {
417
429
  size: 24,
418
430
  strokeWidth: 1.75,
419
- className: "shrink-0"
420
- }
421
- ) : /* @__PURE__ */ jsx(
422
- PanelLeftClose,
423
- {
424
- size: 24,
425
- strokeWidth: 1.75,
426
- className: "shrink-0"
431
+ className: "shrink-0 opacity-60"
427
432
  }
428
433
  ),
429
- !collapsed && /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Collapse" })
434
+ isExpanded && /* @__PURE__ */ jsx("span", { className: "text-sm", children: isLocked ? "Pinned" : "Pin sidebar" })
430
435
  ]
431
436
  }
432
437
  )
@@ -41,7 +41,7 @@ import {
41
41
  Popover,
42
42
  PopoverContent,
43
43
  PopoverTrigger
44
- } from "./chunk-HB5BKRMH.mjs";
44
+ } from "./chunk-F3CU6KEI.mjs";
45
45
  import {
46
46
  ToggleGroup,
47
47
  ToggleGroupItem
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-I4KVSZCH.mjs";
10
10
  import {
11
11
  ColorPicker
12
- } from "./chunk-IW33VLL5.mjs";
12
+ } from "./chunk-X3VEDQPO.mjs";
13
13
  import {
14
14
  Field,
15
15
  FieldError,
@@ -10,8 +10,16 @@ import {
10
10
  } from "./chunk-WNQUEZJF.mjs";
11
11
 
12
12
  // src/components/ui/popover.tsx
13
+ import * as React from "react";
13
14
  import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
14
15
  import { jsx } from "react/jsx-runtime";
16
+ var PopoverPortalContext = React.createContext(void 0);
17
+ function PopoverPortalProvider({
18
+ container,
19
+ children
20
+ }) {
21
+ return /* @__PURE__ */ jsx(PopoverPortalContext.Provider, { value: container, children });
22
+ }
15
23
  function Popover(_a) {
16
24
  var props = __objRest(_a, []);
17
25
  return /* @__PURE__ */ jsx(PopoverPrimitive.Root, __spreadValues({ "data-slot": "popover" }, props));
@@ -33,7 +41,8 @@ function PopoverContent(_a) {
33
41
  "style"
34
42
  ]);
35
43
  const themeVars = useThemeVars();
36
- return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
44
+ const portalContainer = React.useContext(PopoverPortalContext);
45
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { container: portalContainer != null ? portalContainer : void 0, children: /* @__PURE__ */ jsx(
37
46
  PopoverPrimitive.Positioner,
38
47
  {
39
48
  className: "z-[200]",
@@ -104,6 +113,7 @@ function PopoverDescription(_a) {
104
113
  }
105
114
 
106
115
  export {
116
+ PopoverPortalProvider,
107
117
  Popover,
108
118
  PopoverTrigger,
109
119
  PopoverContent,
@@ -0,0 +1,182 @@
1
+ import {
2
+ Separator
3
+ } from "./chunk-2GIYVERS.mjs";
4
+ import {
5
+ Badge
6
+ } from "./chunk-X6RC5UWB.mjs";
7
+ import {
8
+ Input
9
+ } from "./chunk-LBTHZSBT.mjs";
10
+ import {
11
+ Button
12
+ } from "./chunk-NOOEKOWY.mjs";
13
+ import {
14
+ cn
15
+ } from "./chunk-AFML43VJ.mjs";
16
+
17
+ // src/components/ui/appointment-gmail-connect.tsx
18
+ import { Check, Copy, ExternalLink, Link2, Mail, Settings } from "lucide-react";
19
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
+ function GmailIcon({ className }) {
21
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className, "aria-hidden": "true", children: /* @__PURE__ */ jsx(
22
+ "path",
23
+ {
24
+ fill: "#EA4335",
25
+ d: "M24 5.457v13.909c0 .904-.732 1.636-1.636 1.636h-3.819V11.73L12 16.64l-6.545-4.91v9.273H1.636A1.636 1.636 0 0 1 0 19.366V5.457c0-2.023 2.309-3.178 3.927-1.964L5.455 4.64 12 9.548l6.545-4.91 1.528-1.145C21.69 2.28 24 3.434 24 5.457z"
26
+ }
27
+ ) });
28
+ }
29
+ function OutlookIcon({ className }) {
30
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className, "aria-hidden": "true", children: /* @__PURE__ */ jsx(
31
+ "path",
32
+ {
33
+ fill: "#0078D4",
34
+ d: "M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801"
35
+ }
36
+ ) });
37
+ }
38
+ var PROVIDER_META = {
39
+ gmail: { label: "Gmail", iconBg: "bg-[#EA4335]/10", Icon: GmailIcon },
40
+ outlook: { label: "Outlook", iconBg: "bg-[#0078D4]/10", Icon: OutlookIcon }
41
+ };
42
+ var PERMISSIONS = [
43
+ "Read your calendar availability",
44
+ "Send appointment confirmation emails",
45
+ "Create calendar events on your behalf"
46
+ ];
47
+ function AppointmentGmailConnect({
48
+ provider = "gmail",
49
+ connection,
50
+ calendarLink,
51
+ highlighted = false,
52
+ onCopyLink,
53
+ onGoToIntegrations
54
+ }) {
55
+ const { label, iconBg, Icon } = PROVIDER_META[provider];
56
+ if (connection.connected) {
57
+ return /* @__PURE__ */ jsxs(
58
+ "div",
59
+ {
60
+ className: cn(
61
+ "flex flex-col border bg-card",
62
+ highlighted ? "border-primary" : "border-border"
63
+ ),
64
+ children: [
65
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 px-5 py-4", children: [
66
+ /* @__PURE__ */ jsx(
67
+ "div",
68
+ {
69
+ className: cn(
70
+ "flex h-10 w-10 shrink-0 items-center justify-center",
71
+ iconBg
72
+ ),
73
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" })
74
+ }
75
+ ),
76
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
77
+ /* @__PURE__ */ jsxs("p", { className: "text-base font-semibold", children: [
78
+ label,
79
+ " Connected"
80
+ ] }),
81
+ /* @__PURE__ */ jsx("p", { className: "truncate text-sm text-muted-foreground", children: connection.email })
82
+ ] }),
83
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-1.5", children: [
84
+ /* @__PURE__ */ jsxs(
85
+ Button,
86
+ {
87
+ size: "sm",
88
+ variant: "ghost",
89
+ className: "gap-1.5 text-muted-foreground",
90
+ onClick: onGoToIntegrations,
91
+ children: [
92
+ /* @__PURE__ */ jsx(Settings, { className: "h-3.5 w-3.5" }),
93
+ "Manage"
94
+ ]
95
+ }
96
+ ),
97
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
98
+ /* @__PURE__ */ jsxs(Badge, { variant: "success", children: [
99
+ /* @__PURE__ */ jsx(Check, { size: 10 }),
100
+ "Active"
101
+ ] }),
102
+ connection.connectedAt && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
103
+ "Connected since ",
104
+ connection.connectedAt
105
+ ] })
106
+ ] })
107
+ ] })
108
+ ] }),
109
+ /* @__PURE__ */ jsx(Separator, {}),
110
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 px-5 py-4", children: [
111
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "Permissions granted" }),
112
+ PERMISSIONS.map((perm) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
113
+ /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 shrink-0 text-success" }),
114
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: perm })
115
+ ] }, perm))
116
+ ] }),
117
+ calendarLink && /* @__PURE__ */ jsxs(Fragment, { children: [
118
+ /* @__PURE__ */ jsx(Separator, {}),
119
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 px-5 py-4", children: [
120
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
121
+ /* @__PURE__ */ jsx(Link2, { className: "h-4 w-4 text-muted-foreground" }),
122
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Calendar Appointment Link" })
123
+ ] }),
124
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Share with clients so they can self-book." }),
125
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
126
+ /* @__PURE__ */ jsx(
127
+ Input,
128
+ {
129
+ id: "calendar-link",
130
+ readOnly: true,
131
+ value: calendarLink,
132
+ className: "cursor-default select-all pr-10 text-muted-foreground"
133
+ }
134
+ ),
135
+ /* @__PURE__ */ jsx(
136
+ Button,
137
+ {
138
+ type: "button",
139
+ variant: "ghost",
140
+ size: "icon",
141
+ onClick: onCopyLink,
142
+ className: "absolute right-1 top-1/2 h-8 w-8 -translate-y-1/2",
143
+ children: /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" })
144
+ }
145
+ )
146
+ ] })
147
+ ] })
148
+ ] })
149
+ ]
150
+ }
151
+ );
152
+ }
153
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4 border border-border bg-card px-6 py-8 text-center", children: [
154
+ /* @__PURE__ */ jsx("div", { className: "flex h-12 w-12 items-center justify-center bg-muted", children: /* @__PURE__ */ jsx(Mail, { className: "h-6 w-6 text-muted-foreground" }) }),
155
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
156
+ /* @__PURE__ */ jsxs("p", { className: "text-base font-semibold", children: [
157
+ label,
158
+ " not connected"
159
+ ] }),
160
+ /* @__PURE__ */ jsxs("p", { className: "max-w-xs text-sm text-muted-foreground", children: [
161
+ "Connect your ",
162
+ label,
163
+ " account in Integrations to enable calendar booking and appointment confirmations."
164
+ ] })
165
+ ] }),
166
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-xs flex-col gap-2 text-left", children: [
167
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "Once connected, WealthX will be able to:" }),
168
+ PERMISSIONS.map((perm) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
169
+ /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
170
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: perm })
171
+ ] }, perm))
172
+ ] }),
173
+ /* @__PURE__ */ jsxs(Button, { onClick: onGoToIntegrations, className: "gap-2", children: [
174
+ /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" }),
175
+ "Go to Integrations"
176
+ ] })
177
+ ] });
178
+ }
179
+
180
+ export {
181
+ AppointmentGmailConnect
182
+ };
@@ -2,7 +2,7 @@ import {
2
2
  Popover,
3
3
  PopoverContent,
4
4
  PopoverTrigger
5
- } from "./chunk-HB5BKRMH.mjs";
5
+ } from "./chunk-F3CU6KEI.mjs";
6
6
  import {
7
7
  Calendar
8
8
  } from "./chunk-FBNEIYSE.mjs";
@@ -73,11 +73,13 @@ var MEETING_FORMAT_META = {
73
73
  icon: /* @__PURE__ */ jsx(Users, { className: ICON_CLASS }),
74
74
  label: "Microsoft Teams"
75
75
  },
76
+ online: { icon: /* @__PURE__ */ jsx(Video, { className: ICON_CLASS }), label: "Online Meeting" },
76
77
  offline: { icon: /* @__PURE__ */ jsx(MapPin, { className: ICON_CLASS }), label: "In Person" }
77
78
  };
78
79
  var ONLINE_FORMATS = /* @__PURE__ */ new Set([
79
80
  "google-meet",
80
- "microsoft-teams"
81
+ "microsoft-teams",
82
+ "online"
81
83
  ]);
82
84
  function AppointmentDetailSheet({
83
85
  appointment,
@@ -32,7 +32,7 @@ import {
32
32
  } from "./chunk-BS75ICOO.mjs";
33
33
  import {
34
34
  DatePicker
35
- } from "./chunk-TRM3KIHT.mjs";
35
+ } from "./chunk-ICCPK3J2.mjs";
36
36
  import {
37
37
  ToggleGroup,
38
38
  ToggleGroupItem
@@ -2,7 +2,7 @@ import {
2
2
  Popover,
3
3
  PopoverContent,
4
4
  PopoverTrigger
5
- } from "./chunk-HB5BKRMH.mjs";
5
+ } from "./chunk-F3CU6KEI.mjs";
6
6
  import {
7
7
  Input
8
8
  } from "./chunk-LBTHZSBT.mjs";
@@ -93,14 +93,18 @@ function ColorPickerContent({
93
93
  presets = COLOR_PICKER_PRESETS
94
94
  }) {
95
95
  const [hexInput, setHexInput] = React.useState(value);
96
+ const hexInputRef = React.useRef(hexInput);
97
+ hexInputRef.current = hexInput;
96
98
  React.useEffect(() => {
97
- setHexInput(value);
99
+ if (value !== hexInputRef.current) {
100
+ setHexInput(value);
101
+ }
98
102
  }, [value]);
99
103
  function handleHexInputChange(e) {
100
104
  const raw = e.target.value;
101
105
  setHexInput(raw);
102
106
  const normalized = normalizeHex(raw);
103
- if (isValidHex(normalized)) {
107
+ if (/^#[0-9A-Fa-f]{6}$/.test(normalized)) {
104
108
  onChange(normalized);
105
109
  }
106
110
  }
@@ -27,7 +27,7 @@ import {
27
27
  } from "./chunk-2GIYVERS.mjs";
28
28
  import {
29
29
  DatePicker
30
- } from "./chunk-TRM3KIHT.mjs";
30
+ } from "./chunk-ICCPK3J2.mjs";
31
31
  import {
32
32
  formatDateWithWeekday
33
33
  } from "./chunk-LHWJQNLG.mjs";
@@ -262,7 +262,8 @@ function AppointmentAvailabilitySettings({
262
262
  blockedDates: blockedDatesProp,
263
263
  publicHolidays: publicHolidaysProp,
264
264
  onSave,
265
- onBlockedDatesChange
265
+ onBlockedDatesChange,
266
+ onPrefsChange
266
267
  }) {
267
268
  var _a, _b, _c, _d, _e;
268
269
  const [schedule, setSchedule] = React.useState(initialSchedule);
@@ -319,6 +320,7 @@ function AppointmentAvailabilitySettings({
319
320
  );
320
321
  const saveGuard = React.useRef(false);
321
322
  const timeOffGuard = React.useRef(false);
323
+ const prefsChangeGuard = React.useRef(false);
322
324
  React.useEffect(() => {
323
325
  if (!saveGuard.current) {
324
326
  saveGuard.current = true;
@@ -326,6 +328,13 @@ function AppointmentAvailabilitySettings({
326
328
  }
327
329
  onSave == null ? void 0 : onSave(schedule, currentPrefs);
328
330
  }, [schedule, currentPrefs]);
331
+ React.useEffect(() => {
332
+ if (!prefsChangeGuard.current) {
333
+ prefsChangeGuard.current = true;
334
+ return;
335
+ }
336
+ onPrefsChange == null ? void 0 : onPrefsChange(currentPrefs);
337
+ }, [currentPrefs]);
329
338
  React.useEffect(() => {
330
339
  if (!timeOffGuard.current) {
331
340
  timeOffGuard.current = true;
@@ -436,7 +445,7 @@ function AppointmentAvailabilitySettings({
436
445
  value: meetingDuration,
437
446
  onValueChange: (v) => setMeetingDuration(v),
438
447
  children: [
439
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-40", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(MEETING_DURATION_OPTIONS, v) }) }),
448
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-64", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(MEETING_DURATION_OPTIONS, v) }) }),
440
449
  /* @__PURE__ */ jsx(SelectContent, { children: MEETING_DURATION_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
441
450
  ]
442
451
  }
@@ -454,7 +463,7 @@ function AppointmentAvailabilitySettings({
454
463
  value: schedulingBuffer,
455
464
  onValueChange: (v) => setSchedulingBuffer(v),
456
465
  children: [
457
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-40", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(SCHEDULING_BUFFER_OPTIONS, v) }) }),
466
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-64", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(SCHEDULING_BUFFER_OPTIONS, v) }) }),
458
467
  /* @__PURE__ */ jsx(SelectContent, { children: SCHEDULING_BUFFER_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
459
468
  ]
460
469
  }
@@ -472,7 +481,7 @@ function AppointmentAvailabilitySettings({
472
481
  value: maxSlotsPerDay,
473
482
  onValueChange: (v) => setMaxSlotsPerDay(v),
474
483
  children: [
475
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-40", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(MAX_SLOTS_OPTIONS, v) }) }),
484
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-64", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(MAX_SLOTS_OPTIONS, v) }) }),
476
485
  /* @__PURE__ */ jsx(SelectContent, { children: MAX_SLOTS_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
477
486
  ]
478
487
  }
@@ -490,7 +499,7 @@ function AppointmentAvailabilitySettings({
490
499
  value: timezone,
491
500
  onValueChange: (v) => setTimezone(v),
492
501
  children: [
493
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-56", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(TIMEZONE_OPTIONS, v) }) }),
502
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-64", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(TIMEZONE_OPTIONS, v) }) }),
494
503
  /* @__PURE__ */ jsx(SelectContent, { children: TIMEZONE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
495
504
  ]
496
505
  }
@@ -510,7 +519,7 @@ function AppointmentAvailabilitySettings({
510
519
  v
511
520
  ),
512
521
  children: [
513
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(MEETING_PLATFORM_OPTIONS, v) }) }),
522
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-64", children: /* @__PURE__ */ jsx(SelectValue, { children: (v) => selectLabel(MEETING_PLATFORM_OPTIONS, v) }) }),
514
523
  /* @__PURE__ */ jsx(SelectContent, { children: MEETING_PLATFORM_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
515
524
  ]
516
525
  }