@j3m-quantum/ui 1.0.0 → 1.3.1
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/README.md +248 -39
- package/cursor-rules-for-consumers.md +171 -28
- package/dist/index.cjs +3925 -409
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +671 -3
- package/dist/index.d.ts +671 -3
- package/dist/index.js +3820 -409
- package/dist/index.js.map +1 -1
- package/dist/styles/index.css +1540 -279
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React15 from 'react';
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
@@ -7,7 +7,7 @@ import { twMerge } from 'tailwind-merge';
|
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
9
9
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
10
|
-
import { CheckIcon, CircleIcon, ChevronDownIcon, ChevronUpIcon,
|
|
10
|
+
import { SearchIcon, CheckIcon, CircleIcon, ChevronDownIcon, ChevronUpIcon, ChevronRightIcon, ChevronLeftIcon, ArrowLeft, ArrowRight, Loader2Icon, OctagonXIcon, TriangleAlertIcon, InfoIcon, CircleCheckIcon, ChevronRight, MoreHorizontal, MoreHorizontalIcon, XIcon, GripVerticalIcon, PanelLeftIcon, FolderIcon, ShareIcon, TrashIcon, ChevronsUpDownIcon, SparklesIcon, BadgeCheckIcon, CreditCardIcon, BellIcon, LogOutIcon, User, Calendar as Calendar$1, Clock, CalendarX2, ChevronLeft, List, Columns, Grid2x2, Grid3x3, CalendarRange, Plus, Info, Moon, Settings } from 'lucide-react';
|
|
11
11
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
12
12
|
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
13
13
|
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
@@ -17,6 +17,7 @@ import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
|
17
17
|
import { FormProvider, Controller, useFormContext, useFormState } from 'react-hook-form';
|
|
18
18
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
19
19
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
20
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
20
21
|
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
21
22
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
22
23
|
import { getDefaultClassNames, DayPicker } from 'react-day-picker';
|
|
@@ -29,7 +30,6 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
|
29
30
|
import { Toaster as Toaster$1 } from 'sonner';
|
|
30
31
|
import { Command as Command$1 } from 'cmdk';
|
|
31
32
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
32
|
-
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
33
33
|
import * as MenubarPrimitive from '@radix-ui/react-menubar';
|
|
34
34
|
import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
|
|
35
35
|
import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
|
|
@@ -39,12 +39,14 @@ import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
|
|
|
39
39
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
40
40
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
41
41
|
import * as ResizablePrimitive from 'react-resizable-panels';
|
|
42
|
+
import { subMonths, subYears, subWeeks, subDays, addMonths, addYears, addWeeks, addDays, format, startOfWeek, endOfWeek, startOfMonth, endOfMonth, startOfYear, endOfYear, isSameMonth, isSameWeek, isSameDay, isSameYear, isWithinInterval, parseISO, differenceInMinutes, eachDayOfInterval, differenceInDays, startOfDay, setMinutes, setHours, eachHourOfInterval, endOfDay, getHours, getMinutes, addMinutes, isToday, areIntervalsOverlapping } from 'date-fns';
|
|
43
|
+
export { areIntervalsOverlapping, format, getDay, isSameDay, isSameMonth, isToday, parseISO } from 'date-fns';
|
|
42
44
|
|
|
43
45
|
// src/hooks/use-mobile.ts
|
|
44
46
|
var MOBILE_BREAKPOINT = 768;
|
|
45
47
|
function useIsMobile() {
|
|
46
|
-
const [isMobile, setIsMobile] =
|
|
47
|
-
|
|
48
|
+
const [isMobile, setIsMobile] = React15.useState(void 0);
|
|
49
|
+
React15.useEffect(() => {
|
|
48
50
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
49
51
|
const onChange = () => {
|
|
50
52
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
@@ -63,10 +65,10 @@ var buttonVariants = cva(
|
|
|
63
65
|
{
|
|
64
66
|
variants: {
|
|
65
67
|
variant: {
|
|
66
|
-
default: "bg-primary text-primary-foreground
|
|
67
|
-
destructive: "bg-destructive text-destructive-foreground
|
|
68
|
-
outline: "border border-input bg-background
|
|
69
|
-
secondary: "bg-secondary text-secondary-foreground
|
|
68
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
69
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
70
|
+
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
71
|
+
secondary: "bg-secondary text-secondary-foreground border border-input hover:bg-secondary/80",
|
|
70
72
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
71
73
|
link: "text-primary underline-offset-4 hover:underline"
|
|
72
74
|
},
|
|
@@ -85,7 +87,7 @@ var buttonVariants = cva(
|
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
);
|
|
88
|
-
var Button =
|
|
90
|
+
var Button = React15.forwardRef(
|
|
89
91
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
90
92
|
const Comp = asChild ? Slot : "button";
|
|
91
93
|
return /* @__PURE__ */ jsx(
|
|
@@ -193,7 +195,7 @@ function Input({ className, type, ...props }) {
|
|
|
193
195
|
type,
|
|
194
196
|
"data-slot": "input",
|
|
195
197
|
className: cn(
|
|
196
|
-
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-
|
|
198
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-4 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
197
199
|
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
198
200
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
199
201
|
className
|
|
@@ -449,7 +451,7 @@ function Slider({
|
|
|
449
451
|
max = 100,
|
|
450
452
|
...props
|
|
451
453
|
}) {
|
|
452
|
-
const _values =
|
|
454
|
+
const _values = React15.useMemo(
|
|
453
455
|
() => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
|
|
454
456
|
[value, defaultValue, min, max]
|
|
455
457
|
);
|
|
@@ -485,7 +487,7 @@ function Slider({
|
|
|
485
487
|
)
|
|
486
488
|
}
|
|
487
489
|
),
|
|
488
|
-
Array.from({ length: _values.length }, (
|
|
490
|
+
Array.from({ length: _values.length }, (_, index) => /* @__PURE__ */ jsx(
|
|
489
491
|
SliderPrimitive.Thumb,
|
|
490
492
|
{
|
|
491
493
|
"data-slot": "slider-thumb",
|
|
@@ -735,7 +737,7 @@ function Toggle({
|
|
|
735
737
|
}
|
|
736
738
|
);
|
|
737
739
|
}
|
|
738
|
-
var ToggleGroupContext =
|
|
740
|
+
var ToggleGroupContext = React15.createContext({
|
|
739
741
|
size: "default",
|
|
740
742
|
variant: "default",
|
|
741
743
|
spacing: 0
|
|
@@ -772,7 +774,7 @@ function ToggleGroupItem({
|
|
|
772
774
|
size,
|
|
773
775
|
...props
|
|
774
776
|
}) {
|
|
775
|
-
const context =
|
|
777
|
+
const context = React15.useContext(ToggleGroupContext);
|
|
776
778
|
return /* @__PURE__ */ jsx(
|
|
777
779
|
ToggleGroupPrimitive.Item,
|
|
778
780
|
{
|
|
@@ -794,6 +796,125 @@ function ToggleGroupItem({
|
|
|
794
796
|
}
|
|
795
797
|
);
|
|
796
798
|
}
|
|
799
|
+
function ThemeSwitch({
|
|
800
|
+
checked,
|
|
801
|
+
defaultChecked = false,
|
|
802
|
+
onCheckedChange,
|
|
803
|
+
disabled = false,
|
|
804
|
+
className,
|
|
805
|
+
size = "default"
|
|
806
|
+
}) {
|
|
807
|
+
const [isChecked, setIsChecked] = React15.useState(defaultChecked);
|
|
808
|
+
const isControlled = checked !== void 0;
|
|
809
|
+
const currentChecked = isControlled ? checked : isChecked;
|
|
810
|
+
const handleClick = () => {
|
|
811
|
+
if (disabled) return;
|
|
812
|
+
const newValue = !currentChecked;
|
|
813
|
+
if (!isControlled) {
|
|
814
|
+
setIsChecked(newValue);
|
|
815
|
+
}
|
|
816
|
+
onCheckedChange?.(newValue);
|
|
817
|
+
};
|
|
818
|
+
const sizeClasses = {
|
|
819
|
+
sm: {
|
|
820
|
+
track: "h-5 w-9",
|
|
821
|
+
thumb: "size-4",
|
|
822
|
+
icon: "h-2.5 w-2.5",
|
|
823
|
+
translate: "data-[state=checked]:translate-x-4"
|
|
824
|
+
},
|
|
825
|
+
default: {
|
|
826
|
+
track: "h-6 w-11",
|
|
827
|
+
thumb: "size-5",
|
|
828
|
+
icon: "h-3 w-3",
|
|
829
|
+
translate: "data-[state=checked]:translate-x-5"
|
|
830
|
+
},
|
|
831
|
+
lg: {
|
|
832
|
+
track: "h-7 w-14",
|
|
833
|
+
thumb: "size-6",
|
|
834
|
+
icon: "h-3.5 w-3.5",
|
|
835
|
+
translate: "data-[state=checked]:translate-x-7"
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
const sizes = sizeClasses[size];
|
|
839
|
+
return /* @__PURE__ */ jsx(
|
|
840
|
+
"button",
|
|
841
|
+
{
|
|
842
|
+
type: "button",
|
|
843
|
+
role: "switch",
|
|
844
|
+
"aria-checked": currentChecked,
|
|
845
|
+
"aria-label": currentChecked ? "Switch to light mode" : "Switch to dark mode",
|
|
846
|
+
"data-slot": "theme-switch",
|
|
847
|
+
"data-state": currentChecked ? "checked" : "unchecked",
|
|
848
|
+
disabled,
|
|
849
|
+
onClick: handleClick,
|
|
850
|
+
className: cn(
|
|
851
|
+
"peer inline-flex shrink-0 cursor-pointer items-center rounded-full",
|
|
852
|
+
"border border-transparent shadow-xs transition-all outline-none",
|
|
853
|
+
"focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
854
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
855
|
+
"bg-input data-[state=checked]:bg-primary",
|
|
856
|
+
sizes.track,
|
|
857
|
+
className
|
|
858
|
+
),
|
|
859
|
+
children: /* @__PURE__ */ jsx(
|
|
860
|
+
"span",
|
|
861
|
+
{
|
|
862
|
+
"data-state": currentChecked ? "checked" : "unchecked",
|
|
863
|
+
className: cn(
|
|
864
|
+
"pointer-events-none flex items-center justify-center rounded-full",
|
|
865
|
+
"bg-white shadow-lg ring-0 transition-transform",
|
|
866
|
+
"data-[state=unchecked]:translate-x-0.5",
|
|
867
|
+
sizes.thumb,
|
|
868
|
+
sizes.translate
|
|
869
|
+
),
|
|
870
|
+
children: currentChecked ? /* @__PURE__ */ jsx(MoonIcon, { className: cn(sizes.icon, "text-primary") }) : /* @__PURE__ */ jsx(SunIcon, { className: cn(sizes.icon, "text-muted-foreground") })
|
|
871
|
+
}
|
|
872
|
+
)
|
|
873
|
+
}
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
function SunIcon({ className }) {
|
|
877
|
+
return /* @__PURE__ */ jsxs(
|
|
878
|
+
"svg",
|
|
879
|
+
{
|
|
880
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
881
|
+
viewBox: "0 0 24 24",
|
|
882
|
+
fill: "none",
|
|
883
|
+
stroke: "currentColor",
|
|
884
|
+
strokeWidth: "2",
|
|
885
|
+
strokeLinecap: "round",
|
|
886
|
+
strokeLinejoin: "round",
|
|
887
|
+
className,
|
|
888
|
+
children: [
|
|
889
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
|
|
890
|
+
/* @__PURE__ */ jsx("path", { d: "M12 2v2" }),
|
|
891
|
+
/* @__PURE__ */ jsx("path", { d: "M12 20v2" }),
|
|
892
|
+
/* @__PURE__ */ jsx("path", { d: "m4.93 4.93 1.41 1.41" }),
|
|
893
|
+
/* @__PURE__ */ jsx("path", { d: "m17.66 17.66 1.41 1.41" }),
|
|
894
|
+
/* @__PURE__ */ jsx("path", { d: "M2 12h2" }),
|
|
895
|
+
/* @__PURE__ */ jsx("path", { d: "M20 12h2" }),
|
|
896
|
+
/* @__PURE__ */ jsx("path", { d: "m6.34 17.66-1.41 1.41" }),
|
|
897
|
+
/* @__PURE__ */ jsx("path", { d: "m19.07 4.93-1.41 1.41" })
|
|
898
|
+
]
|
|
899
|
+
}
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
function MoonIcon({ className }) {
|
|
903
|
+
return /* @__PURE__ */ jsx(
|
|
904
|
+
"svg",
|
|
905
|
+
{
|
|
906
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
907
|
+
viewBox: "0 0 24 24",
|
|
908
|
+
fill: "none",
|
|
909
|
+
stroke: "currentColor",
|
|
910
|
+
strokeWidth: "2",
|
|
911
|
+
strokeLinecap: "round",
|
|
912
|
+
strokeLinejoin: "round",
|
|
913
|
+
className,
|
|
914
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
|
|
915
|
+
}
|
|
916
|
+
);
|
|
917
|
+
}
|
|
797
918
|
function ToolBarCanvas({
|
|
798
919
|
className,
|
|
799
920
|
...props
|
|
@@ -803,7 +924,7 @@ function ToolBarCanvas({
|
|
|
803
924
|
{
|
|
804
925
|
"data-slot": "toolbar-canvas",
|
|
805
926
|
className: cn(
|
|
806
|
-
"inline-flex items-center gap-1 rounded-full bg-
|
|
927
|
+
"inline-flex items-center gap-1 rounded-full bg-background border border-input p-1.5",
|
|
807
928
|
className
|
|
808
929
|
),
|
|
809
930
|
...props
|
|
@@ -898,7 +1019,7 @@ function PlayerCanvasControls({
|
|
|
898
1019
|
{
|
|
899
1020
|
"data-slot": "player-canvas-controls",
|
|
900
1021
|
className: cn(
|
|
901
|
-
"flex items-center gap-2 px-1.5 py-1.5 rounded-full bg-
|
|
1022
|
+
"flex items-center gap-2 px-1.5 py-1.5 rounded-full bg-background border border-input",
|
|
902
1023
|
className
|
|
903
1024
|
),
|
|
904
1025
|
...props
|
|
@@ -939,7 +1060,7 @@ function PlayerCanvasPlayButton({
|
|
|
939
1060
|
className
|
|
940
1061
|
),
|
|
941
1062
|
style: {
|
|
942
|
-
backgroundColor: "
|
|
1063
|
+
backgroundColor: "var(--j3m-orange-8)",
|
|
943
1064
|
...style
|
|
944
1065
|
},
|
|
945
1066
|
...props,
|
|
@@ -1079,7 +1200,7 @@ function PlayerCanvasProgress({
|
|
|
1079
1200
|
className: "absolute inset-y-0 left-0 rounded-full transition-all duration-200",
|
|
1080
1201
|
style: {
|
|
1081
1202
|
width: `${percentage}%`,
|
|
1082
|
-
backgroundColor: "
|
|
1203
|
+
backgroundColor: "var(--j3m-orange-8)"
|
|
1083
1204
|
}
|
|
1084
1205
|
}
|
|
1085
1206
|
)
|
|
@@ -1103,7 +1224,7 @@ function Label2({
|
|
|
1103
1224
|
);
|
|
1104
1225
|
}
|
|
1105
1226
|
var Form = FormProvider;
|
|
1106
|
-
var FormFieldContext =
|
|
1227
|
+
var FormFieldContext = React15.createContext(
|
|
1107
1228
|
{}
|
|
1108
1229
|
);
|
|
1109
1230
|
var FormField = ({
|
|
@@ -1112,8 +1233,8 @@ var FormField = ({
|
|
|
1112
1233
|
return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
|
|
1113
1234
|
};
|
|
1114
1235
|
var useFormField = () => {
|
|
1115
|
-
const fieldContext =
|
|
1116
|
-
const itemContext =
|
|
1236
|
+
const fieldContext = React15.useContext(FormFieldContext);
|
|
1237
|
+
const itemContext = React15.useContext(FormItemContext);
|
|
1117
1238
|
const { getFieldState } = useFormContext();
|
|
1118
1239
|
const formState = useFormState({ name: fieldContext.name });
|
|
1119
1240
|
const fieldState = getFieldState(fieldContext.name, formState);
|
|
@@ -1130,11 +1251,11 @@ var useFormField = () => {
|
|
|
1130
1251
|
...fieldState
|
|
1131
1252
|
};
|
|
1132
1253
|
};
|
|
1133
|
-
var FormItemContext =
|
|
1254
|
+
var FormItemContext = React15.createContext(
|
|
1134
1255
|
{}
|
|
1135
1256
|
);
|
|
1136
1257
|
function FormItem({ className, ...props }) {
|
|
1137
|
-
const id =
|
|
1258
|
+
const id = React15.useId();
|
|
1138
1259
|
return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx(
|
|
1139
1260
|
"div",
|
|
1140
1261
|
{
|
|
@@ -1418,7 +1539,7 @@ var cardVariants = cva(
|
|
|
1418
1539
|
{
|
|
1419
1540
|
variants: {
|
|
1420
1541
|
variant: {
|
|
1421
|
-
default: "bg-card border
|
|
1542
|
+
default: "bg-card border",
|
|
1422
1543
|
glass: [
|
|
1423
1544
|
"glass-context",
|
|
1424
1545
|
// Enables glass semantic token overrides for children
|
|
@@ -1673,186 +1794,478 @@ function AvatarFallback({
|
|
|
1673
1794
|
}
|
|
1674
1795
|
);
|
|
1675
1796
|
}
|
|
1676
|
-
function
|
|
1797
|
+
function DropdownMenu({
|
|
1798
|
+
...props
|
|
1799
|
+
}) {
|
|
1800
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1801
|
+
}
|
|
1802
|
+
function DropdownMenuPortal({
|
|
1803
|
+
...props
|
|
1804
|
+
}) {
|
|
1805
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
|
|
1806
|
+
}
|
|
1807
|
+
function DropdownMenuTrigger({
|
|
1808
|
+
...props
|
|
1809
|
+
}) {
|
|
1677
1810
|
return /* @__PURE__ */ jsx(
|
|
1678
|
-
|
|
1811
|
+
DropdownMenuPrimitive.Trigger,
|
|
1679
1812
|
{
|
|
1680
|
-
"data-slot": "
|
|
1681
|
-
className: cn("bg-accent animate-pulse rounded-md", className),
|
|
1813
|
+
"data-slot": "dropdown-menu-trigger",
|
|
1682
1814
|
...props
|
|
1683
1815
|
}
|
|
1684
1816
|
);
|
|
1685
1817
|
}
|
|
1686
|
-
function
|
|
1818
|
+
function DropdownMenuContent({
|
|
1819
|
+
className,
|
|
1820
|
+
sideOffset = 4,
|
|
1687
1821
|
...props
|
|
1688
1822
|
}) {
|
|
1689
|
-
return /* @__PURE__ */ jsx(
|
|
1823
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
1824
|
+
DropdownMenuPrimitive.Content,
|
|
1825
|
+
{
|
|
1826
|
+
"data-slot": "dropdown-menu-content",
|
|
1827
|
+
sideOffset,
|
|
1828
|
+
className: cn(
|
|
1829
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
|
1830
|
+
className
|
|
1831
|
+
),
|
|
1832
|
+
...props
|
|
1833
|
+
}
|
|
1834
|
+
) });
|
|
1690
1835
|
}
|
|
1691
|
-
function
|
|
1836
|
+
function DropdownMenuGroup({
|
|
1837
|
+
...props
|
|
1838
|
+
}) {
|
|
1839
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
1840
|
+
}
|
|
1841
|
+
function DropdownMenuItem({
|
|
1692
1842
|
className,
|
|
1843
|
+
inset,
|
|
1844
|
+
variant = "default",
|
|
1693
1845
|
...props
|
|
1694
1846
|
}) {
|
|
1695
1847
|
return /* @__PURE__ */ jsx(
|
|
1696
|
-
|
|
1848
|
+
DropdownMenuPrimitive.Item,
|
|
1697
1849
|
{
|
|
1698
|
-
"data-slot": "
|
|
1699
|
-
|
|
1850
|
+
"data-slot": "dropdown-menu-item",
|
|
1851
|
+
"data-inset": inset,
|
|
1852
|
+
"data-variant": variant,
|
|
1853
|
+
className: cn(
|
|
1854
|
+
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1855
|
+
className
|
|
1856
|
+
),
|
|
1700
1857
|
...props
|
|
1701
1858
|
}
|
|
1702
1859
|
);
|
|
1703
1860
|
}
|
|
1704
|
-
function
|
|
1861
|
+
function DropdownMenuCheckboxItem({
|
|
1705
1862
|
className,
|
|
1706
1863
|
children,
|
|
1864
|
+
checked,
|
|
1707
1865
|
...props
|
|
1708
1866
|
}) {
|
|
1709
|
-
return /* @__PURE__ */
|
|
1710
|
-
|
|
1867
|
+
return /* @__PURE__ */ jsxs(
|
|
1868
|
+
DropdownMenuPrimitive.CheckboxItem,
|
|
1711
1869
|
{
|
|
1712
|
-
"data-slot": "
|
|
1870
|
+
"data-slot": "dropdown-menu-checkbox-item",
|
|
1713
1871
|
className: cn(
|
|
1714
|
-
"focus
|
|
1872
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1715
1873
|
className
|
|
1716
1874
|
),
|
|
1875
|
+
checked,
|
|
1717
1876
|
...props,
|
|
1718
1877
|
children: [
|
|
1719
|
-
children,
|
|
1720
|
-
|
|
1878
|
+
/* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
|
|
1879
|
+
children
|
|
1721
1880
|
]
|
|
1722
1881
|
}
|
|
1723
|
-
)
|
|
1882
|
+
);
|
|
1724
1883
|
}
|
|
1725
|
-
function
|
|
1884
|
+
function DropdownMenuRadioGroup({
|
|
1885
|
+
...props
|
|
1886
|
+
}) {
|
|
1887
|
+
return /* @__PURE__ */ jsx(
|
|
1888
|
+
DropdownMenuPrimitive.RadioGroup,
|
|
1889
|
+
{
|
|
1890
|
+
"data-slot": "dropdown-menu-radio-group",
|
|
1891
|
+
...props
|
|
1892
|
+
}
|
|
1893
|
+
);
|
|
1894
|
+
}
|
|
1895
|
+
function DropdownMenuRadioItem({
|
|
1726
1896
|
className,
|
|
1727
1897
|
children,
|
|
1728
1898
|
...props
|
|
1729
1899
|
}) {
|
|
1730
|
-
return /* @__PURE__ */
|
|
1731
|
-
|
|
1900
|
+
return /* @__PURE__ */ jsxs(
|
|
1901
|
+
DropdownMenuPrimitive.RadioItem,
|
|
1732
1902
|
{
|
|
1733
|
-
"data-slot": "
|
|
1734
|
-
className:
|
|
1903
|
+
"data-slot": "dropdown-menu-radio-item",
|
|
1904
|
+
className: cn(
|
|
1905
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1906
|
+
className
|
|
1907
|
+
),
|
|
1735
1908
|
...props,
|
|
1736
|
-
children:
|
|
1909
|
+
children: [
|
|
1910
|
+
/* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CircleIcon, { className: "size-2 fill-current" }) }) }),
|
|
1911
|
+
children
|
|
1912
|
+
]
|
|
1737
1913
|
}
|
|
1738
1914
|
);
|
|
1739
1915
|
}
|
|
1740
|
-
function
|
|
1916
|
+
function DropdownMenuLabel({
|
|
1741
1917
|
className,
|
|
1918
|
+
inset,
|
|
1742
1919
|
...props
|
|
1743
1920
|
}) {
|
|
1744
1921
|
return /* @__PURE__ */ jsx(
|
|
1745
|
-
|
|
1922
|
+
DropdownMenuPrimitive.Label,
|
|
1746
1923
|
{
|
|
1747
|
-
"data-slot": "
|
|
1748
|
-
|
|
1924
|
+
"data-slot": "dropdown-menu-label",
|
|
1925
|
+
"data-inset": inset,
|
|
1926
|
+
className: cn(
|
|
1927
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
1928
|
+
className
|
|
1929
|
+
),
|
|
1749
1930
|
...props
|
|
1750
1931
|
}
|
|
1751
1932
|
);
|
|
1752
1933
|
}
|
|
1753
|
-
function
|
|
1934
|
+
function DropdownMenuSeparator({
|
|
1754
1935
|
className,
|
|
1755
1936
|
...props
|
|
1756
1937
|
}) {
|
|
1757
1938
|
return /* @__PURE__ */ jsx(
|
|
1758
|
-
|
|
1939
|
+
DropdownMenuPrimitive.Separator,
|
|
1759
1940
|
{
|
|
1760
|
-
"data-slot": "
|
|
1761
|
-
className: cn(
|
|
1762
|
-
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
|
1763
|
-
className
|
|
1764
|
-
),
|
|
1941
|
+
"data-slot": "dropdown-menu-separator",
|
|
1942
|
+
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
1765
1943
|
...props
|
|
1766
1944
|
}
|
|
1767
1945
|
);
|
|
1768
1946
|
}
|
|
1769
|
-
function
|
|
1947
|
+
function DropdownMenuShortcut({
|
|
1770
1948
|
className,
|
|
1771
1949
|
...props
|
|
1772
1950
|
}) {
|
|
1773
1951
|
return /* @__PURE__ */ jsx(
|
|
1774
|
-
|
|
1952
|
+
"span",
|
|
1775
1953
|
{
|
|
1776
|
-
"data-slot": "
|
|
1954
|
+
"data-slot": "dropdown-menu-shortcut",
|
|
1777
1955
|
className: cn(
|
|
1778
|
-
"
|
|
1956
|
+
"text-muted-foreground ml-auto text-xs tracking-widest",
|
|
1779
1957
|
className
|
|
1780
1958
|
),
|
|
1781
1959
|
...props
|
|
1782
1960
|
}
|
|
1783
1961
|
);
|
|
1784
1962
|
}
|
|
1785
|
-
function
|
|
1963
|
+
function DropdownMenuSub({
|
|
1964
|
+
...props
|
|
1965
|
+
}) {
|
|
1966
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
1967
|
+
}
|
|
1968
|
+
function DropdownMenuSubTrigger({
|
|
1786
1969
|
className,
|
|
1970
|
+
inset,
|
|
1971
|
+
children,
|
|
1787
1972
|
...props
|
|
1788
1973
|
}) {
|
|
1789
|
-
return /* @__PURE__ */
|
|
1790
|
-
|
|
1974
|
+
return /* @__PURE__ */ jsxs(
|
|
1975
|
+
DropdownMenuPrimitive.SubTrigger,
|
|
1791
1976
|
{
|
|
1792
|
-
"data-slot": "
|
|
1793
|
-
|
|
1794
|
-
|
|
1977
|
+
"data-slot": "dropdown-menu-sub-trigger",
|
|
1978
|
+
"data-inset": inset,
|
|
1979
|
+
className: cn(
|
|
1980
|
+
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1981
|
+
className
|
|
1982
|
+
),
|
|
1983
|
+
...props,
|
|
1984
|
+
children: [
|
|
1985
|
+
children,
|
|
1986
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
1987
|
+
]
|
|
1795
1988
|
}
|
|
1796
1989
|
);
|
|
1797
1990
|
}
|
|
1798
|
-
function
|
|
1991
|
+
function DropdownMenuSubContent({
|
|
1799
1992
|
className,
|
|
1800
|
-
classNames,
|
|
1801
|
-
showOutsideDays = true,
|
|
1802
|
-
captionLayout = "label",
|
|
1803
|
-
formatters,
|
|
1804
|
-
components,
|
|
1805
1993
|
...props
|
|
1806
1994
|
}) {
|
|
1807
|
-
const defaultClassNames = getDefaultClassNames();
|
|
1808
1995
|
return /* @__PURE__ */ jsx(
|
|
1809
|
-
|
|
1996
|
+
DropdownMenuPrimitive.SubContent,
|
|
1810
1997
|
{
|
|
1811
|
-
|
|
1998
|
+
"data-slot": "dropdown-menu-sub-content",
|
|
1812
1999
|
className: cn(
|
|
1813
|
-
"bg-
|
|
1814
|
-
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
1815
|
-
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
2000
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
|
1816
2001
|
className
|
|
1817
2002
|
),
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
"flex items-center
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
dropdowns: cn(
|
|
1847
|
-
"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
|
|
1848
|
-
defaultClassNames.dropdowns
|
|
1849
|
-
),
|
|
1850
|
-
dropdown_root: cn(
|
|
1851
|
-
"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
|
|
1852
|
-
defaultClassNames.dropdown_root
|
|
2003
|
+
...props
|
|
2004
|
+
}
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
function UserAvatarsDropdown({
|
|
2008
|
+
users,
|
|
2009
|
+
selectedUserId,
|
|
2010
|
+
onSelect,
|
|
2011
|
+
maxVisible = 2,
|
|
2012
|
+
label = "All",
|
|
2013
|
+
className
|
|
2014
|
+
}) {
|
|
2015
|
+
const visibleUsers = users.slice(0, maxVisible);
|
|
2016
|
+
const overflowCount = Math.max(0, users.length - maxVisible);
|
|
2017
|
+
const getInitials = (name) => {
|
|
2018
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
2019
|
+
};
|
|
2020
|
+
const selectedUser = users.find((u) => u.id === selectedUserId);
|
|
2021
|
+
const displayLabel = selectedUserId ? selectedUser?.name || "User" : label;
|
|
2022
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2023
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
2024
|
+
"button",
|
|
2025
|
+
{
|
|
2026
|
+
type: "button",
|
|
2027
|
+
className: cn(
|
|
2028
|
+
"flex items-center gap-2 rounded border border-border bg-background px-3 py-1.5 text-sm transition-colors",
|
|
2029
|
+
"hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2030
|
+
className
|
|
1853
2031
|
),
|
|
1854
|
-
|
|
1855
|
-
"
|
|
2032
|
+
children: [
|
|
2033
|
+
/* @__PURE__ */ jsxs("div", { className: "flex -space-x-2", children: [
|
|
2034
|
+
visibleUsers.map((user) => /* @__PURE__ */ jsxs(
|
|
2035
|
+
Avatar,
|
|
2036
|
+
{
|
|
2037
|
+
className: "size-6 border-2 border-background",
|
|
2038
|
+
children: [
|
|
2039
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }),
|
|
2040
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px]", children: getInitials(user.name) })
|
|
2041
|
+
]
|
|
2042
|
+
},
|
|
2043
|
+
user.id
|
|
2044
|
+
)),
|
|
2045
|
+
overflowCount > 0 && /* @__PURE__ */ jsxs("div", { className: "flex size-6 items-center justify-center rounded-full border-2 border-background bg-muted text-[10px] font-medium", children: [
|
|
2046
|
+
"+",
|
|
2047
|
+
overflowCount
|
|
2048
|
+
] })
|
|
2049
|
+
] }),
|
|
2050
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: displayLabel }),
|
|
2051
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 text-muted-foreground" })
|
|
2052
|
+
]
|
|
2053
|
+
}
|
|
2054
|
+
) }),
|
|
2055
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-48", children: [
|
|
2056
|
+
/* @__PURE__ */ jsxs(
|
|
2057
|
+
DropdownMenuItem,
|
|
2058
|
+
{
|
|
2059
|
+
onClick: () => onSelect(null),
|
|
2060
|
+
className: "flex items-center justify-between",
|
|
2061
|
+
children: [
|
|
2062
|
+
/* @__PURE__ */ jsx("span", { children: "All users" }),
|
|
2063
|
+
selectedUserId === null && /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" })
|
|
2064
|
+
]
|
|
2065
|
+
}
|
|
2066
|
+
),
|
|
2067
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
2068
|
+
users.map((user) => /* @__PURE__ */ jsxs(
|
|
2069
|
+
DropdownMenuItem,
|
|
2070
|
+
{
|
|
2071
|
+
onClick: () => onSelect(user.id),
|
|
2072
|
+
className: "flex items-center justify-between",
|
|
2073
|
+
children: [
|
|
2074
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2075
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-5", children: [
|
|
2076
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }),
|
|
2077
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[8px]", children: getInitials(user.name) })
|
|
2078
|
+
] }),
|
|
2079
|
+
/* @__PURE__ */ jsx("span", { children: user.name })
|
|
2080
|
+
] }),
|
|
2081
|
+
selectedUserId === user.id && /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" })
|
|
2082
|
+
]
|
|
2083
|
+
},
|
|
2084
|
+
user.id
|
|
2085
|
+
))
|
|
2086
|
+
] })
|
|
2087
|
+
] });
|
|
2088
|
+
}
|
|
2089
|
+
function Skeleton({ className, ...props }) {
|
|
2090
|
+
return /* @__PURE__ */ jsx(
|
|
2091
|
+
"div",
|
|
2092
|
+
{
|
|
2093
|
+
"data-slot": "skeleton",
|
|
2094
|
+
className: cn("bg-accent animate-pulse rounded-md", className),
|
|
2095
|
+
...props
|
|
2096
|
+
}
|
|
2097
|
+
);
|
|
2098
|
+
}
|
|
2099
|
+
function Accordion({
|
|
2100
|
+
...props
|
|
2101
|
+
}) {
|
|
2102
|
+
return /* @__PURE__ */ jsx(AccordionPrimitive.Root, { "data-slot": "accordion", ...props });
|
|
2103
|
+
}
|
|
2104
|
+
function AccordionItem({
|
|
2105
|
+
className,
|
|
2106
|
+
...props
|
|
2107
|
+
}) {
|
|
2108
|
+
return /* @__PURE__ */ jsx(
|
|
2109
|
+
AccordionPrimitive.Item,
|
|
2110
|
+
{
|
|
2111
|
+
"data-slot": "accordion-item",
|
|
2112
|
+
className: cn("border-b last:border-b-0", className),
|
|
2113
|
+
...props
|
|
2114
|
+
}
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
function AccordionTrigger({
|
|
2118
|
+
className,
|
|
2119
|
+
children,
|
|
2120
|
+
...props
|
|
2121
|
+
}) {
|
|
2122
|
+
return /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
|
|
2123
|
+
AccordionPrimitive.Trigger,
|
|
2124
|
+
{
|
|
2125
|
+
"data-slot": "accordion-trigger",
|
|
2126
|
+
className: cn(
|
|
2127
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
|
|
2128
|
+
className
|
|
2129
|
+
),
|
|
2130
|
+
...props,
|
|
2131
|
+
children: [
|
|
2132
|
+
children,
|
|
2133
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" })
|
|
2134
|
+
]
|
|
2135
|
+
}
|
|
2136
|
+
) });
|
|
2137
|
+
}
|
|
2138
|
+
function AccordionContent({
|
|
2139
|
+
className,
|
|
2140
|
+
children,
|
|
2141
|
+
...props
|
|
2142
|
+
}) {
|
|
2143
|
+
return /* @__PURE__ */ jsx(
|
|
2144
|
+
AccordionPrimitive.Content,
|
|
2145
|
+
{
|
|
2146
|
+
"data-slot": "accordion-content",
|
|
2147
|
+
className: "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm",
|
|
2148
|
+
...props,
|
|
2149
|
+
children: /* @__PURE__ */ jsx("div", { className: cn("pt-0 pb-4", className), children })
|
|
2150
|
+
}
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
function Tabs({
|
|
2154
|
+
className,
|
|
2155
|
+
...props
|
|
2156
|
+
}) {
|
|
2157
|
+
return /* @__PURE__ */ jsx(
|
|
2158
|
+
TabsPrimitive.Root,
|
|
2159
|
+
{
|
|
2160
|
+
"data-slot": "tabs",
|
|
2161
|
+
className: cn("flex flex-col gap-2", className),
|
|
2162
|
+
...props
|
|
2163
|
+
}
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
function TabsList({
|
|
2167
|
+
className,
|
|
2168
|
+
...props
|
|
2169
|
+
}) {
|
|
2170
|
+
return /* @__PURE__ */ jsx(
|
|
2171
|
+
TabsPrimitive.List,
|
|
2172
|
+
{
|
|
2173
|
+
"data-slot": "tabs-list",
|
|
2174
|
+
className: cn(
|
|
2175
|
+
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px] dark:bg-[#1a1a1a]",
|
|
2176
|
+
className
|
|
2177
|
+
),
|
|
2178
|
+
...props
|
|
2179
|
+
}
|
|
2180
|
+
);
|
|
2181
|
+
}
|
|
2182
|
+
function TabsTrigger({
|
|
2183
|
+
className,
|
|
2184
|
+
...props
|
|
2185
|
+
}) {
|
|
2186
|
+
return /* @__PURE__ */ jsx(
|
|
2187
|
+
TabsPrimitive.Trigger,
|
|
2188
|
+
{
|
|
2189
|
+
"data-slot": "tabs-trigger",
|
|
2190
|
+
className: cn(
|
|
2191
|
+
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-input data-[state=inactive]:hover:bg-accent data-[state=inactive]:hover:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
2192
|
+
className
|
|
2193
|
+
),
|
|
2194
|
+
...props
|
|
2195
|
+
}
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
function TabsContent({
|
|
2199
|
+
className,
|
|
2200
|
+
...props
|
|
2201
|
+
}) {
|
|
2202
|
+
return /* @__PURE__ */ jsx(
|
|
2203
|
+
TabsPrimitive.Content,
|
|
2204
|
+
{
|
|
2205
|
+
"data-slot": "tabs-content",
|
|
2206
|
+
className: cn("flex-1 outline-none", className),
|
|
2207
|
+
...props
|
|
2208
|
+
}
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
2211
|
+
function Calendar({
|
|
2212
|
+
className,
|
|
2213
|
+
classNames,
|
|
2214
|
+
showOutsideDays = true,
|
|
2215
|
+
captionLayout = "label",
|
|
2216
|
+
formatters,
|
|
2217
|
+
components,
|
|
2218
|
+
...props
|
|
2219
|
+
}) {
|
|
2220
|
+
const defaultClassNames = getDefaultClassNames();
|
|
2221
|
+
return /* @__PURE__ */ jsx(
|
|
2222
|
+
DayPicker,
|
|
2223
|
+
{
|
|
2224
|
+
showOutsideDays,
|
|
2225
|
+
className: cn(
|
|
2226
|
+
"bg-card group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent",
|
|
2227
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
2228
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
2229
|
+
className
|
|
2230
|
+
),
|
|
2231
|
+
captionLayout,
|
|
2232
|
+
formatters: {
|
|
2233
|
+
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
|
2234
|
+
...formatters
|
|
2235
|
+
},
|
|
2236
|
+
classNames: {
|
|
2237
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
2238
|
+
months: cn(
|
|
2239
|
+
"flex gap-4 flex-col md:flex-row relative",
|
|
2240
|
+
defaultClassNames.months
|
|
2241
|
+
),
|
|
2242
|
+
month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
|
|
2243
|
+
nav: cn(
|
|
2244
|
+
"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
|
|
2245
|
+
defaultClassNames.nav
|
|
2246
|
+
),
|
|
2247
|
+
button_previous: cn(
|
|
2248
|
+
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none inline-flex items-center justify-center rounded-full hover:bg-muted/50 transition-colors",
|
|
2249
|
+
defaultClassNames.button_previous
|
|
2250
|
+
),
|
|
2251
|
+
button_next: cn(
|
|
2252
|
+
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none inline-flex items-center justify-center rounded-full hover:bg-muted/50 transition-colors",
|
|
2253
|
+
defaultClassNames.button_next
|
|
2254
|
+
),
|
|
2255
|
+
month_caption: cn(
|
|
2256
|
+
"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
|
|
2257
|
+
defaultClassNames.month_caption
|
|
2258
|
+
),
|
|
2259
|
+
dropdowns: cn(
|
|
2260
|
+
"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
|
|
2261
|
+
defaultClassNames.dropdowns
|
|
2262
|
+
),
|
|
2263
|
+
dropdown_root: cn(
|
|
2264
|
+
"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
|
|
2265
|
+
defaultClassNames.dropdown_root
|
|
2266
|
+
),
|
|
2267
|
+
dropdown: cn(
|
|
2268
|
+
"absolute bg-popover inset-0 opacity-0",
|
|
1856
2269
|
defaultClassNames.dropdown
|
|
1857
2270
|
),
|
|
1858
2271
|
caption_label: cn(
|
|
@@ -1944,8 +2357,8 @@ function CalendarDayButton({
|
|
|
1944
2357
|
modifiers,
|
|
1945
2358
|
...props
|
|
1946
2359
|
}) {
|
|
1947
|
-
const ref =
|
|
1948
|
-
|
|
2360
|
+
const ref = React15.useRef(null);
|
|
2361
|
+
React15.useEffect(() => {
|
|
1949
2362
|
if (modifiers.focused) ref.current?.focus();
|
|
1950
2363
|
}, [modifiers.focused]);
|
|
1951
2364
|
return /* @__PURE__ */ jsx(
|
|
@@ -1966,9 +2379,9 @@ function CalendarDayButton({
|
|
|
1966
2379
|
}
|
|
1967
2380
|
);
|
|
1968
2381
|
}
|
|
1969
|
-
var CarouselContext =
|
|
2382
|
+
var CarouselContext = React15.createContext(null);
|
|
1970
2383
|
function useCarousel() {
|
|
1971
|
-
const context =
|
|
2384
|
+
const context = React15.useContext(CarouselContext);
|
|
1972
2385
|
if (!context) {
|
|
1973
2386
|
throw new Error("useCarousel must be used within a <Carousel />");
|
|
1974
2387
|
}
|
|
@@ -1990,20 +2403,20 @@ function Carousel({
|
|
|
1990
2403
|
},
|
|
1991
2404
|
plugins
|
|
1992
2405
|
);
|
|
1993
|
-
const [canScrollPrev, setCanScrollPrev] =
|
|
1994
|
-
const [canScrollNext, setCanScrollNext] =
|
|
1995
|
-
const onSelect =
|
|
2406
|
+
const [canScrollPrev, setCanScrollPrev] = React15.useState(false);
|
|
2407
|
+
const [canScrollNext, setCanScrollNext] = React15.useState(false);
|
|
2408
|
+
const onSelect = React15.useCallback((api2) => {
|
|
1996
2409
|
if (!api2) return;
|
|
1997
2410
|
setCanScrollPrev(api2.canScrollPrev());
|
|
1998
2411
|
setCanScrollNext(api2.canScrollNext());
|
|
1999
2412
|
}, []);
|
|
2000
|
-
const scrollPrev =
|
|
2413
|
+
const scrollPrev = React15.useCallback(() => {
|
|
2001
2414
|
api?.scrollPrev();
|
|
2002
2415
|
}, [api]);
|
|
2003
|
-
const scrollNext =
|
|
2416
|
+
const scrollNext = React15.useCallback(() => {
|
|
2004
2417
|
api?.scrollNext();
|
|
2005
2418
|
}, [api]);
|
|
2006
|
-
const handleKeyDown =
|
|
2419
|
+
const handleKeyDown = React15.useCallback(
|
|
2007
2420
|
(event) => {
|
|
2008
2421
|
if (event.key === "ArrowLeft") {
|
|
2009
2422
|
event.preventDefault();
|
|
@@ -2015,11 +2428,11 @@ function Carousel({
|
|
|
2015
2428
|
},
|
|
2016
2429
|
[scrollPrev, scrollNext]
|
|
2017
2430
|
);
|
|
2018
|
-
|
|
2431
|
+
React15.useEffect(() => {
|
|
2019
2432
|
if (!api || !setApi) return;
|
|
2020
2433
|
setApi(api);
|
|
2021
2434
|
}, [api, setApi]);
|
|
2022
|
-
|
|
2435
|
+
React15.useEffect(() => {
|
|
2023
2436
|
if (!api) return;
|
|
2024
2437
|
onSelect(api);
|
|
2025
2438
|
api.on("reInit", onSelect);
|
|
@@ -2152,9 +2565,9 @@ function CarouselNext({
|
|
|
2152
2565
|
);
|
|
2153
2566
|
}
|
|
2154
2567
|
var THEMES = { light: "", dark: ".dark" };
|
|
2155
|
-
var ChartContext =
|
|
2568
|
+
var ChartContext = React15.createContext(null);
|
|
2156
2569
|
function useChart() {
|
|
2157
|
-
const context =
|
|
2570
|
+
const context = React15.useContext(ChartContext);
|
|
2158
2571
|
if (!context) {
|
|
2159
2572
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
2160
2573
|
}
|
|
@@ -2167,7 +2580,7 @@ function ChartContainer({
|
|
|
2167
2580
|
config,
|
|
2168
2581
|
...props
|
|
2169
2582
|
}) {
|
|
2170
|
-
const uniqueId =
|
|
2583
|
+
const uniqueId = React15.useId();
|
|
2171
2584
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
2172
2585
|
return /* @__PURE__ */ jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs(
|
|
2173
2586
|
"div",
|
|
@@ -2228,7 +2641,7 @@ function ChartTooltipContent({
|
|
|
2228
2641
|
labelKey
|
|
2229
2642
|
}) {
|
|
2230
2643
|
const { config } = useChart();
|
|
2231
|
-
const tooltipLabel =
|
|
2644
|
+
const tooltipLabel = React15.useMemo(() => {
|
|
2232
2645
|
if (hideLabel || !payload?.length) {
|
|
2233
2646
|
return null;
|
|
2234
2647
|
}
|
|
@@ -2522,7 +2935,7 @@ var itemVariants = cva(
|
|
|
2522
2935
|
}
|
|
2523
2936
|
}
|
|
2524
2937
|
);
|
|
2525
|
-
function
|
|
2938
|
+
function Item6({
|
|
2526
2939
|
className,
|
|
2527
2940
|
variant = "default",
|
|
2528
2941
|
size = "default",
|
|
@@ -2930,40 +3343,27 @@ function TooltipContent({
|
|
|
2930
3343
|
}
|
|
2931
3344
|
) });
|
|
2932
3345
|
}
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
var x = React7.createContext(void 0);
|
|
2955
|
-
var U = { setTheme: (e) => {
|
|
2956
|
-
}, themes: [] };
|
|
2957
|
-
var z = () => {
|
|
2958
|
-
var e;
|
|
2959
|
-
return (e = React7.useContext(x)) != null ? e : U;
|
|
2960
|
-
};
|
|
2961
|
-
React7.memo(({ forcedTheme: e, storageKey: i, attribute: s, enableSystem: u, enableColorScheme: m, defaultTheme: a, value: l, themes: h, nonce: d, scriptProps: w }) => {
|
|
2962
|
-
let p = JSON.stringify([s, i, a, e, h, l, u, m]).slice(1, -1);
|
|
2963
|
-
return React7.createElement("script", { ...w, suppressHydrationWarning: true, nonce: typeof window == "undefined" ? d : "", dangerouslySetInnerHTML: { __html: `(${M.toString()})(${p})` } });
|
|
2964
|
-
});
|
|
2965
|
-
var Toaster = ({ ...props }) => {
|
|
2966
|
-
const { theme = "system" } = z();
|
|
3346
|
+
function useDetectTheme() {
|
|
3347
|
+
const [theme, setTheme] = React15.useState("light");
|
|
3348
|
+
React15.useEffect(() => {
|
|
3349
|
+
const isDark = document.documentElement.classList.contains("dark");
|
|
3350
|
+
setTheme(isDark ? "dark" : "light");
|
|
3351
|
+
const observer = new MutationObserver((mutations) => {
|
|
3352
|
+
mutations.forEach((mutation) => {
|
|
3353
|
+
if (mutation.attributeName === "class") {
|
|
3354
|
+
const isDark2 = document.documentElement.classList.contains("dark");
|
|
3355
|
+
setTheme(isDark2 ? "dark" : "light");
|
|
3356
|
+
}
|
|
3357
|
+
});
|
|
3358
|
+
});
|
|
3359
|
+
observer.observe(document.documentElement, { attributes: true });
|
|
3360
|
+
return () => observer.disconnect();
|
|
3361
|
+
}, []);
|
|
3362
|
+
return theme;
|
|
3363
|
+
}
|
|
3364
|
+
var Toaster = ({ theme: themeProp, ...props }) => {
|
|
3365
|
+
const detectedTheme = useDetectTheme();
|
|
3366
|
+
const theme = themeProp ?? detectedTheme;
|
|
2967
3367
|
return /* @__PURE__ */ jsx(
|
|
2968
3368
|
Toaster$1,
|
|
2969
3369
|
{
|
|
@@ -3466,241 +3866,78 @@ function CommandShortcut({
|
|
|
3466
3866
|
}
|
|
3467
3867
|
);
|
|
3468
3868
|
}
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3869
|
+
var SearchTrigger = React15.forwardRef(
|
|
3870
|
+
({
|
|
3871
|
+
className,
|
|
3872
|
+
placeholder = "Search...",
|
|
3873
|
+
showShortcut = true,
|
|
3874
|
+
shortcutKey = "K",
|
|
3875
|
+
shortcutModifier = "\u2318",
|
|
3876
|
+
...props
|
|
3877
|
+
}, ref) => {
|
|
3878
|
+
return /* @__PURE__ */ jsxs(
|
|
3879
|
+
Button,
|
|
3880
|
+
{
|
|
3881
|
+
ref,
|
|
3882
|
+
variant: "outline",
|
|
3883
|
+
"data-slot": "search-trigger",
|
|
3884
|
+
className: cn(
|
|
3885
|
+
"relative h-9 w-full justify-start rounded-full bg-background text-sm text-muted-foreground",
|
|
3886
|
+
"sm:w-64 sm:max-w-[280px]",
|
|
3887
|
+
className
|
|
3888
|
+
),
|
|
3889
|
+
...props,
|
|
3890
|
+
children: [
|
|
3891
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "mr-2 h-4 w-4 shrink-0" }),
|
|
3892
|
+
/* @__PURE__ */ jsx("span", { className: "hidden truncate sm:inline-flex", children: placeholder }),
|
|
3893
|
+
/* @__PURE__ */ jsx("span", { className: "truncate sm:hidden", children: "Search" }),
|
|
3894
|
+
showShortcut && /* @__PURE__ */ jsxs(Kbd, { className: "pointer-events-none absolute right-2 hidden h-5 select-none items-center gap-0.5 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium sm:flex", children: [
|
|
3895
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: shortcutModifier }),
|
|
3896
|
+
shortcutKey
|
|
3897
|
+
] })
|
|
3898
|
+
]
|
|
3899
|
+
}
|
|
3900
|
+
);
|
|
3901
|
+
}
|
|
3902
|
+
);
|
|
3903
|
+
SearchTrigger.displayName = "SearchTrigger";
|
|
3904
|
+
function useSearchShortcut(onOpen, key = "k") {
|
|
3905
|
+
React15.useEffect(() => {
|
|
3906
|
+
const down = (e) => {
|
|
3907
|
+
if (e.key.toLowerCase() === key.toLowerCase() && (e.metaKey || e.ctrlKey)) {
|
|
3908
|
+
e.preventDefault();
|
|
3909
|
+
onOpen();
|
|
3910
|
+
}
|
|
3911
|
+
};
|
|
3912
|
+
document.addEventListener("keydown", down);
|
|
3913
|
+
return () => document.removeEventListener("keydown", down);
|
|
3914
|
+
}, [onOpen, key]);
|
|
3478
3915
|
}
|
|
3479
|
-
function
|
|
3916
|
+
function Menubar({
|
|
3917
|
+
className,
|
|
3480
3918
|
...props
|
|
3481
3919
|
}) {
|
|
3482
3920
|
return /* @__PURE__ */ jsx(
|
|
3483
|
-
|
|
3921
|
+
MenubarPrimitive.Root,
|
|
3484
3922
|
{
|
|
3485
|
-
"data-slot": "
|
|
3923
|
+
"data-slot": "menubar",
|
|
3924
|
+
className: cn(
|
|
3925
|
+
"bg-background flex h-9 items-center gap-1 rounded-md border p-1 shadow-xs",
|
|
3926
|
+
className
|
|
3927
|
+
),
|
|
3486
3928
|
...props
|
|
3487
3929
|
}
|
|
3488
3930
|
);
|
|
3489
3931
|
}
|
|
3490
|
-
function
|
|
3491
|
-
className,
|
|
3492
|
-
sideOffset = 4,
|
|
3932
|
+
function MenubarMenu({
|
|
3493
3933
|
...props
|
|
3494
3934
|
}) {
|
|
3495
|
-
return /* @__PURE__ */ jsx(
|
|
3496
|
-
DropdownMenuPrimitive.Content,
|
|
3497
|
-
{
|
|
3498
|
-
"data-slot": "dropdown-menu-content",
|
|
3499
|
-
sideOffset,
|
|
3500
|
-
className: cn(
|
|
3501
|
-
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
|
3502
|
-
className
|
|
3503
|
-
),
|
|
3504
|
-
...props
|
|
3505
|
-
}
|
|
3506
|
-
) });
|
|
3935
|
+
return /* @__PURE__ */ jsx(MenubarPrimitive.Menu, { "data-slot": "menubar-menu", ...props });
|
|
3507
3936
|
}
|
|
3508
|
-
function
|
|
3937
|
+
function MenubarGroup({
|
|
3509
3938
|
...props
|
|
3510
3939
|
}) {
|
|
3511
|
-
return /* @__PURE__ */ jsx(
|
|
3512
|
-
}
|
|
3513
|
-
function DropdownMenuItem({
|
|
3514
|
-
className,
|
|
3515
|
-
inset,
|
|
3516
|
-
variant = "default",
|
|
3517
|
-
...props
|
|
3518
|
-
}) {
|
|
3519
|
-
return /* @__PURE__ */ jsx(
|
|
3520
|
-
DropdownMenuPrimitive.Item,
|
|
3521
|
-
{
|
|
3522
|
-
"data-slot": "dropdown-menu-item",
|
|
3523
|
-
"data-inset": inset,
|
|
3524
|
-
"data-variant": variant,
|
|
3525
|
-
className: cn(
|
|
3526
|
-
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
3527
|
-
className
|
|
3528
|
-
),
|
|
3529
|
-
...props
|
|
3530
|
-
}
|
|
3531
|
-
);
|
|
3532
|
-
}
|
|
3533
|
-
function DropdownMenuCheckboxItem({
|
|
3534
|
-
className,
|
|
3535
|
-
children,
|
|
3536
|
-
checked,
|
|
3537
|
-
...props
|
|
3538
|
-
}) {
|
|
3539
|
-
return /* @__PURE__ */ jsxs(
|
|
3540
|
-
DropdownMenuPrimitive.CheckboxItem,
|
|
3541
|
-
{
|
|
3542
|
-
"data-slot": "dropdown-menu-checkbox-item",
|
|
3543
|
-
className: cn(
|
|
3544
|
-
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
3545
|
-
className
|
|
3546
|
-
),
|
|
3547
|
-
checked,
|
|
3548
|
-
...props,
|
|
3549
|
-
children: [
|
|
3550
|
-
/* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
|
|
3551
|
-
children
|
|
3552
|
-
]
|
|
3553
|
-
}
|
|
3554
|
-
);
|
|
3555
|
-
}
|
|
3556
|
-
function DropdownMenuRadioGroup({
|
|
3557
|
-
...props
|
|
3558
|
-
}) {
|
|
3559
|
-
return /* @__PURE__ */ jsx(
|
|
3560
|
-
DropdownMenuPrimitive.RadioGroup,
|
|
3561
|
-
{
|
|
3562
|
-
"data-slot": "dropdown-menu-radio-group",
|
|
3563
|
-
...props
|
|
3564
|
-
}
|
|
3565
|
-
);
|
|
3566
|
-
}
|
|
3567
|
-
function DropdownMenuRadioItem({
|
|
3568
|
-
className,
|
|
3569
|
-
children,
|
|
3570
|
-
...props
|
|
3571
|
-
}) {
|
|
3572
|
-
return /* @__PURE__ */ jsxs(
|
|
3573
|
-
DropdownMenuPrimitive.RadioItem,
|
|
3574
|
-
{
|
|
3575
|
-
"data-slot": "dropdown-menu-radio-item",
|
|
3576
|
-
className: cn(
|
|
3577
|
-
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
3578
|
-
className
|
|
3579
|
-
),
|
|
3580
|
-
...props,
|
|
3581
|
-
children: [
|
|
3582
|
-
/* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CircleIcon, { className: "size-2 fill-current" }) }) }),
|
|
3583
|
-
children
|
|
3584
|
-
]
|
|
3585
|
-
}
|
|
3586
|
-
);
|
|
3587
|
-
}
|
|
3588
|
-
function DropdownMenuLabel({
|
|
3589
|
-
className,
|
|
3590
|
-
inset,
|
|
3591
|
-
...props
|
|
3592
|
-
}) {
|
|
3593
|
-
return /* @__PURE__ */ jsx(
|
|
3594
|
-
DropdownMenuPrimitive.Label,
|
|
3595
|
-
{
|
|
3596
|
-
"data-slot": "dropdown-menu-label",
|
|
3597
|
-
"data-inset": inset,
|
|
3598
|
-
className: cn(
|
|
3599
|
-
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
3600
|
-
className
|
|
3601
|
-
),
|
|
3602
|
-
...props
|
|
3603
|
-
}
|
|
3604
|
-
);
|
|
3605
|
-
}
|
|
3606
|
-
function DropdownMenuSeparator({
|
|
3607
|
-
className,
|
|
3608
|
-
...props
|
|
3609
|
-
}) {
|
|
3610
|
-
return /* @__PURE__ */ jsx(
|
|
3611
|
-
DropdownMenuPrimitive.Separator,
|
|
3612
|
-
{
|
|
3613
|
-
"data-slot": "dropdown-menu-separator",
|
|
3614
|
-
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
3615
|
-
...props
|
|
3616
|
-
}
|
|
3617
|
-
);
|
|
3618
|
-
}
|
|
3619
|
-
function DropdownMenuShortcut({
|
|
3620
|
-
className,
|
|
3621
|
-
...props
|
|
3622
|
-
}) {
|
|
3623
|
-
return /* @__PURE__ */ jsx(
|
|
3624
|
-
"span",
|
|
3625
|
-
{
|
|
3626
|
-
"data-slot": "dropdown-menu-shortcut",
|
|
3627
|
-
className: cn(
|
|
3628
|
-
"text-muted-foreground ml-auto text-xs tracking-widest",
|
|
3629
|
-
className
|
|
3630
|
-
),
|
|
3631
|
-
...props
|
|
3632
|
-
}
|
|
3633
|
-
);
|
|
3634
|
-
}
|
|
3635
|
-
function DropdownMenuSub({
|
|
3636
|
-
...props
|
|
3637
|
-
}) {
|
|
3638
|
-
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
3639
|
-
}
|
|
3640
|
-
function DropdownMenuSubTrigger({
|
|
3641
|
-
className,
|
|
3642
|
-
inset,
|
|
3643
|
-
children,
|
|
3644
|
-
...props
|
|
3645
|
-
}) {
|
|
3646
|
-
return /* @__PURE__ */ jsxs(
|
|
3647
|
-
DropdownMenuPrimitive.SubTrigger,
|
|
3648
|
-
{
|
|
3649
|
-
"data-slot": "dropdown-menu-sub-trigger",
|
|
3650
|
-
"data-inset": inset,
|
|
3651
|
-
className: cn(
|
|
3652
|
-
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
3653
|
-
className
|
|
3654
|
-
),
|
|
3655
|
-
...props,
|
|
3656
|
-
children: [
|
|
3657
|
-
children,
|
|
3658
|
-
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
3659
|
-
]
|
|
3660
|
-
}
|
|
3661
|
-
);
|
|
3662
|
-
}
|
|
3663
|
-
function DropdownMenuSubContent({
|
|
3664
|
-
className,
|
|
3665
|
-
...props
|
|
3666
|
-
}) {
|
|
3667
|
-
return /* @__PURE__ */ jsx(
|
|
3668
|
-
DropdownMenuPrimitive.SubContent,
|
|
3669
|
-
{
|
|
3670
|
-
"data-slot": "dropdown-menu-sub-content",
|
|
3671
|
-
className: cn(
|
|
3672
|
-
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
|
3673
|
-
className
|
|
3674
|
-
),
|
|
3675
|
-
...props
|
|
3676
|
-
}
|
|
3677
|
-
);
|
|
3678
|
-
}
|
|
3679
|
-
function Menubar({
|
|
3680
|
-
className,
|
|
3681
|
-
...props
|
|
3682
|
-
}) {
|
|
3683
|
-
return /* @__PURE__ */ jsx(
|
|
3684
|
-
MenubarPrimitive.Root,
|
|
3685
|
-
{
|
|
3686
|
-
"data-slot": "menubar",
|
|
3687
|
-
className: cn(
|
|
3688
|
-
"bg-background flex h-9 items-center gap-1 rounded-md border p-1 shadow-xs",
|
|
3689
|
-
className
|
|
3690
|
-
),
|
|
3691
|
-
...props
|
|
3692
|
-
}
|
|
3693
|
-
);
|
|
3694
|
-
}
|
|
3695
|
-
function MenubarMenu({
|
|
3696
|
-
...props
|
|
3697
|
-
}) {
|
|
3698
|
-
return /* @__PURE__ */ jsx(MenubarPrimitive.Menu, { "data-slot": "menubar-menu", ...props });
|
|
3699
|
-
}
|
|
3700
|
-
function MenubarGroup({
|
|
3701
|
-
...props
|
|
3702
|
-
}) {
|
|
3703
|
-
return /* @__PURE__ */ jsx(MenubarPrimitive.Group, { "data-slot": "menubar-group", ...props });
|
|
3940
|
+
return /* @__PURE__ */ jsx(MenubarPrimitive.Group, { "data-slot": "menubar-group", ...props });
|
|
3704
3941
|
}
|
|
3705
3942
|
function MenubarPortal({
|
|
3706
3943
|
...props
|
|
@@ -4693,9 +4930,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
4693
4930
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
4694
4931
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
4695
4932
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
4696
|
-
var SidebarContext =
|
|
4933
|
+
var SidebarContext = React15.createContext(null);
|
|
4697
4934
|
function useSidebar() {
|
|
4698
|
-
const context =
|
|
4935
|
+
const context = React15.useContext(SidebarContext);
|
|
4699
4936
|
if (!context) {
|
|
4700
4937
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
4701
4938
|
}
|
|
@@ -4711,10 +4948,10 @@ function SidebarProvider({
|
|
|
4711
4948
|
...props
|
|
4712
4949
|
}) {
|
|
4713
4950
|
const isMobile = useIsMobile();
|
|
4714
|
-
const [openMobile, setOpenMobile] =
|
|
4715
|
-
const [_open, _setOpen] =
|
|
4951
|
+
const [openMobile, setOpenMobile] = React15.useState(false);
|
|
4952
|
+
const [_open, _setOpen] = React15.useState(defaultOpen);
|
|
4716
4953
|
const open = openProp ?? _open;
|
|
4717
|
-
const setOpen =
|
|
4954
|
+
const setOpen = React15.useCallback(
|
|
4718
4955
|
(value) => {
|
|
4719
4956
|
const openState = typeof value === "function" ? value(open) : value;
|
|
4720
4957
|
if (setOpenProp) {
|
|
@@ -4726,10 +4963,10 @@ function SidebarProvider({
|
|
|
4726
4963
|
},
|
|
4727
4964
|
[setOpenProp, open]
|
|
4728
4965
|
);
|
|
4729
|
-
const toggleSidebar =
|
|
4966
|
+
const toggleSidebar = React15.useCallback(() => {
|
|
4730
4967
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
4731
4968
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
4732
|
-
|
|
4969
|
+
React15.useEffect(() => {
|
|
4733
4970
|
const handleKeyDown = (event) => {
|
|
4734
4971
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
4735
4972
|
event.preventDefault();
|
|
@@ -4740,7 +4977,7 @@ function SidebarProvider({
|
|
|
4740
4977
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4741
4978
|
}, [toggleSidebar]);
|
|
4742
4979
|
const state = open ? "expanded" : "collapsed";
|
|
4743
|
-
const contextValue =
|
|
4980
|
+
const contextValue = React15.useMemo(
|
|
4744
4981
|
() => ({
|
|
4745
4982
|
state,
|
|
4746
4983
|
open,
|
|
@@ -5198,7 +5435,7 @@ function SidebarMenuSkeleton({
|
|
|
5198
5435
|
showIcon = false,
|
|
5199
5436
|
...props
|
|
5200
5437
|
}) {
|
|
5201
|
-
const width =
|
|
5438
|
+
const width = React15.useMemo(() => {
|
|
5202
5439
|
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
5203
5440
|
}, []);
|
|
5204
5441
|
return /* @__PURE__ */ jsxs(
|
|
@@ -5296,8 +5533,7 @@ var sectionVariants = cva(
|
|
|
5296
5533
|
default: [
|
|
5297
5534
|
"bg-[var(--color-bg-surface)]",
|
|
5298
5535
|
"border border-[var(--color-border-subtle)]",
|
|
5299
|
-
"text-[var(--color-text-main)]"
|
|
5300
|
-
"shadow-sm"
|
|
5536
|
+
"text-[var(--color-text-main)]"
|
|
5301
5537
|
].join(" "),
|
|
5302
5538
|
// Glass Light - frosted glass for dark or image backgrounds
|
|
5303
5539
|
"glass-light": [
|
|
@@ -5342,7 +5578,7 @@ var sectionVariants = cva(
|
|
|
5342
5578
|
}
|
|
5343
5579
|
);
|
|
5344
5580
|
var isGlassVariant = (variant) => variant?.startsWith("glass-") ?? false;
|
|
5345
|
-
var Section =
|
|
5581
|
+
var Section = React15.forwardRef(
|
|
5346
5582
|
({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5347
5583
|
"section",
|
|
5348
5584
|
{
|
|
@@ -5354,7 +5590,7 @@ var Section = React7.forwardRef(
|
|
|
5354
5590
|
)
|
|
5355
5591
|
);
|
|
5356
5592
|
Section.displayName = "Section";
|
|
5357
|
-
var SectionHeader =
|
|
5593
|
+
var SectionHeader = React15.forwardRef(
|
|
5358
5594
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5359
5595
|
"div",
|
|
5360
5596
|
{
|
|
@@ -5369,7 +5605,7 @@ var SectionHeader = React7.forwardRef(
|
|
|
5369
5605
|
)
|
|
5370
5606
|
);
|
|
5371
5607
|
SectionHeader.displayName = "SectionHeader";
|
|
5372
|
-
var SectionTitle =
|
|
5608
|
+
var SectionTitle = React15.forwardRef(
|
|
5373
5609
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5374
5610
|
"h2",
|
|
5375
5611
|
{
|
|
@@ -5383,7 +5619,7 @@ var SectionTitle = React7.forwardRef(
|
|
|
5383
5619
|
)
|
|
5384
5620
|
);
|
|
5385
5621
|
SectionTitle.displayName = "SectionTitle";
|
|
5386
|
-
var SectionDescription =
|
|
5622
|
+
var SectionDescription = React15.forwardRef(
|
|
5387
5623
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5388
5624
|
"p",
|
|
5389
5625
|
{
|
|
@@ -5397,7 +5633,7 @@ var SectionDescription = React7.forwardRef(
|
|
|
5397
5633
|
)
|
|
5398
5634
|
);
|
|
5399
5635
|
SectionDescription.displayName = "SectionDescription";
|
|
5400
|
-
var SectionContent =
|
|
5636
|
+
var SectionContent = React15.forwardRef(
|
|
5401
5637
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5402
5638
|
"div",
|
|
5403
5639
|
{
|
|
@@ -5411,7 +5647,7 @@ var SectionContent = React7.forwardRef(
|
|
|
5411
5647
|
)
|
|
5412
5648
|
);
|
|
5413
5649
|
SectionContent.displayName = "SectionContent";
|
|
5414
|
-
var SectionFooter =
|
|
5650
|
+
var SectionFooter = React15.forwardRef(
|
|
5415
5651
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5416
5652
|
"div",
|
|
5417
5653
|
{
|
|
@@ -5427,7 +5663,3182 @@ var SectionFooter = React7.forwardRef(
|
|
|
5427
5663
|
)
|
|
5428
5664
|
);
|
|
5429
5665
|
SectionFooter.displayName = "SectionFooter";
|
|
5666
|
+
function SearchForm({ ...props }) {
|
|
5667
|
+
return /* @__PURE__ */ jsx("form", { ...props, children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
5668
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "search", className: "sr-only", children: "Search" }),
|
|
5669
|
+
/* @__PURE__ */ jsx(
|
|
5670
|
+
SidebarInput,
|
|
5671
|
+
{
|
|
5672
|
+
id: "search",
|
|
5673
|
+
placeholder: "Type to search...",
|
|
5674
|
+
className: "h-8 pl-7"
|
|
5675
|
+
}
|
|
5676
|
+
),
|
|
5677
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 opacity-50 select-none" })
|
|
5678
|
+
] }) });
|
|
5679
|
+
}
|
|
5680
|
+
function SiteHeader({
|
|
5681
|
+
trigger,
|
|
5682
|
+
breadcrumbs = [
|
|
5683
|
+
{ label: "Building Your Application", href: "#" },
|
|
5684
|
+
{ label: "Data Fetching" }
|
|
5685
|
+
],
|
|
5686
|
+
showSearch = true,
|
|
5687
|
+
className,
|
|
5688
|
+
children
|
|
5689
|
+
}) {
|
|
5690
|
+
return /* @__PURE__ */ jsx(
|
|
5691
|
+
"header",
|
|
5692
|
+
{
|
|
5693
|
+
"data-slot": "site-header",
|
|
5694
|
+
className: cn(
|
|
5695
|
+
"bg-sidebar text-sidebar-foreground sticky top-0 z-50 flex w-full items-center border-b border-sidebar-border",
|
|
5696
|
+
className
|
|
5697
|
+
),
|
|
5698
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex h-[var(--header-height,3.5rem)] w-full items-center gap-[var(--j3m-spacing-s)] px-[var(--j3m-spacing-m)]", children: [
|
|
5699
|
+
trigger,
|
|
5700
|
+
trigger && /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mr-[var(--j3m-spacing-s)] h-4" }),
|
|
5701
|
+
/* @__PURE__ */ jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxs(React15.Fragment, { children: [
|
|
5702
|
+
index > 0 && /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
|
|
5703
|
+
/* @__PURE__ */ jsx(BreadcrumbItem, { children: item.href ? /* @__PURE__ */ jsx(BreadcrumbLink, { href: item.href, children: item.label }) : /* @__PURE__ */ jsx(BreadcrumbPage, { children: item.label }) })
|
|
5704
|
+
] }, index)) }) }),
|
|
5705
|
+
showSearch && /* @__PURE__ */ jsx(SearchForm, { className: "w-full sm:ml-auto sm:w-auto" }),
|
|
5706
|
+
children
|
|
5707
|
+
] })
|
|
5708
|
+
}
|
|
5709
|
+
);
|
|
5710
|
+
}
|
|
5711
|
+
function NavMain({ items, label = "Platform" }) {
|
|
5712
|
+
return /* @__PURE__ */ jsxs(SidebarGroup, { children: [
|
|
5713
|
+
/* @__PURE__ */ jsx(SidebarGroupLabel, { children: label }),
|
|
5714
|
+
/* @__PURE__ */ jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsx(Collapsible, { asChild: true, defaultOpen: item.isActive, children: /* @__PURE__ */ jsxs(SidebarMenuItem, { children: [
|
|
5715
|
+
/* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, tooltip: item.title, children: /* @__PURE__ */ jsxs("a", { href: item.url, children: [
|
|
5716
|
+
item.icon && /* @__PURE__ */ jsx(item.icon, {}),
|
|
5717
|
+
/* @__PURE__ */ jsx("span", { children: item.title })
|
|
5718
|
+
] }) }),
|
|
5719
|
+
item.items?.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5720
|
+
/* @__PURE__ */ jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs(SidebarMenuAction, { className: "data-[state=open]:rotate-90", children: [
|
|
5721
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, {}),
|
|
5722
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle" })
|
|
5723
|
+
] }) }),
|
|
5724
|
+
/* @__PURE__ */ jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: item.items?.map((subItem) => /* @__PURE__ */ jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsx(SidebarMenuSubButton, { asChild: true, children: /* @__PURE__ */ jsx("a", { href: subItem.url, children: /* @__PURE__ */ jsx("span", { children: subItem.title }) }) }) }, subItem.title)) }) })
|
|
5725
|
+
] }) : null
|
|
5726
|
+
] }) }, item.title)) })
|
|
5727
|
+
] });
|
|
5728
|
+
}
|
|
5729
|
+
function NavProjects({ projects, label = "Projects" }) {
|
|
5730
|
+
return /* @__PURE__ */ jsxs(SidebarGroup, { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
5731
|
+
/* @__PURE__ */ jsx(SidebarGroupLabel, { children: label }),
|
|
5732
|
+
/* @__PURE__ */ jsxs(SidebarMenu, { children: [
|
|
5733
|
+
projects.map((item) => /* @__PURE__ */ jsxs(SidebarMenuItem, { children: [
|
|
5734
|
+
/* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxs("a", { href: item.url, children: [
|
|
5735
|
+
/* @__PURE__ */ jsx(item.icon, {}),
|
|
5736
|
+
/* @__PURE__ */ jsx("span", { children: item.name })
|
|
5737
|
+
] }) }),
|
|
5738
|
+
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
5739
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(SidebarMenuAction, { showOnHover: true, children: [
|
|
5740
|
+
/* @__PURE__ */ jsx(MoreHorizontalIcon, {}),
|
|
5741
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "More" })
|
|
5742
|
+
] }) }),
|
|
5743
|
+
/* @__PURE__ */ jsxs(
|
|
5744
|
+
DropdownMenuContent,
|
|
5745
|
+
{
|
|
5746
|
+
className: "w-48 rounded-[var(--j3m-radius-m)]",
|
|
5747
|
+
side: "right",
|
|
5748
|
+
align: "start",
|
|
5749
|
+
sideOffset: 8,
|
|
5750
|
+
children: [
|
|
5751
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5752
|
+
/* @__PURE__ */ jsx(FolderIcon, { className: "text-muted-foreground" }),
|
|
5753
|
+
/* @__PURE__ */ jsx("span", { children: "View Project" })
|
|
5754
|
+
] }),
|
|
5755
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5756
|
+
/* @__PURE__ */ jsx(ShareIcon, { className: "text-muted-foreground" }),
|
|
5757
|
+
/* @__PURE__ */ jsx("span", { children: "Share Project" })
|
|
5758
|
+
] }),
|
|
5759
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5760
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5761
|
+
/* @__PURE__ */ jsx(TrashIcon, { className: "text-muted-foreground" }),
|
|
5762
|
+
/* @__PURE__ */ jsx("span", { children: "Delete Project" })
|
|
5763
|
+
] })
|
|
5764
|
+
]
|
|
5765
|
+
}
|
|
5766
|
+
)
|
|
5767
|
+
] })
|
|
5768
|
+
] }, item.name)),
|
|
5769
|
+
/* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, { className: "text-sidebar-foreground/70", children: [
|
|
5770
|
+
/* @__PURE__ */ jsx(MoreHorizontalIcon, { className: "text-sidebar-foreground/70" }),
|
|
5771
|
+
/* @__PURE__ */ jsx("span", { children: "More" })
|
|
5772
|
+
] }) })
|
|
5773
|
+
] })
|
|
5774
|
+
] });
|
|
5775
|
+
}
|
|
5776
|
+
function NavSecondary({ items, ...props }) {
|
|
5777
|
+
return /* @__PURE__ */ jsx(SidebarGroup, { ...props, children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, size: "sm", children: /* @__PURE__ */ jsxs("a", { href: item.url, children: [
|
|
5778
|
+
/* @__PURE__ */ jsx(item.icon, {}),
|
|
5779
|
+
/* @__PURE__ */ jsx("span", { children: item.title })
|
|
5780
|
+
] }) }) }, item.title)) }) }) });
|
|
5781
|
+
}
|
|
5782
|
+
function NavUser({ user }) {
|
|
5783
|
+
return /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
5784
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
5785
|
+
SidebarMenuButton,
|
|
5786
|
+
{
|
|
5787
|
+
size: "lg",
|
|
5788
|
+
className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
|
|
5789
|
+
children: [
|
|
5790
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
5791
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
5792
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
5793
|
+
] }),
|
|
5794
|
+
/* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
5795
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
5796
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs", children: user.email })
|
|
5797
|
+
] }),
|
|
5798
|
+
/* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "ml-auto size-4" })
|
|
5799
|
+
]
|
|
5800
|
+
}
|
|
5801
|
+
) }),
|
|
5802
|
+
/* @__PURE__ */ jsxs(
|
|
5803
|
+
DropdownMenuContent,
|
|
5804
|
+
{
|
|
5805
|
+
className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-[var(--j3m-radius-m)]",
|
|
5806
|
+
side: "right",
|
|
5807
|
+
align: "end",
|
|
5808
|
+
sideOffset: 8,
|
|
5809
|
+
children: [
|
|
5810
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
|
|
5811
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
5812
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
5813
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
5814
|
+
] }),
|
|
5815
|
+
/* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
5816
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
5817
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs", children: user.email })
|
|
5818
|
+
] })
|
|
5819
|
+
] }) }),
|
|
5820
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5821
|
+
/* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5822
|
+
/* @__PURE__ */ jsx(SparklesIcon, {}),
|
|
5823
|
+
"Upgrade to Pro"
|
|
5824
|
+
] }) }),
|
|
5825
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5826
|
+
/* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
5827
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5828
|
+
/* @__PURE__ */ jsx(BadgeCheckIcon, {}),
|
|
5829
|
+
"Account"
|
|
5830
|
+
] }),
|
|
5831
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5832
|
+
/* @__PURE__ */ jsx(CreditCardIcon, {}),
|
|
5833
|
+
"Billing"
|
|
5834
|
+
] }),
|
|
5835
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5836
|
+
/* @__PURE__ */ jsx(BellIcon, {}),
|
|
5837
|
+
"Notifications"
|
|
5838
|
+
] })
|
|
5839
|
+
] }),
|
|
5840
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5841
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5842
|
+
/* @__PURE__ */ jsx(LogOutIcon, {}),
|
|
5843
|
+
"Log out"
|
|
5844
|
+
] })
|
|
5845
|
+
]
|
|
5846
|
+
}
|
|
5847
|
+
)
|
|
5848
|
+
] }) }) });
|
|
5849
|
+
}
|
|
5850
|
+
|
|
5851
|
+
// src/components/event-calendar/types.ts
|
|
5852
|
+
var DEFAULT_WORKING_HOURS = {
|
|
5853
|
+
0: { from: 0, to: 0 },
|
|
5854
|
+
// Sunday - closed
|
|
5855
|
+
1: { from: 9, to: 17 },
|
|
5856
|
+
// Monday
|
|
5857
|
+
2: { from: 9, to: 17 },
|
|
5858
|
+
// Tuesday
|
|
5859
|
+
3: { from: 9, to: 17 },
|
|
5860
|
+
// Wednesday
|
|
5861
|
+
4: { from: 9, to: 17 },
|
|
5862
|
+
// Thursday
|
|
5863
|
+
5: { from: 9, to: 17 },
|
|
5864
|
+
// Friday
|
|
5865
|
+
6: { from: 0, to: 0 }
|
|
5866
|
+
// Saturday - closed
|
|
5867
|
+
};
|
|
5868
|
+
var DEFAULT_VISIBLE_HOURS = { from: 0, to: 24 };
|
|
5869
|
+
var EVENT_COLORS = {
|
|
5870
|
+
blue: {
|
|
5871
|
+
bg: "bg-blue-500/20",
|
|
5872
|
+
text: "text-blue-700 dark:text-blue-300",
|
|
5873
|
+
border: "border-blue-500"
|
|
5874
|
+
},
|
|
5875
|
+
green: {
|
|
5876
|
+
bg: "bg-green-500/20",
|
|
5877
|
+
text: "text-green-700 dark:text-green-300",
|
|
5878
|
+
border: "border-green-500"
|
|
5879
|
+
},
|
|
5880
|
+
red: {
|
|
5881
|
+
bg: "bg-red-500/20",
|
|
5882
|
+
text: "text-red-700 dark:text-red-300",
|
|
5883
|
+
border: "border-red-500"
|
|
5884
|
+
},
|
|
5885
|
+
yellow: {
|
|
5886
|
+
bg: "bg-yellow-500/20",
|
|
5887
|
+
text: "text-yellow-700 dark:text-yellow-300",
|
|
5888
|
+
border: "border-yellow-500"
|
|
5889
|
+
},
|
|
5890
|
+
purple: {
|
|
5891
|
+
bg: "bg-purple-500/20",
|
|
5892
|
+
text: "text-purple-700 dark:text-purple-300",
|
|
5893
|
+
border: "border-purple-500"
|
|
5894
|
+
},
|
|
5895
|
+
orange: {
|
|
5896
|
+
bg: "bg-primary/20",
|
|
5897
|
+
text: "text-primary dark:text-orange-300",
|
|
5898
|
+
border: "border-primary"
|
|
5899
|
+
}
|
|
5900
|
+
};
|
|
5901
|
+
var VIEW_LABELS = {
|
|
5902
|
+
month: "Month",
|
|
5903
|
+
week: "Week",
|
|
5904
|
+
day: "Day",
|
|
5905
|
+
year: "Year",
|
|
5906
|
+
agenda: "Agenda"
|
|
5907
|
+
};
|
|
5908
|
+
var BADGE_VARIANT_LABELS = {
|
|
5909
|
+
dot: "Dot",
|
|
5910
|
+
colored: "Colored",
|
|
5911
|
+
mixed: "Mixed"
|
|
5912
|
+
};
|
|
5913
|
+
var CalendarContext = React15.createContext(null);
|
|
5914
|
+
function EventCalendarProvider({
|
|
5915
|
+
children,
|
|
5916
|
+
events: initialEvents = [],
|
|
5917
|
+
users: initialUsers = [],
|
|
5918
|
+
defaultDate = /* @__PURE__ */ new Date(),
|
|
5919
|
+
defaultView = "month",
|
|
5920
|
+
defaultBadgeVariant = "colored",
|
|
5921
|
+
defaultUserId = null,
|
|
5922
|
+
defaultWorkingHours = DEFAULT_WORKING_HOURS,
|
|
5923
|
+
defaultVisibleHours = DEFAULT_VISIBLE_HOURS,
|
|
5924
|
+
onEventAdd,
|
|
5925
|
+
onEventUpdate,
|
|
5926
|
+
onEventDelete
|
|
5927
|
+
}) {
|
|
5928
|
+
const [selectedDate, setSelectedDate] = React15.useState(defaultDate);
|
|
5929
|
+
const [selectedUserId, setSelectedUserId] = React15.useState(defaultUserId);
|
|
5930
|
+
const [events, setEventsState] = React15.useState(initialEvents);
|
|
5931
|
+
const [users] = React15.useState(initialUsers);
|
|
5932
|
+
const [badgeVariant, setBadgeVariant] = React15.useState(defaultBadgeVariant);
|
|
5933
|
+
const [view, setView] = React15.useState(defaultView);
|
|
5934
|
+
const [workingHours, setWorkingHours] = React15.useState(defaultWorkingHours);
|
|
5935
|
+
const [visibleHours, setVisibleHours] = React15.useState(defaultVisibleHours);
|
|
5936
|
+
React15.useEffect(() => {
|
|
5937
|
+
setEventsState(initialEvents);
|
|
5938
|
+
}, [initialEvents]);
|
|
5939
|
+
const setEvents = React15.useCallback((newEvents) => {
|
|
5940
|
+
setEventsState(newEvents);
|
|
5941
|
+
}, []);
|
|
5942
|
+
const addEvent = React15.useCallback((event) => {
|
|
5943
|
+
setEventsState((prev) => [...prev, event]);
|
|
5944
|
+
onEventAdd?.(event);
|
|
5945
|
+
}, [onEventAdd]);
|
|
5946
|
+
const updateEvent = React15.useCallback((event) => {
|
|
5947
|
+
setEventsState(
|
|
5948
|
+
(prev) => prev.map((e) => e.id === event.id ? event : e)
|
|
5949
|
+
);
|
|
5950
|
+
onEventUpdate?.(event);
|
|
5951
|
+
}, [onEventUpdate]);
|
|
5952
|
+
const deleteEvent = React15.useCallback((eventId) => {
|
|
5953
|
+
setEventsState((prev) => prev.filter((e) => e.id !== eventId));
|
|
5954
|
+
onEventDelete?.(eventId);
|
|
5955
|
+
}, [onEventDelete]);
|
|
5956
|
+
const goToToday = React15.useCallback(() => {
|
|
5957
|
+
setSelectedDate(/* @__PURE__ */ new Date());
|
|
5958
|
+
}, []);
|
|
5959
|
+
const goToPrevious = React15.useCallback(() => {
|
|
5960
|
+
setSelectedDate((current) => {
|
|
5961
|
+
switch (view) {
|
|
5962
|
+
case "day":
|
|
5963
|
+
return subDays(current, 1);
|
|
5964
|
+
case "week":
|
|
5965
|
+
return subWeeks(current, 1);
|
|
5966
|
+
case "month":
|
|
5967
|
+
return subMonths(current, 1);
|
|
5968
|
+
case "year":
|
|
5969
|
+
return subYears(current, 1);
|
|
5970
|
+
case "agenda":
|
|
5971
|
+
return subMonths(current, 1);
|
|
5972
|
+
default:
|
|
5973
|
+
return current;
|
|
5974
|
+
}
|
|
5975
|
+
});
|
|
5976
|
+
}, [view]);
|
|
5977
|
+
const goToNext = React15.useCallback(() => {
|
|
5978
|
+
setSelectedDate((current) => {
|
|
5979
|
+
switch (view) {
|
|
5980
|
+
case "day":
|
|
5981
|
+
return addDays(current, 1);
|
|
5982
|
+
case "week":
|
|
5983
|
+
return addWeeks(current, 1);
|
|
5984
|
+
case "month":
|
|
5985
|
+
return addMonths(current, 1);
|
|
5986
|
+
case "year":
|
|
5987
|
+
return addYears(current, 1);
|
|
5988
|
+
case "agenda":
|
|
5989
|
+
return addMonths(current, 1);
|
|
5990
|
+
default:
|
|
5991
|
+
return current;
|
|
5992
|
+
}
|
|
5993
|
+
});
|
|
5994
|
+
}, [view]);
|
|
5995
|
+
const contextValue = React15.useMemo(
|
|
5996
|
+
() => ({
|
|
5997
|
+
// State
|
|
5998
|
+
selectedDate,
|
|
5999
|
+
selectedUserId,
|
|
6000
|
+
events,
|
|
6001
|
+
users,
|
|
6002
|
+
badgeVariant,
|
|
6003
|
+
view,
|
|
6004
|
+
workingHours,
|
|
6005
|
+
visibleHours,
|
|
6006
|
+
// Actions
|
|
6007
|
+
setSelectedDate,
|
|
6008
|
+
setSelectedUserId,
|
|
6009
|
+
setEvents,
|
|
6010
|
+
addEvent,
|
|
6011
|
+
updateEvent,
|
|
6012
|
+
deleteEvent,
|
|
6013
|
+
setBadgeVariant,
|
|
6014
|
+
setView,
|
|
6015
|
+
setWorkingHours,
|
|
6016
|
+
setVisibleHours,
|
|
6017
|
+
goToToday,
|
|
6018
|
+
goToPrevious,
|
|
6019
|
+
goToNext
|
|
6020
|
+
}),
|
|
6021
|
+
[
|
|
6022
|
+
selectedDate,
|
|
6023
|
+
selectedUserId,
|
|
6024
|
+
events,
|
|
6025
|
+
users,
|
|
6026
|
+
badgeVariant,
|
|
6027
|
+
view,
|
|
6028
|
+
workingHours,
|
|
6029
|
+
visibleHours,
|
|
6030
|
+
setEvents,
|
|
6031
|
+
addEvent,
|
|
6032
|
+
updateEvent,
|
|
6033
|
+
deleteEvent,
|
|
6034
|
+
goToToday,
|
|
6035
|
+
goToPrevious,
|
|
6036
|
+
goToNext
|
|
6037
|
+
]
|
|
6038
|
+
);
|
|
6039
|
+
return /* @__PURE__ */ jsx(CalendarContext.Provider, { value: contextValue, children });
|
|
6040
|
+
}
|
|
6041
|
+
function useEventCalendar() {
|
|
6042
|
+
const context = React15.useContext(CalendarContext);
|
|
6043
|
+
if (!context) {
|
|
6044
|
+
throw new Error("useEventCalendar must be used within an EventCalendarProvider");
|
|
6045
|
+
}
|
|
6046
|
+
return context;
|
|
6047
|
+
}
|
|
6048
|
+
function useFilteredEvents() {
|
|
6049
|
+
const { events, selectedUserId } = useEventCalendar();
|
|
6050
|
+
return React15.useMemo(() => {
|
|
6051
|
+
if (!selectedUserId) return events;
|
|
6052
|
+
return events.filter((event) => event.user.id === selectedUserId);
|
|
6053
|
+
}, [events, selectedUserId]);
|
|
6054
|
+
}
|
|
6055
|
+
function useEventsInRange(startDate, endDate) {
|
|
6056
|
+
const filteredEvents = useFilteredEvents();
|
|
6057
|
+
return React15.useMemo(() => {
|
|
6058
|
+
return filteredEvents.filter((event) => {
|
|
6059
|
+
const eventStart = new Date(event.startDate);
|
|
6060
|
+
const eventEnd = new Date(event.endDate);
|
|
6061
|
+
return eventStart <= endDate && eventEnd >= startDate;
|
|
6062
|
+
});
|
|
6063
|
+
}, [filteredEvents, startDate, endDate]);
|
|
6064
|
+
}
|
|
6065
|
+
function rangeText(view, date) {
|
|
6066
|
+
const formatString = "MMM d, yyyy";
|
|
6067
|
+
let start;
|
|
6068
|
+
let end;
|
|
6069
|
+
switch (view) {
|
|
6070
|
+
case "agenda":
|
|
6071
|
+
start = startOfMonth(date);
|
|
6072
|
+
end = endOfMonth(date);
|
|
6073
|
+
break;
|
|
6074
|
+
case "year":
|
|
6075
|
+
start = startOfYear(date);
|
|
6076
|
+
end = endOfYear(date);
|
|
6077
|
+
break;
|
|
6078
|
+
case "month":
|
|
6079
|
+
start = startOfMonth(date);
|
|
6080
|
+
end = endOfMonth(date);
|
|
6081
|
+
break;
|
|
6082
|
+
case "week":
|
|
6083
|
+
start = startOfWeek(date);
|
|
6084
|
+
end = endOfWeek(date);
|
|
6085
|
+
break;
|
|
6086
|
+
case "day":
|
|
6087
|
+
return format(date, formatString);
|
|
6088
|
+
default:
|
|
6089
|
+
return "Error while formatting";
|
|
6090
|
+
}
|
|
6091
|
+
return `${format(start, formatString)} - ${format(end, formatString)}`;
|
|
6092
|
+
}
|
|
6093
|
+
function navigateDate(date, view, direction) {
|
|
6094
|
+
const operations = {
|
|
6095
|
+
agenda: direction === "next" ? addMonths : subMonths,
|
|
6096
|
+
year: direction === "next" ? addYears : subYears,
|
|
6097
|
+
month: direction === "next" ? addMonths : subMonths,
|
|
6098
|
+
week: direction === "next" ? addWeeks : subWeeks,
|
|
6099
|
+
day: direction === "next" ? addDays : subDays
|
|
6100
|
+
};
|
|
6101
|
+
return operations[view](date, 1);
|
|
6102
|
+
}
|
|
6103
|
+
function getEventsCount(events, date, view) {
|
|
6104
|
+
const compareFns = {
|
|
6105
|
+
agenda: isSameMonth,
|
|
6106
|
+
year: isSameYear,
|
|
6107
|
+
day: isSameDay,
|
|
6108
|
+
week: isSameWeek,
|
|
6109
|
+
month: isSameMonth
|
|
6110
|
+
};
|
|
6111
|
+
return events.filter(
|
|
6112
|
+
(event) => compareFns[view](new Date(event.startDate), date)
|
|
6113
|
+
).length;
|
|
6114
|
+
}
|
|
6115
|
+
function getCurrentEvents(events) {
|
|
6116
|
+
const now = /* @__PURE__ */ new Date();
|
|
6117
|
+
return events.filter(
|
|
6118
|
+
(event) => isWithinInterval(now, {
|
|
6119
|
+
start: parseISO(event.startDate),
|
|
6120
|
+
end: parseISO(event.endDate)
|
|
6121
|
+
})
|
|
6122
|
+
) || [];
|
|
6123
|
+
}
|
|
6124
|
+
function groupEvents(dayEvents) {
|
|
6125
|
+
const sortedEvents = dayEvents.sort(
|
|
6126
|
+
(a, b) => parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime()
|
|
6127
|
+
);
|
|
6128
|
+
const groups = [];
|
|
6129
|
+
for (const event of sortedEvents) {
|
|
6130
|
+
const eventStart = parseISO(event.startDate);
|
|
6131
|
+
let placed = false;
|
|
6132
|
+
for (const group of groups) {
|
|
6133
|
+
const lastEventInGroup = group[group.length - 1];
|
|
6134
|
+
const lastEventEnd = parseISO(lastEventInGroup.endDate);
|
|
6135
|
+
if (eventStart >= lastEventEnd) {
|
|
6136
|
+
group.push(event);
|
|
6137
|
+
placed = true;
|
|
6138
|
+
break;
|
|
6139
|
+
}
|
|
6140
|
+
}
|
|
6141
|
+
if (!placed) groups.push([event]);
|
|
6142
|
+
}
|
|
6143
|
+
return groups;
|
|
6144
|
+
}
|
|
6145
|
+
function getEventBlockStyle(event, day, groupIndex, groupSize, visibleHoursRange, hourHeight = 96) {
|
|
6146
|
+
const startDate = parseISO(event.startDate);
|
|
6147
|
+
const endDate = parseISO(event.endDate);
|
|
6148
|
+
const dayStart = new Date(day);
|
|
6149
|
+
dayStart.setHours(0, 0, 0, 0);
|
|
6150
|
+
const eventStart = startDate < dayStart ? dayStart : startDate;
|
|
6151
|
+
const startMinutes = differenceInMinutes(eventStart, dayStart);
|
|
6152
|
+
const durationMinutes = differenceInMinutes(endDate, eventStart);
|
|
6153
|
+
const visibleStartMinutes = (visibleHoursRange?.from ?? 0) * 60;
|
|
6154
|
+
const topMinutes = startMinutes - visibleStartMinutes;
|
|
6155
|
+
const topPx = topMinutes / 60 * hourHeight;
|
|
6156
|
+
const heightPx = Math.max(durationMinutes / 60 * hourHeight, hourHeight / 4);
|
|
6157
|
+
const width = 100 / groupSize;
|
|
6158
|
+
const left = groupIndex * width;
|
|
6159
|
+
return {
|
|
6160
|
+
top: `${topPx}px`,
|
|
6161
|
+
height: `${heightPx}px`,
|
|
6162
|
+
width: `${width}%`,
|
|
6163
|
+
left: `${left}%`
|
|
6164
|
+
};
|
|
6165
|
+
}
|
|
6166
|
+
function isWorkingHour(day, hour, workingHours) {
|
|
6167
|
+
const dayIndex = day.getDay();
|
|
6168
|
+
const dayHours = workingHours[dayIndex];
|
|
6169
|
+
return hour >= dayHours.from && hour < dayHours.to;
|
|
6170
|
+
}
|
|
6171
|
+
function getVisibleHours(visibleHours, singleDayEvents) {
|
|
6172
|
+
let earliestEventHour = visibleHours.from;
|
|
6173
|
+
let latestEventHour = visibleHours.to;
|
|
6174
|
+
singleDayEvents.forEach((event) => {
|
|
6175
|
+
const startHour = parseISO(event.startDate).getHours();
|
|
6176
|
+
const endTime = parseISO(event.endDate);
|
|
6177
|
+
const endHour = endTime.getHours() + (endTime.getMinutes() > 0 ? 1 : 0);
|
|
6178
|
+
if (startHour < earliestEventHour) earliestEventHour = startHour;
|
|
6179
|
+
if (endHour > latestEventHour) latestEventHour = endHour;
|
|
6180
|
+
});
|
|
6181
|
+
latestEventHour = Math.min(latestEventHour, 24);
|
|
6182
|
+
const hours = Array.from(
|
|
6183
|
+
{ length: latestEventHour - earliestEventHour },
|
|
6184
|
+
(_, i) => i + earliestEventHour
|
|
6185
|
+
);
|
|
6186
|
+
return { hours, earliestEventHour, latestEventHour };
|
|
6187
|
+
}
|
|
6188
|
+
function getCalendarCells(selectedDate) {
|
|
6189
|
+
const currentYear = selectedDate.getFullYear();
|
|
6190
|
+
const currentMonth = selectedDate.getMonth();
|
|
6191
|
+
const getDaysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
6192
|
+
const getFirstDayOfMonth = (year, month) => new Date(year, month, 1).getDay();
|
|
6193
|
+
const daysInMonth = getDaysInMonth(currentYear, currentMonth);
|
|
6194
|
+
const firstDayOfMonth = getFirstDayOfMonth(currentYear, currentMonth);
|
|
6195
|
+
const daysInPrevMonth = getDaysInMonth(currentYear, currentMonth - 1);
|
|
6196
|
+
const totalDays = firstDayOfMonth + daysInMonth;
|
|
6197
|
+
const prevMonthCells = Array.from({ length: firstDayOfMonth }, (_, i) => ({
|
|
6198
|
+
day: daysInPrevMonth - firstDayOfMonth + i + 1,
|
|
6199
|
+
currentMonth: false,
|
|
6200
|
+
date: new Date(
|
|
6201
|
+
currentYear,
|
|
6202
|
+
currentMonth - 1,
|
|
6203
|
+
daysInPrevMonth - firstDayOfMonth + i + 1
|
|
6204
|
+
)
|
|
6205
|
+
}));
|
|
6206
|
+
const currentMonthCells = Array.from({ length: daysInMonth }, (_, i) => ({
|
|
6207
|
+
day: i + 1,
|
|
6208
|
+
currentMonth: true,
|
|
6209
|
+
date: new Date(currentYear, currentMonth, i + 1)
|
|
6210
|
+
}));
|
|
6211
|
+
const nextMonthCells = Array.from(
|
|
6212
|
+
{ length: (7 - totalDays % 7) % 7 },
|
|
6213
|
+
(_, i) => ({
|
|
6214
|
+
day: i + 1,
|
|
6215
|
+
currentMonth: false,
|
|
6216
|
+
date: new Date(currentYear, currentMonth + 1, i + 1)
|
|
6217
|
+
})
|
|
6218
|
+
);
|
|
6219
|
+
return [...prevMonthCells, ...currentMonthCells, ...nextMonthCells];
|
|
6220
|
+
}
|
|
6221
|
+
function calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate) {
|
|
6222
|
+
const monthStart = startOfMonth(selectedDate);
|
|
6223
|
+
const monthEnd = endOfMonth(selectedDate);
|
|
6224
|
+
const eventPositions = {};
|
|
6225
|
+
const occupiedPositions = {};
|
|
6226
|
+
eachDayOfInterval({ start: monthStart, end: monthEnd }).forEach((day) => {
|
|
6227
|
+
occupiedPositions[day.toISOString()] = [false, false, false];
|
|
6228
|
+
});
|
|
6229
|
+
const sortedEvents = [
|
|
6230
|
+
...multiDayEvents.sort((a, b) => {
|
|
6231
|
+
const aDuration = differenceInDays(
|
|
6232
|
+
parseISO(a.endDate),
|
|
6233
|
+
parseISO(a.startDate)
|
|
6234
|
+
);
|
|
6235
|
+
const bDuration = differenceInDays(
|
|
6236
|
+
parseISO(b.endDate),
|
|
6237
|
+
parseISO(b.startDate)
|
|
6238
|
+
);
|
|
6239
|
+
return bDuration - aDuration || parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime();
|
|
6240
|
+
}),
|
|
6241
|
+
...singleDayEvents.sort(
|
|
6242
|
+
(a, b) => parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime()
|
|
6243
|
+
)
|
|
6244
|
+
];
|
|
6245
|
+
sortedEvents.forEach((event) => {
|
|
6246
|
+
const eventStart = parseISO(event.startDate);
|
|
6247
|
+
const eventEnd = parseISO(event.endDate);
|
|
6248
|
+
const eventDays = eachDayOfInterval({
|
|
6249
|
+
start: eventStart < monthStart ? monthStart : eventStart,
|
|
6250
|
+
end: eventEnd > monthEnd ? monthEnd : eventEnd
|
|
6251
|
+
});
|
|
6252
|
+
let position = -1;
|
|
6253
|
+
for (let i = 0; i < 3; i++) {
|
|
6254
|
+
if (eventDays.every((day) => {
|
|
6255
|
+
const dayPositions = occupiedPositions[startOfDay(day).toISOString()];
|
|
6256
|
+
return dayPositions && !dayPositions[i];
|
|
6257
|
+
})) {
|
|
6258
|
+
position = i;
|
|
6259
|
+
break;
|
|
6260
|
+
}
|
|
6261
|
+
}
|
|
6262
|
+
if (position !== -1) {
|
|
6263
|
+
eventDays.forEach((day) => {
|
|
6264
|
+
const dayKey = startOfDay(day).toISOString();
|
|
6265
|
+
occupiedPositions[dayKey][position] = true;
|
|
6266
|
+
});
|
|
6267
|
+
eventPositions[event.id] = position;
|
|
6268
|
+
}
|
|
6269
|
+
});
|
|
6270
|
+
return eventPositions;
|
|
6271
|
+
}
|
|
6272
|
+
function getMonthCellEvents(date, events, eventPositions) {
|
|
6273
|
+
const eventsForDate = events.filter((event) => {
|
|
6274
|
+
const eventStart = parseISO(event.startDate);
|
|
6275
|
+
const eventEnd = parseISO(event.endDate);
|
|
6276
|
+
return date >= eventStart && date <= eventEnd || isSameDay(date, eventStart) || isSameDay(date, eventEnd);
|
|
6277
|
+
});
|
|
6278
|
+
return eventsForDate.map((event) => ({
|
|
6279
|
+
...event,
|
|
6280
|
+
position: eventPositions[event.id] ?? -1,
|
|
6281
|
+
isMultiDay: event.startDate !== event.endDate
|
|
6282
|
+
})).sort((a, b) => {
|
|
6283
|
+
if (a.isMultiDay && !b.isMultiDay) return -1;
|
|
6284
|
+
if (!a.isMultiDay && b.isMultiDay) return 1;
|
|
6285
|
+
return a.position - b.position;
|
|
6286
|
+
});
|
|
6287
|
+
}
|
|
6288
|
+
function getMonthDays(date, weekStartsOn = 0) {
|
|
6289
|
+
const start = startOfWeek(startOfMonth(date), { weekStartsOn });
|
|
6290
|
+
const end = endOfWeek(endOfMonth(date), { weekStartsOn });
|
|
6291
|
+
return eachDayOfInterval({ start, end });
|
|
6292
|
+
}
|
|
6293
|
+
function getWeekDays(date, weekStartsOn = 0) {
|
|
6294
|
+
const start = startOfWeek(date, { weekStartsOn });
|
|
6295
|
+
const end = endOfWeek(date, { weekStartsOn });
|
|
6296
|
+
return eachDayOfInterval({ start, end });
|
|
6297
|
+
}
|
|
6298
|
+
function getDayHours(date, start = 0, end = 24) {
|
|
6299
|
+
const dayStart = setMinutes(setHours(date, start), 0);
|
|
6300
|
+
const dayEnd = setMinutes(setHours(date, end - 1), 59);
|
|
6301
|
+
return eachHourOfInterval({ start: dayStart, end: dayEnd });
|
|
6302
|
+
}
|
|
6303
|
+
function getYearMonths(date) {
|
|
6304
|
+
const start = startOfYear(date);
|
|
6305
|
+
const months = [];
|
|
6306
|
+
for (let i = 0; i < 12; i++) {
|
|
6307
|
+
months.push(new Date(start.getFullYear(), i, 1));
|
|
6308
|
+
}
|
|
6309
|
+
return months;
|
|
6310
|
+
}
|
|
6311
|
+
function getEventsForDate(events, date) {
|
|
6312
|
+
return events.filter((event) => {
|
|
6313
|
+
const eventStart = parseISO(event.startDate);
|
|
6314
|
+
const eventEnd = parseISO(event.endDate);
|
|
6315
|
+
return isWithinInterval(date, {
|
|
6316
|
+
start: startOfDay(eventStart),
|
|
6317
|
+
end: endOfDay(eventEnd)
|
|
6318
|
+
}) || isSameDay(eventStart, date) || isSameDay(eventEnd, date);
|
|
6319
|
+
});
|
|
6320
|
+
}
|
|
6321
|
+
function getEventsInRange(events, start, end) {
|
|
6322
|
+
return events.filter((event) => {
|
|
6323
|
+
const eventStart = parseISO(event.startDate);
|
|
6324
|
+
const eventEnd = parseISO(event.endDate);
|
|
6325
|
+
return eventStart >= start && eventStart <= end || eventEnd >= start && eventEnd <= end || eventStart <= start && eventEnd >= end;
|
|
6326
|
+
});
|
|
6327
|
+
}
|
|
6328
|
+
function splitEventsByDuration(events) {
|
|
6329
|
+
const singleDayEvents = [];
|
|
6330
|
+
const multiDayEvents = [];
|
|
6331
|
+
events.forEach((event) => {
|
|
6332
|
+
const start = parseISO(event.startDate);
|
|
6333
|
+
const end = parseISO(event.endDate);
|
|
6334
|
+
if (isSameDay(start, end)) {
|
|
6335
|
+
singleDayEvents.push(event);
|
|
6336
|
+
} else {
|
|
6337
|
+
multiDayEvents.push(event);
|
|
6338
|
+
}
|
|
6339
|
+
});
|
|
6340
|
+
return { singleDayEvents, multiDayEvents };
|
|
6341
|
+
}
|
|
6342
|
+
function isMultiDayEvent(event) {
|
|
6343
|
+
const start = parseISO(event.startDate);
|
|
6344
|
+
const end = parseISO(event.endDate);
|
|
6345
|
+
return !isSameDay(start, end);
|
|
6346
|
+
}
|
|
6347
|
+
function getEventDuration(event) {
|
|
6348
|
+
const start = parseISO(event.startDate);
|
|
6349
|
+
const end = parseISO(event.endDate);
|
|
6350
|
+
return differenceInDays(end, start) + 1;
|
|
6351
|
+
}
|
|
6352
|
+
function getEventDurationMinutes(event) {
|
|
6353
|
+
const start = parseISO(event.startDate);
|
|
6354
|
+
const end = parseISO(event.endDate);
|
|
6355
|
+
return differenceInMinutes(end, start);
|
|
6356
|
+
}
|
|
6357
|
+
function sortEvents(events) {
|
|
6358
|
+
return [...events].sort((a, b) => {
|
|
6359
|
+
const startDiff = parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime();
|
|
6360
|
+
if (startDiff !== 0) return startDiff;
|
|
6361
|
+
return getEventDuration(b) - getEventDuration(a);
|
|
6362
|
+
});
|
|
6363
|
+
}
|
|
6364
|
+
function getTimePosition(event, visibleHoursRange) {
|
|
6365
|
+
const start = parseISO(event.startDate);
|
|
6366
|
+
const hours = getHours(start);
|
|
6367
|
+
const minutes = getMinutes(start);
|
|
6368
|
+
const startHour = visibleHoursRange?.from ?? 0;
|
|
6369
|
+
const totalMinutes = (hours - startHour) * 60 + minutes;
|
|
6370
|
+
const totalDayMinutes = ((visibleHoursRange?.to ?? 24) - startHour) * 60;
|
|
6371
|
+
return totalMinutes / totalDayMinutes * 100;
|
|
6372
|
+
}
|
|
6373
|
+
function getTimeHeight(event, visibleHoursRange) {
|
|
6374
|
+
const duration = getEventDurationMinutes(event);
|
|
6375
|
+
const totalDayMinutes = ((visibleHoursRange?.to ?? 24) - (visibleHoursRange?.from ?? 0)) * 60;
|
|
6376
|
+
return Math.min(duration / totalDayMinutes * 100, 100);
|
|
6377
|
+
}
|
|
6378
|
+
function formatTime(date, use24h = false) {
|
|
6379
|
+
return format(date, use24h ? "HH:mm" : "h:mm a");
|
|
6380
|
+
}
|
|
6381
|
+
function getWeekDayNames(weekStartsOn = 0, shortNames = true) {
|
|
6382
|
+
const days = [
|
|
6383
|
+
"Sunday",
|
|
6384
|
+
"Monday",
|
|
6385
|
+
"Tuesday",
|
|
6386
|
+
"Wednesday",
|
|
6387
|
+
"Thursday",
|
|
6388
|
+
"Friday",
|
|
6389
|
+
"Saturday"
|
|
6390
|
+
];
|
|
6391
|
+
const rotated = [...days.slice(weekStartsOn), ...days.slice(0, weekStartsOn)];
|
|
6392
|
+
return shortNames ? rotated.map((d) => d.slice(0, 3)) : rotated;
|
|
6393
|
+
}
|
|
6394
|
+
function getHeaderLabel(date, view) {
|
|
6395
|
+
switch (view) {
|
|
6396
|
+
case "day":
|
|
6397
|
+
return format(date, "EEEE, MMMM d, yyyy");
|
|
6398
|
+
case "week":
|
|
6399
|
+
const weekStart = startOfWeek(date);
|
|
6400
|
+
const weekEnd = endOfWeek(date);
|
|
6401
|
+
if (weekStart.getMonth() === weekEnd.getMonth()) {
|
|
6402
|
+
return format(weekStart, "MMMM d") + " - " + format(weekEnd, "d, yyyy");
|
|
6403
|
+
}
|
|
6404
|
+
return format(weekStart, "MMM d") + " - " + format(weekEnd, "MMM d, yyyy");
|
|
6405
|
+
case "month":
|
|
6406
|
+
return format(date, "MMMM yyyy");
|
|
6407
|
+
case "year":
|
|
6408
|
+
return format(date, "yyyy");
|
|
6409
|
+
case "agenda":
|
|
6410
|
+
return format(date, "MMMM yyyy");
|
|
6411
|
+
default:
|
|
6412
|
+
return format(date, "MMMM yyyy");
|
|
6413
|
+
}
|
|
6414
|
+
}
|
|
6415
|
+
function getViewDateRange(date, view) {
|
|
6416
|
+
switch (view) {
|
|
6417
|
+
case "day":
|
|
6418
|
+
return { start: startOfDay(date), end: endOfDay(date) };
|
|
6419
|
+
case "week":
|
|
6420
|
+
return { start: startOfWeek(date), end: endOfWeek(date) };
|
|
6421
|
+
case "month":
|
|
6422
|
+
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6423
|
+
case "year":
|
|
6424
|
+
return { start: startOfYear(date), end: endOfYear(date) };
|
|
6425
|
+
case "agenda":
|
|
6426
|
+
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6427
|
+
default:
|
|
6428
|
+
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6431
|
+
function formatDateRange(start, end) {
|
|
6432
|
+
if (isSameDay(start, end)) {
|
|
6433
|
+
return format(start, "MMM d, yyyy");
|
|
6434
|
+
}
|
|
6435
|
+
if (start.getFullYear() === end.getFullYear()) {
|
|
6436
|
+
if (start.getMonth() === end.getMonth()) {
|
|
6437
|
+
return format(start, "MMM d") + " - " + format(end, "d, yyyy");
|
|
6438
|
+
}
|
|
6439
|
+
return format(start, "MMM d") + " - " + format(end, "MMM d, yyyy");
|
|
6440
|
+
}
|
|
6441
|
+
return format(start, "MMM d, yyyy") + " - " + format(end, "MMM d, yyyy");
|
|
6442
|
+
}
|
|
6443
|
+
function createDefaultEvent(startDate, duration = 60) {
|
|
6444
|
+
return {
|
|
6445
|
+
title: "",
|
|
6446
|
+
description: "",
|
|
6447
|
+
startDate: startDate.toISOString(),
|
|
6448
|
+
endDate: addMinutes(startDate, duration).toISOString(),
|
|
6449
|
+
color: "blue",
|
|
6450
|
+
user: {
|
|
6451
|
+
id: "",
|
|
6452
|
+
name: ""
|
|
6453
|
+
}
|
|
6454
|
+
};
|
|
6455
|
+
}
|
|
6456
|
+
function generateEventId() {
|
|
6457
|
+
return `event_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
6458
|
+
}
|
|
6459
|
+
function calculateDropDates(event, newStartDate) {
|
|
6460
|
+
const originalStart = parseISO(event.startDate);
|
|
6461
|
+
const originalEnd = parseISO(event.endDate);
|
|
6462
|
+
const duration = differenceInMinutes(originalEnd, originalStart);
|
|
6463
|
+
const newStart = newStartDate;
|
|
6464
|
+
const newEnd = addMinutes(newStart, duration);
|
|
6465
|
+
return {
|
|
6466
|
+
startDate: newStart.toISOString(),
|
|
6467
|
+
endDate: newEnd.toISOString()
|
|
6468
|
+
};
|
|
6469
|
+
}
|
|
6470
|
+
function snapToInterval(date, intervalMinutes = 15) {
|
|
6471
|
+
const minutes = getMinutes(date);
|
|
6472
|
+
const snappedMinutes = Math.round(minutes / intervalMinutes) * intervalMinutes;
|
|
6473
|
+
return setMinutes(date, snappedMinutes);
|
|
6474
|
+
}
|
|
6475
|
+
var colorClasses = {
|
|
6476
|
+
blue: {
|
|
6477
|
+
dot: "bg-blue-500",
|
|
6478
|
+
bg: "bg-blue-50 dark:bg-blue-950/50",
|
|
6479
|
+
text: "text-blue-600 dark:text-blue-400",
|
|
6480
|
+
border: "border-l-blue-500",
|
|
6481
|
+
solid: "bg-blue-500"
|
|
6482
|
+
},
|
|
6483
|
+
green: {
|
|
6484
|
+
dot: "bg-green-500",
|
|
6485
|
+
bg: "bg-green-50 dark:bg-green-950/50",
|
|
6486
|
+
text: "text-green-600 dark:text-green-400",
|
|
6487
|
+
border: "border-l-green-500",
|
|
6488
|
+
solid: "bg-green-500"
|
|
6489
|
+
},
|
|
6490
|
+
red: {
|
|
6491
|
+
dot: "bg-red-500",
|
|
6492
|
+
bg: "bg-red-50 dark:bg-red-950/50",
|
|
6493
|
+
text: "text-red-600 dark:text-red-400",
|
|
6494
|
+
border: "border-l-red-500",
|
|
6495
|
+
solid: "bg-red-500"
|
|
6496
|
+
},
|
|
6497
|
+
yellow: {
|
|
6498
|
+
dot: "bg-yellow-500",
|
|
6499
|
+
bg: "bg-yellow-50 dark:bg-yellow-950/50",
|
|
6500
|
+
text: "text-yellow-600 dark:text-yellow-400",
|
|
6501
|
+
border: "border-l-yellow-500",
|
|
6502
|
+
solid: "bg-yellow-500"
|
|
6503
|
+
},
|
|
6504
|
+
purple: {
|
|
6505
|
+
dot: "bg-purple-500",
|
|
6506
|
+
bg: "bg-purple-50 dark:bg-purple-950/50",
|
|
6507
|
+
text: "text-purple-600 dark:text-purple-400",
|
|
6508
|
+
border: "border-l-purple-500",
|
|
6509
|
+
solid: "bg-purple-500"
|
|
6510
|
+
},
|
|
6511
|
+
orange: {
|
|
6512
|
+
dot: "bg-primary",
|
|
6513
|
+
bg: "bg-orange-50 dark:bg-orange-950/50",
|
|
6514
|
+
text: "text-primary dark:text-orange-400",
|
|
6515
|
+
border: "border-l-primary",
|
|
6516
|
+
solid: "bg-primary"
|
|
6517
|
+
}
|
|
6518
|
+
};
|
|
6519
|
+
function EventBadge({
|
|
6520
|
+
event,
|
|
6521
|
+
variant = "colored",
|
|
6522
|
+
className,
|
|
6523
|
+
showTime = false,
|
|
6524
|
+
compact = false,
|
|
6525
|
+
isDragging = false,
|
|
6526
|
+
onClick
|
|
6527
|
+
}) {
|
|
6528
|
+
const colors = colorClasses[event.color];
|
|
6529
|
+
const startTime = format(parseISO(event.startDate), "h:mm a");
|
|
6530
|
+
const handleClick = (e) => {
|
|
6531
|
+
e.stopPropagation();
|
|
6532
|
+
onClick?.(event, e);
|
|
6533
|
+
};
|
|
6534
|
+
if (variant === "dot") {
|
|
6535
|
+
return /* @__PURE__ */ jsxs(
|
|
6536
|
+
"button",
|
|
6537
|
+
{
|
|
6538
|
+
type: "button",
|
|
6539
|
+
onClick: handleClick,
|
|
6540
|
+
className: cn(
|
|
6541
|
+
"flex items-center gap-1.5 rounded-sm px-1.5 py-0.5 text-left text-xs transition-colors",
|
|
6542
|
+
"hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6543
|
+
isDragging && "opacity-50",
|
|
6544
|
+
className
|
|
6545
|
+
),
|
|
6546
|
+
children: [
|
|
6547
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-2 shrink-0 rounded-full", colors.dot) }),
|
|
6548
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: event.title }),
|
|
6549
|
+
showTime && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: startTime })
|
|
6550
|
+
]
|
|
6551
|
+
}
|
|
6552
|
+
);
|
|
6553
|
+
}
|
|
6554
|
+
if (variant === "mixed") {
|
|
6555
|
+
return /* @__PURE__ */ jsxs(
|
|
6556
|
+
"button",
|
|
6557
|
+
{
|
|
6558
|
+
type: "button",
|
|
6559
|
+
onClick: handleClick,
|
|
6560
|
+
className: cn(
|
|
6561
|
+
"flex items-center gap-1.5 rounded-sm border-l-2 px-1.5 py-0.5 text-left text-xs transition-colors",
|
|
6562
|
+
"hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6563
|
+
colors.border,
|
|
6564
|
+
isDragging && "opacity-50",
|
|
6565
|
+
className
|
|
6566
|
+
),
|
|
6567
|
+
children: [
|
|
6568
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: event.title }),
|
|
6569
|
+
showTime && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: startTime })
|
|
6570
|
+
]
|
|
6571
|
+
}
|
|
6572
|
+
);
|
|
6573
|
+
}
|
|
6574
|
+
return /* @__PURE__ */ jsxs(
|
|
6575
|
+
"button",
|
|
6576
|
+
{
|
|
6577
|
+
type: "button",
|
|
6578
|
+
onClick: handleClick,
|
|
6579
|
+
className: cn(
|
|
6580
|
+
"flex flex-col items-start rounded-sm border-l-[3px] text-left text-xs transition-colors",
|
|
6581
|
+
"hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6582
|
+
colors.border,
|
|
6583
|
+
colors.bg,
|
|
6584
|
+
colors.text,
|
|
6585
|
+
compact ? "px-1.5 py-0.5" : "px-2 py-1",
|
|
6586
|
+
isDragging && "opacity-50 shadow-lg",
|
|
6587
|
+
className
|
|
6588
|
+
),
|
|
6589
|
+
children: [
|
|
6590
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium max-w-full", children: event.title }),
|
|
6591
|
+
showTime && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: startTime })
|
|
6592
|
+
]
|
|
6593
|
+
}
|
|
6594
|
+
);
|
|
6595
|
+
}
|
|
6596
|
+
function MoreEvents({ count, onClick, className }) {
|
|
6597
|
+
return /* @__PURE__ */ jsxs(
|
|
6598
|
+
"button",
|
|
6599
|
+
{
|
|
6600
|
+
type: "button",
|
|
6601
|
+
onClick,
|
|
6602
|
+
className: cn(
|
|
6603
|
+
"w-full rounded-sm px-2 py-0.5 text-left text-xs text-muted-foreground transition-colors",
|
|
6604
|
+
"hover:bg-muted hover:text-foreground",
|
|
6605
|
+
className
|
|
6606
|
+
),
|
|
6607
|
+
children: [
|
|
6608
|
+
count,
|
|
6609
|
+
" more..."
|
|
6610
|
+
]
|
|
6611
|
+
}
|
|
6612
|
+
);
|
|
6613
|
+
}
|
|
6614
|
+
function TimeIndicator({ className }) {
|
|
6615
|
+
const [now, setNow] = React15.useState(/* @__PURE__ */ new Date());
|
|
6616
|
+
React15.useEffect(() => {
|
|
6617
|
+
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
6618
|
+
return () => clearInterval(interval);
|
|
6619
|
+
}, []);
|
|
6620
|
+
const hours = now.getHours();
|
|
6621
|
+
const minutes = now.getMinutes();
|
|
6622
|
+
const topPercent = (hours * 60 + minutes) / (24 * 60) * 100;
|
|
6623
|
+
return /* @__PURE__ */ jsxs(
|
|
6624
|
+
"div",
|
|
6625
|
+
{
|
|
6626
|
+
className: cn(
|
|
6627
|
+
"pointer-events-none absolute left-0 right-0 z-20 flex items-center",
|
|
6628
|
+
className
|
|
6629
|
+
),
|
|
6630
|
+
style: { top: `${topPercent}%` },
|
|
6631
|
+
children: [
|
|
6632
|
+
/* @__PURE__ */ jsx("div", { className: "size-2.5 -translate-x-1/2 rounded-full bg-red-500" }),
|
|
6633
|
+
/* @__PURE__ */ jsx("div", { className: "h-0.5 flex-1 bg-red-500" })
|
|
6634
|
+
]
|
|
6635
|
+
}
|
|
6636
|
+
);
|
|
6637
|
+
}
|
|
6638
|
+
function DateBadge({ date, className }) {
|
|
6639
|
+
return /* @__PURE__ */ jsxs(
|
|
6640
|
+
"div",
|
|
6641
|
+
{
|
|
6642
|
+
className: cn(
|
|
6643
|
+
"flex flex-col w-14 overflow-hidden border border-border rounded-md",
|
|
6644
|
+
className
|
|
6645
|
+
),
|
|
6646
|
+
children: [
|
|
6647
|
+
/* @__PURE__ */ jsx("div", { className: "bg-foreground text-background text-[10px] font-bold text-center py-1.5 uppercase tracking-wider", children: format(date, "MMM") }),
|
|
6648
|
+
/* @__PURE__ */ jsx("div", { className: "bg-background text-foreground text-2xl font-bold text-center py-2.5", children: format(date, "d") })
|
|
6649
|
+
]
|
|
6650
|
+
}
|
|
6651
|
+
);
|
|
6652
|
+
}
|
|
6653
|
+
var DragContext = React15.createContext(null);
|
|
6654
|
+
function DragProvider({
|
|
6655
|
+
children,
|
|
6656
|
+
snapMinutes = 15,
|
|
6657
|
+
onDragStart,
|
|
6658
|
+
onDragEnd
|
|
6659
|
+
}) {
|
|
6660
|
+
const [draggedEvent, setDraggedEventState] = React15.useState(null);
|
|
6661
|
+
const [isDragging, setIsDragging] = React15.useState(false);
|
|
6662
|
+
const { updateEvent } = useEventCalendar();
|
|
6663
|
+
const setDraggedEvent = React15.useCallback((event) => {
|
|
6664
|
+
setDraggedEventState(event);
|
|
6665
|
+
setIsDragging(!!event);
|
|
6666
|
+
if (event) {
|
|
6667
|
+
onDragStart?.(event);
|
|
6668
|
+
}
|
|
6669
|
+
}, [onDragStart]);
|
|
6670
|
+
const handleDrop = React15.useCallback((newStartDate) => {
|
|
6671
|
+
if (!draggedEvent) return;
|
|
6672
|
+
const snappedDate = snapToInterval(newStartDate, snapMinutes);
|
|
6673
|
+
const { startDate, endDate } = calculateDropDates(draggedEvent, snappedDate);
|
|
6674
|
+
const updatedEvent = {
|
|
6675
|
+
...draggedEvent,
|
|
6676
|
+
startDate,
|
|
6677
|
+
endDate
|
|
6678
|
+
};
|
|
6679
|
+
updateEvent(updatedEvent);
|
|
6680
|
+
onDragEnd?.(updatedEvent, new Date(startDate), new Date(endDate));
|
|
6681
|
+
setDraggedEvent(null);
|
|
6682
|
+
}, [draggedEvent, snapMinutes, updateEvent, onDragEnd, setDraggedEvent]);
|
|
6683
|
+
const contextValue = React15.useMemo(
|
|
6684
|
+
() => ({
|
|
6685
|
+
draggedEvent,
|
|
6686
|
+
setDraggedEvent,
|
|
6687
|
+
isDragging
|
|
6688
|
+
}),
|
|
6689
|
+
[draggedEvent, setDraggedEvent, isDragging]
|
|
6690
|
+
);
|
|
6691
|
+
return /* @__PURE__ */ jsx(DragContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(DragDropHandler, { onDrop: handleDrop, children }) });
|
|
6692
|
+
}
|
|
6693
|
+
function useDrag() {
|
|
6694
|
+
const context = React15.useContext(DragContext);
|
|
6695
|
+
if (!context) {
|
|
6696
|
+
throw new Error("useDrag must be used within a DragProvider");
|
|
6697
|
+
}
|
|
6698
|
+
return context;
|
|
6699
|
+
}
|
|
6700
|
+
function DragDropHandler({ children, onDrop }) {
|
|
6701
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
6702
|
+
}
|
|
6703
|
+
function DraggableEvent({
|
|
6704
|
+
event,
|
|
6705
|
+
children,
|
|
6706
|
+
disabled = false
|
|
6707
|
+
}) {
|
|
6708
|
+
const { setDraggedEvent, isDragging, draggedEvent } = useDrag();
|
|
6709
|
+
const isDragged = draggedEvent?.id === event.id;
|
|
6710
|
+
const handleDragStart = (e) => {
|
|
6711
|
+
if (disabled) return;
|
|
6712
|
+
e.dataTransfer.effectAllowed = "move";
|
|
6713
|
+
e.dataTransfer.setData("text/plain", event.id);
|
|
6714
|
+
setDraggedEvent(event);
|
|
6715
|
+
};
|
|
6716
|
+
const handleDragEnd = () => {
|
|
6717
|
+
setDraggedEvent(null);
|
|
6718
|
+
};
|
|
6719
|
+
return /* @__PURE__ */ jsx(
|
|
6720
|
+
"div",
|
|
6721
|
+
{
|
|
6722
|
+
draggable: !disabled,
|
|
6723
|
+
onDragStart: handleDragStart,
|
|
6724
|
+
onDragEnd: handleDragEnd,
|
|
6725
|
+
className: isDragged ? "opacity-50" : "",
|
|
6726
|
+
style: { cursor: disabled ? "default" : "grab" },
|
|
6727
|
+
children
|
|
6728
|
+
}
|
|
6729
|
+
);
|
|
6730
|
+
}
|
|
6731
|
+
function DroppableZone({
|
|
6732
|
+
date,
|
|
6733
|
+
children,
|
|
6734
|
+
onDrop,
|
|
6735
|
+
className
|
|
6736
|
+
}) {
|
|
6737
|
+
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6738
|
+
const { updateEvent } = useEventCalendar();
|
|
6739
|
+
const [isOver, setIsOver] = React15.useState(false);
|
|
6740
|
+
const handleDragOver = (e) => {
|
|
6741
|
+
e.preventDefault();
|
|
6742
|
+
e.dataTransfer.dropEffect = "move";
|
|
6743
|
+
setIsOver(true);
|
|
6744
|
+
};
|
|
6745
|
+
const handleDragLeave = () => {
|
|
6746
|
+
setIsOver(false);
|
|
6747
|
+
};
|
|
6748
|
+
const handleDrop = (e) => {
|
|
6749
|
+
e.preventDefault();
|
|
6750
|
+
setIsOver(false);
|
|
6751
|
+
if (!draggedEvent) return;
|
|
6752
|
+
const { startDate, endDate } = calculateDropDates(draggedEvent, date);
|
|
6753
|
+
const updatedEvent = {
|
|
6754
|
+
...draggedEvent,
|
|
6755
|
+
startDate,
|
|
6756
|
+
endDate
|
|
6757
|
+
};
|
|
6758
|
+
updateEvent(updatedEvent);
|
|
6759
|
+
onDrop?.(updatedEvent, date);
|
|
6760
|
+
setDraggedEvent(null);
|
|
6761
|
+
};
|
|
6762
|
+
return /* @__PURE__ */ jsx(
|
|
6763
|
+
"div",
|
|
6764
|
+
{
|
|
6765
|
+
onDragOver: handleDragOver,
|
|
6766
|
+
onDragLeave: handleDragLeave,
|
|
6767
|
+
onDrop: handleDrop,
|
|
6768
|
+
className,
|
|
6769
|
+
"data-drag-over": isOver,
|
|
6770
|
+
children
|
|
6771
|
+
}
|
|
6772
|
+
);
|
|
6773
|
+
}
|
|
6774
|
+
function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
6775
|
+
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6776
|
+
const { updateEvent } = useEventCalendar();
|
|
6777
|
+
const [isOver, setIsOver] = React15.useState(false);
|
|
6778
|
+
const dropTargetDate = React15.useMemo(() => {
|
|
6779
|
+
const targetDate = new Date(date);
|
|
6780
|
+
if (hour !== void 0) {
|
|
6781
|
+
targetDate.setHours(hour, minute, 0, 0);
|
|
6782
|
+
}
|
|
6783
|
+
return targetDate;
|
|
6784
|
+
}, [date, hour, minute]);
|
|
6785
|
+
const handleDragOver = React15.useCallback((e) => {
|
|
6786
|
+
e.preventDefault();
|
|
6787
|
+
e.dataTransfer.dropEffect = "move";
|
|
6788
|
+
if (!isOver) setIsOver(true);
|
|
6789
|
+
}, [isOver]);
|
|
6790
|
+
const handleDragLeave = React15.useCallback(() => {
|
|
6791
|
+
setIsOver(false);
|
|
6792
|
+
}, []);
|
|
6793
|
+
const handleDrop = React15.useCallback((e) => {
|
|
6794
|
+
e.preventDefault();
|
|
6795
|
+
setIsOver(false);
|
|
6796
|
+
if (!draggedEvent) return;
|
|
6797
|
+
const { startDate, endDate } = calculateDropDates(draggedEvent, dropTargetDate);
|
|
6798
|
+
const updatedEvent = {
|
|
6799
|
+
...draggedEvent,
|
|
6800
|
+
startDate,
|
|
6801
|
+
endDate
|
|
6802
|
+
};
|
|
6803
|
+
updateEvent(updatedEvent);
|
|
6804
|
+
onDrop?.(updatedEvent, dropTargetDate);
|
|
6805
|
+
setDraggedEvent(null);
|
|
6806
|
+
}, [draggedEvent, dropTargetDate, updateEvent, onDrop, setDraggedEvent]);
|
|
6807
|
+
return {
|
|
6808
|
+
isOver,
|
|
6809
|
+
dropProps: {
|
|
6810
|
+
onDragOver: handleDragOver,
|
|
6811
|
+
onDragLeave: handleDragLeave,
|
|
6812
|
+
onDrop: handleDrop,
|
|
6813
|
+
"data-drag-over": isOver
|
|
6814
|
+
}
|
|
6815
|
+
};
|
|
6816
|
+
}
|
|
6817
|
+
function useDraggable(event, disabled = false) {
|
|
6818
|
+
const { setDraggedEvent, draggedEvent } = useDrag();
|
|
6819
|
+
const isDragged = draggedEvent?.id === event.id;
|
|
6820
|
+
const handleDragStart = React15.useCallback((e) => {
|
|
6821
|
+
if (disabled) return;
|
|
6822
|
+
e.dataTransfer.effectAllowed = "move";
|
|
6823
|
+
e.dataTransfer.setData("text/plain", event.id);
|
|
6824
|
+
setDraggedEvent(event);
|
|
6825
|
+
}, [disabled, event, setDraggedEvent]);
|
|
6826
|
+
const handleDragEnd = React15.useCallback(() => {
|
|
6827
|
+
setDraggedEvent(null);
|
|
6828
|
+
}, [setDraggedEvent]);
|
|
6829
|
+
return {
|
|
6830
|
+
isDragged,
|
|
6831
|
+
dragProps: {
|
|
6832
|
+
draggable: !disabled,
|
|
6833
|
+
onDragStart: handleDragStart,
|
|
6834
|
+
onDragEnd: handleDragEnd,
|
|
6835
|
+
style: { cursor: disabled ? "default" : "grab" }
|
|
6836
|
+
}
|
|
6837
|
+
};
|
|
6838
|
+
}
|
|
6839
|
+
var WEEK_DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
6840
|
+
function DraggableEventWrapper({
|
|
6841
|
+
event,
|
|
6842
|
+
children
|
|
6843
|
+
}) {
|
|
6844
|
+
const { isDragged, dragProps } = useDraggable(event);
|
|
6845
|
+
return /* @__PURE__ */ jsx(
|
|
6846
|
+
"div",
|
|
6847
|
+
{
|
|
6848
|
+
...dragProps,
|
|
6849
|
+
className: cn(
|
|
6850
|
+
"transition-opacity",
|
|
6851
|
+
isDragged && "opacity-50"
|
|
6852
|
+
),
|
|
6853
|
+
children
|
|
6854
|
+
}
|
|
6855
|
+
);
|
|
6856
|
+
}
|
|
6857
|
+
function MonthView({
|
|
6858
|
+
className,
|
|
6859
|
+
maxEventsPerDay = 3,
|
|
6860
|
+
weekStartsOn = 0,
|
|
6861
|
+
onEventClick,
|
|
6862
|
+
onDateClick,
|
|
6863
|
+
onMoreClick
|
|
6864
|
+
}) {
|
|
6865
|
+
const { selectedDate, badgeVariant, setSelectedDate, setView } = useEventCalendar();
|
|
6866
|
+
const filteredEvents = useFilteredEvents();
|
|
6867
|
+
const { singleDayEvents, multiDayEvents } = React15.useMemo(
|
|
6868
|
+
() => splitEventsByDuration(filteredEvents),
|
|
6869
|
+
[filteredEvents]
|
|
6870
|
+
);
|
|
6871
|
+
const cells = React15.useMemo(
|
|
6872
|
+
() => getCalendarCells(selectedDate),
|
|
6873
|
+
[selectedDate]
|
|
6874
|
+
);
|
|
6875
|
+
const eventPositions = React15.useMemo(
|
|
6876
|
+
() => calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate),
|
|
6877
|
+
[multiDayEvents, singleDayEvents, selectedDate]
|
|
6878
|
+
);
|
|
6879
|
+
const allEvents = [...multiDayEvents, ...singleDayEvents];
|
|
6880
|
+
const handleDateClick = (date) => {
|
|
6881
|
+
setSelectedDate(date);
|
|
6882
|
+
setView("day");
|
|
6883
|
+
onDateClick?.(date);
|
|
6884
|
+
};
|
|
6885
|
+
const handleMoreClick = (date, events) => {
|
|
6886
|
+
setSelectedDate(date);
|
|
6887
|
+
setView("day");
|
|
6888
|
+
onMoreClick?.(date, events);
|
|
6889
|
+
};
|
|
6890
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("", className), children: [
|
|
6891
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 divide-x divide-border/50", children: WEEK_DAYS.map((day) => /* @__PURE__ */ jsx(
|
|
6892
|
+
"div",
|
|
6893
|
+
{
|
|
6894
|
+
className: "flex items-center justify-center py-2",
|
|
6895
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: day })
|
|
6896
|
+
},
|
|
6897
|
+
day
|
|
6898
|
+
)) }),
|
|
6899
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 overflow-hidden", children: cells.map((cell) => /* @__PURE__ */ jsx(
|
|
6900
|
+
DayCell,
|
|
6901
|
+
{
|
|
6902
|
+
cell,
|
|
6903
|
+
events: allEvents,
|
|
6904
|
+
eventPositions,
|
|
6905
|
+
selectedDate,
|
|
6906
|
+
badgeVariant,
|
|
6907
|
+
maxEvents: maxEventsPerDay,
|
|
6908
|
+
onDateClick: handleDateClick,
|
|
6909
|
+
onEventClick,
|
|
6910
|
+
onMoreClick: handleMoreClick
|
|
6911
|
+
},
|
|
6912
|
+
cell.date.toISOString()
|
|
6913
|
+
)) })
|
|
6914
|
+
] });
|
|
6915
|
+
}
|
|
6916
|
+
function DayCell({
|
|
6917
|
+
cell,
|
|
6918
|
+
events,
|
|
6919
|
+
eventPositions,
|
|
6920
|
+
selectedDate,
|
|
6921
|
+
badgeVariant,
|
|
6922
|
+
maxEvents,
|
|
6923
|
+
onDateClick,
|
|
6924
|
+
onEventClick,
|
|
6925
|
+
onMoreClick
|
|
6926
|
+
}) {
|
|
6927
|
+
const { date, currentMonth } = cell;
|
|
6928
|
+
const isCurrentDay = isToday(date);
|
|
6929
|
+
const isSelectedDay = isSameDay(date, selectedDate);
|
|
6930
|
+
const { isOver, dropProps } = useDroppable({ date });
|
|
6931
|
+
const cellEvents = getMonthCellEvents(date, events, eventPositions);
|
|
6932
|
+
const positionedEvents = cellEvents.filter((e) => e.position !== -1);
|
|
6933
|
+
const hiddenEvents = cellEvents.filter((e) => e.position === -1);
|
|
6934
|
+
const slots = [null, null, null];
|
|
6935
|
+
positionedEvents.forEach((event) => {
|
|
6936
|
+
if (event.position >= 0 && event.position < 3) {
|
|
6937
|
+
slots[event.position] = event;
|
|
6938
|
+
}
|
|
6939
|
+
});
|
|
6940
|
+
const hiddenCount = hiddenEvents.length + positionedEvents.filter((e) => e.position >= 3).length;
|
|
6941
|
+
const isEventStart = (event) => isSameDay(parseISO(event.startDate), date);
|
|
6942
|
+
return /* @__PURE__ */ jsxs(
|
|
6943
|
+
"div",
|
|
6944
|
+
{
|
|
6945
|
+
...dropProps,
|
|
6946
|
+
className: cn(
|
|
6947
|
+
"relative min-h-[120px] border-b border-r border-border/50 p-1 transition-colors",
|
|
6948
|
+
!currentMonth && "bg-muted/30",
|
|
6949
|
+
isOver && "bg-primary/10 ring-2 ring-primary/50 ring-inset"
|
|
6950
|
+
),
|
|
6951
|
+
children: [
|
|
6952
|
+
/* @__PURE__ */ jsx(
|
|
6953
|
+
"button",
|
|
6954
|
+
{
|
|
6955
|
+
type: "button",
|
|
6956
|
+
onClick: () => onDateClick(date),
|
|
6957
|
+
className: cn(
|
|
6958
|
+
"mb-1 flex size-7 items-center justify-center text-sm transition-colors",
|
|
6959
|
+
"hover:bg-muted rounded-sm",
|
|
6960
|
+
isCurrentDay && "bg-primary text-primary-foreground hover:bg-primary/90 rounded-sm",
|
|
6961
|
+
isSelectedDay && !isCurrentDay && "bg-muted font-semibold rounded-sm",
|
|
6962
|
+
!currentMonth && "text-muted-foreground"
|
|
6963
|
+
),
|
|
6964
|
+
children: cell.day
|
|
6965
|
+
}
|
|
6966
|
+
),
|
|
6967
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
6968
|
+
slots.map((event, index) => {
|
|
6969
|
+
if (!event) {
|
|
6970
|
+
return /* @__PURE__ */ jsx("div", { className: "h-5" }, `empty-${index}`);
|
|
6971
|
+
}
|
|
6972
|
+
const showTitle = isEventStart(event) || startOfDay(date).getDay() === 0;
|
|
6973
|
+
return /* @__PURE__ */ jsx(DraggableEventWrapper, { event, children: /* @__PURE__ */ jsx(
|
|
6974
|
+
EventBadge,
|
|
6975
|
+
{
|
|
6976
|
+
event,
|
|
6977
|
+
variant: badgeVariant,
|
|
6978
|
+
compact: true,
|
|
6979
|
+
showTime: showTitle,
|
|
6980
|
+
onClick: (e) => onEventClick?.(e),
|
|
6981
|
+
className: cn(
|
|
6982
|
+
"w-full",
|
|
6983
|
+
// If not showing title, make it appear as a continuation
|
|
6984
|
+
!showTitle && "rounded-l-none border-l-0"
|
|
6985
|
+
)
|
|
6986
|
+
}
|
|
6987
|
+
) }, event.id);
|
|
6988
|
+
}),
|
|
6989
|
+
hiddenCount > 0 && /* @__PURE__ */ jsx(
|
|
6990
|
+
MoreEvents,
|
|
6991
|
+
{
|
|
6992
|
+
count: hiddenCount,
|
|
6993
|
+
onClick: () => onMoreClick(date, cellEvents)
|
|
6994
|
+
}
|
|
6995
|
+
)
|
|
6996
|
+
] })
|
|
6997
|
+
]
|
|
6998
|
+
}
|
|
6999
|
+
);
|
|
7000
|
+
}
|
|
7001
|
+
function DraggableEventWrapper2({
|
|
7002
|
+
event,
|
|
7003
|
+
children,
|
|
7004
|
+
className,
|
|
7005
|
+
style
|
|
7006
|
+
}) {
|
|
7007
|
+
const { isDragged, dragProps } = useDraggable(event);
|
|
7008
|
+
return /* @__PURE__ */ jsx(
|
|
7009
|
+
"div",
|
|
7010
|
+
{
|
|
7011
|
+
...dragProps,
|
|
7012
|
+
className: cn(
|
|
7013
|
+
className,
|
|
7014
|
+
"transition-opacity",
|
|
7015
|
+
isDragged && "opacity-50"
|
|
7016
|
+
),
|
|
7017
|
+
style,
|
|
7018
|
+
children
|
|
7019
|
+
}
|
|
7020
|
+
);
|
|
7021
|
+
}
|
|
7022
|
+
function DroppableTimeSlot({
|
|
7023
|
+
date,
|
|
7024
|
+
hour,
|
|
7025
|
+
minute,
|
|
7026
|
+
className,
|
|
7027
|
+
onClick
|
|
7028
|
+
}) {
|
|
7029
|
+
const { isOver, dropProps } = useDroppable({ date, hour, minute });
|
|
7030
|
+
return /* @__PURE__ */ jsx(
|
|
7031
|
+
"div",
|
|
7032
|
+
{
|
|
7033
|
+
...dropProps,
|
|
7034
|
+
onClick,
|
|
7035
|
+
className: cn(
|
|
7036
|
+
className,
|
|
7037
|
+
"cursor-pointer transition-colors hover:bg-accent",
|
|
7038
|
+
isOver && "bg-primary/20"
|
|
7039
|
+
)
|
|
7040
|
+
}
|
|
7041
|
+
);
|
|
7042
|
+
}
|
|
7043
|
+
function WeekView({
|
|
7044
|
+
className,
|
|
7045
|
+
weekStartsOn = 0,
|
|
7046
|
+
onEventClick,
|
|
7047
|
+
onDateClick,
|
|
7048
|
+
onTimeClick
|
|
7049
|
+
}) {
|
|
7050
|
+
const {
|
|
7051
|
+
selectedDate,
|
|
7052
|
+
badgeVariant,
|
|
7053
|
+
workingHours,
|
|
7054
|
+
visibleHours
|
|
7055
|
+
} = useEventCalendar();
|
|
7056
|
+
const filteredEvents = useFilteredEvents();
|
|
7057
|
+
const { singleDayEvents, multiDayEvents } = React15.useMemo(
|
|
7058
|
+
() => splitEventsByDuration(filteredEvents),
|
|
7059
|
+
[filteredEvents]
|
|
7060
|
+
);
|
|
7061
|
+
const { hours, earliestEventHour, latestEventHour } = getVisibleHours(
|
|
7062
|
+
visibleHours,
|
|
7063
|
+
singleDayEvents
|
|
7064
|
+
);
|
|
7065
|
+
const weekStart = startOfWeek(selectedDate, { weekStartsOn });
|
|
7066
|
+
const weekDays = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
|
|
7067
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7068
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center border-b py-4 text-sm text-muted-foreground sm:hidden", children: [
|
|
7069
|
+
/* @__PURE__ */ jsx("p", { children: "Weekly view is not available on smaller devices." }),
|
|
7070
|
+
/* @__PURE__ */ jsx("p", { children: "Please switch to daily or monthly view." })
|
|
7071
|
+
] }),
|
|
7072
|
+
/* @__PURE__ */ jsxs("div", { className: cn("hidden flex-col sm:flex", className), children: [
|
|
7073
|
+
/* @__PURE__ */ jsx(
|
|
7074
|
+
WeekViewMultiDayEventsRow,
|
|
7075
|
+
{
|
|
7076
|
+
selectedDate,
|
|
7077
|
+
multiDayEvents
|
|
7078
|
+
}
|
|
7079
|
+
),
|
|
7080
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-20 flex border-b border-border/50", children: [
|
|
7081
|
+
/* @__PURE__ */ jsx("div", { className: "w-18" }),
|
|
7082
|
+
/* @__PURE__ */ jsx("div", { className: "grid flex-1 grid-cols-7 divide-x divide-border/50 border-l border-border/50", children: weekDays.map((day, index) => /* @__PURE__ */ jsxs(
|
|
7083
|
+
"span",
|
|
7084
|
+
{
|
|
7085
|
+
className: "py-2 text-center text-xs font-medium text-muted-foreground",
|
|
7086
|
+
children: [
|
|
7087
|
+
format(day, "EE"),
|
|
7088
|
+
" ",
|
|
7089
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1 font-semibold text-foreground", children: format(day, "d") })
|
|
7090
|
+
]
|
|
7091
|
+
},
|
|
7092
|
+
index
|
|
7093
|
+
)) })
|
|
7094
|
+
] }),
|
|
7095
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "h-[736px]", type: "always", children: /* @__PURE__ */ jsxs("div", { className: "flex overflow-hidden", children: [
|
|
7096
|
+
/* @__PURE__ */ jsx("div", { className: "relative w-18", children: hours.map((hour, index) => /* @__PURE__ */ jsx("div", { className: "relative", style: { height: "96px" }, children: /* @__PURE__ */ jsx("div", { className: "absolute -top-3 right-2 flex h-6 items-center", children: index !== 0 && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: format((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), "hh a") }) }) }, hour)) }),
|
|
7097
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 border-l border-border/50", children: [
|
|
7098
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 divide-x divide-border/50", children: weekDays.map((day, dayIndex) => {
|
|
7099
|
+
const dayEvents = singleDayEvents.filter(
|
|
7100
|
+
(event) => isSameDay(parseISO(event.startDate), day) || isSameDay(parseISO(event.endDate), day)
|
|
7101
|
+
);
|
|
7102
|
+
const groupedEvents = groupEvents(dayEvents);
|
|
7103
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
7104
|
+
hours.map((hour, index) => {
|
|
7105
|
+
const isDisabled = !isWorkingHour(day, hour, workingHours);
|
|
7106
|
+
return /* @__PURE__ */ jsxs(
|
|
7107
|
+
"div",
|
|
7108
|
+
{
|
|
7109
|
+
className: cn(
|
|
7110
|
+
"relative",
|
|
7111
|
+
isDisabled && "bg-[repeating-linear-gradient(45deg,transparent,transparent_5px,rgba(0,0,0,0.04)_5px,rgba(0,0,0,0.04)_10px)] dark:bg-[repeating-linear-gradient(45deg,transparent,transparent_5px,rgba(255,255,255,0.04)_5px,rgba(255,255,255,0.04)_10px)]"
|
|
7112
|
+
),
|
|
7113
|
+
style: { height: "96px" },
|
|
7114
|
+
children: [
|
|
7115
|
+
index !== 0 && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 border-b border-border/40" }),
|
|
7116
|
+
/* @__PURE__ */ jsx(
|
|
7117
|
+
DroppableTimeSlot,
|
|
7118
|
+
{
|
|
7119
|
+
date: day,
|
|
7120
|
+
hour,
|
|
7121
|
+
minute: 0,
|
|
7122
|
+
className: "absolute inset-x-0 top-0 h-[24px]",
|
|
7123
|
+
onClick: () => onTimeClick?.(day, hour, 0)
|
|
7124
|
+
}
|
|
7125
|
+
),
|
|
7126
|
+
/* @__PURE__ */ jsx(
|
|
7127
|
+
DroppableTimeSlot,
|
|
7128
|
+
{
|
|
7129
|
+
date: day,
|
|
7130
|
+
hour,
|
|
7131
|
+
minute: 15,
|
|
7132
|
+
className: "absolute inset-x-0 top-[24px] h-[24px]",
|
|
7133
|
+
onClick: () => onTimeClick?.(day, hour, 15)
|
|
7134
|
+
}
|
|
7135
|
+
),
|
|
7136
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-1/2 border-b border-dashed border-border/30" }),
|
|
7137
|
+
/* @__PURE__ */ jsx(
|
|
7138
|
+
DroppableTimeSlot,
|
|
7139
|
+
{
|
|
7140
|
+
date: day,
|
|
7141
|
+
hour,
|
|
7142
|
+
minute: 30,
|
|
7143
|
+
className: "absolute inset-x-0 top-[48px] h-[24px]",
|
|
7144
|
+
onClick: () => onTimeClick?.(day, hour, 30)
|
|
7145
|
+
}
|
|
7146
|
+
),
|
|
7147
|
+
/* @__PURE__ */ jsx(
|
|
7148
|
+
DroppableTimeSlot,
|
|
7149
|
+
{
|
|
7150
|
+
date: day,
|
|
7151
|
+
hour,
|
|
7152
|
+
minute: 45,
|
|
7153
|
+
className: "absolute inset-x-0 top-[72px] h-[24px]",
|
|
7154
|
+
onClick: () => onTimeClick?.(day, hour, 45)
|
|
7155
|
+
}
|
|
7156
|
+
)
|
|
7157
|
+
]
|
|
7158
|
+
},
|
|
7159
|
+
hour
|
|
7160
|
+
);
|
|
7161
|
+
}),
|
|
7162
|
+
groupedEvents.map(
|
|
7163
|
+
(group, groupIndex) => group.map((event) => {
|
|
7164
|
+
let style = getEventBlockStyle(
|
|
7165
|
+
event,
|
|
7166
|
+
day,
|
|
7167
|
+
groupIndex,
|
|
7168
|
+
groupedEvents.length,
|
|
7169
|
+
{ from: earliestEventHour}
|
|
7170
|
+
);
|
|
7171
|
+
const hasOverlap = groupedEvents.some(
|
|
7172
|
+
(otherGroup, otherIndex) => otherIndex !== groupIndex && otherGroup.some(
|
|
7173
|
+
(otherEvent) => areIntervalsOverlapping(
|
|
7174
|
+
{
|
|
7175
|
+
start: parseISO(event.startDate),
|
|
7176
|
+
end: parseISO(event.endDate)
|
|
7177
|
+
},
|
|
7178
|
+
{
|
|
7179
|
+
start: parseISO(otherEvent.startDate),
|
|
7180
|
+
end: parseISO(otherEvent.endDate)
|
|
7181
|
+
}
|
|
7182
|
+
)
|
|
7183
|
+
)
|
|
7184
|
+
);
|
|
7185
|
+
if (!hasOverlap) {
|
|
7186
|
+
style = { ...style, width: "100%", left: "0%" };
|
|
7187
|
+
}
|
|
7188
|
+
return /* @__PURE__ */ jsx(
|
|
7189
|
+
DraggableEventWrapper2,
|
|
7190
|
+
{
|
|
7191
|
+
event,
|
|
7192
|
+
className: "absolute px-0.5 py-0.5",
|
|
7193
|
+
style,
|
|
7194
|
+
children: /* @__PURE__ */ jsx(
|
|
7195
|
+
EventBadge,
|
|
7196
|
+
{
|
|
7197
|
+
event,
|
|
7198
|
+
variant: badgeVariant,
|
|
7199
|
+
showTime: true,
|
|
7200
|
+
onClick: (e) => onEventClick?.(e),
|
|
7201
|
+
className: "h-full w-full"
|
|
7202
|
+
}
|
|
7203
|
+
)
|
|
7204
|
+
},
|
|
7205
|
+
event.id
|
|
7206
|
+
);
|
|
7207
|
+
})
|
|
7208
|
+
)
|
|
7209
|
+
] }, dayIndex);
|
|
7210
|
+
}) }),
|
|
7211
|
+
weekDays.some((day) => isToday(day)) && /* @__PURE__ */ jsx(
|
|
7212
|
+
CalendarTimeline,
|
|
7213
|
+
{
|
|
7214
|
+
firstVisibleHour: earliestEventHour,
|
|
7215
|
+
lastVisibleHour: latestEventHour
|
|
7216
|
+
}
|
|
7217
|
+
)
|
|
7218
|
+
] })
|
|
7219
|
+
] }) })
|
|
7220
|
+
] })
|
|
7221
|
+
] });
|
|
7222
|
+
}
|
|
7223
|
+
function WeekViewMultiDayEventsRow({
|
|
7224
|
+
selectedDate,
|
|
7225
|
+
multiDayEvents
|
|
7226
|
+
}) {
|
|
7227
|
+
const { badgeVariant } = useEventCalendar();
|
|
7228
|
+
if (multiDayEvents.length === 0) return null;
|
|
7229
|
+
const weekStart = startOfWeek(selectedDate);
|
|
7230
|
+
const weekDays = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
|
|
7231
|
+
return /* @__PURE__ */ jsxs("div", { className: "hidden border-b sm:flex", children: [
|
|
7232
|
+
/* @__PURE__ */ jsx("div", { className: "w-18 shrink-0" }),
|
|
7233
|
+
/* @__PURE__ */ jsx("div", { className: "grid flex-1 grid-cols-7 divide-x border-l", children: weekDays.map((day, index) => {
|
|
7234
|
+
const dayMultiEvents = multiDayEvents.filter((event) => {
|
|
7235
|
+
const start = parseISO(event.startDate);
|
|
7236
|
+
const end = parseISO(event.endDate);
|
|
7237
|
+
return day >= start && day <= end;
|
|
7238
|
+
});
|
|
7239
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-h-[32px] space-y-1 p-1", children: [
|
|
7240
|
+
dayMultiEvents.slice(0, 2).map((event) => /* @__PURE__ */ jsx(
|
|
7241
|
+
EventBadge,
|
|
7242
|
+
{
|
|
7243
|
+
event,
|
|
7244
|
+
variant: badgeVariant,
|
|
7245
|
+
compact: true,
|
|
7246
|
+
className: "w-full"
|
|
7247
|
+
},
|
|
7248
|
+
event.id
|
|
7249
|
+
)),
|
|
7250
|
+
dayMultiEvents.length > 2 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground text-center", children: [
|
|
7251
|
+
"+",
|
|
7252
|
+
dayMultiEvents.length - 2,
|
|
7253
|
+
" more"
|
|
7254
|
+
] })
|
|
7255
|
+
] }, index);
|
|
7256
|
+
}) })
|
|
7257
|
+
] });
|
|
7258
|
+
}
|
|
7259
|
+
function CalendarTimeline({
|
|
7260
|
+
firstVisibleHour,
|
|
7261
|
+
lastVisibleHour
|
|
7262
|
+
}) {
|
|
7263
|
+
const [currentTime, setCurrentTime] = React15.useState(/* @__PURE__ */ new Date());
|
|
7264
|
+
React15.useEffect(() => {
|
|
7265
|
+
const interval = setInterval(() => {
|
|
7266
|
+
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7267
|
+
}, 6e4);
|
|
7268
|
+
return () => clearInterval(interval);
|
|
7269
|
+
}, []);
|
|
7270
|
+
const currentHour = currentTime.getHours();
|
|
7271
|
+
const currentMinute = currentTime.getMinutes();
|
|
7272
|
+
if (currentHour < firstVisibleHour || currentHour >= lastVisibleHour) {
|
|
7273
|
+
return null;
|
|
7274
|
+
}
|
|
7275
|
+
const minutesSinceStart = (currentHour - firstVisibleHour) * 60 + currentMinute;
|
|
7276
|
+
const totalMinutes = (lastVisibleHour - firstVisibleHour) * 60;
|
|
7277
|
+
const topPercent = minutesSinceStart / totalMinutes * 100;
|
|
7278
|
+
return /* @__PURE__ */ jsxs(
|
|
7279
|
+
"div",
|
|
7280
|
+
{
|
|
7281
|
+
className: "pointer-events-none absolute inset-x-0 z-30 flex items-center",
|
|
7282
|
+
style: { top: `${topPercent}%` },
|
|
7283
|
+
children: [
|
|
7284
|
+
/* @__PURE__ */ jsx("div", { className: "size-3 -translate-x-1/2 rounded-full bg-red-500" }),
|
|
7285
|
+
/* @__PURE__ */ jsx("div", { className: "h-0.5 flex-1 bg-red-500" })
|
|
7286
|
+
]
|
|
7287
|
+
}
|
|
7288
|
+
);
|
|
7289
|
+
}
|
|
7290
|
+
function DraggableEventWrapper3({
|
|
7291
|
+
event,
|
|
7292
|
+
children,
|
|
7293
|
+
className,
|
|
7294
|
+
style
|
|
7295
|
+
}) {
|
|
7296
|
+
const { isDragged, dragProps } = useDraggable(event);
|
|
7297
|
+
return /* @__PURE__ */ jsx(
|
|
7298
|
+
"div",
|
|
7299
|
+
{
|
|
7300
|
+
...dragProps,
|
|
7301
|
+
className: cn(
|
|
7302
|
+
className,
|
|
7303
|
+
"transition-opacity",
|
|
7304
|
+
isDragged && "opacity-50"
|
|
7305
|
+
),
|
|
7306
|
+
style,
|
|
7307
|
+
children
|
|
7308
|
+
}
|
|
7309
|
+
);
|
|
7310
|
+
}
|
|
7311
|
+
function DroppableTimeSlot2({
|
|
7312
|
+
date,
|
|
7313
|
+
hour,
|
|
7314
|
+
minute,
|
|
7315
|
+
className,
|
|
7316
|
+
onClick
|
|
7317
|
+
}) {
|
|
7318
|
+
const { isOver, dropProps } = useDroppable({ date, hour, minute });
|
|
7319
|
+
return /* @__PURE__ */ jsx(
|
|
7320
|
+
"div",
|
|
7321
|
+
{
|
|
7322
|
+
...dropProps,
|
|
7323
|
+
onClick,
|
|
7324
|
+
className: cn(
|
|
7325
|
+
className,
|
|
7326
|
+
"cursor-pointer transition-colors hover:bg-accent",
|
|
7327
|
+
isOver && "bg-primary/20"
|
|
7328
|
+
)
|
|
7329
|
+
}
|
|
7330
|
+
);
|
|
7331
|
+
}
|
|
7332
|
+
function DayView({
|
|
7333
|
+
className,
|
|
7334
|
+
showSidebar = true,
|
|
7335
|
+
onEventClick,
|
|
7336
|
+
onTimeClick
|
|
7337
|
+
}) {
|
|
7338
|
+
const {
|
|
7339
|
+
selectedDate,
|
|
7340
|
+
setSelectedDate,
|
|
7341
|
+
badgeVariant,
|
|
7342
|
+
users,
|
|
7343
|
+
workingHours,
|
|
7344
|
+
visibleHours
|
|
7345
|
+
} = useEventCalendar();
|
|
7346
|
+
const filteredEvents = useFilteredEvents();
|
|
7347
|
+
const { singleDayEvents, multiDayEvents } = React15.useMemo(
|
|
7348
|
+
() => splitEventsByDuration(filteredEvents),
|
|
7349
|
+
[filteredEvents]
|
|
7350
|
+
);
|
|
7351
|
+
const { hours, earliestEventHour, latestEventHour } = getVisibleHours(
|
|
7352
|
+
visibleHours,
|
|
7353
|
+
singleDayEvents
|
|
7354
|
+
);
|
|
7355
|
+
const currentEvents = React15.useMemo(() => {
|
|
7356
|
+
if (!isToday(selectedDate)) return [];
|
|
7357
|
+
return getCurrentEvents(singleDayEvents);
|
|
7358
|
+
}, [singleDayEvents, selectedDate]);
|
|
7359
|
+
const dayEvents = singleDayEvents.filter((event) => {
|
|
7360
|
+
const eventDate = parseISO(event.startDate);
|
|
7361
|
+
return eventDate.getDate() === selectedDate.getDate() && eventDate.getMonth() === selectedDate.getMonth() && eventDate.getFullYear() === selectedDate.getFullYear();
|
|
7362
|
+
});
|
|
7363
|
+
const groupedEvents = groupEvents(dayEvents);
|
|
7364
|
+
const handleDateSelect = (date) => {
|
|
7365
|
+
if (date) {
|
|
7366
|
+
setSelectedDate(date);
|
|
7367
|
+
}
|
|
7368
|
+
};
|
|
7369
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex", className), children: [
|
|
7370
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
7371
|
+
multiDayEvents.length > 0 && /* @__PURE__ */ jsx(
|
|
7372
|
+
DayViewMultiDayEventsRow,
|
|
7373
|
+
{
|
|
7374
|
+
selectedDate,
|
|
7375
|
+
multiDayEvents
|
|
7376
|
+
}
|
|
7377
|
+
),
|
|
7378
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-20 flex border-b border-border/50", children: [
|
|
7379
|
+
/* @__PURE__ */ jsx("div", { className: "w-18" }),
|
|
7380
|
+
/* @__PURE__ */ jsxs("span", { className: "flex-1 border-l border-border/50 py-2 text-center text-xs font-medium text-muted-foreground", children: [
|
|
7381
|
+
format(selectedDate, "EE"),
|
|
7382
|
+
" ",
|
|
7383
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: format(selectedDate, "d") })
|
|
7384
|
+
] })
|
|
7385
|
+
] }),
|
|
7386
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "h-[800px]", type: "always", children: /* @__PURE__ */ jsxs("div", { className: "flex", children: [
|
|
7387
|
+
/* @__PURE__ */ jsx("div", { className: "relative w-18", children: hours.map((hour, index) => /* @__PURE__ */ jsx("div", { className: "relative", style: { height: "96px" }, children: /* @__PURE__ */ jsx("div", { className: "absolute -top-3 right-2 flex h-6 items-center", children: index !== 0 && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: format((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), "hh a") }) }) }, hour)) }),
|
|
7388
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 border-l border-border/50", children: [
|
|
7389
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
7390
|
+
hours.map((hour, index) => {
|
|
7391
|
+
const isDisabled = !isWorkingHour(selectedDate, hour, workingHours);
|
|
7392
|
+
return /* @__PURE__ */ jsxs(
|
|
7393
|
+
"div",
|
|
7394
|
+
{
|
|
7395
|
+
className: cn(
|
|
7396
|
+
"relative",
|
|
7397
|
+
isDisabled && "bg-[repeating-linear-gradient(45deg,transparent,transparent_5px,rgba(0,0,0,0.04)_5px,rgba(0,0,0,0.04)_10px)] dark:bg-[repeating-linear-gradient(45deg,transparent,transparent_5px,rgba(255,255,255,0.04)_5px,rgba(255,255,255,0.04)_10px)]"
|
|
7398
|
+
),
|
|
7399
|
+
style: { height: "96px" },
|
|
7400
|
+
children: [
|
|
7401
|
+
index !== 0 && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 border-b border-border/40" }),
|
|
7402
|
+
/* @__PURE__ */ jsx(
|
|
7403
|
+
DroppableTimeSlot2,
|
|
7404
|
+
{
|
|
7405
|
+
date: selectedDate,
|
|
7406
|
+
hour,
|
|
7407
|
+
minute: 0,
|
|
7408
|
+
className: "absolute inset-x-0 top-0 h-[24px]",
|
|
7409
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 0)
|
|
7410
|
+
}
|
|
7411
|
+
),
|
|
7412
|
+
/* @__PURE__ */ jsx(
|
|
7413
|
+
DroppableTimeSlot2,
|
|
7414
|
+
{
|
|
7415
|
+
date: selectedDate,
|
|
7416
|
+
hour,
|
|
7417
|
+
minute: 15,
|
|
7418
|
+
className: "absolute inset-x-0 top-[24px] h-[24px]",
|
|
7419
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 15)
|
|
7420
|
+
}
|
|
7421
|
+
),
|
|
7422
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-1/2 border-b border-dashed border-border/30" }),
|
|
7423
|
+
/* @__PURE__ */ jsx(
|
|
7424
|
+
DroppableTimeSlot2,
|
|
7425
|
+
{
|
|
7426
|
+
date: selectedDate,
|
|
7427
|
+
hour,
|
|
7428
|
+
minute: 30,
|
|
7429
|
+
className: "absolute inset-x-0 top-[48px] h-[24px]",
|
|
7430
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 30)
|
|
7431
|
+
}
|
|
7432
|
+
),
|
|
7433
|
+
/* @__PURE__ */ jsx(
|
|
7434
|
+
DroppableTimeSlot2,
|
|
7435
|
+
{
|
|
7436
|
+
date: selectedDate,
|
|
7437
|
+
hour,
|
|
7438
|
+
minute: 45,
|
|
7439
|
+
className: "absolute inset-x-0 top-[72px] h-[24px]",
|
|
7440
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 45)
|
|
7441
|
+
}
|
|
7442
|
+
)
|
|
7443
|
+
]
|
|
7444
|
+
},
|
|
7445
|
+
hour
|
|
7446
|
+
);
|
|
7447
|
+
}),
|
|
7448
|
+
groupedEvents.map(
|
|
7449
|
+
(group, groupIndex) => group.map((event) => {
|
|
7450
|
+
let style = getEventBlockStyle(
|
|
7451
|
+
event,
|
|
7452
|
+
selectedDate,
|
|
7453
|
+
groupIndex,
|
|
7454
|
+
groupedEvents.length,
|
|
7455
|
+
{ from: earliestEventHour}
|
|
7456
|
+
);
|
|
7457
|
+
const hasOverlap = groupedEvents.some(
|
|
7458
|
+
(otherGroup, otherIndex) => otherIndex !== groupIndex && otherGroup.some(
|
|
7459
|
+
(otherEvent) => areIntervalsOverlapping(
|
|
7460
|
+
{
|
|
7461
|
+
start: parseISO(event.startDate),
|
|
7462
|
+
end: parseISO(event.endDate)
|
|
7463
|
+
},
|
|
7464
|
+
{
|
|
7465
|
+
start: parseISO(otherEvent.startDate),
|
|
7466
|
+
end: parseISO(otherEvent.endDate)
|
|
7467
|
+
}
|
|
7468
|
+
)
|
|
7469
|
+
)
|
|
7470
|
+
);
|
|
7471
|
+
if (!hasOverlap) {
|
|
7472
|
+
style = { ...style, width: "100%", left: "0%" };
|
|
7473
|
+
}
|
|
7474
|
+
return /* @__PURE__ */ jsx(
|
|
7475
|
+
DraggableEventWrapper3,
|
|
7476
|
+
{
|
|
7477
|
+
event,
|
|
7478
|
+
className: "absolute px-1 py-0.5",
|
|
7479
|
+
style,
|
|
7480
|
+
children: /* @__PURE__ */ jsx(
|
|
7481
|
+
EventBadge,
|
|
7482
|
+
{
|
|
7483
|
+
event,
|
|
7484
|
+
variant: badgeVariant,
|
|
7485
|
+
showTime: true,
|
|
7486
|
+
onClick: (e) => onEventClick?.(e),
|
|
7487
|
+
className: "h-full w-full"
|
|
7488
|
+
}
|
|
7489
|
+
)
|
|
7490
|
+
},
|
|
7491
|
+
event.id
|
|
7492
|
+
);
|
|
7493
|
+
})
|
|
7494
|
+
)
|
|
7495
|
+
] }),
|
|
7496
|
+
isToday(selectedDate) && /* @__PURE__ */ jsx(
|
|
7497
|
+
CalendarTimeline2,
|
|
7498
|
+
{
|
|
7499
|
+
firstVisibleHour: earliestEventHour,
|
|
7500
|
+
lastVisibleHour: latestEventHour
|
|
7501
|
+
}
|
|
7502
|
+
)
|
|
7503
|
+
] })
|
|
7504
|
+
] }) })
|
|
7505
|
+
] }),
|
|
7506
|
+
showSidebar && /* @__PURE__ */ jsxs("div", { className: "hidden w-64 divide-y border-l md:block", children: [
|
|
7507
|
+
/* @__PURE__ */ jsx(
|
|
7508
|
+
Calendar,
|
|
7509
|
+
{
|
|
7510
|
+
className: "mx-auto w-fit",
|
|
7511
|
+
mode: "single",
|
|
7512
|
+
selected: selectedDate,
|
|
7513
|
+
onSelect: handleDateSelect
|
|
7514
|
+
}
|
|
7515
|
+
),
|
|
7516
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-3", children: [
|
|
7517
|
+
currentEvents.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 px-4 pt-4", children: [
|
|
7518
|
+
/* @__PURE__ */ jsxs("span", { className: "relative mt-[5px] flex size-2.5", children: [
|
|
7519
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-full animate-ping rounded-full bg-green-400 opacity-75" }),
|
|
7520
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex size-2.5 rounded-full bg-green-600" })
|
|
7521
|
+
] }),
|
|
7522
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: "Happening now" })
|
|
7523
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "p-4 text-center text-sm italic text-muted-foreground", children: "No appointments or consultations at the moment" }),
|
|
7524
|
+
currentEvents.length > 0 && /* @__PURE__ */ jsx(ScrollArea, { className: "h-[422px] px-4", type: "always", children: /* @__PURE__ */ jsx("div", { className: "space-y-6 pb-4", children: currentEvents.map((event) => {
|
|
7525
|
+
const user = users.find((u) => u.id === event.user.id);
|
|
7526
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
7527
|
+
/* @__PURE__ */ jsx("p", { className: "line-clamp-2 text-sm font-semibold", children: event.title }),
|
|
7528
|
+
user && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
7529
|
+
/* @__PURE__ */ jsx(User, { className: "size-3.5" }),
|
|
7530
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: user.name })
|
|
7531
|
+
] }),
|
|
7532
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
7533
|
+
/* @__PURE__ */ jsx(Calendar$1, { className: "size-3.5" }),
|
|
7534
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: format(/* @__PURE__ */ new Date(), "MMM d, yyyy") })
|
|
7535
|
+
] }),
|
|
7536
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
7537
|
+
/* @__PURE__ */ jsx(Clock, { className: "size-3.5" }),
|
|
7538
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm", children: [
|
|
7539
|
+
format(parseISO(event.startDate), "h:mm a"),
|
|
7540
|
+
" -",
|
|
7541
|
+
" ",
|
|
7542
|
+
format(parseISO(event.endDate), "h:mm a")
|
|
7543
|
+
] })
|
|
7544
|
+
] })
|
|
7545
|
+
] }, event.id);
|
|
7546
|
+
}) }) })
|
|
7547
|
+
] })
|
|
7548
|
+
] })
|
|
7549
|
+
] });
|
|
7550
|
+
}
|
|
7551
|
+
function DayViewMultiDayEventsRow({
|
|
7552
|
+
selectedDate,
|
|
7553
|
+
multiDayEvents
|
|
7554
|
+
}) {
|
|
7555
|
+
const { badgeVariant } = useEventCalendar();
|
|
7556
|
+
const relevantEvents = multiDayEvents.filter((event) => {
|
|
7557
|
+
const start = parseISO(event.startDate);
|
|
7558
|
+
const end = parseISO(event.endDate);
|
|
7559
|
+
return selectedDate >= start && selectedDate <= end;
|
|
7560
|
+
});
|
|
7561
|
+
if (relevantEvents.length === 0) return null;
|
|
7562
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex border-b", children: [
|
|
7563
|
+
/* @__PURE__ */ jsx("div", { className: "w-18 shrink-0" }),
|
|
7564
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 space-y-1 border-l p-2", children: relevantEvents.map((event) => /* @__PURE__ */ jsx(
|
|
7565
|
+
EventBadge,
|
|
7566
|
+
{
|
|
7567
|
+
event,
|
|
7568
|
+
variant: badgeVariant,
|
|
7569
|
+
className: "w-full"
|
|
7570
|
+
},
|
|
7571
|
+
event.id
|
|
7572
|
+
)) })
|
|
7573
|
+
] });
|
|
7574
|
+
}
|
|
7575
|
+
function CalendarTimeline2({
|
|
7576
|
+
firstVisibleHour,
|
|
7577
|
+
lastVisibleHour
|
|
7578
|
+
}) {
|
|
7579
|
+
const [currentTime, setCurrentTime] = React15.useState(/* @__PURE__ */ new Date());
|
|
7580
|
+
React15.useEffect(() => {
|
|
7581
|
+
const interval = setInterval(() => {
|
|
7582
|
+
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7583
|
+
}, 6e4);
|
|
7584
|
+
return () => clearInterval(interval);
|
|
7585
|
+
}, []);
|
|
7586
|
+
const currentHour = currentTime.getHours();
|
|
7587
|
+
const currentMinute = currentTime.getMinutes();
|
|
7588
|
+
if (currentHour < firstVisibleHour || currentHour >= lastVisibleHour) {
|
|
7589
|
+
return null;
|
|
7590
|
+
}
|
|
7591
|
+
const minutesSinceStart = (currentHour - firstVisibleHour) * 60 + currentMinute;
|
|
7592
|
+
const totalMinutes = (lastVisibleHour - firstVisibleHour) * 60;
|
|
7593
|
+
const topPercent = minutesSinceStart / totalMinutes * 100;
|
|
7594
|
+
return /* @__PURE__ */ jsxs(
|
|
7595
|
+
"div",
|
|
7596
|
+
{
|
|
7597
|
+
className: "pointer-events-none absolute inset-x-0 z-30 flex items-center",
|
|
7598
|
+
style: { top: `${topPercent}%` },
|
|
7599
|
+
children: [
|
|
7600
|
+
/* @__PURE__ */ jsx("div", { className: "size-3 -translate-x-1/2 rounded-full bg-red-500" }),
|
|
7601
|
+
/* @__PURE__ */ jsx("div", { className: "h-0.5 flex-1 bg-red-500" })
|
|
7602
|
+
]
|
|
7603
|
+
}
|
|
7604
|
+
);
|
|
7605
|
+
}
|
|
7606
|
+
function YearView({
|
|
7607
|
+
className,
|
|
7608
|
+
weekStartsOn = 0,
|
|
7609
|
+
onMonthClick,
|
|
7610
|
+
onDateClick
|
|
7611
|
+
}) {
|
|
7612
|
+
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7613
|
+
const filteredEvents = useFilteredEvents();
|
|
7614
|
+
const months = React15.useMemo(() => {
|
|
7615
|
+
const yearStart = startOfYear(selectedDate);
|
|
7616
|
+
return Array.from({ length: 12 }, (_, i) => addMonths(yearStart, i));
|
|
7617
|
+
}, [selectedDate]);
|
|
7618
|
+
const handleMonthClick = (date) => {
|
|
7619
|
+
setSelectedDate(date);
|
|
7620
|
+
setView("month");
|
|
7621
|
+
onMonthClick?.(date);
|
|
7622
|
+
};
|
|
7623
|
+
const handleDateClick = (date) => {
|
|
7624
|
+
setSelectedDate(date);
|
|
7625
|
+
setView("day");
|
|
7626
|
+
onDateClick?.(date);
|
|
7627
|
+
};
|
|
7628
|
+
return /* @__PURE__ */ jsx(ScrollArea, { className: cn("h-full", className), type: "always", children: /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4", children: months.map((month) => /* @__PURE__ */ jsx(
|
|
7629
|
+
YearViewMonth,
|
|
7630
|
+
{
|
|
7631
|
+
month,
|
|
7632
|
+
events: filteredEvents,
|
|
7633
|
+
onMonthClick: () => handleMonthClick(month),
|
|
7634
|
+
onDateClick: handleDateClick
|
|
7635
|
+
},
|
|
7636
|
+
month.toString()
|
|
7637
|
+
)) }) }) });
|
|
7638
|
+
}
|
|
7639
|
+
function YearViewMonth({
|
|
7640
|
+
month,
|
|
7641
|
+
events,
|
|
7642
|
+
onMonthClick,
|
|
7643
|
+
onDateClick
|
|
7644
|
+
}) {
|
|
7645
|
+
const cells = getCalendarCells(month);
|
|
7646
|
+
const monthEvents = events.filter((event) => {
|
|
7647
|
+
const eventStart = parseISO(event.startDate);
|
|
7648
|
+
return isSameMonth(eventStart, month);
|
|
7649
|
+
});
|
|
7650
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-sm border border-border/50 bg-card p-3", children: [
|
|
7651
|
+
/* @__PURE__ */ jsxs(
|
|
7652
|
+
"button",
|
|
7653
|
+
{
|
|
7654
|
+
type: "button",
|
|
7655
|
+
onClick: onMonthClick,
|
|
7656
|
+
className: "mb-2 w-full text-left text-sm font-semibold transition-colors hover:text-primary",
|
|
7657
|
+
children: [
|
|
7658
|
+
format(month, "MMMM"),
|
|
7659
|
+
monthEvents.length > 0 && /* @__PURE__ */ jsxs("span", { className: "ml-2 text-xs font-normal text-muted-foreground", children: [
|
|
7660
|
+
"(",
|
|
7661
|
+
monthEvents.length,
|
|
7662
|
+
")"
|
|
7663
|
+
] })
|
|
7664
|
+
]
|
|
7665
|
+
}
|
|
7666
|
+
),
|
|
7667
|
+
/* @__PURE__ */ jsx("div", { className: "mb-1 grid grid-cols-7", children: ["S", "M", "T", "W", "T", "F", "S"].map((day, i) => /* @__PURE__ */ jsx(
|
|
7668
|
+
"div",
|
|
7669
|
+
{
|
|
7670
|
+
className: "text-center text-[10px] font-medium text-muted-foreground",
|
|
7671
|
+
children: day
|
|
7672
|
+
},
|
|
7673
|
+
i
|
|
7674
|
+
)) }),
|
|
7675
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7", children: cells.map((cell) => /* @__PURE__ */ jsx(
|
|
7676
|
+
YearViewDayCell,
|
|
7677
|
+
{
|
|
7678
|
+
cell,
|
|
7679
|
+
month,
|
|
7680
|
+
events,
|
|
7681
|
+
onDateClick
|
|
7682
|
+
},
|
|
7683
|
+
cell.date.toISOString()
|
|
7684
|
+
)) })
|
|
7685
|
+
] });
|
|
7686
|
+
}
|
|
7687
|
+
function YearViewDayCell({
|
|
7688
|
+
cell,
|
|
7689
|
+
month,
|
|
7690
|
+
events,
|
|
7691
|
+
onDateClick
|
|
7692
|
+
}) {
|
|
7693
|
+
const { date, currentMonth } = cell;
|
|
7694
|
+
const isCurrentDay = isToday(date);
|
|
7695
|
+
const dayEvents = events.filter((event) => {
|
|
7696
|
+
const eventStart = parseISO(event.startDate);
|
|
7697
|
+
const eventEnd = parseISO(event.endDate);
|
|
7698
|
+
return date >= eventStart && date <= eventEnd || isSameDay(eventStart, date) || isSameDay(eventEnd, date);
|
|
7699
|
+
});
|
|
7700
|
+
const hasEvents = dayEvents.length > 0;
|
|
7701
|
+
if (!currentMonth) {
|
|
7702
|
+
return /* @__PURE__ */ jsx("div", { className: "aspect-square" });
|
|
7703
|
+
}
|
|
7704
|
+
return /* @__PURE__ */ jsxs(
|
|
7705
|
+
"button",
|
|
7706
|
+
{
|
|
7707
|
+
type: "button",
|
|
7708
|
+
onClick: () => onDateClick(date),
|
|
7709
|
+
className: cn(
|
|
7710
|
+
"relative flex aspect-square items-center justify-center text-[11px] transition-colors",
|
|
7711
|
+
"hover:bg-muted rounded-sm",
|
|
7712
|
+
isCurrentDay && "bg-primary text-primary-foreground rounded-sm hover:bg-primary/90"
|
|
7713
|
+
),
|
|
7714
|
+
children: [
|
|
7715
|
+
cell.day,
|
|
7716
|
+
hasEvents && !isCurrentDay && /* @__PURE__ */ jsx("span", { className: "absolute bottom-0.5 left-1/2 size-1 -translate-x-1/2 rounded-full bg-primary" })
|
|
7717
|
+
]
|
|
7718
|
+
}
|
|
7719
|
+
);
|
|
7720
|
+
}
|
|
7721
|
+
var colorClasses2 = {
|
|
7722
|
+
blue: { border: "border-l-blue-500", bg: "bg-blue-50 dark:bg-blue-950/20" },
|
|
7723
|
+
green: { border: "border-l-green-500", bg: "bg-green-50 dark:bg-green-950/20" },
|
|
7724
|
+
red: { border: "border-l-red-500", bg: "bg-red-50 dark:bg-red-950/20" },
|
|
7725
|
+
yellow: { border: "border-l-yellow-500", bg: "bg-yellow-50 dark:bg-yellow-950/20" },
|
|
7726
|
+
purple: { border: "border-l-purple-500", bg: "bg-purple-50 dark:bg-purple-950/20" },
|
|
7727
|
+
orange: { border: "border-l-primary", bg: "bg-orange-50 dark:bg-orange-950/20" }
|
|
7728
|
+
};
|
|
7729
|
+
function AgendaView({
|
|
7730
|
+
className,
|
|
7731
|
+
emptyMessage = "No events scheduled for the selected month",
|
|
7732
|
+
onEventClick,
|
|
7733
|
+
onDateClick
|
|
7734
|
+
}) {
|
|
7735
|
+
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7736
|
+
const filteredEvents = useFilteredEvents();
|
|
7737
|
+
const { singleDayEvents, multiDayEvents } = React15.useMemo(
|
|
7738
|
+
() => splitEventsByDuration(filteredEvents),
|
|
7739
|
+
[filteredEvents]
|
|
7740
|
+
);
|
|
7741
|
+
const eventsByDay = React15.useMemo(() => {
|
|
7742
|
+
const allDates = /* @__PURE__ */ new Map();
|
|
7743
|
+
singleDayEvents.forEach((event) => {
|
|
7744
|
+
const eventDate = parseISO(event.startDate);
|
|
7745
|
+
if (!isSameMonth(eventDate, selectedDate)) return;
|
|
7746
|
+
const dateKey = format(eventDate, "yyyy-MM-dd");
|
|
7747
|
+
if (!allDates.has(dateKey)) {
|
|
7748
|
+
allDates.set(dateKey, {
|
|
7749
|
+
date: startOfDay(eventDate),
|
|
7750
|
+
events: [],
|
|
7751
|
+
multiDayEvents: []
|
|
7752
|
+
});
|
|
7753
|
+
}
|
|
7754
|
+
allDates.get(dateKey)?.events.push(event);
|
|
7755
|
+
});
|
|
7756
|
+
multiDayEvents.forEach((event) => {
|
|
7757
|
+
const eventStart = parseISO(event.startDate);
|
|
7758
|
+
const eventEnd = parseISO(event.endDate);
|
|
7759
|
+
let currentDate = startOfDay(eventStart);
|
|
7760
|
+
const lastDate = endOfDay(eventEnd);
|
|
7761
|
+
while (currentDate <= lastDate) {
|
|
7762
|
+
if (isSameMonth(currentDate, selectedDate)) {
|
|
7763
|
+
const dateKey = format(currentDate, "yyyy-MM-dd");
|
|
7764
|
+
if (!allDates.has(dateKey)) {
|
|
7765
|
+
allDates.set(dateKey, {
|
|
7766
|
+
date: new Date(currentDate),
|
|
7767
|
+
events: [],
|
|
7768
|
+
multiDayEvents: []
|
|
7769
|
+
});
|
|
7770
|
+
}
|
|
7771
|
+
allDates.get(dateKey)?.multiDayEvents.push(event);
|
|
7772
|
+
}
|
|
7773
|
+
currentDate = new Date(currentDate.setDate(currentDate.getDate() + 1));
|
|
7774
|
+
}
|
|
7775
|
+
});
|
|
7776
|
+
return Array.from(allDates.values()).sort(
|
|
7777
|
+
(a, b) => a.date.getTime() - b.date.getTime()
|
|
7778
|
+
);
|
|
7779
|
+
}, [singleDayEvents, multiDayEvents, selectedDate]);
|
|
7780
|
+
const hasAnyEvents = singleDayEvents.length > 0 || multiDayEvents.length > 0;
|
|
7781
|
+
const handleDateClick = (date) => {
|
|
7782
|
+
setSelectedDate(date);
|
|
7783
|
+
setView("day");
|
|
7784
|
+
onDateClick?.(date);
|
|
7785
|
+
};
|
|
7786
|
+
return /* @__PURE__ */ jsx("div", { className: cn("h-[800px]", className), children: /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", type: "always", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6 p-4", children: [
|
|
7787
|
+
eventsByDay.map((dayGroup) => /* @__PURE__ */ jsx(
|
|
7788
|
+
AgendaDayGroup,
|
|
7789
|
+
{
|
|
7790
|
+
date: dayGroup.date,
|
|
7791
|
+
events: dayGroup.events,
|
|
7792
|
+
multiDayEvents: dayGroup.multiDayEvents,
|
|
7793
|
+
onDateClick: handleDateClick,
|
|
7794
|
+
onEventClick
|
|
7795
|
+
},
|
|
7796
|
+
format(dayGroup.date, "yyyy-MM-dd")
|
|
7797
|
+
)),
|
|
7798
|
+
!hasAnyEvents && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2 py-20 text-muted-foreground", children: [
|
|
7799
|
+
/* @__PURE__ */ jsx(CalendarX2, { className: "size-10" }),
|
|
7800
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm md:text-base", children: emptyMessage })
|
|
7801
|
+
] })
|
|
7802
|
+
] }) }) });
|
|
7803
|
+
}
|
|
7804
|
+
function AgendaDayGroup({
|
|
7805
|
+
date,
|
|
7806
|
+
events,
|
|
7807
|
+
multiDayEvents,
|
|
7808
|
+
onDateClick,
|
|
7809
|
+
onEventClick
|
|
7810
|
+
}) {
|
|
7811
|
+
const isCurrentDay = isToday(date);
|
|
7812
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
7813
|
+
/* @__PURE__ */ jsxs(
|
|
7814
|
+
"button",
|
|
7815
|
+
{
|
|
7816
|
+
type: "button",
|
|
7817
|
+
onClick: () => onDateClick(date),
|
|
7818
|
+
className: cn(
|
|
7819
|
+
"mb-3 flex items-center gap-2 text-left transition-colors hover:text-primary",
|
|
7820
|
+
isCurrentDay && "text-primary"
|
|
7821
|
+
),
|
|
7822
|
+
children: [
|
|
7823
|
+
/* @__PURE__ */ jsx(
|
|
7824
|
+
"span",
|
|
7825
|
+
{
|
|
7826
|
+
className: cn(
|
|
7827
|
+
"flex size-8 items-center justify-center rounded-full text-sm font-bold",
|
|
7828
|
+
isCurrentDay && "bg-primary text-primary-foreground"
|
|
7829
|
+
),
|
|
7830
|
+
children: format(date, "d")
|
|
7831
|
+
}
|
|
7832
|
+
),
|
|
7833
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
7834
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: format(date, "EEEE") }),
|
|
7835
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 text-muted-foreground", children: format(date, "MMMM d, yyyy") })
|
|
7836
|
+
] })
|
|
7837
|
+
]
|
|
7838
|
+
}
|
|
7839
|
+
),
|
|
7840
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 pl-10", children: [
|
|
7841
|
+
multiDayEvents.map((event) => /* @__PURE__ */ jsx(
|
|
7842
|
+
AgendaEventCard,
|
|
7843
|
+
{
|
|
7844
|
+
event,
|
|
7845
|
+
isMultiDay: true,
|
|
7846
|
+
onClick: () => onEventClick?.(event)
|
|
7847
|
+
},
|
|
7848
|
+
`multi-${event.id}`
|
|
7849
|
+
)),
|
|
7850
|
+
events.map((event) => /* @__PURE__ */ jsx(
|
|
7851
|
+
AgendaEventCard,
|
|
7852
|
+
{
|
|
7853
|
+
event,
|
|
7854
|
+
onClick: () => onEventClick?.(event)
|
|
7855
|
+
},
|
|
7856
|
+
event.id
|
|
7857
|
+
))
|
|
7858
|
+
] })
|
|
7859
|
+
] });
|
|
7860
|
+
}
|
|
7861
|
+
function AgendaEventCard({ event, isMultiDay, onClick }) {
|
|
7862
|
+
const colors = colorClasses2[event.color];
|
|
7863
|
+
const startTime = format(parseISO(event.startDate), "h:mm a");
|
|
7864
|
+
const endTime = format(parseISO(event.endDate), "h:mm a");
|
|
7865
|
+
const getInitials = (name) => {
|
|
7866
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
7867
|
+
};
|
|
7868
|
+
return /* @__PURE__ */ jsxs(
|
|
7869
|
+
"button",
|
|
7870
|
+
{
|
|
7871
|
+
type: "button",
|
|
7872
|
+
onClick,
|
|
7873
|
+
className: cn(
|
|
7874
|
+
"flex w-full items-start gap-3 rounded-lg border-l-4 p-3 text-left transition-colors",
|
|
7875
|
+
"hover:opacity-90",
|
|
7876
|
+
colors.border,
|
|
7877
|
+
colors.bg
|
|
7878
|
+
),
|
|
7879
|
+
children: [
|
|
7880
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-10 shrink-0", children: [
|
|
7881
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: event.user.picturePath, alt: event.user.name }),
|
|
7882
|
+
/* @__PURE__ */ jsx(AvatarFallback, { children: getInitials(event.user.name) })
|
|
7883
|
+
] }),
|
|
7884
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
7885
|
+
isMultiDay && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Multi-day event" }),
|
|
7886
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold truncate", children: event.title }),
|
|
7887
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: event.user.name }),
|
|
7888
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
7889
|
+
startTime,
|
|
7890
|
+
" - ",
|
|
7891
|
+
endTime
|
|
7892
|
+
] }),
|
|
7893
|
+
event.description && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground line-clamp-2", children: event.description })
|
|
7894
|
+
] })
|
|
7895
|
+
]
|
|
7896
|
+
}
|
|
7897
|
+
);
|
|
7898
|
+
}
|
|
7899
|
+
var VIEW_CONFIG = [
|
|
7900
|
+
{ view: "day", icon: List, label: "View by day" },
|
|
7901
|
+
{ view: "week", icon: Columns, label: "View by week" },
|
|
7902
|
+
{ view: "month", icon: Grid2x2, label: "View by month" },
|
|
7903
|
+
{ view: "year", icon: Grid3x3, label: "View by year" },
|
|
7904
|
+
{ view: "agenda", icon: CalendarRange, label: "View by agenda" }
|
|
7905
|
+
];
|
|
7906
|
+
function CalendarHeader({
|
|
7907
|
+
className,
|
|
7908
|
+
showViewSwitcher = true,
|
|
7909
|
+
showUserFilter = true,
|
|
7910
|
+
showBadgeVariant = false,
|
|
7911
|
+
// Hidden by default, controlled via settings
|
|
7912
|
+
showToday = true,
|
|
7913
|
+
showAddButton = true,
|
|
7914
|
+
onAddClick
|
|
7915
|
+
}) {
|
|
7916
|
+
const {
|
|
7917
|
+
selectedDate,
|
|
7918
|
+
view,
|
|
7919
|
+
setView,
|
|
7920
|
+
setSelectedDate,
|
|
7921
|
+
selectedUserId,
|
|
7922
|
+
setSelectedUserId,
|
|
7923
|
+
users,
|
|
7924
|
+
badgeVariant,
|
|
7925
|
+
setBadgeVariant,
|
|
7926
|
+
goToPrevious,
|
|
7927
|
+
goToNext
|
|
7928
|
+
} = useEventCalendar();
|
|
7929
|
+
const filteredEvents = useFilteredEvents();
|
|
7930
|
+
const eventCount = filteredEvents.length;
|
|
7931
|
+
const { start: rangeStart, end: rangeEnd } = getViewDateRange(selectedDate, view);
|
|
7932
|
+
const dateRangeLabel = formatDateRange(rangeStart, rangeEnd);
|
|
7933
|
+
const getInitials = (name) => {
|
|
7934
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
7935
|
+
};
|
|
7936
|
+
const handleTodayClick = () => {
|
|
7937
|
+
setSelectedDate(/* @__PURE__ */ new Date());
|
|
7938
|
+
};
|
|
7939
|
+
const today = /* @__PURE__ */ new Date();
|
|
7940
|
+
return /* @__PURE__ */ jsxs(
|
|
7941
|
+
"div",
|
|
7942
|
+
{
|
|
7943
|
+
className: cn(
|
|
7944
|
+
"flex flex-col gap-4 border-b border-border p-4 lg:flex-row lg:items-center lg:justify-between",
|
|
7945
|
+
className
|
|
7946
|
+
),
|
|
7947
|
+
children: [
|
|
7948
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7949
|
+
/* @__PURE__ */ jsxs(
|
|
7950
|
+
"button",
|
|
7951
|
+
{
|
|
7952
|
+
type: "button",
|
|
7953
|
+
onClick: handleTodayClick,
|
|
7954
|
+
className: "flex size-14 flex-col items-start overflow-hidden rounded-lg border focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
7955
|
+
children: [
|
|
7956
|
+
/* @__PURE__ */ jsx("p", { className: "flex h-6 w-full items-center justify-center bg-primary text-center text-xs font-semibold text-primary-foreground", children: format(today, "MMM").toUpperCase() }),
|
|
7957
|
+
/* @__PURE__ */ jsx("p", { className: "flex w-full flex-1 items-center justify-center text-lg font-bold", children: today.getDate() })
|
|
7958
|
+
]
|
|
7959
|
+
}
|
|
7960
|
+
),
|
|
7961
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
7962
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7963
|
+
/* @__PURE__ */ jsxs("span", { className: "text-lg font-semibold", children: [
|
|
7964
|
+
format(selectedDate, "MMMM"),
|
|
7965
|
+
" ",
|
|
7966
|
+
selectedDate.getFullYear()
|
|
7967
|
+
] }),
|
|
7968
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "px-1.5", children: [
|
|
7969
|
+
eventCount,
|
|
7970
|
+
" event",
|
|
7971
|
+
eventCount !== 1 ? "s" : ""
|
|
7972
|
+
] })
|
|
7973
|
+
] }),
|
|
7974
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7975
|
+
/* @__PURE__ */ jsxs(
|
|
7976
|
+
Button,
|
|
7977
|
+
{
|
|
7978
|
+
variant: "outline",
|
|
7979
|
+
size: "icon",
|
|
7980
|
+
className: "size-7 [&_svg]:size-4",
|
|
7981
|
+
onClick: goToPrevious,
|
|
7982
|
+
children: [
|
|
7983
|
+
/* @__PURE__ */ jsx(ChevronLeft, {}),
|
|
7984
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Previous" })
|
|
7985
|
+
]
|
|
7986
|
+
}
|
|
7987
|
+
),
|
|
7988
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: dateRangeLabel }),
|
|
7989
|
+
/* @__PURE__ */ jsxs(
|
|
7990
|
+
Button,
|
|
7991
|
+
{
|
|
7992
|
+
variant: "outline",
|
|
7993
|
+
size: "icon",
|
|
7994
|
+
className: "size-7 [&_svg]:size-4",
|
|
7995
|
+
onClick: goToNext,
|
|
7996
|
+
children: [
|
|
7997
|
+
/* @__PURE__ */ jsx(ChevronRight, {}),
|
|
7998
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Next" })
|
|
7999
|
+
]
|
|
8000
|
+
}
|
|
8001
|
+
)
|
|
8002
|
+
] })
|
|
8003
|
+
] })
|
|
8004
|
+
] }),
|
|
8005
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1.5 sm:flex-row sm:justify-between", children: [
|
|
8006
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-1.5", children: [
|
|
8007
|
+
showViewSwitcher && /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-1 rounded-full border border-border px-1 py-1", children: VIEW_CONFIG.map((config, index) => {
|
|
8008
|
+
const Icon2 = config.icon;
|
|
8009
|
+
const isFirst = index === 0;
|
|
8010
|
+
const isLast = index === VIEW_CONFIG.length - 1;
|
|
8011
|
+
const isActive = view === config.view;
|
|
8012
|
+
return /* @__PURE__ */ jsx(
|
|
8013
|
+
Button,
|
|
8014
|
+
{
|
|
8015
|
+
"aria-label": config.label,
|
|
8016
|
+
size: "icon",
|
|
8017
|
+
variant: isActive ? "default" : "ghost",
|
|
8018
|
+
className: cn(
|
|
8019
|
+
"size-8 border-0 [&_svg]:size-4",
|
|
8020
|
+
isFirst && "rounded-l-full rounded-r-sm",
|
|
8021
|
+
isLast && "rounded-r-full rounded-l-sm",
|
|
8022
|
+
!isFirst && !isLast && "rounded-sm"
|
|
8023
|
+
),
|
|
8024
|
+
onClick: () => setView(config.view),
|
|
8025
|
+
children: /* @__PURE__ */ jsx(Icon2, { strokeWidth: 1.8 })
|
|
8026
|
+
},
|
|
8027
|
+
config.view
|
|
8028
|
+
);
|
|
8029
|
+
}) }),
|
|
8030
|
+
showUserFilter && users.length > 0 && /* @__PURE__ */ jsxs(
|
|
8031
|
+
Select,
|
|
8032
|
+
{
|
|
8033
|
+
value: selectedUserId || "all",
|
|
8034
|
+
onValueChange: (value) => setSelectedUserId(value === "all" ? null : value),
|
|
8035
|
+
children: [
|
|
8036
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "flex-1 md:w-48", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8037
|
+
/* @__PURE__ */ jsxs(SelectContent, { align: "end", children: [
|
|
8038
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "all", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8039
|
+
/* @__PURE__ */ jsxs("div", { className: "flex -space-x-2", children: [
|
|
8040
|
+
users.slice(0, 2).map((user) => /* @__PURE__ */ jsxs(Avatar, { className: "size-6 border-2 border-background", children: [
|
|
8041
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.picturePath, alt: user.name }),
|
|
8042
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px]", children: getInitials(user.name) })
|
|
8043
|
+
] }, user.id)),
|
|
8044
|
+
users.length > 2 && /* @__PURE__ */ jsxs("div", { className: "flex size-6 items-center justify-center rounded-full border-2 border-background bg-muted text-[10px] font-medium", children: [
|
|
8045
|
+
"+",
|
|
8046
|
+
users.length - 2
|
|
8047
|
+
] })
|
|
8048
|
+
] }),
|
|
8049
|
+
"All"
|
|
8050
|
+
] }) }),
|
|
8051
|
+
users.map((user) => /* @__PURE__ */ jsx(SelectItem, { value: user.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8052
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-6", children: [
|
|
8053
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.picturePath, alt: user.name }),
|
|
8054
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px]", children: getInitials(user.name) })
|
|
8055
|
+
] }),
|
|
8056
|
+
/* @__PURE__ */ jsx("p", { className: "truncate", children: user.name })
|
|
8057
|
+
] }) }, user.id))
|
|
8058
|
+
] })
|
|
8059
|
+
]
|
|
8060
|
+
}
|
|
8061
|
+
)
|
|
8062
|
+
] }),
|
|
8063
|
+
showAddButton && /* @__PURE__ */ jsxs(Button, { onClick: onAddClick, className: "w-full sm:w-auto", children: [
|
|
8064
|
+
/* @__PURE__ */ jsx(Plus, {}),
|
|
8065
|
+
"Add Event"
|
|
8066
|
+
] })
|
|
8067
|
+
] })
|
|
8068
|
+
]
|
|
8069
|
+
}
|
|
8070
|
+
);
|
|
8071
|
+
}
|
|
8072
|
+
function CalendarHeaderCompact({
|
|
8073
|
+
className,
|
|
8074
|
+
showAddButton = true,
|
|
8075
|
+
onAddClick
|
|
8076
|
+
}) {
|
|
8077
|
+
const {
|
|
8078
|
+
selectedDate,
|
|
8079
|
+
setSelectedDate,
|
|
8080
|
+
view,
|
|
8081
|
+
setView,
|
|
8082
|
+
goToPrevious,
|
|
8083
|
+
goToNext
|
|
8084
|
+
} = useEventCalendar();
|
|
8085
|
+
const filteredEvents = useFilteredEvents();
|
|
8086
|
+
const eventCount = filteredEvents.length;
|
|
8087
|
+
const today = /* @__PURE__ */ new Date();
|
|
8088
|
+
const handleTodayClick = () => {
|
|
8089
|
+
setSelectedDate(/* @__PURE__ */ new Date());
|
|
8090
|
+
};
|
|
8091
|
+
return /* @__PURE__ */ jsxs(
|
|
8092
|
+
"div",
|
|
8093
|
+
{
|
|
8094
|
+
className: cn(
|
|
8095
|
+
"flex items-center justify-between border-b border-border p-3",
|
|
8096
|
+
className
|
|
8097
|
+
),
|
|
8098
|
+
children: [
|
|
8099
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8100
|
+
/* @__PURE__ */ jsxs(
|
|
8101
|
+
"button",
|
|
8102
|
+
{
|
|
8103
|
+
type: "button",
|
|
8104
|
+
onClick: handleTodayClick,
|
|
8105
|
+
className: "flex size-10 flex-col items-start overflow-hidden rounded border focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
8106
|
+
children: [
|
|
8107
|
+
/* @__PURE__ */ jsx("p", { className: "flex h-4 w-full items-center justify-center bg-primary text-center text-[8px] font-semibold text-primary-foreground", children: format(today, "MMM").toUpperCase() }),
|
|
8108
|
+
/* @__PURE__ */ jsx("p", { className: "flex w-full flex-1 items-center justify-center text-sm font-bold", children: today.getDate() })
|
|
8109
|
+
]
|
|
8110
|
+
}
|
|
8111
|
+
),
|
|
8112
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
8113
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: format(selectedDate, "MMM yyyy") }),
|
|
8114
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
8115
|
+
eventCount,
|
|
8116
|
+
" events"
|
|
8117
|
+
] })
|
|
8118
|
+
] })
|
|
8119
|
+
] }),
|
|
8120
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8121
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", className: "size-8", onClick: goToPrevious, children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" }) }),
|
|
8122
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", className: "size-8", onClick: goToNext, children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" }) }),
|
|
8123
|
+
/* @__PURE__ */ jsxs("div", { className: "ml-2 inline-flex items-center gap-0.5 rounded-full border border-border px-0.5 py-0.5", children: [
|
|
8124
|
+
/* @__PURE__ */ jsx(
|
|
8125
|
+
Button,
|
|
8126
|
+
{
|
|
8127
|
+
size: "icon",
|
|
8128
|
+
variant: view === "day" ? "default" : "ghost",
|
|
8129
|
+
className: "size-6 rounded-l-full rounded-r-sm border-0 [&_svg]:size-3",
|
|
8130
|
+
onClick: () => setView("day"),
|
|
8131
|
+
children: /* @__PURE__ */ jsx(List, { strokeWidth: 1.8 })
|
|
8132
|
+
}
|
|
8133
|
+
),
|
|
8134
|
+
/* @__PURE__ */ jsx(
|
|
8135
|
+
Button,
|
|
8136
|
+
{
|
|
8137
|
+
size: "icon",
|
|
8138
|
+
variant: view === "week" ? "default" : "ghost",
|
|
8139
|
+
className: "size-6 rounded-sm border-0 [&_svg]:size-3",
|
|
8140
|
+
onClick: () => setView("week"),
|
|
8141
|
+
children: /* @__PURE__ */ jsx(Columns, { strokeWidth: 1.8 })
|
|
8142
|
+
}
|
|
8143
|
+
),
|
|
8144
|
+
/* @__PURE__ */ jsx(
|
|
8145
|
+
Button,
|
|
8146
|
+
{
|
|
8147
|
+
size: "icon",
|
|
8148
|
+
variant: view === "month" ? "default" : "ghost",
|
|
8149
|
+
className: "size-6 rounded-r-full rounded-l-sm border-0 [&_svg]:size-3",
|
|
8150
|
+
onClick: () => setView("month"),
|
|
8151
|
+
children: /* @__PURE__ */ jsx(Grid2x2, { strokeWidth: 1.8 })
|
|
8152
|
+
}
|
|
8153
|
+
)
|
|
8154
|
+
] }),
|
|
8155
|
+
showAddButton && /* @__PURE__ */ jsx(Button, { size: "sm", onClick: onAddClick, className: "ml-2 size-8 p-0", children: /* @__PURE__ */ jsx(Plus, { className: "size-4" }) })
|
|
8156
|
+
] })
|
|
8157
|
+
]
|
|
8158
|
+
}
|
|
8159
|
+
);
|
|
8160
|
+
}
|
|
8161
|
+
var EVENT_COLORS2 = [
|
|
8162
|
+
{ value: "blue", label: "Blue", className: "bg-blue-500" },
|
|
8163
|
+
{ value: "green", label: "Green", className: "bg-green-500" },
|
|
8164
|
+
{ value: "red", label: "Red", className: "bg-red-500" },
|
|
8165
|
+
{ value: "yellow", label: "Yellow", className: "bg-yellow-500" },
|
|
8166
|
+
{ value: "purple", label: "Purple", className: "bg-purple-500" },
|
|
8167
|
+
{ value: "orange", label: "Orange", className: "bg-primary" }
|
|
8168
|
+
];
|
|
8169
|
+
function EventDialog({
|
|
8170
|
+
open,
|
|
8171
|
+
onOpenChange,
|
|
8172
|
+
mode = "add",
|
|
8173
|
+
event,
|
|
8174
|
+
defaultDate = /* @__PURE__ */ new Date(),
|
|
8175
|
+
defaultUserId
|
|
8176
|
+
}) {
|
|
8177
|
+
const { addEvent, updateEvent, deleteEvent, users } = useEventCalendar();
|
|
8178
|
+
const [title, setTitle] = React15.useState("");
|
|
8179
|
+
const [description, setDescription] = React15.useState("");
|
|
8180
|
+
const [startDate, setStartDate] = React15.useState("");
|
|
8181
|
+
const [startTime, setStartTime] = React15.useState("");
|
|
8182
|
+
const [endDate, setEndDate] = React15.useState("");
|
|
8183
|
+
const [endTime, setEndTime] = React15.useState("");
|
|
8184
|
+
const [color, setColor] = React15.useState("blue");
|
|
8185
|
+
const [userId, setUserId] = React15.useState("");
|
|
8186
|
+
const [isSubmitting, setIsSubmitting] = React15.useState(false);
|
|
8187
|
+
React15.useEffect(() => {
|
|
8188
|
+
if (open) {
|
|
8189
|
+
if (mode === "edit" && event) {
|
|
8190
|
+
const start = parseISO(event.startDate);
|
|
8191
|
+
const end = parseISO(event.endDate);
|
|
8192
|
+
setTitle(event.title);
|
|
8193
|
+
setDescription(event.description || "");
|
|
8194
|
+
setStartDate(format(start, "yyyy-MM-dd"));
|
|
8195
|
+
setStartTime(format(start, "HH:mm"));
|
|
8196
|
+
setEndDate(format(end, "yyyy-MM-dd"));
|
|
8197
|
+
setEndTime(format(end, "HH:mm"));
|
|
8198
|
+
setColor(event.color);
|
|
8199
|
+
setUserId(event.user.id);
|
|
8200
|
+
} else {
|
|
8201
|
+
const start = defaultDate;
|
|
8202
|
+
const end = setMinutes(setHours(defaultDate, defaultDate.getHours() + 1), 0);
|
|
8203
|
+
setTitle("");
|
|
8204
|
+
setDescription("");
|
|
8205
|
+
setStartDate(format(start, "yyyy-MM-dd"));
|
|
8206
|
+
setStartTime(format(start, "HH:mm"));
|
|
8207
|
+
setEndDate(format(end, "yyyy-MM-dd"));
|
|
8208
|
+
setEndTime(format(end, "HH:mm"));
|
|
8209
|
+
setColor("blue");
|
|
8210
|
+
setUserId(defaultUserId || users[0]?.id || "");
|
|
8211
|
+
}
|
|
8212
|
+
}
|
|
8213
|
+
}, [open, mode, event, defaultDate, defaultUserId, users]);
|
|
8214
|
+
const handleSubmit = async (e) => {
|
|
8215
|
+
e.preventDefault();
|
|
8216
|
+
setIsSubmitting(true);
|
|
8217
|
+
try {
|
|
8218
|
+
const [startYear, startMonth, startDay] = startDate.split("-").map(Number);
|
|
8219
|
+
const [startHour, startMinute] = startTime.split(":").map(Number);
|
|
8220
|
+
const [endYear, endMonth, endDay] = endDate.split("-").map(Number);
|
|
8221
|
+
const [endHour, endMinute] = endTime.split(":").map(Number);
|
|
8222
|
+
const startDateTime = new Date(startYear, startMonth - 1, startDay, startHour, startMinute);
|
|
8223
|
+
const endDateTime = new Date(endYear, endMonth - 1, endDay, endHour, endMinute);
|
|
8224
|
+
const selectedUser = users.find((u) => u.id === userId);
|
|
8225
|
+
if (mode === "edit" && event) {
|
|
8226
|
+
const updatedEvent = {
|
|
8227
|
+
...event,
|
|
8228
|
+
title,
|
|
8229
|
+
description,
|
|
8230
|
+
startDate: startDateTime.toISOString(),
|
|
8231
|
+
endDate: endDateTime.toISOString(),
|
|
8232
|
+
color,
|
|
8233
|
+
user: {
|
|
8234
|
+
id: userId,
|
|
8235
|
+
name: selectedUser?.name || "Unknown"
|
|
8236
|
+
}
|
|
8237
|
+
};
|
|
8238
|
+
updateEvent(updatedEvent);
|
|
8239
|
+
} else {
|
|
8240
|
+
const newEvent = {
|
|
8241
|
+
id: generateEventId(),
|
|
8242
|
+
title,
|
|
8243
|
+
description,
|
|
8244
|
+
startDate: startDateTime.toISOString(),
|
|
8245
|
+
endDate: endDateTime.toISOString(),
|
|
8246
|
+
color,
|
|
8247
|
+
user: {
|
|
8248
|
+
id: userId,
|
|
8249
|
+
name: selectedUser?.name || "Unknown"
|
|
8250
|
+
}
|
|
8251
|
+
};
|
|
8252
|
+
addEvent(newEvent);
|
|
8253
|
+
}
|
|
8254
|
+
onOpenChange(false);
|
|
8255
|
+
} catch (error) {
|
|
8256
|
+
console.error("Failed to save event:", error);
|
|
8257
|
+
} finally {
|
|
8258
|
+
setIsSubmitting(false);
|
|
8259
|
+
}
|
|
8260
|
+
};
|
|
8261
|
+
const handleDelete = () => {
|
|
8262
|
+
if (event) {
|
|
8263
|
+
deleteEvent(event.id);
|
|
8264
|
+
onOpenChange(false);
|
|
8265
|
+
}
|
|
8266
|
+
};
|
|
8267
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { className: "sm:max-w-[500px]", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
|
|
8268
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
8269
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: mode === "edit" ? "Edit Event" : "Add Event" }),
|
|
8270
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: mode === "edit" ? "Make changes to your event below." : "Fill in the details for your new event." })
|
|
8271
|
+
] }),
|
|
8272
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 py-4", children: [
|
|
8273
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8274
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "title", children: "Title" }),
|
|
8275
|
+
/* @__PURE__ */ jsx(
|
|
8276
|
+
Input,
|
|
8277
|
+
{
|
|
8278
|
+
id: "title",
|
|
8279
|
+
value: title,
|
|
8280
|
+
onChange: (e) => setTitle(e.target.value),
|
|
8281
|
+
placeholder: "Event title",
|
|
8282
|
+
required: true
|
|
8283
|
+
}
|
|
8284
|
+
)
|
|
8285
|
+
] }),
|
|
8286
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8287
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "description", children: "Description" }),
|
|
8288
|
+
/* @__PURE__ */ jsx(
|
|
8289
|
+
Textarea,
|
|
8290
|
+
{
|
|
8291
|
+
id: "description",
|
|
8292
|
+
value: description,
|
|
8293
|
+
onChange: (e) => setDescription(e.target.value),
|
|
8294
|
+
placeholder: "Event description (optional)",
|
|
8295
|
+
rows: 3
|
|
8296
|
+
}
|
|
8297
|
+
)
|
|
8298
|
+
] }),
|
|
8299
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
8300
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8301
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "startDate", children: "Start Date" }),
|
|
8302
|
+
/* @__PURE__ */ jsx(
|
|
8303
|
+
Input,
|
|
8304
|
+
{
|
|
8305
|
+
id: "startDate",
|
|
8306
|
+
type: "date",
|
|
8307
|
+
value: startDate,
|
|
8308
|
+
onChange: (e) => setStartDate(e.target.value),
|
|
8309
|
+
required: true
|
|
8310
|
+
}
|
|
8311
|
+
)
|
|
8312
|
+
] }),
|
|
8313
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8314
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "startTime", children: "Start Time" }),
|
|
8315
|
+
/* @__PURE__ */ jsx(
|
|
8316
|
+
Input,
|
|
8317
|
+
{
|
|
8318
|
+
id: "startTime",
|
|
8319
|
+
type: "time",
|
|
8320
|
+
value: startTime,
|
|
8321
|
+
onChange: (e) => setStartTime(e.target.value),
|
|
8322
|
+
required: true
|
|
8323
|
+
}
|
|
8324
|
+
)
|
|
8325
|
+
] })
|
|
8326
|
+
] }),
|
|
8327
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
8328
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8329
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "endDate", children: "End Date" }),
|
|
8330
|
+
/* @__PURE__ */ jsx(
|
|
8331
|
+
Input,
|
|
8332
|
+
{
|
|
8333
|
+
id: "endDate",
|
|
8334
|
+
type: "date",
|
|
8335
|
+
value: endDate,
|
|
8336
|
+
onChange: (e) => setEndDate(e.target.value),
|
|
8337
|
+
required: true
|
|
8338
|
+
}
|
|
8339
|
+
)
|
|
8340
|
+
] }),
|
|
8341
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8342
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "endTime", children: "End Time" }),
|
|
8343
|
+
/* @__PURE__ */ jsx(
|
|
8344
|
+
Input,
|
|
8345
|
+
{
|
|
8346
|
+
id: "endTime",
|
|
8347
|
+
type: "time",
|
|
8348
|
+
value: endTime,
|
|
8349
|
+
onChange: (e) => setEndTime(e.target.value),
|
|
8350
|
+
required: true
|
|
8351
|
+
}
|
|
8352
|
+
)
|
|
8353
|
+
] })
|
|
8354
|
+
] }),
|
|
8355
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
8356
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8357
|
+
/* @__PURE__ */ jsx(Label2, { children: "Color" }),
|
|
8358
|
+
/* @__PURE__ */ jsxs(Select, { value: color, onValueChange: (v) => setColor(v), children: [
|
|
8359
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8360
|
+
/* @__PURE__ */ jsx(
|
|
8361
|
+
"span",
|
|
8362
|
+
{
|
|
8363
|
+
className: cn(
|
|
8364
|
+
"size-3 rounded-full",
|
|
8365
|
+
EVENT_COLORS2.find((c) => c.value === color)?.className
|
|
8366
|
+
)
|
|
8367
|
+
}
|
|
8368
|
+
),
|
|
8369
|
+
EVENT_COLORS2.find((c) => c.value === color)?.label
|
|
8370
|
+
] }) }) }),
|
|
8371
|
+
/* @__PURE__ */ jsx(SelectContent, { children: EVENT_COLORS2.map((c) => /* @__PURE__ */ jsx(SelectItem, { value: c.value, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8372
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-3 rounded-full", c.className) }),
|
|
8373
|
+
c.label
|
|
8374
|
+
] }) }, c.value)) })
|
|
8375
|
+
] })
|
|
8376
|
+
] }),
|
|
8377
|
+
users.length > 0 && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8378
|
+
/* @__PURE__ */ jsx(Label2, { children: "Assignee" }),
|
|
8379
|
+
/* @__PURE__ */ jsxs(Select, { value: userId, onValueChange: setUserId, children: [
|
|
8380
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select user" }) }),
|
|
8381
|
+
/* @__PURE__ */ jsx(SelectContent, { children: users.map((user) => /* @__PURE__ */ jsx(SelectItem, { value: user.id, children: user.name }, user.id)) })
|
|
8382
|
+
] })
|
|
8383
|
+
] })
|
|
8384
|
+
] })
|
|
8385
|
+
] }),
|
|
8386
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "flex-row justify-between gap-2", children: [
|
|
8387
|
+
mode === "edit" ? /* @__PURE__ */ jsx(
|
|
8388
|
+
Button,
|
|
8389
|
+
{
|
|
8390
|
+
type: "button",
|
|
8391
|
+
variant: "destructive",
|
|
8392
|
+
onClick: handleDelete,
|
|
8393
|
+
disabled: isSubmitting,
|
|
8394
|
+
children: "Delete"
|
|
8395
|
+
}
|
|
8396
|
+
) : /* @__PURE__ */ jsx("div", {}),
|
|
8397
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8398
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
8399
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting || !title.trim(), children: isSubmitting ? "Saving..." : mode === "edit" ? "Save Changes" : "Add Event" })
|
|
8400
|
+
] })
|
|
8401
|
+
] })
|
|
8402
|
+
] }) }) });
|
|
8403
|
+
}
|
|
8404
|
+
function QuickAddEvent({
|
|
8405
|
+
date,
|
|
8406
|
+
onAdd,
|
|
8407
|
+
onOpenDialog,
|
|
8408
|
+
onClose
|
|
8409
|
+
}) {
|
|
8410
|
+
const [title, setTitle] = React15.useState("");
|
|
8411
|
+
const { users } = useEventCalendar();
|
|
8412
|
+
const handleSubmit = (e) => {
|
|
8413
|
+
e.preventDefault();
|
|
8414
|
+
if (!title.trim()) return;
|
|
8415
|
+
const end = setMinutes(setHours(date, date.getHours() + 1), 0);
|
|
8416
|
+
onAdd({
|
|
8417
|
+
title,
|
|
8418
|
+
description: "",
|
|
8419
|
+
startDate: date.toISOString(),
|
|
8420
|
+
endDate: end.toISOString(),
|
|
8421
|
+
color: "blue",
|
|
8422
|
+
user: {
|
|
8423
|
+
id: users[0]?.id || "",
|
|
8424
|
+
name: users[0]?.name || "Unknown"
|
|
8425
|
+
}
|
|
8426
|
+
});
|
|
8427
|
+
onClose();
|
|
8428
|
+
};
|
|
8429
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-2 p-3", children: [
|
|
8430
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: format(date, "EEE, MMM d, h:mm a") }),
|
|
8431
|
+
/* @__PURE__ */ jsx(
|
|
8432
|
+
Input,
|
|
8433
|
+
{
|
|
8434
|
+
value: title,
|
|
8435
|
+
onChange: (e) => setTitle(e.target.value),
|
|
8436
|
+
placeholder: "Add title",
|
|
8437
|
+
className: "h-8",
|
|
8438
|
+
autoFocus: true
|
|
8439
|
+
}
|
|
8440
|
+
),
|
|
8441
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8442
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", disabled: !title.trim(), children: "Add" }),
|
|
8443
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onOpenDialog, children: "More options" })
|
|
8444
|
+
] })
|
|
8445
|
+
] });
|
|
8446
|
+
}
|
|
8447
|
+
function ChangeBadgeVariantInput() {
|
|
8448
|
+
const { badgeVariant, setBadgeVariant } = useEventCalendar();
|
|
8449
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
8450
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Change badge variant" }),
|
|
8451
|
+
/* @__PURE__ */ jsxs(
|
|
8452
|
+
Select,
|
|
8453
|
+
{
|
|
8454
|
+
value: badgeVariant,
|
|
8455
|
+
onValueChange: (value) => setBadgeVariant(value),
|
|
8456
|
+
children: [
|
|
8457
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8458
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
8459
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "dot", children: "Dot" }),
|
|
8460
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "colored", children: "Colored" }),
|
|
8461
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "mixed", children: "Mixed" })
|
|
8462
|
+
] })
|
|
8463
|
+
]
|
|
8464
|
+
}
|
|
8465
|
+
)
|
|
8466
|
+
] });
|
|
8467
|
+
}
|
|
8468
|
+
var HOUR_OPTIONS = Array.from({ length: 25 }, (_, i) => {
|
|
8469
|
+
if (i === 0) return { value: "0", label: "12 AM" };
|
|
8470
|
+
if (i === 12) return { value: "12", label: "12 PM" };
|
|
8471
|
+
if (i === 24) return { value: "24", label: "12 AM (next)" };
|
|
8472
|
+
if (i < 12) return { value: String(i), label: `${i} AM` };
|
|
8473
|
+
return { value: String(i), label: `${i - 12} PM` };
|
|
8474
|
+
});
|
|
8475
|
+
function ChangeVisibleHoursInput() {
|
|
8476
|
+
const { visibleHours, setVisibleHours } = useEventCalendar();
|
|
8477
|
+
const [from, setFrom] = React15.useState(visibleHours.from);
|
|
8478
|
+
const [to, setTo] = React15.useState(visibleHours.to);
|
|
8479
|
+
const handleApply = () => {
|
|
8480
|
+
const toHour = to === 0 ? 24 : to;
|
|
8481
|
+
setVisibleHours({ from, to: toHour });
|
|
8482
|
+
};
|
|
8483
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8484
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8485
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Change visible hours" }),
|
|
8486
|
+
/* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 100, children: /* @__PURE__ */ jsxs(Tooltip2, { children: [
|
|
8487
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(Info, { className: "size-3" }) }),
|
|
8488
|
+
/* @__PURE__ */ jsx(TooltipContent, { className: "max-w-80 text-center", children: /* @__PURE__ */ jsx("p", { children: "If an event falls outside the specified visible hours, the visible hours will automatically adjust to include that event." }) })
|
|
8489
|
+
] }) })
|
|
8490
|
+
] }),
|
|
8491
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
8492
|
+
/* @__PURE__ */ jsx("p", { children: "From" }),
|
|
8493
|
+
/* @__PURE__ */ jsxs(Select, { value: String(from), onValueChange: (v) => setFrom(Number(v)), children: [
|
|
8494
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-28", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8495
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS.slice(0, 24).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8496
|
+
] }),
|
|
8497
|
+
/* @__PURE__ */ jsx("p", { children: "To" }),
|
|
8498
|
+
/* @__PURE__ */ jsxs(Select, { value: String(to), onValueChange: (v) => setTo(Number(v)), children: [
|
|
8499
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-28", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8500
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS.slice(1).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8501
|
+
] })
|
|
8502
|
+
] }),
|
|
8503
|
+
/* @__PURE__ */ jsx(Button, { className: "mt-4 w-fit", onClick: handleApply, children: "Apply" })
|
|
8504
|
+
] });
|
|
8505
|
+
}
|
|
8506
|
+
var DAYS_OF_WEEK = [
|
|
8507
|
+
{ index: 0, name: "Sunday" },
|
|
8508
|
+
{ index: 1, name: "Monday" },
|
|
8509
|
+
{ index: 2, name: "Tuesday" },
|
|
8510
|
+
{ index: 3, name: "Wednesday" },
|
|
8511
|
+
{ index: 4, name: "Thursday" },
|
|
8512
|
+
{ index: 5, name: "Friday" },
|
|
8513
|
+
{ index: 6, name: "Saturday" }
|
|
8514
|
+
];
|
|
8515
|
+
var HOUR_OPTIONS2 = Array.from({ length: 25 }, (_, i) => {
|
|
8516
|
+
if (i === 0) return { value: "0", label: "12 AM" };
|
|
8517
|
+
if (i === 12) return { value: "12", label: "12 PM" };
|
|
8518
|
+
if (i === 24) return { value: "24", label: "12 AM (next)" };
|
|
8519
|
+
if (i < 12) return { value: String(i), label: `${i} AM` };
|
|
8520
|
+
return { value: String(i), label: `${i - 12} PM` };
|
|
8521
|
+
});
|
|
8522
|
+
function ChangeWorkingHoursInput() {
|
|
8523
|
+
const { workingHours, setWorkingHours } = useEventCalendar();
|
|
8524
|
+
const [localWorkingHours, setLocalWorkingHours] = React15.useState({
|
|
8525
|
+
...workingHours
|
|
8526
|
+
});
|
|
8527
|
+
const handleToggleDay = (dayId) => {
|
|
8528
|
+
setLocalWorkingHours((prev) => ({
|
|
8529
|
+
...prev,
|
|
8530
|
+
[dayId]: prev[dayId].from > 0 || prev[dayId].to > 0 ? { from: 0, to: 0 } : { from: 9, to: 17 }
|
|
8531
|
+
}));
|
|
8532
|
+
};
|
|
8533
|
+
const handleTimeChange = (dayId, timeType, value) => {
|
|
8534
|
+
const hour = Number(value);
|
|
8535
|
+
setLocalWorkingHours((prev) => {
|
|
8536
|
+
const updatedDay = { ...prev[dayId], [timeType]: hour };
|
|
8537
|
+
if (timeType === "to" && hour === 0 && updatedDay.from === 0) {
|
|
8538
|
+
updatedDay.to = 24;
|
|
8539
|
+
}
|
|
8540
|
+
return { ...prev, [dayId]: updatedDay };
|
|
8541
|
+
});
|
|
8542
|
+
};
|
|
8543
|
+
const handleSave = () => {
|
|
8544
|
+
const updatedWorkingHours = { ...localWorkingHours };
|
|
8545
|
+
for (const dayId in updatedWorkingHours) {
|
|
8546
|
+
const day = updatedWorkingHours[parseInt(dayId)];
|
|
8547
|
+
const isDayActive = localWorkingHours[parseInt(dayId)].from > 0 || localWorkingHours[parseInt(dayId)].to > 0;
|
|
8548
|
+
if (isDayActive) {
|
|
8549
|
+
if (day.from === 0 && day.to === 0) {
|
|
8550
|
+
updatedWorkingHours[dayId] = { from: 0, to: 24 };
|
|
8551
|
+
} else if (day.to === 0 && day.from > 0) {
|
|
8552
|
+
updatedWorkingHours[dayId] = { ...day, to: 24 };
|
|
8553
|
+
}
|
|
8554
|
+
} else {
|
|
8555
|
+
updatedWorkingHours[dayId] = { from: 0, to: 0 };
|
|
8556
|
+
}
|
|
8557
|
+
}
|
|
8558
|
+
setWorkingHours(updatedWorkingHours);
|
|
8559
|
+
};
|
|
8560
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8561
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8562
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Change working hours" }),
|
|
8563
|
+
/* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 100, children: /* @__PURE__ */ jsxs(Tooltip2, { children: [
|
|
8564
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(Info, { className: "size-3" }) }),
|
|
8565
|
+
/* @__PURE__ */ jsx(TooltipContent, { className: "max-w-80 text-center", children: /* @__PURE__ */ jsx("p", { children: "This will apply a dashed background to the hour cells that fall outside the working hours \u2014 only for week and day views." }) })
|
|
8566
|
+
] }) })
|
|
8567
|
+
] }),
|
|
8568
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: DAYS_OF_WEEK.map((day) => {
|
|
8569
|
+
const isDayActive = localWorkingHours[day.index].from > 0 || localWorkingHours[day.index].to > 0;
|
|
8570
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 sm:gap-4", children: [
|
|
8571
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-32 items-center gap-2 sm:w-36", children: [
|
|
8572
|
+
/* @__PURE__ */ jsx(
|
|
8573
|
+
Switch,
|
|
8574
|
+
{
|
|
8575
|
+
checked: isDayActive,
|
|
8576
|
+
onCheckedChange: () => handleToggleDay(day.index)
|
|
8577
|
+
}
|
|
8578
|
+
),
|
|
8579
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: day.name.slice(0, 3) })
|
|
8580
|
+
] }),
|
|
8581
|
+
isDayActive ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
8582
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8583
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "From" }),
|
|
8584
|
+
/* @__PURE__ */ jsxs(
|
|
8585
|
+
Select,
|
|
8586
|
+
{
|
|
8587
|
+
value: String(localWorkingHours[day.index].from),
|
|
8588
|
+
onValueChange: (v) => handleTimeChange(day.index, "from", v),
|
|
8589
|
+
children: [
|
|
8590
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-24", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8591
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS2.slice(0, 24).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8592
|
+
]
|
|
8593
|
+
}
|
|
8594
|
+
)
|
|
8595
|
+
] }),
|
|
8596
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8597
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "To" }),
|
|
8598
|
+
/* @__PURE__ */ jsxs(
|
|
8599
|
+
Select,
|
|
8600
|
+
{
|
|
8601
|
+
value: String(localWorkingHours[day.index].to),
|
|
8602
|
+
onValueChange: (v) => handleTimeChange(day.index, "to", v),
|
|
8603
|
+
children: [
|
|
8604
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-24", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8605
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS2.slice(1).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8606
|
+
]
|
|
8607
|
+
}
|
|
8608
|
+
)
|
|
8609
|
+
] })
|
|
8610
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
|
|
8611
|
+
/* @__PURE__ */ jsx(Moon, { className: "size-4" }),
|
|
8612
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "Closed" })
|
|
8613
|
+
] })
|
|
8614
|
+
] }, day.index);
|
|
8615
|
+
}) }),
|
|
8616
|
+
/* @__PURE__ */ jsx(Button, { className: "mt-4 w-fit", onClick: handleSave, children: "Apply" })
|
|
8617
|
+
] });
|
|
8618
|
+
}
|
|
8619
|
+
function CalendarSettingsPanel({
|
|
8620
|
+
className,
|
|
8621
|
+
showBadgeVariant = true,
|
|
8622
|
+
showVisibleHours = true,
|
|
8623
|
+
showWorkingHours = true
|
|
8624
|
+
}) {
|
|
8625
|
+
return /* @__PURE__ */ jsx(Accordion, { type: "single", collapsible: true, className: cn("relative z-10 bg-background", className), children: /* @__PURE__ */ jsxs(AccordionItem, { value: "settings", className: "border-none", children: [
|
|
8626
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "flex-none gap-2 py-0 hover:no-underline", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8627
|
+
/* @__PURE__ */ jsx(Settings, { className: "size-4" }),
|
|
8628
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold", children: "Calendar settings" })
|
|
8629
|
+
] }) }),
|
|
8630
|
+
/* @__PURE__ */ jsx(AccordionContent, { children: /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col gap-6", children: [
|
|
8631
|
+
showBadgeVariant && /* @__PURE__ */ jsx(ChangeBadgeVariantInput, {}),
|
|
8632
|
+
showVisibleHours && /* @__PURE__ */ jsx(ChangeVisibleHoursInput, {}),
|
|
8633
|
+
showWorkingHours && /* @__PURE__ */ jsx(ChangeWorkingHoursInput, {})
|
|
8634
|
+
] }) })
|
|
8635
|
+
] }) });
|
|
8636
|
+
}
|
|
8637
|
+
function useMediaQuery(query) {
|
|
8638
|
+
const [matches, setMatches] = React15.useState(false);
|
|
8639
|
+
React15.useEffect(() => {
|
|
8640
|
+
const media = window.matchMedia(query);
|
|
8641
|
+
setMatches(media.matches);
|
|
8642
|
+
const listener = (event) => {
|
|
8643
|
+
setMatches(event.matches);
|
|
8644
|
+
};
|
|
8645
|
+
media.addEventListener("change", listener);
|
|
8646
|
+
return () => media.removeEventListener("change", listener);
|
|
8647
|
+
}, [query]);
|
|
8648
|
+
return matches;
|
|
8649
|
+
}
|
|
8650
|
+
function BigCalendar({
|
|
8651
|
+
className,
|
|
8652
|
+
compact = "auto",
|
|
8653
|
+
bordered = true,
|
|
8654
|
+
showHeader = true,
|
|
8655
|
+
showAddButton = true,
|
|
8656
|
+
showSettings = true,
|
|
8657
|
+
enableDragDrop = true,
|
|
8658
|
+
weekStartsOn = 0,
|
|
8659
|
+
maxEventsPerDay = 3,
|
|
8660
|
+
config,
|
|
8661
|
+
...providerProps
|
|
8662
|
+
}) {
|
|
8663
|
+
return /* @__PURE__ */ jsx(EventCalendarProvider, { ...providerProps, children: /* @__PURE__ */ jsx(DragProvider, { children: /* @__PURE__ */ jsx(
|
|
8664
|
+
BigCalendarInner,
|
|
8665
|
+
{
|
|
8666
|
+
className,
|
|
8667
|
+
compact,
|
|
8668
|
+
bordered,
|
|
8669
|
+
showHeader,
|
|
8670
|
+
showAddButton,
|
|
8671
|
+
showSettings,
|
|
8672
|
+
enableDragDrop,
|
|
8673
|
+
weekStartsOn,
|
|
8674
|
+
maxEventsPerDay,
|
|
8675
|
+
config
|
|
8676
|
+
}
|
|
8677
|
+
) }) });
|
|
8678
|
+
}
|
|
8679
|
+
function BigCalendarInner({
|
|
8680
|
+
className,
|
|
8681
|
+
compact,
|
|
8682
|
+
bordered,
|
|
8683
|
+
showHeader,
|
|
8684
|
+
showAddButton,
|
|
8685
|
+
showSettings,
|
|
8686
|
+
enableDragDrop,
|
|
8687
|
+
weekStartsOn,
|
|
8688
|
+
maxEventsPerDay
|
|
8689
|
+
}) {
|
|
8690
|
+
const { view, setView } = useEventCalendar();
|
|
8691
|
+
const [dialogOpen, setDialogOpen] = React15.useState(false);
|
|
8692
|
+
const [selectedEvent, setSelectedEvent] = React15.useState(null);
|
|
8693
|
+
const [dialogMode, setDialogMode] = React15.useState("add");
|
|
8694
|
+
const [defaultDate, setDefaultDate] = React15.useState(/* @__PURE__ */ new Date());
|
|
8695
|
+
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
8696
|
+
const isCompact = compact === "auto" ? isMobile : compact;
|
|
8697
|
+
const handleAddClick = () => {
|
|
8698
|
+
setSelectedEvent(null);
|
|
8699
|
+
setDialogMode("add");
|
|
8700
|
+
setDefaultDate(/* @__PURE__ */ new Date());
|
|
8701
|
+
setDialogOpen(true);
|
|
8702
|
+
};
|
|
8703
|
+
const handleEventClick = (event) => {
|
|
8704
|
+
setSelectedEvent(event);
|
|
8705
|
+
setDialogMode("edit");
|
|
8706
|
+
setDialogOpen(true);
|
|
8707
|
+
};
|
|
8708
|
+
const handleDateClick = (date) => {
|
|
8709
|
+
setDefaultDate(date);
|
|
8710
|
+
};
|
|
8711
|
+
const handleMoreClick = (date, events) => {
|
|
8712
|
+
setDefaultDate(date);
|
|
8713
|
+
setView("day");
|
|
8714
|
+
};
|
|
8715
|
+
const handleTimeClick = (date, hour, minute) => {
|
|
8716
|
+
setSelectedEvent(null);
|
|
8717
|
+
setDialogMode("add");
|
|
8718
|
+
const clickedDate = new Date(date);
|
|
8719
|
+
clickedDate.setHours(hour, minute, 0, 0);
|
|
8720
|
+
setDefaultDate(clickedDate);
|
|
8721
|
+
setDialogOpen(true);
|
|
8722
|
+
};
|
|
8723
|
+
const Wrapper = bordered ? Card : "div";
|
|
8724
|
+
const Content14 = bordered ? CardContent : "div";
|
|
8725
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8726
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4 relative", className), children: [
|
|
8727
|
+
/* @__PURE__ */ jsxs(
|
|
8728
|
+
Wrapper,
|
|
8729
|
+
{
|
|
8730
|
+
className: cn(
|
|
8731
|
+
"flex min-h-[600px] flex-col overflow-hidden rounded-sm",
|
|
8732
|
+
!bordered && "border border-border bg-card"
|
|
8733
|
+
),
|
|
8734
|
+
children: [
|
|
8735
|
+
showHeader && (isCompact ? /* @__PURE__ */ jsx(
|
|
8736
|
+
CalendarHeaderCompact,
|
|
8737
|
+
{
|
|
8738
|
+
showAddButton,
|
|
8739
|
+
onAddClick: handleAddClick
|
|
8740
|
+
}
|
|
8741
|
+
) : /* @__PURE__ */ jsx(
|
|
8742
|
+
CalendarHeader,
|
|
8743
|
+
{
|
|
8744
|
+
showAddButton,
|
|
8745
|
+
onAddClick: handleAddClick
|
|
8746
|
+
}
|
|
8747
|
+
)),
|
|
8748
|
+
/* @__PURE__ */ jsx(Content14, { className: cn("flex-1 overflow-hidden", bordered ? "p-0" : ""), children: /* @__PURE__ */ jsx(
|
|
8749
|
+
CalendarView,
|
|
8750
|
+
{
|
|
8751
|
+
view,
|
|
8752
|
+
weekStartsOn,
|
|
8753
|
+
maxEventsPerDay,
|
|
8754
|
+
onEventClick: handleEventClick,
|
|
8755
|
+
onDateClick: handleDateClick,
|
|
8756
|
+
onMoreClick: handleMoreClick,
|
|
8757
|
+
onTimeClick: handleTimeClick
|
|
8758
|
+
}
|
|
8759
|
+
) })
|
|
8760
|
+
]
|
|
8761
|
+
}
|
|
8762
|
+
),
|
|
8763
|
+
showSettings && /* @__PURE__ */ jsx(CalendarSettingsPanel, {})
|
|
8764
|
+
] }),
|
|
8765
|
+
/* @__PURE__ */ jsx(
|
|
8766
|
+
EventDialog,
|
|
8767
|
+
{
|
|
8768
|
+
open: dialogOpen,
|
|
8769
|
+
onOpenChange: setDialogOpen,
|
|
8770
|
+
mode: dialogMode,
|
|
8771
|
+
event: selectedEvent,
|
|
8772
|
+
defaultDate
|
|
8773
|
+
}
|
|
8774
|
+
)
|
|
8775
|
+
] });
|
|
8776
|
+
}
|
|
8777
|
+
function CalendarView({
|
|
8778
|
+
view,
|
|
8779
|
+
weekStartsOn,
|
|
8780
|
+
maxEventsPerDay,
|
|
8781
|
+
onEventClick,
|
|
8782
|
+
onDateClick,
|
|
8783
|
+
onMoreClick,
|
|
8784
|
+
onTimeClick
|
|
8785
|
+
}) {
|
|
8786
|
+
switch (view) {
|
|
8787
|
+
case "month":
|
|
8788
|
+
return /* @__PURE__ */ jsx(
|
|
8789
|
+
MonthView,
|
|
8790
|
+
{
|
|
8791
|
+
className: "h-full",
|
|
8792
|
+
weekStartsOn,
|
|
8793
|
+
maxEventsPerDay,
|
|
8794
|
+
onEventClick,
|
|
8795
|
+
onDateClick,
|
|
8796
|
+
onMoreClick
|
|
8797
|
+
}
|
|
8798
|
+
);
|
|
8799
|
+
case "week":
|
|
8800
|
+
return /* @__PURE__ */ jsx(
|
|
8801
|
+
WeekView,
|
|
8802
|
+
{
|
|
8803
|
+
className: "h-full",
|
|
8804
|
+
weekStartsOn,
|
|
8805
|
+
onEventClick,
|
|
8806
|
+
onDateClick,
|
|
8807
|
+
onTimeClick
|
|
8808
|
+
}
|
|
8809
|
+
);
|
|
8810
|
+
case "day":
|
|
8811
|
+
return /* @__PURE__ */ jsx(
|
|
8812
|
+
DayView,
|
|
8813
|
+
{
|
|
8814
|
+
className: "h-full",
|
|
8815
|
+
onEventClick,
|
|
8816
|
+
onTimeClick
|
|
8817
|
+
}
|
|
8818
|
+
);
|
|
8819
|
+
case "year":
|
|
8820
|
+
return /* @__PURE__ */ jsx(
|
|
8821
|
+
YearView,
|
|
8822
|
+
{
|
|
8823
|
+
className: "h-full",
|
|
8824
|
+
weekStartsOn,
|
|
8825
|
+
onDateClick
|
|
8826
|
+
}
|
|
8827
|
+
);
|
|
8828
|
+
case "agenda":
|
|
8829
|
+
return /* @__PURE__ */ jsx(
|
|
8830
|
+
AgendaView,
|
|
8831
|
+
{
|
|
8832
|
+
className: "h-full",
|
|
8833
|
+
onEventClick,
|
|
8834
|
+
onDateClick
|
|
8835
|
+
}
|
|
8836
|
+
);
|
|
8837
|
+
default:
|
|
8838
|
+
return null;
|
|
8839
|
+
}
|
|
8840
|
+
}
|
|
5430
8841
|
|
|
5431
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarDayButton, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea,
|
|
8842
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AgendaView, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Avatar, AvatarFallback, AvatarImage, BADGE_VARIANT_LABELS, Badge, BigCalendar, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarContext, CalendarDayButton, CalendarHeader, CalendarHeaderCompact, CalendarSettingsPanel, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChangeBadgeVariantInput, ChangeVisibleHoursInput, ChangeWorkingHoursInput, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DEFAULT_VISIBLE_HOURS, DEFAULT_WORKING_HOURS, DateBadge, DayView, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DragContext, DragProvider, DraggableEvent, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, DroppableZone, EVENT_COLORS, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, EventBadge, EventCalendarProvider, EventDialog, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, Item6 as Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label2 as Label, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MonthView, MoreEvents, NativeSelect, NativeSelectOptGroup, NativeSelectOption, NavMain, NavProjects, NavSecondary, NavUser, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PlayerCanvas, PlayerCanvasActionButton, PlayerCanvasControls, PlayerCanvasDivider, PlayerCanvasInfo, PlayerCanvasLabel, PlayerCanvasPlayButton, PlayerCanvasProgress, PlayerCanvasSkipButton, PlayerCanvasTitle, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, QuickAddEvent, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, SearchForm, SearchTrigger, Section, SectionContent, SectionDescription, SectionFooter, SectionHeader, SectionTitle, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBody, 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, SiteHeader, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeSwitch, TimeIndicator, Toaster, Toggle, ToggleGroup, ToggleGroupItem, ToolBarCanvas, ToolBarCanvasButton, ToolBarCanvasDivider, ToolBarCanvasGroup, Tooltip2 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserAvatarsDropdown, VIEW_LABELS, WeekView, YearView, badgeVariants, buttonGroupVariants, buttonVariants, calculateDropDates, calculateMonthEventPositions, cardVariants, createDefaultEvent, formatDateRange, formatTime, generateEventId, getCalendarCells, getCurrentEvents, getDayHours, getEventBlockStyle, getEventDuration, getEventDurationMinutes, getEventsCount, getEventsForDate, getEventsInRange, getHeaderLabel, getMonthCellEvents, getMonthDays, getTimeHeight, getTimePosition, getViewDateRange, getVisibleHours, getWeekDayNames, getWeekDays, getYearMonths, groupEvents, isMultiDayEvent, isWorkingHour, navigateDate, navigationMenuTriggerStyle, playerCanvasPlayButtonVariants, playerCanvasSkipButtonVariants, rangeText, sectionVariants, snapToInterval, sortEvents, splitEventsByDuration, toggleVariants, toolBarCanvasButtonVariants, useDrag, useDraggable, useDroppable, useEventCalendar, useEventsInRange, useFilteredEvents, useFormField, useIsMobile, useSearchShortcut, useSidebar };
|
|
5432
8843
|
//# sourceMappingURL=index.js.map
|
|
5433
8844
|
//# sourceMappingURL=index.js.map
|