@bizapps/design-system-testing 1.0.10 → 1.6.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.
package/dist/main.js CHANGED
@@ -1,18 +1,20 @@
1
1
  "use client";
2
- import { SearchIcon, BellIcon, CircleHelpIcon, ChevronDownIcon, ChevronLeftIcon, MoreHorizontalIcon, ChevronRightIcon, MinusIcon, CheckIcon, LoaderCircle, ChevronUpIcon, X, ChevronLeft, ChevronRight, ExternalLinkIcon, XIcon, ChevronsUpDownIcon, UploadIcon, Loader2Icon, LoaderIcon, PipetteIcon, CalendarIcon, MenuIcon, Funnel, ArrowUp, ArrowDown, ArrowUpDown, Ellipsis, Rows2, Eye, Search, House, Plane, Wallet, LayoutDashboardIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, CircleCheckIcon } from 'lucide-react';
2
+ import { SearchIcon, BellIcon, CircleHelpIcon, ChevronDownIcon, ChevronLeftIcon, MoreHorizontalIcon, ChevronRightIcon, MinusIcon, CheckIcon, LoaderCircle, ChevronUpIcon, X, ChevronLeft, ChevronRight, ExternalLinkIcon, ChevronsUpDownIcon, XIcon, UploadIcon, Loader2Icon, LoaderIcon, PipetteIcon, CalendarIcon, MenuIcon, Pencil, Clock, Funnel, ArrowUp, ArrowDown, ArrowUpDown, Ellipsis, Rows2, Eye, Search, House, Plane, Wallet, LayoutDashboardIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, CircleCheckIcon } from 'lucide-react';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
7
- import { createContext, memo, useRef, useState, useMemo, useCallback, useEffect, forwardRef, Fragment, useId, useContext, useLayoutEffect } from 'react';
8
- import { Avatar as Avatar$1, Checkbox as Checkbox$1, Slot, Select as Select$1, Toggle as Toggle$1, ToggleGroup, Separator as Separator$1, Progress as Progress$1, Slider as Slider$1, Switch as Switch$1, Tabs as Tabs$1, Tooltip as Tooltip$1, Popover as Popover$1, Dialog as Dialog$1, AlertDialog as AlertDialog$1, Accordion as Accordion$1, DropdownMenu as DropdownMenu$1, RadioGroup as RadioGroup$1, NavigationMenu as NavigationMenu$1 } from 'radix-ui';
9
- import { getDefaultClassNames, DayPicker } from 'react-day-picker';
7
+ import { createContext, memo, useRef, useState, useMemo, useCallback, useEffect, forwardRef, Fragment, useId, useContext, useLayoutEffect, isValidElement, cloneElement } from 'react';
8
+ import { Avatar as Avatar$1, Checkbox as Checkbox$1, Slot, Select as Select$1, Label as Label$1, Popover as Popover$1, Toggle as Toggle$1, ToggleGroup, Separator as Separator$1, Progress as Progress$1, Slider as Slider$1, Switch as Switch$1, Tabs as Tabs$1, Tooltip as Tooltip$1, Dialog as Dialog$1, AlertDialog as AlertDialog$1, Accordion as Accordion$1, DropdownMenu as DropdownMenu$1, RadioGroup as RadioGroup$1, NavigationMenu as NavigationMenu$1 } from 'radix-ui';
10
9
  import { isSameDay, isToday, format, addDays } from 'date-fns';
11
10
  import useEmblaCarousel from 'embla-carousel-react';
12
- import { motion, AnimatePresence } from 'motion/react';
11
+ import { isValidPhoneNumber, validatePhoneNumberLength, parsePhoneNumberFromString, AsYouType } from 'libphonenumber-js';
13
12
  import { Command } from 'cmdk';
13
+ import * as countryFlags from 'country-flag-icons/react/3x2';
14
+ import { motion, AnimatePresence } from 'motion/react';
14
15
  import { useDropzone } from 'react-dropzone';
15
16
  import Color from 'color';
17
+ import { getDefaultClassNames, DayPicker } from 'react-day-picker';
16
18
  import { ScheduleXCalendar } from '@schedule-x/react';
17
19
  import { createCalendar, viewMonthGrid, viewWeek, viewDay, viewMonthAgenda } from '@schedule-x/calendar';
18
20
  import { createEventsServicePlugin } from '@schedule-x/events-service';
@@ -452,174 +454,6 @@ function Button({
452
454
  }
453
455
  );
454
456
  }
455
- function Calendar({
456
- className,
457
- classNames,
458
- showOutsideDays = true,
459
- captionLayout = "dropdown",
460
- buttonVariant = "ghost",
461
- locale,
462
- formatters,
463
- components,
464
- fromYear,
465
- toYear,
466
- ...props
467
- }) {
468
- const defaultClassNames = getDefaultClassNames();
469
- return /* @__PURE__ */ jsx(
470
- DayPicker,
471
- {
472
- showOutsideDays,
473
- className: cn(
474
- "group/calendar bg-background p-3 font-sans [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent",
475
- String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
476
- String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
477
- className
478
- ),
479
- captionLayout,
480
- startMonth: new Date(fromYear ?? 1900, 0),
481
- endMonth: new Date(toYear ?? 2100, 11),
482
- locale,
483
- formatters: {
484
- formatMonthDropdown: (date) => date.toLocaleString(locale?.code, { month: "short" }),
485
- ...formatters
486
- },
487
- classNames: {
488
- root: cn("w-fit", defaultClassNames.root),
489
- months: cn("relative flex flex-col gap-3 md:flex-row", defaultClassNames.months),
490
- month: cn("flex w-full flex-col gap-3", defaultClassNames.month),
491
- nav: cn(
492
- "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-2",
493
- defaultClassNames.nav
494
- ),
495
- button_previous: cn(
496
- buttonVariants({ variant: buttonVariant }),
497
- "size-7 p-0 select-none opacity-50 aria-disabled:opacity-30 transition-opacity duration-150 hover:opacity-100",
498
- defaultClassNames.button_previous
499
- ),
500
- button_next: cn(
501
- buttonVariants({ variant: buttonVariant }),
502
- "size-7 p-0 select-none opacity-50 aria-disabled:opacity-30 transition-opacity duration-150 hover:opacity-100",
503
- defaultClassNames.button_next
504
- ),
505
- month_caption: cn(
506
- "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size) tracking-tight",
507
- defaultClassNames.month_caption
508
- ),
509
- dropdowns: cn(
510
- "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-semibold",
511
- defaultClassNames.dropdowns
512
- ),
513
- dropdown_root: cn(
514
- "relative rounded-(--cell-radius)",
515
- defaultClassNames.dropdown_root
516
- ),
517
- dropdown: cn("absolute inset-0 bg-popover opacity-0", defaultClassNames.dropdown),
518
- caption_label: cn(
519
- "font-semibold select-none",
520
- captionLayout === "label" ? "text-sm" : "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
521
- defaultClassNames.caption_label
522
- ),
523
- weekdays: cn("flex gap-1", defaultClassNames.weekdays),
524
- weekday: cn(
525
- "flex-1 rounded-(--cell-radius) text-[0.75rem] font-semibold text-muted-foreground/70 select-none tracking-wide",
526
- defaultClassNames.weekday
527
- ),
528
- week: cn("mt-2 flex w-full gap-1", defaultClassNames.week),
529
- week_number_header: cn(
530
- "w-(--cell-size) select-none",
531
- defaultClassNames.week_number_header
532
- ),
533
- week_number: cn(
534
- "text-[0.75rem] text-muted-foreground/50 select-none",
535
- defaultClassNames.week_number
536
- ),
537
- day: cn(
538
- "group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)",
539
- props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)" : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)",
540
- defaultClassNames.day
541
- ),
542
- range_start: cn(
543
- "relative isolate z-0 rounded-l-md bg-primary/8 after:absolute after:inset-y-0 after:right-0 after:w-3 after:bg-primary/8",
544
- defaultClassNames.range_start
545
- ),
546
- range_middle: cn("rounded-none bg-primary/8", defaultClassNames.range_middle),
547
- range_end: cn(
548
- "relative isolate z-0 rounded-r-md bg-primary/8 after:absolute after:inset-y-0 after:left-0 after:w-3 after:bg-primary/8",
549
- defaultClassNames.range_end
550
- ),
551
- today: cn("rounded-md bg-accent text-accent-foreground", defaultClassNames.today),
552
- outside: cn(
553
- "text-muted-foreground/50 aria-selected:text-muted-foreground/50",
554
- defaultClassNames.outside
555
- ),
556
- disabled: cn("text-muted-foreground/40 opacity-50", defaultClassNames.disabled),
557
- hidden: cn("invisible", defaultClassNames.hidden),
558
- ...classNames
559
- },
560
- components: {
561
- Root: ({ className: className2, rootRef, ...props2 }) => {
562
- return /* @__PURE__ */ jsx(
563
- "div",
564
- {
565
- "data-slot": "calendar",
566
- ref: rootRef,
567
- className: cn(className2),
568
- ...props2
569
- }
570
- );
571
- },
572
- Chevron: ({ className: className2, orientation, ...props2 }) => {
573
- if (orientation === "left") {
574
- return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
575
- }
576
- if (orientation === "right") {
577
- return /* @__PURE__ */ jsx(ChevronRightIcon, { className: cn("size-4", className2), ...props2 });
578
- }
579
- return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
580
- },
581
- DayButton: ({ ...props2 }) => /* @__PURE__ */ jsx(CalendarDayButton, { locale, ...props2 }),
582
- WeekNumber: ({ children, ...props2 }) => {
583
- return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
584
- },
585
- ...components
586
- },
587
- ...props
588
- }
589
- );
590
- }
591
- function CalendarDayButton({
592
- className,
593
- day,
594
- modifiers,
595
- locale,
596
- ...props
597
- }) {
598
- const defaultClassNames = getDefaultClassNames();
599
- const ref = useRef(null);
600
- useEffect(() => {
601
- if (modifiers.focused) ref.current?.focus();
602
- }, [modifiers.focused]);
603
- return /* @__PURE__ */ jsx(
604
- Button,
605
- {
606
- ref,
607
- variant: "ghost",
608
- size: "icon-sm",
609
- "data-day": day.date.toLocaleDateString(locale?.code),
610
- "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
611
- "data-range-start": modifiers.range_start,
612
- "data-range-end": modifiers.range_end,
613
- "data-range-middle": modifiers.range_middle,
614
- className: cn(
615
- "group-data-[focused=true]/day:ring-primary/40 data-[range-end=true]:!bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:!bg-primary/8 data-[range-middle=true]:text-foreground data-[range-start=true]:!bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:!bg-primary data-[selected-single=true]:text-primary-foreground relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 !rounded-md border-0 !bg-transparent leading-none font-normal transition-colors duration-150 group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:rounded-md group-data-[focused=true]/day:ring-[2px] hover:!bg-transparent data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[selected-single=true]:rounded-md [&>span]:text-xs [&>span]:font-medium [&>span]:opacity-75",
616
- defaultClassNames.day,
617
- className
618
- ),
619
- ...props
620
- }
621
- );
622
- }
623
457
  function useControllableState({
624
458
  prop,
625
459
  defaultProp,
@@ -1105,6 +939,22 @@ function Input({ className, type, ...props }) {
1105
939
  }
1106
940
  );
1107
941
  }
942
+ function Label({ className, ...props }) {
943
+ return /* @__PURE__ */ jsx(
944
+ Label$1.Root,
945
+ {
946
+ "data-slot": "label",
947
+ className: cn(
948
+ "text-foreground text-sm leading-6 font-medium transition-colors select-none",
949
+ "group-has-disabled/field:cursor-not-allowed group-has-disabled/field:opacity-50",
950
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
951
+ "aria-invalid:text-destructive dark:aria-invalid:text-destructive/90",
952
+ className
953
+ ),
954
+ ...props
955
+ }
956
+ );
957
+ }
1108
958
 
1109
959
  // src/utils/urlSecurity.ts
1110
960
  var SAFE_HREF_PROTOCOLS = /* @__PURE__ */ new Set(["https:", "http:", "mailto:", "tel:"]);
@@ -1186,15 +1036,412 @@ function Link({
1186
1036
  truncate ? /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap", children }) : children,
1187
1037
  isExternal && !disabled && /* @__PURE__ */ jsxs(Fragment$1, { children: [
1188
1038
  /* @__PURE__ */ jsx(
1189
- ExternalLinkIcon,
1039
+ ExternalLinkIcon,
1040
+ {
1041
+ "aria-hidden": "true",
1042
+ size: externalIconSize,
1043
+ className: "shrink-0"
1044
+ }
1045
+ ),
1046
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(opens in new tab)" })
1047
+ ] })
1048
+ ]
1049
+ }
1050
+ );
1051
+ }
1052
+ function validatePhone(value) {
1053
+ if (!value) {
1054
+ return { isValid: false };
1055
+ }
1056
+ if (isValidPhoneNumber(value)) {
1057
+ return { isValid: true };
1058
+ }
1059
+ return { isValid: false, problem: validatePhoneNumberLength(value) ?? "INVALID" };
1060
+ }
1061
+ function Popover({ ...props }) {
1062
+ return /* @__PURE__ */ jsx(Popover$1.Root, { "data-slot": "popover", ...props });
1063
+ }
1064
+ function PopoverTrigger({ ...props }) {
1065
+ return /* @__PURE__ */ jsx(Popover$1.Trigger, { "data-slot": "popover-trigger", ...props });
1066
+ }
1067
+ function PopoverContent({
1068
+ className,
1069
+ align = "center",
1070
+ sideOffset = 4,
1071
+ container,
1072
+ ...props
1073
+ }) {
1074
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { container, children: /* @__PURE__ */ jsx(
1075
+ Popover$1.Content,
1076
+ {
1077
+ "data-slot": "popover-content",
1078
+ align,
1079
+ sideOffset,
1080
+ className: cn(
1081
+ "bg-popover text-popover-foreground ring-foreground/5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-1 rounded-3xl p-4 text-sm shadow-lg ring-1 outline-hidden duration-100",
1082
+ className
1083
+ ),
1084
+ ...props
1085
+ }
1086
+ ) });
1087
+ }
1088
+ function PopoverAnchor({ ...props }) {
1089
+ return /* @__PURE__ */ jsx(Popover$1.Anchor, { "data-slot": "popover-anchor", ...props });
1090
+ }
1091
+ function PopoverHeader({ className, ...props }) {
1092
+ return /* @__PURE__ */ jsx(
1093
+ "div",
1094
+ {
1095
+ "data-slot": "popover-header",
1096
+ className: cn("flex flex-col gap-1 text-sm", className),
1097
+ ...props
1098
+ }
1099
+ );
1100
+ }
1101
+ function PopoverTitle({ className, ...props }) {
1102
+ return /* @__PURE__ */ jsx(
1103
+ "div",
1104
+ {
1105
+ "data-slot": "popover-title",
1106
+ className: cn("text-base font-medium", className),
1107
+ ...props
1108
+ }
1109
+ );
1110
+ }
1111
+ function PopoverDescription({ className, ...props }) {
1112
+ return /* @__PURE__ */ jsx(
1113
+ "p",
1114
+ {
1115
+ "data-slot": "popover-description",
1116
+ className: cn("text-muted-foreground", className),
1117
+ ...props
1118
+ }
1119
+ );
1120
+ }
1121
+ function stripLeadingDialCode(raw, dialCode) {
1122
+ if (!raw.startsWith("+")) {
1123
+ return raw.replace(/\D/g, "");
1124
+ }
1125
+ const parsed = parsePhoneNumberFromString(raw);
1126
+ if (parsed) {
1127
+ return parsed.nationalNumber;
1128
+ }
1129
+ const digits = raw.replace(/\D/g, "");
1130
+ const code = dialCode.replace(/\D/g, "");
1131
+ return code && digits.startsWith(code) ? digits.length > code.length ? digits.slice(code.length) : "" : digits;
1132
+ }
1133
+ var flagByCode = countryFlags;
1134
+ function CountryFlag({
1135
+ code,
1136
+ flagUrl,
1137
+ className
1138
+ }) {
1139
+ const isoCode = (code || "").toUpperCase();
1140
+ const FlagComponent = flagByCode[isoCode];
1141
+ const flag = flagUrl ? /* @__PURE__ */ jsx("img", { src: flagUrl, alt: "", "aria-hidden": "true", className: "size-full object-cover" }) : FlagComponent ? /* @__PURE__ */ jsx(FlagComponent, { "aria-hidden": "true", className: "size-full" }) : null;
1142
+ return /* @__PURE__ */ jsx(
1143
+ "span",
1144
+ {
1145
+ "data-slot": "phone-field-country-flag",
1146
+ "data-country": isoCode || void 0,
1147
+ "data-fallback": flag ? void 0 : "true",
1148
+ "aria-hidden": "true",
1149
+ className: cn(
1150
+ "size-4 shrink-0 overflow-hidden rounded-[2px]",
1151
+ !flag && "bg-muted rounded-full",
1152
+ className
1153
+ ),
1154
+ children: flag
1155
+ }
1156
+ );
1157
+ }
1158
+ function PhoneField({
1159
+ countries,
1160
+ value,
1161
+ onValueChange,
1162
+ onValidityChange,
1163
+ defaultCountry,
1164
+ placeholder = "Phone number",
1165
+ disabled = false,
1166
+ className,
1167
+ container,
1168
+ name,
1169
+ ...inputProps
1170
+ }) {
1171
+ const [open, setOpen] = useState(false);
1172
+ const [pickedCode, setPickedCode] = useState(
1173
+ (defaultCountry ?? countries[0]?.code)?.toUpperCase()
1174
+ );
1175
+ const [internalValue, setInternalValue] = useState("");
1176
+ const listRef = useRef(null);
1177
+ const inputRef = useRef(null);
1178
+ const caretRef = useRef(null);
1179
+ const lastValidityRef = useRef(null);
1180
+ const listId = `${useId()}-countries-list`;
1181
+ const isControlled = value !== void 0;
1182
+ const currentValue = isControlled ? value : internalValue;
1183
+ const parsed = currentValue ? parsePhoneNumberFromString(currentValue) : void 0;
1184
+ const parsedCountry = parsed?.country;
1185
+ const parsedCallingCode = parsed?.countryCallingCode;
1186
+ const countryInList = parsedCountry !== void 0 && countries.some((country) => country.code.toUpperCase() === parsedCountry);
1187
+ const callingCodeInList = parsedCallingCode !== void 0 && countries.some(
1188
+ (country) => country.dialCode.replace(/\D/g, "") === parsedCallingCode
1189
+ );
1190
+ const pickedCountry = pickedCode ? countries.find((country) => country.code.toUpperCase() === pickedCode.toUpperCase()) : void 0;
1191
+ const pickMatchesValue = pickedCountry !== void 0 && pickedCountry.dialCode.replace(/\D/g, "") === parsedCallingCode;
1192
+ const representedCode = countryInList ? parsedCountry : pickMatchesValue ? pickedCountry.code : callingCodeInList ? countries.find(
1193
+ (country) => country.dialCode.replace(/\D/g, "") === parsedCallingCode
1194
+ )?.code : void 0;
1195
+ const selectedCode = representedCode ?? pickedCode ?? defaultCountry ?? countries[0]?.code;
1196
+ const selectedCountry = countries.find(
1197
+ (country) => country.code.toUpperCase() === selectedCode?.toUpperCase()
1198
+ ) ?? countries[0];
1199
+ const dialCode = selectedCountry ? selectedCountry.dialCode.replace(/\D/g, "") : "";
1200
+ const emitDialCode = parsedCallingCode ?? dialCode;
1201
+ const nationalDigits = parsed ? parsed.nationalNumber : currentValue ? stripLeadingDialCode(currentValue, dialCode) : "";
1202
+ const canFormat = selectedCountry !== void 0 && (!parsed || countryInList || callingCodeInList);
1203
+ const inputValue = selectedCountry && canFormat && nationalDigits ? new AsYouType((selectedCountry.code || "").toUpperCase()).input(
1204
+ nationalDigits
1205
+ ) : nationalDigits;
1206
+ const isInvalid = inputProps["aria-invalid"] === true || inputProps["aria-invalid"] === "true";
1207
+ const { isValid, problem } = validatePhone(currentValue);
1208
+ useEffect(() => {
1209
+ const last = lastValidityRef.current;
1210
+ if (last && last.isValid === isValid && last.problem === problem) {
1211
+ return;
1212
+ }
1213
+ lastValidityRef.current = { isValid, problem };
1214
+ onValidityChange?.({ isValid, problem });
1215
+ }, [isValid, problem, onValidityChange]);
1216
+ useLayoutEffect(() => {
1217
+ const input = inputRef.current;
1218
+ const caret = caretRef.current;
1219
+ if (!input || !caret || document.activeElement !== input) {
1220
+ return;
1221
+ }
1222
+ const digitsBefore = caret.raw.slice(0, caret.start).replace(/\D/g, "").length;
1223
+ let position = 0;
1224
+ if (digitsBefore > 0) {
1225
+ let digitsSeen = 0;
1226
+ for (let i = 0; i < inputValue.length; i++) {
1227
+ if (/\d/.test(inputValue[i])) {
1228
+ digitsSeen += 1;
1229
+ }
1230
+ position = i + 1;
1231
+ if (digitsSeen >= digitsBefore) {
1232
+ break;
1233
+ }
1234
+ }
1235
+ }
1236
+ input.setSelectionRange(position, position + (caret.end - caret.start));
1237
+ caretRef.current = null;
1238
+ }, [inputValue]);
1239
+ const handleSearchChange = () => {
1240
+ requestAnimationFrame(() => listRef.current?.scrollTo({ top: 0 }));
1241
+ };
1242
+ function handleCountrySelect(code) {
1243
+ setPickedCode(code);
1244
+ setOpen(false);
1245
+ const nextCountry = countries.find(
1246
+ (country) => country.code.toUpperCase() === code.toUpperCase()
1247
+ );
1248
+ if (nextCountry && nationalDigits) {
1249
+ const next = `+${nextCountry.dialCode.replace(/\D/g, "")}${nationalDigits}`;
1250
+ onValueChange?.(next);
1251
+ if (!isControlled) {
1252
+ setInternalValue(next);
1253
+ }
1254
+ }
1255
+ }
1256
+ function deriveFromE164(e164) {
1257
+ const parsed2 = parsePhoneNumberFromString(e164);
1258
+ if (!parsed2?.nationalNumber) {
1259
+ return void 0;
1260
+ }
1261
+ const countryMatch = parsed2.country ? countries.find((country) => country.code.toUpperCase() === parsed2.country) : void 0;
1262
+ const nextPickedCode = countryMatch ? countryMatch.code : parsed2.countryCallingCode ? countries.find(
1263
+ (country) => country.dialCode.replace(/\D/g, "") === parsed2.countryCallingCode
1264
+ )?.code : void 0;
1265
+ return {
1266
+ nationalNumber: parsed2.nationalNumber,
1267
+ emitCode: parsed2.countryCallingCode,
1268
+ nextPickedCode
1269
+ };
1270
+ }
1271
+ function handleInputChange(raw, nativeEvent) {
1272
+ const input = inputRef.current;
1273
+ if (input) {
1274
+ caretRef.current = {
1275
+ raw,
1276
+ start: input.selectionStart ?? raw.length,
1277
+ end: input.selectionEnd ?? raw.length
1278
+ };
1279
+ }
1280
+ if (!selectedCountry) return;
1281
+ let national = stripLeadingDialCode(raw, dialCode);
1282
+ let emitCode = emitDialCode;
1283
+ let nextPickedCode;
1284
+ const plusIndex = raw.indexOf("+");
1285
+ if (plusIndex === 0) {
1286
+ const derived = deriveFromE164(raw);
1287
+ if (derived) {
1288
+ emitCode = derived.emitCode || emitDialCode;
1289
+ nextPickedCode = derived.nextPickedCode;
1290
+ } else if (nativeEvent?.inputType === "insertFromPaste") {
1291
+ national = "";
1292
+ }
1293
+ } else if (plusIndex > 0) {
1294
+ const pasted = nativeEvent?.inputType === "insertFromPaste" && nativeEvent.data?.startsWith("+") ? nativeEvent.data : void 0;
1295
+ if (pasted) {
1296
+ const derived = deriveFromE164(pasted);
1297
+ const prefixDigits = raw.slice(0, plusIndex).replace(/\D/g, "");
1298
+ const suffixDigits = raw.slice(plusIndex + pasted.length).replace(/\D/g, "");
1299
+ if (derived) {
1300
+ national = prefixDigits + derived.nationalNumber + suffixDigits;
1301
+ emitCode = derived.emitCode || emitDialCode;
1302
+ nextPickedCode = derived.nextPickedCode;
1303
+ } else {
1304
+ national = prefixDigits + suffixDigits;
1305
+ }
1306
+ }
1307
+ }
1308
+ const next = national ? `+${emitCode}${national}` : "";
1309
+ const grew = national.replace(/\D/g, "").length > nationalDigits.length;
1310
+ const isPaste = nativeEvent?.inputType === "insertFromPaste";
1311
+ if (grew && !isPaste && validatePhoneNumberLength(next) === "TOO_LONG") {
1312
+ if (input) {
1313
+ const caret = Math.max(0, (input.selectionStart ?? inputValue.length) - 1);
1314
+ input.value = inputValue;
1315
+ input.setSelectionRange(caret, caret);
1316
+ }
1317
+ caretRef.current = null;
1318
+ return;
1319
+ }
1320
+ if (nextPickedCode) {
1321
+ setPickedCode(nextPickedCode);
1322
+ }
1323
+ onValueChange?.(next);
1324
+ if (!isControlled) {
1325
+ setInternalValue(next);
1326
+ }
1327
+ }
1328
+ return /* @__PURE__ */ jsxs(
1329
+ "div",
1330
+ {
1331
+ "data-slot": "phone-field",
1332
+ "data-invalid": isInvalid || void 0,
1333
+ className: cn(
1334
+ "border-input flex h-9 w-full min-w-0 items-center overflow-hidden rounded-md border bg-transparent shadow-xs transition-[color,box-shadow]",
1335
+ "focus-within:border-ring focus-within:ring-ring/30 focus-within:ring-3",
1336
+ "data-[invalid=true]:border-destructive data-[invalid=true]:ring-destructive/20 data-[invalid=true]:ring-3",
1337
+ "dark:data-[invalid=true]:border-destructive/50 dark:data-[invalid=true]:ring-destructive/40",
1338
+ className
1339
+ ),
1340
+ children: [
1341
+ /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
1342
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1343
+ "button",
1344
+ {
1345
+ type: "button",
1346
+ "data-slot": "phone-field-country-select",
1347
+ disabled,
1348
+ "aria-expanded": open,
1349
+ "aria-haspopup": "listbox",
1350
+ "aria-controls": open ? listId : void 0,
1351
+ "aria-label": selectedCountry ? `${selectedCountry.name} ${selectedCountry.dialCode}` : void 0,
1352
+ className: cn(
1353
+ "flex h-full shrink-0 cursor-pointer items-center gap-1.5 border-r border-input px-2.5 text-sm font-medium outline-none select-none",
1354
+ "hover:bg-muted",
1355
+ "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50"
1356
+ ),
1357
+ children: selectedCountry && /* @__PURE__ */ jsxs(Fragment$1, { children: [
1358
+ /* @__PURE__ */ jsx(
1359
+ CountryFlag,
1360
+ {
1361
+ code: selectedCountry.code,
1362
+ flagUrl: selectedCountry.flagUrl
1363
+ }
1364
+ ),
1365
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: selectedCountry.dialCode }),
1366
+ /* @__PURE__ */ jsx(ChevronsUpDownIcon, { size: 14, className: "text-muted-foreground shrink-0" })
1367
+ ] })
1368
+ }
1369
+ ) }),
1370
+ /* @__PURE__ */ jsx(
1371
+ PopoverContent,
1190
1372
  {
1191
- "aria-hidden": "true",
1192
- size: externalIconSize,
1193
- className: "shrink-0"
1373
+ className: "w-72 rounded-xl p-0",
1374
+ align: "start",
1375
+ container,
1376
+ children: /* @__PURE__ */ jsxs(Command, { className: "rounded-xl", label: "Search countries", children: [
1377
+ /* @__PURE__ */ jsxs("div", { className: "border-border flex items-center gap-2 border-b px-3", children: [
1378
+ /* @__PURE__ */ jsx(SearchIcon, { size: 14, className: "text-muted-foreground shrink-0" }),
1379
+ /* @__PURE__ */ jsx(
1380
+ Command.Input,
1381
+ {
1382
+ placeholder: "Search country...",
1383
+ onValueChange: handleSearchChange,
1384
+ className: "placeholder:text-muted-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none"
1385
+ }
1386
+ )
1387
+ ] }),
1388
+ /* @__PURE__ */ jsx("div", { id: listId, children: /* @__PURE__ */ jsxs(Command.List, { ref: listRef, className: "max-h-56 overflow-y-auto p-1", children: [
1389
+ /* @__PURE__ */ jsx(Command.Empty, { className: "text-muted-foreground py-4 text-center text-sm", children: "No country found." }),
1390
+ countries.map((country) => /* @__PURE__ */ jsxs(
1391
+ Command.Item,
1392
+ {
1393
+ value: country.code,
1394
+ keywords: [country.name, country.dialCode],
1395
+ "data-slot": "phone-field-country-item",
1396
+ onSelect: () => handleCountrySelect(country.code),
1397
+ className: cn(
1398
+ "flex cursor-pointer items-center justify-between gap-2 rounded-md px-2 py-1.5 text-sm outline-none select-none",
1399
+ "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground",
1400
+ "hover:bg-accent hover:text-accent-foreground"
1401
+ ),
1402
+ children: [
1403
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [
1404
+ /* @__PURE__ */ jsx(CountryFlag, { code: country.code, flagUrl: country.flagUrl }),
1405
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: country.name })
1406
+ ] }),
1407
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
1408
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground tabular-nums", children: country.dialCode }),
1409
+ selectedCode?.toUpperCase() === country.code.toUpperCase() && /* @__PURE__ */ jsx(
1410
+ CheckIcon,
1411
+ {
1412
+ size: 14,
1413
+ className: "text-[var(--color-main-blue-primary)] shrink-0"
1414
+ }
1415
+ )
1416
+ ] })
1417
+ ]
1418
+ },
1419
+ country.code
1420
+ ))
1421
+ ] }) })
1422
+ ] })
1194
1423
  }
1195
- ),
1196
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(opens in new tab)" })
1197
- ] })
1424
+ )
1425
+ ] }),
1426
+ /* @__PURE__ */ jsx(
1427
+ Input,
1428
+ {
1429
+ ref: inputRef,
1430
+ ...inputProps,
1431
+ "data-slot": "phone-field-input",
1432
+ type: "tel",
1433
+ value: inputValue,
1434
+ onChange: (event) => handleInputChange(event.target.value, event.nativeEvent),
1435
+ placeholder,
1436
+ disabled,
1437
+ autoComplete: inputProps.autoComplete ?? "tel",
1438
+ className: cn(
1439
+ "h-full flex-1 rounded-none border-0 bg-transparent shadow-none",
1440
+ "px-3 focus-visible:border-transparent focus-visible:ring-0"
1441
+ )
1442
+ }
1443
+ ),
1444
+ name !== void 0 && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: currentValue, "data-slot": "phone-field-hidden-input" })
1198
1445
  ]
1199
1446
  }
1200
1447
  );
@@ -1429,31 +1676,37 @@ function SelectContent({
1429
1676
  className,
1430
1677
  children,
1431
1678
  position = "popper",
1679
+ maxHeight,
1680
+ style,
1432
1681
  ...props
1433
1682
  }) {
1683
+ const resolvedMaxHeight = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
1434
1684
  return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsxs(
1435
1685
  Select$1.Content,
1436
1686
  {
1437
1687
  "data-slot": "select-content",
1438
1688
  className: cn(
1439
- "border-border bg-popover text-popover-foreground relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
1689
+ "border-border bg-popover text-popover-foreground relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-hidden rounded-md border shadow-md",
1440
1690
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
1441
1691
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1442
1692
  "data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1",
1443
- position === "popper" && "w-[--radix-select-trigger-width]",
1693
+ position === "popper" && "w-(--radix-select-trigger-width)",
1444
1694
  className
1445
1695
  ),
1446
1696
  position,
1697
+ style: {
1698
+ ...resolvedMaxHeight ? {
1699
+ maxHeight: `min(${resolvedMaxHeight}, var(--radix-select-content-available-height))`
1700
+ } : null,
1701
+ ...style
1702
+ },
1447
1703
  ...props,
1448
1704
  children: [
1449
1705
  /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
1450
1706
  /* @__PURE__ */ jsx(
1451
1707
  Select$1.Viewport,
1452
1708
  {
1453
- className: cn(
1454
- "p-1",
1455
- position === "popper" && "h-[--radix-select-trigger-height]"
1456
- ),
1709
+ className: cn("scroll-my-1 p-1", position === "popper" && "w-full"),
1457
1710
  children
1458
1711
  }
1459
1712
  ),
@@ -1580,7 +1833,7 @@ var progressVariants = cva("relative flex w-full items-center overflow-x-hidden
1580
1833
  size: "md"
1581
1834
  }
1582
1835
  });
1583
- var progressIndicatorVariants = cva("size-full flex-1 transition-all", {
1836
+ var progressIndicatorVariants = cva("size-full flex-1 transition-all rounded-[5px]", {
1584
1837
  variants: {
1585
1838
  variant: {
1586
1839
  default: "bg-[var(--color-main-blue-primary)]",
@@ -1745,7 +1998,8 @@ var ease = {
1745
1998
  smooth: [0.4, 0, 0.2, 1],
1746
1999
  enter: [0, 0, 0.2, 1],
1747
2000
  exit: [0.4, 0, 1, 1],
1748
- linear: [0, 0, 1, 1]
2001
+ linear: [0, 0, 1, 1],
2002
+ drawer: [0.22, 1, 0.36, 1]
1749
2003
  };
1750
2004
  var spring = {
1751
2005
  gentle: { type: "spring", stiffness: 260, damping: 28 },
@@ -1789,6 +2043,15 @@ var transition = {
1789
2043
  card: {
1790
2044
  duration: duration.fast,
1791
2045
  ease: ease.smooth
2046
+ },
2047
+ // Drawer / slide panel — smooth enter, fast exit
2048
+ drawer: {
2049
+ duration: 0.3,
2050
+ ease: ease.drawer
2051
+ },
2052
+ drawerExit: {
2053
+ duration: 0.2,
2054
+ ease: ease.exit
1792
2055
  }
1793
2056
  };
1794
2057
  var fadeIn = {
@@ -2253,65 +2516,6 @@ function TooltipContent({
2253
2516
  }
2254
2517
  ) });
2255
2518
  }
2256
- function Popover({ ...props }) {
2257
- return /* @__PURE__ */ jsx(Popover$1.Root, { "data-slot": "popover", ...props });
2258
- }
2259
- function PopoverTrigger({ ...props }) {
2260
- return /* @__PURE__ */ jsx(Popover$1.Trigger, { "data-slot": "popover-trigger", ...props });
2261
- }
2262
- function PopoverContent({
2263
- className,
2264
- align = "center",
2265
- sideOffset = 4,
2266
- ...props
2267
- }) {
2268
- return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
2269
- Popover$1.Content,
2270
- {
2271
- "data-slot": "popover-content",
2272
- align,
2273
- sideOffset,
2274
- className: cn(
2275
- "bg-popover text-popover-foreground ring-foreground/5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-1 rounded-3xl p-4 text-sm shadow-lg ring-1 outline-hidden duration-100",
2276
- className
2277
- ),
2278
- ...props
2279
- }
2280
- ) });
2281
- }
2282
- function PopoverAnchor({ ...props }) {
2283
- return /* @__PURE__ */ jsx(Popover$1.Anchor, { "data-slot": "popover-anchor", ...props });
2284
- }
2285
- function PopoverHeader({ className, ...props }) {
2286
- return /* @__PURE__ */ jsx(
2287
- "div",
2288
- {
2289
- "data-slot": "popover-header",
2290
- className: cn("flex flex-col gap-1 text-sm", className),
2291
- ...props
2292
- }
2293
- );
2294
- }
2295
- function PopoverTitle({ className, ...props }) {
2296
- return /* @__PURE__ */ jsx(
2297
- "div",
2298
- {
2299
- "data-slot": "popover-title",
2300
- className: cn("text-base font-medium", className),
2301
- ...props
2302
- }
2303
- );
2304
- }
2305
- function PopoverDescription({ className, ...props }) {
2306
- return /* @__PURE__ */ jsx(
2307
- "p",
2308
- {
2309
- "data-slot": "popover-description",
2310
- className: cn("text-muted-foreground", className),
2311
- ...props
2312
- }
2313
- );
2314
- }
2315
2519
  var TEXT_SIZES = [12, 14, 16, 18, 20, 24, 28, 32, 40, 48];
2316
2520
  var TEXT_WEIGHTS = [100, 200, 300, 400, 500, 700, 800, 900];
2317
2521
  function Text({
@@ -2366,7 +2570,7 @@ function DialogTrigger({ ...props }) {
2366
2570
  }
2367
2571
  function DialogPortal({ children, ...props }) {
2368
2572
  const isOpen = useContext(DialogContext);
2369
- return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "dialog-portal", forceMount: true, ...props, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isOpen && children }) });
2573
+ return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "dialog-portal", forceMount: true, ...props, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "sync", children: isOpen && children }) });
2370
2574
  }
2371
2575
  function DialogClose({ ...props }) {
2372
2576
  return /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "dialog-close", ...props });
@@ -2393,7 +2597,7 @@ function DialogContent({
2393
2597
  ...props
2394
2598
  }) {
2395
2599
  return /* @__PURE__ */ jsxs(DialogPortal, { children: [
2396
- /* @__PURE__ */ jsx(DialogOverlay, {}),
2600
+ /* @__PURE__ */ jsx(DialogOverlay, {}, "dialog-overlay"),
2397
2601
  /* @__PURE__ */ jsx(
2398
2602
  Dialog$1.Content,
2399
2603
  {
@@ -2430,7 +2634,8 @@ function DialogContent({
2430
2634
  ]
2431
2635
  }
2432
2636
  )
2433
- }
2637
+ },
2638
+ "dialog-content"
2434
2639
  )
2435
2640
  ] });
2436
2641
  }
@@ -2533,7 +2738,7 @@ function AlertDialogPortal({
2533
2738
  ...props
2534
2739
  }) {
2535
2740
  const isOpen = useContext(AlertDialogContext);
2536
- return /* @__PURE__ */ jsx(AlertDialog$1.Portal, { "data-slot": "alert-dialog-portal", forceMount: true, ...props, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isOpen && children }) });
2741
+ return /* @__PURE__ */ jsx(AlertDialog$1.Portal, { "data-slot": "alert-dialog-portal", forceMount: true, ...props, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "sync", children: isOpen && children }) });
2537
2742
  }
2538
2743
  function AlertDialogOverlay({
2539
2744
  className,
@@ -2575,7 +2780,8 @@ function AlertDialogContent({
2575
2780
  AlertDialogOverlay,
2576
2781
  {
2577
2782
  className: cn(variant === "dark-glass" && "bg-primary/60 backdrop-blur-md")
2578
- }
2783
+ },
2784
+ "alert-dialog-overlay"
2579
2785
  ),
2580
2786
  /* @__PURE__ */ jsx(
2581
2787
  AlertDialog$1.Content,
@@ -2609,7 +2815,8 @@ function AlertDialogContent({
2609
2815
  ]
2610
2816
  }
2611
2817
  )
2612
- }
2818
+ },
2819
+ "alert-dialog-content"
2613
2820
  )
2614
2821
  ] });
2615
2822
  }
@@ -2770,6 +2977,17 @@ function AccordionContent({
2770
2977
  }
2771
2978
  );
2772
2979
  }
2980
+ function createMatchFilter(mode) {
2981
+ return (value, search, keywords = []) => {
2982
+ const query = search.toLowerCase().trim();
2983
+ if (!query) return 1;
2984
+ const haystacks = [value, ...keywords].map((s) => s.toLowerCase());
2985
+ const matched = mode === "substring" ? haystacks.some((h) => h.includes(query)) : haystacks.some(
2986
+ (h) => h.startsWith(query) || h.split(/\s+/).some((word) => word.startsWith(query))
2987
+ );
2988
+ return matched ? 1 : 0;
2989
+ };
2990
+ }
2773
2991
  function Combobox({
2774
2992
  options,
2775
2993
  value,
@@ -2778,10 +2996,17 @@ function Combobox({
2778
2996
  searchPlaceholder = "Search...",
2779
2997
  emptyMessage = "No results found.",
2780
2998
  disabled = false,
2781
- className
2999
+ className,
3000
+ container,
3001
+ matchMode = "fuzzy"
2782
3002
  }) {
2783
3003
  const [open, setOpen] = useState(false);
3004
+ const listRef = useRef(null);
2784
3005
  const selected = options.find((opt) => opt.value === value);
3006
+ const filter = matchMode === "fuzzy" ? void 0 : createMatchFilter(matchMode);
3007
+ const handleSearchChange = () => {
3008
+ requestAnimationFrame(() => listRef.current?.scrollTo({ top: 0 }));
3009
+ };
2785
3010
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
2786
3011
  /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2787
3012
  Button,
@@ -2801,18 +3026,19 @@ function Combobox({
2801
3026
  ]
2802
3027
  }
2803
3028
  ) }),
2804
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-64 rounded-lg p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { className: "rounded-lg", children: [
3029
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-64 rounded-lg p-0", align: "start", container, children: /* @__PURE__ */ jsxs(Command, { className: "rounded-lg", filter, children: [
2805
3030
  /* @__PURE__ */ jsxs("div", { className: "border-border flex items-center gap-2 border-b px-3", children: [
2806
3031
  /* @__PURE__ */ jsx(SearchIcon, { size: 14, className: "text-muted-foreground shrink-0" }),
2807
3032
  /* @__PURE__ */ jsx(
2808
3033
  Command.Input,
2809
3034
  {
2810
3035
  placeholder: searchPlaceholder,
3036
+ onValueChange: handleSearchChange,
2811
3037
  className: "placeholder:text-muted-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50"
2812
3038
  }
2813
3039
  )
2814
3040
  ] }),
2815
- /* @__PURE__ */ jsxs(Command.List, { className: "max-h-56 overflow-y-auto p-1", children: [
3041
+ /* @__PURE__ */ jsxs(Command.List, { ref: listRef, className: "max-h-56 overflow-y-auto p-1", children: [
2816
3042
  /* @__PURE__ */ jsx(Command.Empty, { className: "text-muted-foreground py-4 text-center text-sm", children: emptyMessage }),
2817
3043
  options.map((option) => /* @__PURE__ */ jsxs(
2818
3044
  Command.Item,
@@ -4077,92 +4303,325 @@ var ColorPickerFormat = ({ className, ...props }) => {
4077
4303
  "relative flex w-full items-center gap-1 -space-x-px rounded-md",
4078
4304
  className
4079
4305
  ),
4080
- ...props,
4081
- children: [
4082
- /* @__PURE__ */ jsx(
4083
- Input2,
4084
- {
4085
- className: "bg-muted h-8 w-[5rem] rounded-md px-2 text-xs",
4086
- readOnly: true,
4087
- type: "text",
4088
- value: displayHex
4089
- }
4090
- ),
4091
- /* @__PURE__ */ jsx(PercentageInput, { value: alpha, onChange: setAlpha })
4092
- ]
4093
- }
4094
- );
4095
- }
4096
- if (mode === "css") {
4097
- const rgb = color.rgb().array().map((value) => Math.round(value));
4098
- return /* @__PURE__ */ jsx("div", { className: cn("w-full rounded-md", className), ...props, children: /* @__PURE__ */ jsx(
4099
- Input2,
4100
- {
4101
- className: "bg-muted h-8 w-full rounded-md px-2 text-xs shadow-none",
4102
- readOnly: true,
4103
- type: "text",
4104
- value: `rgba(${rgb.join(", ")}, ${alpha}%)`,
4105
- ...props
4106
- }
4107
- ) });
4108
- }
4109
- return null;
4110
- };
4111
- var ColorPickerPresets = ({ colors, className, ...props }) => {
4112
- const { hue, saturation, lightness, alpha, setHue, setSaturation, setLightness, setAlpha } = useColorPicker();
4113
- const currentHex = Color.hsl(hue, saturation, lightness, alpha / 100).hex();
4114
- return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-1.5", className), ...props, children: colors.map((hex) => {
4115
- const isActive = Color(hex).hex().toUpperCase() === currentHex.toUpperCase();
4116
- return /* @__PURE__ */ jsx(
4117
- "button",
4118
- {
4119
- type: "button",
4120
- className: cn(
4121
- "size-5 cursor-pointer rounded-[3px] border transition-all",
4122
- "hover:scale-110 hover:shadow-md",
4123
- isActive && "ring-ring ring-offset-background ring-2 ring-offset-1"
4306
+ ...props,
4307
+ children: [
4308
+ /* @__PURE__ */ jsx(
4309
+ Input2,
4310
+ {
4311
+ className: "bg-muted h-8 w-[5rem] rounded-md px-2 text-xs",
4312
+ readOnly: true,
4313
+ type: "text",
4314
+ value: displayHex
4315
+ }
4316
+ ),
4317
+ /* @__PURE__ */ jsx(PercentageInput, { value: alpha, onChange: setAlpha })
4318
+ ]
4319
+ }
4320
+ );
4321
+ }
4322
+ if (mode === "css") {
4323
+ const rgb = color.rgb().array().map((value) => Math.round(value));
4324
+ return /* @__PURE__ */ jsx("div", { className: cn("w-full rounded-md", className), ...props, children: /* @__PURE__ */ jsx(
4325
+ Input2,
4326
+ {
4327
+ className: "bg-muted h-8 w-full rounded-md px-2 text-xs shadow-none",
4328
+ readOnly: true,
4329
+ type: "text",
4330
+ value: `rgba(${rgb.join(", ")}, ${alpha}%)`,
4331
+ ...props
4332
+ }
4333
+ ) });
4334
+ }
4335
+ return null;
4336
+ };
4337
+ var ColorPickerPresets = ({ colors, className, ...props }) => {
4338
+ const { hue, saturation, lightness, alpha, setHue, setSaturation, setLightness, setAlpha } = useColorPicker();
4339
+ const currentHex = Color.hsl(hue, saturation, lightness, alpha / 100).hex();
4340
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-1.5", className), ...props, children: colors.map((hex) => {
4341
+ const isActive = Color(hex).hex().toUpperCase() === currentHex.toUpperCase();
4342
+ return /* @__PURE__ */ jsx(
4343
+ "button",
4344
+ {
4345
+ type: "button",
4346
+ className: cn(
4347
+ "size-5 cursor-pointer rounded-[3px] border transition-all",
4348
+ "hover:scale-110 hover:shadow-md",
4349
+ isActive && "ring-ring ring-offset-background ring-2 ring-offset-1"
4350
+ ),
4351
+ style: { backgroundColor: hex },
4352
+ onClick: () => {
4353
+ const color = Color(hex);
4354
+ const [h, s, l] = color.hsl().array();
4355
+ setHue(h);
4356
+ setSaturation(s);
4357
+ setLightness(l);
4358
+ setAlpha(100);
4359
+ },
4360
+ "aria-label": hex,
4361
+ title: hex
4362
+ },
4363
+ hex
4364
+ );
4365
+ }) });
4366
+ };
4367
+ ColorPickerPresets.displayName = "ColorPickerPresets";
4368
+ function Calendar({
4369
+ className,
4370
+ classNames,
4371
+ modifiersClassNames,
4372
+ showOutsideDays = true,
4373
+ captionLayout = "dropdown",
4374
+ buttonVariant = "ghost",
4375
+ locale,
4376
+ formatters,
4377
+ components,
4378
+ fromYear,
4379
+ toYear,
4380
+ ...props
4381
+ }) {
4382
+ const defaultClassNames = getDefaultClassNames();
4383
+ const resolvedComponents = useMemo(
4384
+ () => ({
4385
+ Root: ({ className: className2, rootRef, ...rootProps }) => {
4386
+ return /* @__PURE__ */ jsx(
4387
+ "div",
4388
+ {
4389
+ "data-slot": "calendar",
4390
+ ref: rootRef,
4391
+ className: cn(className2),
4392
+ ...rootProps
4393
+ }
4394
+ );
4395
+ },
4396
+ Chevron: ({ className: className2, orientation, ...chevronProps }) => {
4397
+ if (orientation === "left") {
4398
+ return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...chevronProps });
4399
+ }
4400
+ if (orientation === "right") {
4401
+ return /* @__PURE__ */ jsx(ChevronRightIcon, { className: cn("size-4", className2), ...chevronProps });
4402
+ }
4403
+ return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...chevronProps });
4404
+ },
4405
+ DayButton: (dayButtonProps) => /* @__PURE__ */ jsx(CalendarDayButton, { locale, ...dayButtonProps }),
4406
+ WeekNumber: ({ children, ...weekNumberProps }) => {
4407
+ return /* @__PURE__ */ jsx("td", { ...weekNumberProps, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
4408
+ },
4409
+ ...components
4410
+ }),
4411
+ [locale, components]
4412
+ );
4413
+ return /* @__PURE__ */ jsx(
4414
+ DayPicker,
4415
+ {
4416
+ showOutsideDays,
4417
+ className: cn(
4418
+ "group/calendar bg-background p-3 font-sans [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent",
4419
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
4420
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
4421
+ className
4422
+ ),
4423
+ captionLayout,
4424
+ startMonth: new Date(fromYear ?? 1900, 0),
4425
+ endMonth: new Date(toYear ?? 2100, 11),
4426
+ locale,
4427
+ formatters: {
4428
+ formatMonthDropdown: (date) => date.toLocaleString(locale?.code, { month: "short" }),
4429
+ ...formatters
4430
+ },
4431
+ classNames: {
4432
+ root: cn("w-fit", defaultClassNames.root),
4433
+ months: cn("relative flex flex-col gap-3 md:flex-row", defaultClassNames.months),
4434
+ month: cn("flex w-full flex-col gap-3", defaultClassNames.month),
4435
+ nav: cn(
4436
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-2",
4437
+ defaultClassNames.nav
4438
+ ),
4439
+ button_previous: cn(
4440
+ buttonVariants({ variant: buttonVariant }),
4441
+ "size-7 p-0 select-none opacity-50 aria-disabled:opacity-30 transition-opacity duration-150 hover:opacity-100",
4442
+ defaultClassNames.button_previous
4443
+ ),
4444
+ button_next: cn(
4445
+ buttonVariants({ variant: buttonVariant }),
4446
+ "size-7 p-0 select-none opacity-50 aria-disabled:opacity-30 transition-opacity duration-150 hover:opacity-100",
4447
+ defaultClassNames.button_next
4448
+ ),
4449
+ month_caption: cn(
4450
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size) tracking-tight",
4451
+ defaultClassNames.month_caption
4452
+ ),
4453
+ dropdowns: cn(
4454
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-semibold",
4455
+ defaultClassNames.dropdowns
4456
+ ),
4457
+ dropdown_root: cn(
4458
+ "relative rounded-(--cell-radius)",
4459
+ defaultClassNames.dropdown_root
4460
+ ),
4461
+ dropdown: cn("absolute inset-0 bg-popover opacity-0", defaultClassNames.dropdown),
4462
+ caption_label: cn(
4463
+ "font-semibold select-none",
4464
+ captionLayout === "label" ? "text-sm" : "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
4465
+ defaultClassNames.caption_label
4466
+ ),
4467
+ weekdays: cn("flex gap-1", defaultClassNames.weekdays),
4468
+ weekday: cn(
4469
+ "flex-1 rounded-(--cell-radius) text-[0.75rem] font-semibold text-muted-foreground/70 select-none tracking-wide",
4470
+ defaultClassNames.weekday
4471
+ ),
4472
+ week: cn("mt-2 flex w-full gap-1", defaultClassNames.week),
4473
+ week_number_header: cn(
4474
+ "w-(--cell-size) select-none",
4475
+ defaultClassNames.week_number_header
4476
+ ),
4477
+ week_number: cn(
4478
+ "text-[0.75rem] text-muted-foreground/50 select-none",
4479
+ defaultClassNames.week_number
4480
+ ),
4481
+ day: cn(
4482
+ "group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)",
4483
+ props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)" : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)",
4484
+ defaultClassNames.day
4485
+ ),
4486
+ range_start: cn(
4487
+ "relative isolate z-0 rounded-l-md bg-primary/8 after:absolute after:inset-y-0 after:right-0 after:w-3 after:bg-primary/8",
4488
+ defaultClassNames.range_start
4124
4489
  ),
4125
- style: { backgroundColor: hex },
4126
- onClick: () => {
4127
- const color = Color(hex);
4128
- const [h, s, l] = color.hsl().array();
4129
- setHue(h);
4130
- setSaturation(s);
4131
- setLightness(l);
4132
- setAlpha(100);
4133
- },
4134
- "aria-label": hex,
4135
- title: hex
4490
+ range_middle: cn("rounded-none bg-primary/8", defaultClassNames.range_middle),
4491
+ range_end: cn(
4492
+ "relative isolate z-0 rounded-r-md bg-primary/8 after:absolute after:inset-y-0 after:left-0 after:w-3 after:bg-primary/8",
4493
+ defaultClassNames.range_end
4494
+ ),
4495
+ today: cn("rounded-md bg-accent text-accent-foreground", defaultClassNames.today),
4496
+ outside: cn(
4497
+ "text-muted-foreground/50 aria-selected:text-muted-foreground/50",
4498
+ defaultClassNames.outside
4499
+ ),
4500
+ disabled: cn("text-muted-foreground/40 opacity-50", defaultClassNames.disabled),
4501
+ hidden: cn("invisible", defaultClassNames.hidden),
4502
+ ...classNames
4136
4503
  },
4137
- hex
4138
- );
4139
- }) });
4140
- };
4141
- ColorPickerPresets.displayName = "ColorPickerPresets";
4142
- function DatePicker({
4143
- mode = "single",
4144
- selected,
4145
- onSelect,
4146
- placeholder = "Pick a date",
4147
- disabled = false,
4504
+ modifiersClassNames: {
4505
+ preview_start: "relative isolate z-0 rounded-l-md bg-primary/8 after:absolute after:inset-y-0 after:right-0 after:w-3 after:bg-primary/8",
4506
+ preview_middle: "rounded-none bg-primary/8",
4507
+ preview_end: "relative isolate z-0 rounded-r-md bg-primary/8 after:absolute after:inset-y-0 after:left-0 after:w-3 after:bg-primary/8",
4508
+ ...modifiersClassNames
4509
+ },
4510
+ components: resolvedComponents,
4511
+ ...props
4512
+ }
4513
+ );
4514
+ }
4515
+ function CalendarDayButton({
4148
4516
  className,
4149
- fromDate,
4150
- toDate
4517
+ day,
4518
+ modifiers,
4519
+ locale,
4520
+ ...props
4151
4521
  }) {
4522
+ const defaultClassNames = getDefaultClassNames();
4523
+ const ref = useRef(null);
4524
+ useEffect(() => {
4525
+ if (modifiers.focused) ref.current?.focus();
4526
+ }, [modifiers.focused]);
4527
+ const isPreviewEdge = Boolean(
4528
+ (modifiers.preview_start || modifiers.preview_end) && !modifiers.selected
4529
+ );
4530
+ return /* @__PURE__ */ jsx(
4531
+ Button,
4532
+ {
4533
+ ref,
4534
+ variant: "ghost",
4535
+ size: "icon-sm",
4536
+ "data-day": day.date.toLocaleDateString(locale?.code),
4537
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
4538
+ "data-range-start": modifiers.range_start,
4539
+ "data-range-end": modifiers.range_end,
4540
+ "data-range-middle": modifiers.range_middle,
4541
+ "data-preview-middle": Boolean(modifiers.preview_middle),
4542
+ "data-preview-edge": isPreviewEdge,
4543
+ className: cn(
4544
+ "group-data-[focused=true]/day:ring-primary/40 data-[preview-edge=true]:ring-primary/50 data-[preview-edge=true]:text-primary data-[preview-middle=true]:text-primary data-[range-end=true]:!bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:!bg-primary/8 data-[range-middle=true]:text-foreground data-[range-start=true]:!bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:!bg-primary data-[selected-single=true]:text-primary-foreground relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 !rounded-md border-0 !bg-transparent leading-none font-normal transition-colors duration-150 group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:rounded-md group-data-[focused=true]/day:ring-[2px] hover:!bg-transparent data-[preview-edge=true]:rounded-md data-[preview-edge=true]:font-medium data-[preview-edge=true]:ring-[2px] data-[preview-middle=true]:font-medium data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[selected-single=true]:rounded-md [&>span]:text-xs [&>span]:font-medium [&>span]:opacity-75",
4545
+ defaultClassNames.day,
4546
+ className
4547
+ ),
4548
+ ...props
4549
+ }
4550
+ );
4551
+ }
4552
+ function DatePicker(props) {
4553
+ const {
4554
+ placeholder = "Pick a date",
4555
+ disabled = false,
4556
+ className,
4557
+ fromDate,
4558
+ toDate,
4559
+ numberOfMonths = 1
4560
+ } = props;
4152
4561
  const [open, setOpen] = useState(false);
4562
+ const [awaitingRangeEnd, setAwaitingRangeEnd] = useState(false);
4563
+ const [previewDate, setPreviewDate] = useState(void 0);
4153
4564
  const label = useMemo(() => {
4154
- if (mode === "range") {
4155
- const range = selected;
4156
- if (range?.from && range?.to)
4157
- return `${format(range.from, "MMM d, yyyy")} \u2013 ${format(range.to, "MMM d, yyyy")}`;
4158
- if (range?.from) return `${format(range.from, "MMM d, yyyy")} \u2013 \u2026`;
4159
- return placeholder;
4160
- }
4161
- const date = selected;
4162
- return date ? format(date, "MMM d, yyyy") : placeholder;
4163
- }, [mode, selected, placeholder]);
4164
- const hasValue = mode === "range" ? !!selected?.from : !!selected;
4165
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
4565
+ if (props.mode === "range") {
4566
+ const range = props.selected;
4567
+ if (!range?.from) return placeholder;
4568
+ if (!range.to) return `${format(range.from, "MMM d, yyyy")} \u2013 \u2026`;
4569
+ return `${format(range.from, "MMM d, yyyy")} \u2013 ${format(range.to, "MMM d, yyyy")}`;
4570
+ }
4571
+ return props.selected ? format(props.selected, "MMM d, yyyy") : placeholder;
4572
+ }, [props.mode, props.selected, placeholder]);
4573
+ const handleOpenChange = (nextOpen) => {
4574
+ setOpen(nextOpen);
4575
+ if (!nextOpen) {
4576
+ setAwaitingRangeEnd(false);
4577
+ setPreviewDate(void 0);
4578
+ }
4579
+ };
4580
+ const handleRangeSelect = (range, triggerDate) => {
4581
+ if (props.mode !== "range") return;
4582
+ const emit = props.onSelect;
4583
+ if (!awaitingRangeEnd) {
4584
+ setAwaitingRangeEnd(true);
4585
+ emit?.({ from: triggerDate, to: void 0 });
4586
+ return;
4587
+ }
4588
+ emit?.(range);
4589
+ if (!range?.from || !range.to) {
4590
+ setAwaitingRangeEnd(!!range?.from);
4591
+ return;
4592
+ }
4593
+ setAwaitingRangeEnd(false);
4594
+ setPreviewDate(void 0);
4595
+ setOpen(false);
4596
+ };
4597
+ const rangeFrom = props.mode === "range" ? props.selected?.from : void 0;
4598
+ const previewModifiers = useMemo(() => {
4599
+ if (!awaitingRangeEnd || !rangeFrom || !previewDate) return void 0;
4600
+ if (isSameDay(rangeFrom, previewDate)) return void 0;
4601
+ const [start, end] = previewDate < rangeFrom ? [previewDate, rangeFrom] : [rangeFrom, previewDate];
4602
+ return {
4603
+ preview_start: start,
4604
+ preview_middle: { after: start, before: end },
4605
+ preview_end: end
4606
+ };
4607
+ }, [awaitingRangeEnd, rangeFrom, previewDate]);
4608
+ const handleDayPreview = (day, dayModifiers) => {
4609
+ if (!awaitingRangeEnd) return;
4610
+ if (dayModifiers.disabled || dayModifiers.hidden) return;
4611
+ setPreviewDate((current) => current && isSameDay(current, day) ? current : day);
4612
+ };
4613
+ const dateConstraints = useMemo(() => {
4614
+ const disabledMatchers = [];
4615
+ if (fromDate) disabledMatchers.push({ before: fromDate });
4616
+ if (toDate) disabledMatchers.push({ after: toDate });
4617
+ return {
4618
+ ...disabledMatchers.length > 0 && { disabled: disabledMatchers },
4619
+ ...fromDate && { startMonth: fromDate },
4620
+ ...toDate && { endMonth: toDate }
4621
+ };
4622
+ }, [fromDate, toDate]);
4623
+ const hasValue = props.mode === "range" ? !!props.selected?.from : !!props.selected;
4624
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
4166
4625
  /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
4167
4626
  Button,
4168
4627
  {
@@ -4180,36 +4639,36 @@ function DatePicker({
4180
4639
  ]
4181
4640
  }
4182
4641
  ) }),
4183
- /* @__PURE__ */ jsx(PopoverContent, { "data-slot": "date-picker-content", className: "w-auto p-0", align: "start", children: mode === "range" ? /* @__PURE__ */ jsx(
4184
- Calendar,
4185
- {
4186
- ...{
4642
+ /* @__PURE__ */ jsx(PopoverContent, { "data-slot": "date-picker-content", className: "w-auto p-0", align: "start", children: props.mode === "range" ? (
4643
+ // Clearing the preview on the wrapper instead of per day
4644
+ // avoids the blank frame `onDayMouseLeave` would cause when
4645
+ // the pointer travels from one day to the next.
4646
+ /* @__PURE__ */ jsx("div", { onMouseLeave: () => setPreviewDate(void 0), children: /* @__PURE__ */ jsx(
4647
+ Calendar,
4648
+ {
4187
4649
  mode: "range",
4188
- selected,
4189
- onSelect: (range) => {
4190
- onSelect?.(range);
4191
- if (range?.to) setOpen(false);
4192
- },
4193
- fromDate,
4194
- toDate,
4195
- numberOfMonths: 2,
4196
- initialFocus: true
4650
+ selected: props.selected,
4651
+ onSelect: handleRangeSelect,
4652
+ modifiers: previewModifiers,
4653
+ onDayMouseEnter: handleDayPreview,
4654
+ onDayFocus: handleDayPreview,
4655
+ numberOfMonths,
4656
+ autoFocus: true,
4657
+ ...dateConstraints
4197
4658
  }
4198
- }
4659
+ ) })
4199
4660
  ) : /* @__PURE__ */ jsx(
4200
4661
  Calendar,
4201
4662
  {
4202
- ...{
4203
- mode: "single",
4204
- selected,
4205
- onSelect: (date) => {
4206
- onSelect?.(date);
4207
- setOpen(false);
4208
- },
4209
- fromDate,
4210
- toDate,
4211
- initialFocus: true
4212
- }
4663
+ mode: "single",
4664
+ selected: props.selected,
4665
+ onSelect: (date) => {
4666
+ props.onSelect?.(date);
4667
+ setOpen(false);
4668
+ },
4669
+ numberOfMonths,
4670
+ autoFocus: true,
4671
+ ...dateConstraints
4213
4672
  }
4214
4673
  ) })
4215
4674
  ] });
@@ -4334,6 +4793,7 @@ var Navbar = forwardRef(
4334
4793
  notifications,
4335
4794
  avatarSrc,
4336
4795
  avatarFallback,
4796
+ showUtilityBar = true,
4337
4797
  onNavLinkClick,
4338
4798
  onSearchClick,
4339
4799
  onHelpClick,
@@ -4405,7 +4865,7 @@ var Navbar = forwardRef(
4405
4865
  ] }),
4406
4866
  /* @__PURE__ */ jsx("nav", { className: "ml-auto flex h-full items-center", children: navigationLinks.map((link, i) => /* @__PURE__ */ jsx(NavLinkItem, { link, onNavLinkClick }, i)) })
4407
4867
  ] }) }),
4408
- /* @__PURE__ */ jsx("div", { className: "bg-background border-border border-b px-4 md:px-6", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex h-9 max-w-screen-2xl items-center justify-between", children: [
4868
+ showUtilityBar && /* @__PURE__ */ jsx("div", { className: "bg-background border-border border-b px-4 md:px-6", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex h-9 max-w-screen-2xl items-center justify-between", children: [
4409
4869
  /* @__PURE__ */ jsx("nav", { className: "flex items-center", children: utilityLinks.map((link, i) => /* @__PURE__ */ jsxs(Fragment, { children: [
4410
4870
  i > 0 && /* @__PURE__ */ jsx("span", { className: "text-border mx-3 select-none", children: "|" }),
4411
4871
  /* @__PURE__ */ jsx(
@@ -4650,6 +5110,8 @@ function NavigationMenuIndicator({
4650
5110
  }
4651
5111
  );
4652
5112
  }
5113
+
5114
+ // src/components/authorization/policy.ts
4653
5115
  function matchPermission(pattern, permission) {
4654
5116
  if (pattern === "*") return true;
4655
5117
  if (pattern === permission) return true;
@@ -4665,41 +5127,46 @@ function matchesAny(permissionSet, permission) {
4665
5127
  }
4666
5128
  return false;
4667
5129
  }
5130
+ function can(permissionSet, perms, mode = "any") {
5131
+ const list = Array.isArray(perms) ? perms : [perms];
5132
+ if (list.length === 0) return false;
5133
+ if (permissionSet.has("*")) return true;
5134
+ if (mode === "all") {
5135
+ return list.every((p) => matchesAny(permissionSet, p));
5136
+ }
5137
+ return list.some((p) => matchesAny(permissionSet, p));
5138
+ }
4668
5139
  var AbilityContext = createContext(void 0);
4669
5140
  AbilityContext.displayName = "AbilityContext";
4670
5141
  function AbilityProvider({ children, permissions }) {
4671
5142
  const [permissionSet, setPermissionSet] = useState(
4672
5143
  () => new Set(permissions ?? [])
4673
5144
  );
4674
- const can = useCallback(
4675
- (perms, mode = "any") => {
4676
- const list = Array.isArray(perms) ? perms : [perms];
4677
- if (list.length === 0) return false;
4678
- if (permissionSet.has("*")) return true;
4679
- if (mode === "all") {
4680
- return list.every((p) => matchesAny(permissionSet, p));
4681
- }
4682
- return list.some((p) => matchesAny(permissionSet, p));
4683
- },
5145
+ const [imperativelyResolved, setImperativelyResolved] = useState(false);
5146
+ const status = permissions !== void 0 || imperativelyResolved ? "ready" : "loading";
5147
+ const can2 = useCallback(
5148
+ (perms, mode = "any") => can(permissionSet, perms, mode),
4684
5149
  [permissionSet]
4685
5150
  );
4686
5151
  const setAbilities = useCallback((perms) => {
4687
5152
  setPermissionSet(new Set(perms));
5153
+ setImperativelyResolved(true);
4688
5154
  }, []);
4689
5155
  const clearAbilities = useCallback(() => {
4690
5156
  setPermissionSet(/* @__PURE__ */ new Set());
5157
+ setImperativelyResolved(true);
4691
5158
  }, []);
4692
- const syncedKey = useRef(permissions ? permissions.join("|") : null);
5159
+ const permissionKey = permissions === void 0 ? null : [...permissions].sort().join("|");
5160
+ const syncedKey = useRef(permissionKey);
4693
5161
  useEffect(() => {
4694
- if (permissions === void 0) return;
4695
- const key = permissions.join("|");
4696
- if (key === syncedKey.current) return;
4697
- syncedKey.current = key;
5162
+ if (permissionKey === null) return;
5163
+ if (permissionKey === syncedKey.current) return;
5164
+ syncedKey.current = permissionKey;
4698
5165
  setPermissionSet(new Set(permissions));
4699
- }, [permissions]);
5166
+ }, [permissionKey, permissions]);
4700
5167
  const value = useMemo(
4701
- () => ({ can, setAbilities, clearAbilities }),
4702
- [can, setAbilities, clearAbilities]
5168
+ () => ({ can: can2, setAbilities, clearAbilities, status }),
5169
+ [can2, setAbilities, clearAbilities, status]
4703
5170
  );
4704
5171
  return /* @__PURE__ */ jsx(AbilityContext.Provider, { value, children });
4705
5172
  }
@@ -4711,36 +5178,194 @@ function useAbility() {
4711
5178
  return context;
4712
5179
  }
4713
5180
  function useCan(permissions, mode = "any") {
4714
- const { can } = useAbility();
4715
- return can(permissions, mode);
5181
+ const { can: can2 } = useAbility();
5182
+ return can2(permissions, mode);
5183
+ }
5184
+ function useAbilityStatus() {
5185
+ return useAbility().status;
5186
+ }
5187
+
5188
+ // src/components/authorization/permissions.generated.ts
5189
+ var KNOWN_PERMISSIONS = [];
5190
+
5191
+ // src/components/authorization/permission-catalog.ts
5192
+ var CATALOG = new Set(KNOWN_PERMISSIONS);
5193
+ var warned = /* @__PURE__ */ new Set();
5194
+ function warnUnknownPermission(permission) {
5195
+ if (process.env.NODE_ENV === "production") return;
5196
+ if (CATALOG.size === 0) return;
5197
+ const requested = Array.isArray(permission) ? permission : [permission];
5198
+ for (const entry of requested) {
5199
+ if (entry.includes("*")) continue;
5200
+ if (CATALOG.has(entry) || warned.has(entry)) continue;
5201
+ warned.add(entry);
5202
+ console.warn(
5203
+ `[Can] Unknown permission "${entry}". It is not in the generated permission catalog. Check for a typo, or regenerate the catalog with \`pnpm generate-permissions\`.`
5204
+ );
5205
+ }
5206
+ }
5207
+ var FOCUS_TRAVERSAL_KEYS = /* @__PURE__ */ new Set(["Tab", "Escape"]);
5208
+ function blockInteraction(event) {
5209
+ event.preventDefault();
5210
+ event.stopPropagation();
5211
+ }
5212
+ function blockNonTraversalKey(event) {
5213
+ if (!FOCUS_TRAVERSAL_KEYS.has(event.key)) blockInteraction(event);
5214
+ }
5215
+ var warnedRenderPropMisuse = /* @__PURE__ */ new Set();
5216
+ function warnRenderPropVoidsProps(voided) {
5217
+ if (process.env.NODE_ENV === "production") return;
5218
+ if (voided.length === 0) return;
5219
+ const key = voided.join(",");
5220
+ if (warnedRenderPropMisuse.has(key)) return;
5221
+ warnedRenderPropMisuse.add(key);
5222
+ console.warn(
5223
+ `[Can] \`children\` is a function, so ${voided.map((prop) => `\`${prop}\``).join(", ")} ${voided.length === 1 ? "is" : "are"} ignored. A render prop owns every state: read \`allowed\` and \`status\` and render the disabled, loading and denied cases yourself, or pass an element instead of a function.`
5224
+ );
5225
+ }
5226
+ function disableElement(child) {
5227
+ return cloneElement(child, {
5228
+ "aria-disabled": "true",
5229
+ className: cn(child.props.className, "cursor-not-allowed opacity-50"),
5230
+ onClickCapture: blockInteraction,
5231
+ onKeyDownCapture: blockNonTraversalKey,
5232
+ onKeyUpCapture: blockNonTraversalKey,
5233
+ onPointerDownCapture: blockInteraction,
5234
+ onMouseDownCapture: blockInteraction
5235
+ });
5236
+ }
5237
+ function InteractionFirewall({ children }) {
5238
+ return /* @__PURE__ */ jsx(
5239
+ "span",
5240
+ {
5241
+ "data-slot": "can-blocked",
5242
+ className: "contents",
5243
+ onClickCapture: blockInteraction,
5244
+ onPointerDownCapture: blockInteraction,
5245
+ onMouseDownCapture: blockInteraction,
5246
+ onKeyDownCapture: blockNonTraversalKey,
5247
+ onKeyUpCapture: blockNonTraversalKey,
5248
+ children
5249
+ }
5250
+ );
5251
+ }
5252
+ function DisabledSubtree({
5253
+ children,
5254
+ className,
5255
+ ...props
5256
+ }) {
5257
+ const { "data-slot": _incomingDataSlot, ...restProps } = props;
5258
+ return /* @__PURE__ */ jsx(
5259
+ "span",
5260
+ {
5261
+ "data-slot": "can-disabled",
5262
+ "aria-disabled": "true",
5263
+ className: cn(
5264
+ "inline-flex cursor-not-allowed opacity-50",
5265
+ "*:pointer-events-none",
5266
+ className
5267
+ ),
5268
+ onClickCapture: blockInteraction,
5269
+ onPointerDownCapture: blockInteraction,
5270
+ onMouseDownCapture: blockInteraction,
5271
+ onKeyDownCapture: blockNonTraversalKey,
5272
+ onKeyUpCapture: blockNonTraversalKey,
5273
+ ...restProps,
5274
+ children
5275
+ }
5276
+ );
4716
5277
  }
4717
- function Can({ permission, mode = "any", negate = false, fallback = null, children }) {
4718
- const { can } = useAbility();
4719
- const hasPermission = can(permission, mode);
5278
+ function Can({
5279
+ permission,
5280
+ mode = "any",
5281
+ negate = false,
5282
+ behavior = "hide",
5283
+ reason = null,
5284
+ fallback = null,
5285
+ loading,
5286
+ children
5287
+ }) {
5288
+ warnUnknownPermission(permission);
5289
+ const { can: can2, status } = useAbility();
5290
+ const hasPermission = status === "ready" && can2(permission, mode);
4720
5291
  const show = negate ? !hasPermission : hasPermission;
4721
5292
  if (typeof children === "function") {
4722
- return /* @__PURE__ */ jsx(Fragment$1, { children: children(show) });
5293
+ warnRenderPropVoidsProps([
5294
+ ...behavior === "disable" ? ["behavior='disable'"] : [],
5295
+ ...reason !== null ? ["reason"] : [],
5296
+ ...fallback !== null ? ["fallback"] : [],
5297
+ ...loading !== void 0 ? ["loading"] : []
5298
+ ]);
5299
+ return /* @__PURE__ */ jsx(Fragment$1, { children: children({ allowed: show, status }) });
5300
+ }
5301
+ if (status === "loading" && loading !== void 0) {
5302
+ return /* @__PURE__ */ jsx(Fragment$1, { children: loading });
4723
5303
  }
4724
- return show ? /* @__PURE__ */ jsx(Fragment$1, { children }) : /* @__PURE__ */ jsx(Fragment$1, { children: fallback });
5304
+ if (show) {
5305
+ return /* @__PURE__ */ jsx(Fragment$1, { children });
5306
+ }
5307
+ if (behavior === "disable") {
5308
+ if (isValidElement(children) && children.type !== Fragment) {
5309
+ const disabledChild = disableElement(children);
5310
+ if (reason === null) {
5311
+ return /* @__PURE__ */ jsx(InteractionFirewall, { children: disabledChild });
5312
+ }
5313
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
5314
+ /* @__PURE__ */ jsx(InteractionFirewall, { children: /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: disabledChild }) }),
5315
+ /* @__PURE__ */ jsx(TooltipContent, { children: reason })
5316
+ ] });
5317
+ }
5318
+ if (reason === null) {
5319
+ return /* @__PURE__ */ jsx(DisabledSubtree, { children });
5320
+ }
5321
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
5322
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DisabledSubtree, { children }) }),
5323
+ /* @__PURE__ */ jsx(TooltipContent, { children: reason })
5324
+ ] });
5325
+ }
5326
+ return /* @__PURE__ */ jsx(Fragment$1, { children: fallback });
4725
5327
  }
4726
5328
  Can.displayName = "Can";
4727
- function CanNot({ permission, mode = "any", fallback = null, children }) {
4728
- return /* @__PURE__ */ jsx(Can, { permission, mode, negate: true, fallback, children });
5329
+ function CanNot({
5330
+ permission,
5331
+ mode = "any",
5332
+ behavior = "hide",
5333
+ reason = null,
5334
+ fallback = null,
5335
+ loading,
5336
+ children
5337
+ }) {
5338
+ return /* @__PURE__ */ jsx(
5339
+ Can,
5340
+ {
5341
+ permission,
5342
+ mode,
5343
+ negate: true,
5344
+ behavior,
5345
+ reason,
5346
+ fallback,
5347
+ loading,
5348
+ children
5349
+ }
5350
+ );
4729
5351
  }
4730
5352
  CanNot.displayName = "CanNot";
4731
- var MOBILE_BREAKPOINT = 768;
4732
- function useIsMobile() {
4733
- const [isMobile, setIsMobile] = useState(void 0);
5353
+ function useMediaQuery(query) {
5354
+ const [matches, setMatches] = useState(false);
4734
5355
  useEffect(() => {
4735
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
4736
- const onChange = () => {
4737
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
4738
- };
4739
- mql.addEventListener("change", onChange);
4740
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
4741
- return () => mql.removeEventListener("change", onChange);
4742
- }, []);
4743
- return !!isMobile;
5356
+ if (typeof window === "undefined") return;
5357
+ const mql = window.matchMedia(query);
5358
+ setMatches(mql.matches);
5359
+ const handler = (e) => setMatches(e.matches);
5360
+ mql.addEventListener("change", handler);
5361
+ return () => mql.removeEventListener("change", handler);
5362
+ }, [query]);
5363
+ return matches;
5364
+ }
5365
+
5366
+ // src/hooks/use-mobile.ts
5367
+ function useIsMobile() {
5368
+ return useMediaQuery("(max-width: 767px)");
4744
5369
  }
4745
5370
  function Sheet({ ...props }) {
4746
5371
  return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "sheet", ...props });
@@ -4933,6 +5558,39 @@ function SidebarProvider({
4933
5558
  }
4934
5559
  ) });
4935
5560
  }
5561
+ function SidebarResizeHandle() {
5562
+ const dragRef = useRef(null);
5563
+ return /* @__PURE__ */ jsx(
5564
+ "div",
5565
+ {
5566
+ "data-slot": "sidebar-resize-handle",
5567
+ className: "absolute inset-y-0 right-0 w-1 cursor-col-resize opacity-0 transition-opacity hover:opacity-100 hover:bg-sidebar-border group-data-[state=collapsed]:hidden",
5568
+ onPointerDown: (e) => {
5569
+ e.preventDefault();
5570
+ const wrapper = e.currentTarget.closest('[data-slot="sidebar-wrapper"]');
5571
+ if (!wrapper) return;
5572
+ const container = e.currentTarget.closest('[data-slot="sidebar-container"]');
5573
+ const gap = container?.parentElement?.querySelector('[data-slot="sidebar-gap"]') ?? null;
5574
+ const currentWidth = container ? parseFloat(getComputedStyle(container).width) : 256;
5575
+ if (container) container.style.transition = "none";
5576
+ if (gap) gap.style.transition = "none";
5577
+ dragRef.current = { startX: e.clientX, startWidth: currentWidth, wrapper, container: container ?? null, gap };
5578
+ e.currentTarget.setPointerCapture(e.pointerId);
5579
+ },
5580
+ onPointerMove: (e) => {
5581
+ if (!dragRef.current) return;
5582
+ const { startX, startWidth, wrapper } = dragRef.current;
5583
+ const newWidth = Math.max(160, Math.min(480, startWidth + (e.clientX - startX)));
5584
+ wrapper.style.setProperty("--sidebar-width", `${newWidth}px`);
5585
+ },
5586
+ onPointerUp: () => {
5587
+ if (dragRef.current?.container) dragRef.current.container.style.transition = "";
5588
+ if (dragRef.current?.gap) dragRef.current.gap.style.transition = "";
5589
+ dragRef.current = null;
5590
+ }
5591
+ }
5592
+ );
5593
+ }
4936
5594
  function Sidebar({
4937
5595
  side = "left",
4938
5596
  variant = "sidebar",
@@ -5003,7 +5661,7 @@ function Sidebar({
5003
5661
  )
5004
5662
  }
5005
5663
  ),
5006
- /* @__PURE__ */ jsx(
5664
+ /* @__PURE__ */ jsxs(
5007
5665
  "div",
5008
5666
  {
5009
5667
  "data-slot": "sidebar-container",
@@ -5015,15 +5673,18 @@ function Sidebar({
5015
5673
  className
5016
5674
  ),
5017
5675
  ...props,
5018
- children: /* @__PURE__ */ jsx(
5019
- "div",
5020
- {
5021
- "data-sidebar": "sidebar",
5022
- "data-slot": "sidebar-inner",
5023
- className: "bg-sidebar group-data-[variant=floating]:ring-sidebar-border flex size-full flex-col group-data-[variant=floating]:rounded-2xl group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1",
5024
- children
5025
- }
5026
- )
5676
+ children: [
5677
+ /* @__PURE__ */ jsx(
5678
+ "div",
5679
+ {
5680
+ "data-sidebar": "sidebar",
5681
+ "data-slot": "sidebar-inner",
5682
+ className: "bg-sidebar group-data-[variant=floating]:ring-sidebar-border flex size-full flex-col group-data-[variant=floating]:rounded-2xl group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1",
5683
+ children
5684
+ }
5685
+ ),
5686
+ /* @__PURE__ */ jsx(SidebarResizeHandle, {})
5687
+ ]
5027
5688
  }
5028
5689
  )
5029
5690
  ]
@@ -5140,7 +5801,7 @@ function SidebarContent({ className, ...props }) {
5140
5801
  "data-slot": "sidebar-content",
5141
5802
  "data-sidebar": "content",
5142
5803
  className: cn(
5143
- "no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-auto [--radius:var(--radius-xl)] group-data-[collapsible=icon]:overflow-hidden",
5804
+ "no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto overflow-x-hidden [--radius:var(--radius-xl)] group-data-[collapsible=icon]:overflow-hidden",
5144
5805
  className
5145
5806
  ),
5146
5807
  ...props
@@ -5435,6 +6096,7 @@ function AppShell({
5435
6096
  onItemClick,
5436
6097
  brandName = "Total Portal",
5437
6098
  showHeader = true,
6099
+ header,
5438
6100
  open,
5439
6101
  onOpenChange,
5440
6102
  defaultOpen,
@@ -5455,7 +6117,7 @@ function AppShell({
5455
6117
  /* @__PURE__ */ jsx(SidebarTrigger, { variant: "ghost", className: "size-8 shrink-0" }),
5456
6118
  /* @__PURE__ */ jsx(SidebarBrand, { brandName })
5457
6119
  ] }),
5458
- /* @__PURE__ */ jsx(SidebarContent, { children: /* @__PURE__ */ jsx(SidebarGroup, { children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: items.map((item) => {
6120
+ /* @__PURE__ */ jsx(SidebarContent, { className: "overflow-x:hidden", children: /* @__PURE__ */ jsx(SidebarGroup, { children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: items.map((item) => {
5459
6121
  const menuItem = /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
5460
6122
  SidebarMenuButton,
5461
6123
  {
@@ -5484,7 +6146,7 @@ function AppShell({
5484
6146
  }) }) }) }) })
5485
6147
  ] }),
5486
6148
  /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
5487
- showHeader ? /* @__PURE__ */ jsxs("header", { className: "flex h-14 items-center gap-2 border-b px-4", children: [
6149
+ header ? header : showHeader ? /* @__PURE__ */ jsxs("header", { className: "flex h-14 items-center gap-2 border-b px-4", children: [
5488
6150
  /* @__PURE__ */ jsx(SidebarTrigger, { variant: "ghost", className: "size-8 shrink-0 md:hidden" }),
5489
6151
  /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: brandName })
5490
6152
  ] }) : /* @__PURE__ */ jsx(SidebarTrigger, { variant: "ghost", className: "size-8 shrink-0 md:hidden" }),
@@ -6098,14 +6760,9 @@ var eventCalendarStyles = `
6098
6760
  font-weight: 600;
6099
6761
  }
6100
6762
 
6101
- /* \u2500\u2500 Event modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
6763
+ /* \u2500\u2500 Event modal \u2014 hidden; replaced by TCCE Popover in event-calendar.tsx \u2500\u2500 */
6102
6764
  .sx-tcce .sx__event-modal {
6103
- border-radius: var(--border-radius-article, 0.875rem);
6104
- border: 1px solid var(--color-border);
6105
- font-size: 13px;
6106
- min-width: 220px;
6107
- max-width: 300px;
6108
- background: var(--color-background);
6765
+ display: none !important;
6109
6766
  }
6110
6767
  .sx-tcce .sx__event-modal__title {
6111
6768
  font-size: 14px;
@@ -6250,8 +6907,43 @@ function useEventCalendar({
6250
6907
  return () => unsubscribe?.();
6251
6908
  }, []);
6252
6909
  return {
6253
- calendarApp: calendarApp.current
6910
+ calendarApp: calendarApp.current,
6911
+ eventModal: eventModal.current
6912
+ };
6913
+ }
6914
+ var EVENT_COLOR = {
6915
+ default: "#22205f",
6916
+ primary: "#22205f",
6917
+ success: "#00a824",
6918
+ warning: "#c8a23b",
6919
+ danger: "#ea3a3d"
6920
+ };
6921
+ function getFixedAnchorRect(el) {
6922
+ const rect = el.getBoundingClientRect();
6923
+ let ancestor = el.parentElement;
6924
+ while (ancestor && ancestor !== document.documentElement) {
6925
+ if (window.getComputedStyle(ancestor).transform !== "none") {
6926
+ const cb = ancestor.getBoundingClientRect();
6927
+ return new DOMRect(rect.left - cb.left, rect.top - cb.top, rect.width, rect.height);
6928
+ }
6929
+ ancestor = ancestor.parentElement;
6930
+ }
6931
+ return rect;
6932
+ }
6933
+ function formatEventTime(start, end) {
6934
+ const isAllDay = start.length === 10;
6935
+ if (isAllDay) {
6936
+ const date = /* @__PURE__ */ new Date(`${start}T00:00:00`);
6937
+ return date.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
6938
+ }
6939
+ const fmt = (s) => {
6940
+ const [, time] = s.split(" ");
6941
+ const [h, m] = time.split(":").map(Number);
6942
+ const ampm = h >= 12 ? "PM" : "AM";
6943
+ const hour = h % 12 || 12;
6944
+ return `${hour}:${m.toString().padStart(2, "0")} ${ampm}`;
6254
6945
  };
6946
+ return `${fmt(start)} \u2013 ${fmt(end)}`;
6255
6947
  }
6256
6948
  function EventCalendar({
6257
6949
  events,
@@ -6264,26 +6956,116 @@ function EventCalendar({
6264
6956
  className
6265
6957
  }) {
6266
6958
  const [currentView, setCurrentView] = useState(defaultView);
6959
+ const [selectedEvent, setSelectedEvent] = useState(null);
6960
+ const [anchorRect, setAnchorRect] = useState(null);
6961
+ const clickedEventElRef = useRef(false);
6267
6962
  const handleViewChange = useCallback(
6268
6963
  (view) => {
6269
6964
  setCurrentView(view);
6270
6965
  onViewChange?.(view);
6271
6966
  },
6272
- [onViewChange]
6967
+ [onViewChange]
6968
+ );
6969
+ const handleEventClick = useCallback(
6970
+ (event) => {
6971
+ setSelectedEvent(event);
6972
+ onEventClick?.(event);
6973
+ },
6974
+ [onEventClick]
6975
+ );
6976
+ const { calendarApp, eventModal } = useEventCalendar({
6977
+ events,
6978
+ defaultView,
6979
+ defaultDate,
6980
+ locale,
6981
+ onEventClick: handleEventClick,
6982
+ onEventCreate,
6983
+ onViewChange: handleViewChange
6984
+ });
6985
+ useEffect(() => {
6986
+ const unsub = eventModal.calendarEventElement.subscribe((el) => {
6987
+ if (!el) {
6988
+ if (clickedEventElRef.current) {
6989
+ clickedEventElRef.current = false;
6990
+ } else {
6991
+ setSelectedEvent(null);
6992
+ setAnchorRect(null);
6993
+ }
6994
+ } else {
6995
+ setAnchorRect(getFixedAnchorRect(el));
6996
+ }
6997
+ });
6998
+ return unsub;
6999
+ }, [eventModal]);
7000
+ const handlePopoverOpenChange = useCallback(
7001
+ (open) => {
7002
+ if (!open) {
7003
+ eventModal.close();
7004
+ setSelectedEvent(null);
7005
+ setAnchorRect(null);
7006
+ }
7007
+ },
7008
+ [eventModal]
6273
7009
  );
6274
- const { calendarApp } = useEventCalendar({
6275
- events,
6276
- defaultView,
6277
- defaultDate,
6278
- locale,
6279
- onEventClick,
6280
- onEventCreate,
6281
- onViewChange: handleViewChange
6282
- });
6283
7010
  const contextValue = useMemo(() => ({ currentView }), [currentView]);
6284
7011
  return /* @__PURE__ */ jsxs(EventCalendarContext.Provider, { value: contextValue, children: [
6285
7012
  /* @__PURE__ */ jsx("style", { href: "tcce-event-calendar", precedence: "default", children: eventCalendarStyles }),
6286
- /* @__PURE__ */ jsx("div", { "data-slot": "event-calendar", className: cn("sx-tcce w-full", className), children: /* @__PURE__ */ jsx(ScheduleXCalendar, { calendarApp: calendarApp ?? null }) })
7013
+ /* @__PURE__ */ jsxs(Popover, { open: !!selectedEvent && !!anchorRect, onOpenChange: handlePopoverOpenChange, children: [
7014
+ /* @__PURE__ */ jsx("div", { "data-slot": "event-calendar", className: cn("sx-tcce w-full", className), children: /* @__PURE__ */ jsx(ScheduleXCalendar, { calendarApp: calendarApp ?? null }) }),
7015
+ anchorRect && /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx(
7016
+ "span",
7017
+ {
7018
+ style: {
7019
+ position: "fixed",
7020
+ top: anchorRect.top,
7021
+ left: anchorRect.left,
7022
+ width: anchorRect.width,
7023
+ height: anchorRect.height,
7024
+ pointerEvents: "none"
7025
+ }
7026
+ }
7027
+ ) }),
7028
+ /* @__PURE__ */ jsx(
7029
+ PopoverContent,
7030
+ {
7031
+ side: "right",
7032
+ align: "start",
7033
+ className: "w-65 gap-2",
7034
+ onPointerDownOutside: (e) => {
7035
+ const target = e.target;
7036
+ const isEventEl = target.closest(
7037
+ ".sx__month-grid-event, .sx__time-grid-event, .sx__month-agenda-event"
7038
+ );
7039
+ if (isEventEl) {
7040
+ e.preventDefault();
7041
+ clickedEventElRef.current = true;
7042
+ }
7043
+ },
7044
+ children: selectedEvent && /* @__PURE__ */ jsxs(Fragment$1, { children: [
7045
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
7046
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
7047
+ /* @__PURE__ */ jsx(
7048
+ "span",
7049
+ {
7050
+ className: "size-2 shrink-0 rounded-full",
7051
+ style: {
7052
+ backgroundColor: EVENT_COLOR[selectedEvent.color ?? "default"]
7053
+ }
7054
+ }
7055
+ ),
7056
+ /* @__PURE__ */ jsx("span", { className: "font-heading text-sm font-semibold leading-tight", children: selectedEvent.title })
7057
+ ] }),
7058
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Edit event", children: /* @__PURE__ */ jsx(Pencil, { size: 14 }) })
7059
+ ] }),
7060
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
7061
+ /* @__PURE__ */ jsx(Clock, { size: 13, className: "shrink-0" }),
7062
+ /* @__PURE__ */ jsx("span", { children: formatEventTime(selectedEvent.start, selectedEvent.end) })
7063
+ ] }),
7064
+ selectedEvent.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: selectedEvent.description })
7065
+ ] })
7066
+ }
7067
+ )
7068
+ ] })
6287
7069
  ] });
6288
7070
  }
6289
7071
  function useAppForm(schema, options) {
@@ -6362,7 +7144,7 @@ function TableHead({ className, ...props }) {
6362
7144
  {
6363
7145
  "data-slot": "table-head",
6364
7146
  className: cn(
6365
- "text-foreground has([role=checkbox])]:pr-0 h-12 px-3 text-left align-middle font-medium whitespace-nowrap",
7147
+ "text-foreground has-[[role=checkbox]]:pr-0 h-12 px-3 text-left align-middle font-medium whitespace-nowrap",
6366
7148
  className
6367
7149
  ),
6368
7150
  ...props
@@ -6375,7 +7157,7 @@ function TableCell({ className, ...props }) {
6375
7157
  {
6376
7158
  "data-slot": "table-cell",
6377
7159
  className: cn(
6378
- "has([role=checkbox])]:pr-0 p-3 align-middle whitespace-nowrap",
7160
+ "has-[[role=checkbox]]:pr-0 p-3 align-middle whitespace-nowrap",
6379
7161
  className
6380
7162
  ),
6381
7163
  ...props
@@ -6625,18 +7407,6 @@ function TablePaginationBase({
6625
7407
  );
6626
7408
  }
6627
7409
  var TablePagination = memo(TablePaginationBase);
6628
- function useMediaQuery(query) {
6629
- const [matches, setMatches] = useState(false);
6630
- useEffect(() => {
6631
- if (typeof window === "undefined") return;
6632
- const mql = window.matchMedia(query);
6633
- setMatches(mql.matches);
6634
- const handler = (e) => setMatches(e.matches);
6635
- mql.addEventListener("change", handler);
6636
- return () => mql.removeEventListener("change", handler);
6637
- }, [query]);
6638
- return matches;
6639
- }
6640
7410
  var TableContext = createContext(null);
6641
7411
  function useTableContext() {
6642
7412
  const ctx = useContext(TableContext);
@@ -6648,6 +7418,13 @@ function useTableContext() {
6648
7418
  function useTableContextSafe() {
6649
7419
  return useContext(TableContext);
6650
7420
  }
7421
+
7422
+ // src/components/compounds/Table/cell-size-class.ts
7423
+ var cellSizeClass = {
7424
+ sm: "px-3 py-1.5 text-xs",
7425
+ md: "px-5 py-2.5 text-sm",
7426
+ lg: "px-6 py-3 text-sm"
7427
+ };
6651
7428
  var cardPadding = {
6652
7429
  sm: "p-3",
6653
7430
  md: "p-4",
@@ -6985,6 +7762,9 @@ function DataTableHeaderCell({ header }) {
6985
7762
  },
6986
7763
  className: cn(
6987
7764
  "bg-primary text-primary-foreground",
7765
+ // Same density padding as the body cells: without it the header
7766
+ // label and the cell value below it sit at different offsets.
7767
+ cellSizeClass[meta.size ?? tableSize],
6988
7768
  canResize && "relative",
6989
7769
  meta.align === "center" && "text-center",
6990
7770
  meta.align === "right" && "text-right",
@@ -7374,11 +8154,6 @@ function useTablePersistence({
7374
8154
  persistDensity
7375
8155
  };
7376
8156
  }
7377
- var cellSizeClass = {
7378
- sm: "px-1 py-0 text-xs",
7379
- md: "px-5 py-2.5 text-sm",
7380
- lg: "px-6 py-3 text-sm"
7381
- };
7382
8157
  function resolveClassName(value, row) {
7383
8158
  return typeof value === "function" ? value(row) : value;
7384
8159
  }
@@ -7419,6 +8194,13 @@ function DataTableCell({
7419
8194
  }
7420
8195
  );
7421
8196
  }
8197
+ var INTERACTIVE_CELL_CONTENT = 'button, a, input, select, textarea, [role="button"], [role="checkbox"], [role="menuitem"], [role="link"]';
8198
+ function isInteractiveCellEvent(event) {
8199
+ const target = event.target;
8200
+ if (!(target instanceof Element)) return false;
8201
+ const match = target.closest(INTERACTIVE_CELL_CONTENT);
8202
+ return match !== null && match !== event.currentTarget;
8203
+ }
7422
8204
  function DataTableRow({ row, classNames }) {
7423
8205
  const { onRowClick, variant } = useTableContext();
7424
8206
  const clickable = Boolean(onRowClick);
@@ -7431,12 +8213,15 @@ function DataTableRow({ row, classNames }) {
7431
8213
  "data-clickable": clickable || void 0,
7432
8214
  role: clickable ? "button" : void 0,
7433
8215
  tabIndex: clickable ? 0 : void 0,
7434
- onClick: clickable ? () => onRowClick?.(row.original) : void 0,
8216
+ onClick: clickable ? (e) => {
8217
+ if (isInteractiveCellEvent(e)) return;
8218
+ onRowClick?.(row.original);
8219
+ } : void 0,
7435
8220
  onKeyDown: clickable ? (e) => {
7436
- if (e.key === "Enter" || e.key === " ") {
7437
- e.preventDefault();
7438
- onRowClick?.(row.original);
7439
- }
8221
+ if (e.key !== "Enter" && e.key !== " ") return;
8222
+ if (isInteractiveCellEvent(e)) return;
8223
+ e.preventDefault();
8224
+ onRowClick?.(row.original);
7440
8225
  } : void 0,
7441
8226
  className: cn("hover:bg-muted", clickable && "cursor-pointer", rowClassName),
7442
8227
  children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(DataTableCell, { cell, cellClassName }, cell.id))
@@ -8037,7 +8822,7 @@ function DataTableFooter({ pagination, selectedCount, className }) {
8037
8822
  className: cn("flex items-center justify-between border-t px-4 py-2", className),
8038
8823
  children: [
8039
8824
  selectedCount != null && selectedCount > 0 && /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "text-muted-foreground text-xs", children: `${selectedCount} row${selectedCount > 1 ? "s" : ""} selected` }),
8040
- /* @__PURE__ */ jsx(TablePagination, { ...pagination })
8825
+ /* @__PURE__ */ jsx("div", { className: "ml-auto", children: /* @__PURE__ */ jsx(TablePagination, { ...pagination }) })
8041
8826
  ]
8042
8827
  }
8043
8828
  );
@@ -8146,18 +8931,21 @@ function DataTableSearch({
8146
8931
  debounce = 300
8147
8932
  }) {
8148
8933
  const ctx = useTableContextSafe();
8149
- const [inputValue, setInputValue] = useState("");
8150
8934
  const globalFilter = ctx?.globalFilter;
8151
8935
  const setGlobalFilter = ctx?.setGlobalFilter;
8936
+ const committedValue = globalFilter ?? "";
8937
+ const [inputValue, setInputValue] = useState(committedValue);
8152
8938
  useEffect(() => {
8153
- if (globalFilter === "") setInputValue("");
8939
+ if (globalFilter === void 0) return;
8940
+ setInputValue(globalFilter);
8154
8941
  }, [globalFilter]);
8155
8942
  useEffect(() => {
8943
+ if (inputValue === committedValue) return;
8156
8944
  const timer = setTimeout(() => {
8157
8945
  setGlobalFilter?.(inputValue);
8158
8946
  }, debounce);
8159
8947
  return () => clearTimeout(timer);
8160
- }, [inputValue, debounce, setGlobalFilter]);
8948
+ }, [inputValue, committedValue, debounce, setGlobalFilter]);
8161
8949
  const handleClear = () => {
8162
8950
  setInputValue("");
8163
8951
  setGlobalFilter?.("");
@@ -8178,7 +8966,13 @@ function DataTableSearch({
8178
8966
  onChange: (e) => setInputValue(e.target.value),
8179
8967
  placeholder,
8180
8968
  "aria-label": placeholder,
8181
- className: "h-8 w-48 pr-8 pl-8 text-sm"
8969
+ className: cn(
8970
+ "h-8 w-48 pr-9 pl-9 text-sm",
8971
+ "[&::-webkit-search-cancel-button]:appearance-none",
8972
+ "[&::-webkit-search-decoration]:appearance-none",
8973
+ "[&::-webkit-search-results-button]:appearance-none",
8974
+ "[&::-webkit-search-results-decoration]:appearance-none"
8975
+ )
8182
8976
  }
8183
8977
  ),
8184
8978
  inputValue && /* @__PURE__ */ jsx(
@@ -8188,12 +8982,382 @@ function DataTableSearch({
8188
8982
  size: "icon-sm",
8189
8983
  onClick: handleClear,
8190
8984
  "aria-label": "Clear search",
8191
- className: "text-muted-foreground hover:text-foreground absolute right-0.5 size-6",
8985
+ className: "text-muted-foreground hover:text-foreground absolute top-1/2 right-1.5 size-6 -translate-y-1/2",
8192
8986
  children: /* @__PURE__ */ jsx(X, { className: "size-3.5", "aria-hidden": "true" })
8193
8987
  }
8194
8988
  )
8195
8989
  ] });
8196
8990
  }
8991
+ function BottomNav({ items, className }) {
8992
+ return /* @__PURE__ */ jsx(
8993
+ "nav",
8994
+ {
8995
+ "data-slot": "bottom-nav",
8996
+ className: cn(
8997
+ "fixed bottom-0 left-0 right-0 z-50 mx-4 mb-4 rounded-2xl bg-background shadow-[0_-4px_20px_rgba(0,0,0,0.08)]",
8998
+ className
8999
+ ),
9000
+ children: /* @__PURE__ */ jsx("div", { className: "flex h-20 items-center justify-around px-4", children: items.map(({ label, href, icon, isActive, onClick }) => /* @__PURE__ */ jsxs(
9001
+ "a",
9002
+ {
9003
+ href,
9004
+ onClick,
9005
+ "data-slot": "bottom-nav-item",
9006
+ className: cn(
9007
+ "group flex flex-col items-center gap-0 transition-colors",
9008
+ isActive ? "text-primary" : "text-muted-foreground"
9009
+ ),
9010
+ children: [
9011
+ /* @__PURE__ */ jsxs(
9012
+ "span",
9013
+ {
9014
+ className: cn(
9015
+ "flex h-12 items-center justify-center rounded-2xl transition-all",
9016
+ isActive ? "flex-col gap-0.5 bg-primary/10 px-4" : "w-12 group-hover:bg-muted group-active:bg-primary/10"
9017
+ ),
9018
+ children: [
9019
+ /* @__PURE__ */ jsx("span", { className: "h-6 w-6 shrink-0", children: icon }),
9020
+ isActive && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-semibold leading-none", children: label })
9021
+ ]
9022
+ }
9023
+ ),
9024
+ /* @__PURE__ */ jsx(
9025
+ "span",
9026
+ {
9027
+ className: cn(
9028
+ "text-[10px] font-medium",
9029
+ isActive ? "invisible" : "visible"
9030
+ ),
9031
+ children: label
9032
+ }
9033
+ ),
9034
+ /* @__PURE__ */ jsx(
9035
+ "span",
9036
+ {
9037
+ className: cn(
9038
+ "h-1 w-5 rounded-full transition-all",
9039
+ isActive ? "bg-primary" : "bg-transparent"
9040
+ )
9041
+ }
9042
+ )
9043
+ ]
9044
+ },
9045
+ href
9046
+ )) })
9047
+ }
9048
+ );
9049
+ }
9050
+ var BottomNavTabsContext = createContext(null);
9051
+ function useBottomNavTabsContext() {
9052
+ const ctx = useContext(BottomNavTabsContext);
9053
+ if (!ctx) throw new Error("BottomNavTabsList must be inside BottomNavTabs");
9054
+ return ctx;
9055
+ }
9056
+ function BottomNavTabs({
9057
+ defaultValue,
9058
+ value: controlledValue,
9059
+ onValueChange,
9060
+ ...props
9061
+ }) {
9062
+ const [internalValue, setInternalValue] = useState(controlledValue ?? defaultValue ?? "");
9063
+ const activeValue = controlledValue ?? internalValue;
9064
+ const listId = useId();
9065
+ const handleValueChange = (v) => {
9066
+ if (controlledValue === void 0) setInternalValue(v);
9067
+ onValueChange?.(v);
9068
+ };
9069
+ return /* @__PURE__ */ jsx(BottomNavTabsContext.Provider, { value: { activeValue, listId }, children: /* @__PURE__ */ jsx(
9070
+ Tabs$1.Root,
9071
+ {
9072
+ "data-slot": "bottom-nav-tabs",
9073
+ value: activeValue,
9074
+ onValueChange: handleValueChange,
9075
+ ...props
9076
+ }
9077
+ ) });
9078
+ }
9079
+ function BottomNavTabsContent({
9080
+ className,
9081
+ ...props
9082
+ }) {
9083
+ return /* @__PURE__ */ jsx(TabsContent, { className: cn("pb-28", className), ...props });
9084
+ }
9085
+ function BottomNavTabsList({ items, className }) {
9086
+ const { activeValue, listId } = useBottomNavTabsContext();
9087
+ return /* @__PURE__ */ jsx(
9088
+ "nav",
9089
+ {
9090
+ "data-slot": "bottom-nav-tabs-list",
9091
+ className: cn(
9092
+ "fixed bottom-0 left-0 right-0 z-50 mx-6 max-w- mb-4 rounded-2xl bg-background shadow-[0_-4px_20px_rgba(0,0,0,0.08)]",
9093
+ className
9094
+ ),
9095
+ children: /* @__PURE__ */ jsx(Tabs$1.List, { className: "flex h-20 items-center justify-around px-4", children: items.map(({ value, label, icon, activeIcon }) => {
9096
+ const isActive = value === activeValue;
9097
+ return /* @__PURE__ */ jsxs(
9098
+ Tabs$1.Trigger,
9099
+ {
9100
+ value,
9101
+ "data-slot": "bottom-nav-tabs-trigger",
9102
+ className: cn(
9103
+ "group flex flex-col items-center transition-colors",
9104
+ "data-[state=active]:text-primary data-[state=inactive]:text-muted-foreground",
9105
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-2xl"
9106
+ ),
9107
+ children: [
9108
+ /* @__PURE__ */ jsxs("span", { className: "relative flex h-15 w-16 flex-col items-center justify-center gap-1.5", children: [
9109
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: isActive && /* @__PURE__ */ jsx(
9110
+ motion.span,
9111
+ {
9112
+ layoutId: `${listId}-pill`,
9113
+ className: "absolute inset-0 rounded-2xl bg-primary/10",
9114
+ transition: spring.snappy
9115
+ }
9116
+ ) }),
9117
+ /* @__PURE__ */ jsx("span", { className: "relative z-10 h-6 w-6", children: isActive ? activeIcon ?? icon : icon }),
9118
+ /* @__PURE__ */ jsx("span", { className: "relative z-10 text-[10px] font-medium leading-none", children: label })
9119
+ ] }),
9120
+ /* @__PURE__ */ jsx(
9121
+ "span",
9122
+ {
9123
+ className: cn(
9124
+ "mt-1 h-1 w-6 rounded-full transition-colors",
9125
+ isActive ? "bg-primary" : "bg-transparent"
9126
+ )
9127
+ }
9128
+ )
9129
+ ]
9130
+ },
9131
+ value
9132
+ );
9133
+ }) })
9134
+ }
9135
+ );
9136
+ }
9137
+ var DrawerContext = createContext({ isOpen: false, modal: true });
9138
+ function Drawer({ children, open, onOpenChange, modal = true, ...props }) {
9139
+ const [internalOpen, setInternalOpen] = useState(props.defaultOpen ?? false);
9140
+ const isOpen = open !== void 0 ? open : internalOpen;
9141
+ return /* @__PURE__ */ jsx(DrawerContext.Provider, { value: { isOpen, modal }, children: /* @__PURE__ */ jsx(
9142
+ Dialog$1.Root,
9143
+ {
9144
+ "data-slot": "drawer",
9145
+ modal,
9146
+ ...props,
9147
+ open: isOpen,
9148
+ onOpenChange: (v) => {
9149
+ setInternalOpen(v);
9150
+ onOpenChange?.(v);
9151
+ },
9152
+ children
9153
+ }
9154
+ ) });
9155
+ }
9156
+ function DrawerTrigger({ ...props }) {
9157
+ return /* @__PURE__ */ jsx(Dialog$1.Trigger, { "data-slot": "drawer-trigger", ...props });
9158
+ }
9159
+ function DrawerClose({ ...props }) {
9160
+ return /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "drawer-close", ...props });
9161
+ }
9162
+ function DrawerPortal({ children, ...props }) {
9163
+ const { isOpen } = useContext(DrawerContext);
9164
+ return /* @__PURE__ */ jsx(Dialog$1.Portal, { forceMount: true, ...props, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "sync", children: isOpen && children }) });
9165
+ }
9166
+ function DrawerOverlay({ className, ...props }) {
9167
+ return /* @__PURE__ */ jsx(Dialog$1.Overlay, { "data-slot": "drawer-overlay", asChild: true, forceMount: true, ...props, children: /* @__PURE__ */ jsx(
9168
+ motion.div,
9169
+ {
9170
+ className: cn(
9171
+ "fixed inset-0 isolate z-50 bg-black/30 supports-backdrop-filter:backdrop-blur-sm",
9172
+ className
9173
+ ),
9174
+ initial: { opacity: 0 },
9175
+ animate: { opacity: 1 },
9176
+ exit: { opacity: 0 },
9177
+ transition: { duration: duration.normal, ease: ease.smooth }
9178
+ }
9179
+ ) });
9180
+ }
9181
+ var sizeClasses = {
9182
+ sm: "w-64",
9183
+ md: "w-80",
9184
+ lg: "w-96",
9185
+ xl: "w-[30rem]",
9186
+ full: "w-screen"
9187
+ };
9188
+ function DrawerContent({
9189
+ className,
9190
+ children,
9191
+ side = "right",
9192
+ size = "md",
9193
+ showCloseButton = true,
9194
+ resizable = false,
9195
+ ...props
9196
+ }) {
9197
+ const isHorizontal = side === "left" || side === "right";
9198
+ const xInitial = side === "right" ? "100%" : side === "left" ? "-100%" : 0;
9199
+ const yInitial = side === "bottom" ? "100%" : side === "top" ? "-100%" : 0;
9200
+ const dragRef = useRef(null);
9201
+ const { modal } = useContext(DrawerContext);
9202
+ return /* @__PURE__ */ jsxs(DrawerPortal, { children: [
9203
+ modal && /* @__PURE__ */ jsx(DrawerOverlay, {}, "drawer-overlay"),
9204
+ /* @__PURE__ */ jsx(
9205
+ Dialog$1.Content,
9206
+ {
9207
+ "data-slot": "drawer-content",
9208
+ "data-side": side,
9209
+ asChild: true,
9210
+ forceMount: true,
9211
+ className: cn(
9212
+ "fixed z-50 flex flex-col bg-popover text-popover-foreground shadow-xl outline-none",
9213
+ side === "left" && "inset-y-0 left-0",
9214
+ side === "right" && "inset-y-0 right-0",
9215
+ side === "top" && "inset-x-0 top-0",
9216
+ side === "bottom" && "inset-x-0 bottom-0",
9217
+ isHorizontal && sizeClasses[size],
9218
+ !isHorizontal && "h-auto min-h-40",
9219
+ className
9220
+ ),
9221
+ ...props,
9222
+ children: /* @__PURE__ */ jsxs(
9223
+ motion.div,
9224
+ {
9225
+ className: cn("flex flex-col", isHorizontal && "h-full"),
9226
+ initial: { x: xInitial, y: yInitial, opacity: 0 },
9227
+ animate: { x: 0, y: 0, opacity: 1, transition: transition.drawer },
9228
+ exit: { x: xInitial, y: yInitial, opacity: 0, transition: transition.drawerExit },
9229
+ children: [
9230
+ children,
9231
+ showCloseButton && /* @__PURE__ */ jsx(Dialog$1.Close, { "data-slot": "drawer-close", asChild: true, children: /* @__PURE__ */ jsxs(
9232
+ Button,
9233
+ {
9234
+ variant: "ghost",
9235
+ className: "absolute top-4 right-4",
9236
+ size: "icon-sm",
9237
+ children: [
9238
+ /* @__PURE__ */ jsx(XIcon, {}),
9239
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
9240
+ ]
9241
+ }
9242
+ ) }),
9243
+ resizable && /* @__PURE__ */ jsx(
9244
+ "div",
9245
+ {
9246
+ "data-slot": "drawer-resize-handle",
9247
+ className: cn(
9248
+ "absolute opacity-0 transition-opacity hover:opacity-100 hover:bg-border",
9249
+ side === "right" && "inset-y-0 left-0 w-1 cursor-col-resize",
9250
+ side === "left" && "inset-y-0 right-0 w-1 cursor-col-resize",
9251
+ side === "top" && "inset-x-0 bottom-0 h-1 cursor-row-resize",
9252
+ side === "bottom" && "inset-x-0 top-0 h-1 cursor-row-resize"
9253
+ ),
9254
+ onPointerDown: (e) => {
9255
+ e.preventDefault();
9256
+ const content = e.currentTarget.parentElement;
9257
+ if (!content) return;
9258
+ const startSize = isHorizontal ? parseFloat(getComputedStyle(content).width) : parseFloat(getComputedStyle(content).height);
9259
+ content.style.transition = "none";
9260
+ dragRef.current = {
9261
+ startPos: isHorizontal ? e.clientX : e.clientY,
9262
+ startSize,
9263
+ content
9264
+ };
9265
+ e.currentTarget.setPointerCapture(e.pointerId);
9266
+ },
9267
+ onPointerMove: (e) => {
9268
+ if (!dragRef.current) return;
9269
+ const { startPos, startSize, content } = dragRef.current;
9270
+ const delta = (isHorizontal ? e.clientX : e.clientY) - startPos;
9271
+ let newSize;
9272
+ if (side === "right") {
9273
+ newSize = Math.max(160, Math.min(window.innerWidth * 0.9, startSize - delta));
9274
+ } else if (side === "left") {
9275
+ newSize = Math.max(160, Math.min(window.innerWidth * 0.9, startSize + delta));
9276
+ } else if (side === "bottom") {
9277
+ newSize = Math.max(80, Math.min(window.innerHeight * 0.9, startSize - delta));
9278
+ } else {
9279
+ newSize = Math.max(80, Math.min(window.innerHeight * 0.9, startSize + delta));
9280
+ }
9281
+ content.style[isHorizontal ? "width" : "height"] = `${newSize}px`;
9282
+ },
9283
+ onPointerUp: () => {
9284
+ if (dragRef.current?.content) {
9285
+ dragRef.current.content.style.transition = "";
9286
+ }
9287
+ dragRef.current = null;
9288
+ },
9289
+ onPointerCancel: () => {
9290
+ if (dragRef.current?.content) {
9291
+ dragRef.current.content.style.transition = "";
9292
+ }
9293
+ dragRef.current = null;
9294
+ }
9295
+ }
9296
+ )
9297
+ ]
9298
+ }
9299
+ )
9300
+ },
9301
+ "drawer-content"
9302
+ )
9303
+ ] });
9304
+ }
9305
+ function DrawerHeader({ className, ...props }) {
9306
+ return /* @__PURE__ */ jsx(
9307
+ "div",
9308
+ {
9309
+ "data-slot": "drawer-header",
9310
+ className: cn("flex shrink-0 flex-col gap-1.5 p-6", className),
9311
+ ...props
9312
+ }
9313
+ );
9314
+ }
9315
+ function DrawerBody({ className, ...props }) {
9316
+ return /* @__PURE__ */ jsx(
9317
+ "div",
9318
+ {
9319
+ "data-slot": "drawer-body",
9320
+ className: cn("flex-1 overflow-y-auto px-6 pb-6", className),
9321
+ ...props
9322
+ }
9323
+ );
9324
+ }
9325
+ function DrawerFooter({ className, ...props }) {
9326
+ return /* @__PURE__ */ jsx(
9327
+ "div",
9328
+ {
9329
+ "data-slot": "drawer-footer",
9330
+ className: cn(
9331
+ "border-border mt-auto flex shrink-0 flex-wrap items-center justify-end gap-2 border-t px-6 py-4",
9332
+ className
9333
+ ),
9334
+ ...props
9335
+ }
9336
+ );
9337
+ }
9338
+ function DrawerTitle({ className, ...props }) {
9339
+ return /* @__PURE__ */ jsx(
9340
+ Dialog$1.Title,
9341
+ {
9342
+ "data-slot": "drawer-title",
9343
+ className: cn("font-heading text-base leading-none font-semibold", className),
9344
+ ...props
9345
+ }
9346
+ );
9347
+ }
9348
+ function DrawerDescription({
9349
+ className,
9350
+ ...props
9351
+ }) {
9352
+ return /* @__PURE__ */ jsx(
9353
+ Dialog$1.Description,
9354
+ {
9355
+ "data-slot": "drawer-description",
9356
+ className: cn("text-sm text-muted-foreground", className),
9357
+ ...props
9358
+ }
9359
+ );
9360
+ }
8197
9361
  function TCCEProvider({
8198
9362
  children,
8199
9363
  permissions,
@@ -8203,6 +9367,6 @@ function TCCEProvider({
8203
9367
  return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: tooltipDelayDuration, children: /* @__PURE__ */ jsx(AbilityProvider, { permissions, children: /* @__PURE__ */ jsx(Toaster, { position: toasterPosition, children }) }) });
8204
9368
  }
8205
9369
 
8206
- export { AbilityProvider, Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge2 as Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, Can, CanNot, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, Checkbox, ColorPicker, ColorPickerAlpha, ColorPickerEyeDropper, ColorPickerFormat, ColorPickerHue, ColorPickerOutput, ColorPickerPresets, ColorPickerSelection, Combobox, DataTable, DataTableCardView, DataTableColumnFilter, DataTableFooter, DataTableHeaderCell, DataTableRowActions, DataTableSearch, DataTableSkeleton, DataTableToolbar, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Dropzone, DropzoneContent, DropzoneEmptyState, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EventCalendar, Field, FieldDescription, FieldError, FieldGroup, FieldLabel, FilterOption, Input, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Link, Logo, MiniCalendar, MiniCalendarDay, MiniCalendarDays, MiniCalendarNavigation, Navbar, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PinInput, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, SegmentedControl, SegmentedControlItem, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, SpinnerDots, SpinnerLoader, Status, StatusIndicator, StatusLabel, Switch, TCCEProvider, TEXT_SIZES, TEXT_WEIGHTS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TablePagination, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, Textarea, Toaster, Toggle, ToggleGroup2 as ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alertVariants, animation, avatarVariants, badgeVariants2 as badgeVariants, buttonVariants, columnFiltersToArrayQueryParams, columnFiltersToJsonString, columnFiltersToQueryParams, columnFiltersToRecord, createBackendParams, createBackendParamsWithFilters, duration, ease, fadeIn, getActiveFilterCount, getActiveFilterValues, getColumnValueCounts, getUniqueColumnValues, hasActiveFilters, linkVariants, logos, matchPermission, mergeFilters, multiSelectFilter, navigationMenuTriggerStyle, parseJsonToFilters, parseQueryParamsToFilters, progressIndicatorVariants, progressVariants, scaleIn, searchInArray, skeletonVariants, slideRight, slideUp, sortRecordToSortingState, sortingStateToJsonString, sortingStateToRecord, spinnerDotsVariants, spinnerLoaderVariants, spinnerVariants, spring, stagger, toggleVariants, tooltipContentVariants, transition, useAbility, useAppForm, useCan, useCarousel, useColorPicker, useColumnFilter, useSidebar, useTableContext, useTableData, useTableFiltering, useTableGlobalFilter, useTableSizing, useTableSorting, useTableVisibility, useToast };
9370
+ export { AbilityProvider, Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge2 as Badge, BottomNav, BottomNavTabs, BottomNavTabsContent, BottomNavTabsList, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Can, CanNot, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, Checkbox, ColorPicker, ColorPickerAlpha, ColorPickerEyeDropper, ColorPickerFormat, ColorPickerHue, ColorPickerOutput, ColorPickerPresets, ColorPickerSelection, Combobox, DataTable, DataTableCardView, DataTableColumnFilter, DataTableFooter, DataTableHeaderCell, DataTableRowActions, DataTableSearch, DataTableSkeleton, DataTableToolbar, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Dropzone, DropzoneContent, DropzoneEmptyState, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EventCalendar, Field, FieldDescription, FieldError, FieldGroup, FieldLabel, FilterOption, Input, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, KNOWN_PERMISSIONS, Label, Link, Logo, MiniCalendar, MiniCalendarDay, MiniCalendarDays, MiniCalendarNavigation, Navbar, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PhoneField, PinInput, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, SegmentedControl, SegmentedControlItem, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, SpinnerDots, SpinnerLoader, Status, StatusIndicator, StatusLabel, Switch, TCCEProvider, TEXT_SIZES, TEXT_WEIGHTS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TablePagination, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Text, Textarea, Toaster, Toggle, ToggleGroup2 as ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alertVariants, animation, avatarVariants, badgeVariants2 as badgeVariants, buttonVariants, columnFiltersToArrayQueryParams, columnFiltersToJsonString, columnFiltersToQueryParams, columnFiltersToRecord, createBackendParams, createBackendParamsWithFilters, duration, ease, fadeIn, getActiveFilterCount, getActiveFilterValues, getColumnValueCounts, getUniqueColumnValues, hasActiveFilters, linkVariants, logos, matchPermission, mergeFilters, multiSelectFilter, navigationMenuTriggerStyle, parseJsonToFilters, parseQueryParamsToFilters, progressIndicatorVariants, progressVariants, scaleIn, searchInArray, skeletonVariants, slideRight, slideUp, sortRecordToSortingState, sortingStateToJsonString, sortingStateToRecord, spinnerDotsVariants, spinnerLoaderVariants, spinnerVariants, spring, stagger, toggleVariants, tooltipContentVariants, transition, useAbility, useAbilityStatus, useAppForm, useCan, useCarousel, useColorPicker, useColumnFilter, useSidebar, useTableContext, useTableData, useTableFiltering, useTableGlobalFilter, useTableSizing, useTableSorting, useTableVisibility, useToast, validatePhone };
8207
9371
  //# sourceMappingURL=main.js.map
8208
9372
  //# sourceMappingURL=main.js.map