@j3m-quantum/ui 0.9.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -20
- package/dist/index.cjs +3702 -306
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +654 -3
- package/dist/index.d.ts +654 -3
- package/dist/index.js +3596 -304
- package/dist/index.js.map +1 -1
- package/dist/styles/index.css +1273 -317
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React14 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] = React14.useState(void 0);
|
|
49
|
+
React14.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 = React14.forwardRef(
|
|
89
91
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
90
92
|
const Comp = asChild ? Slot : "button";
|
|
91
93
|
return /* @__PURE__ */ jsx(
|
|
@@ -449,7 +451,7 @@ function Slider({
|
|
|
449
451
|
max = 100,
|
|
450
452
|
...props
|
|
451
453
|
}) {
|
|
452
|
-
const _values =
|
|
454
|
+
const _values = React14.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 = React14.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 = React14.useContext(ToggleGroupContext);
|
|
776
778
|
return /* @__PURE__ */ jsx(
|
|
777
779
|
ToggleGroupPrimitive.Item,
|
|
778
780
|
{
|
|
@@ -803,7 +805,7 @@ function ToolBarCanvas({
|
|
|
803
805
|
{
|
|
804
806
|
"data-slot": "toolbar-canvas",
|
|
805
807
|
className: cn(
|
|
806
|
-
"inline-flex items-center gap-1 rounded-full bg-
|
|
808
|
+
"inline-flex items-center gap-1 rounded-full bg-background border border-input p-1.5",
|
|
807
809
|
className
|
|
808
810
|
),
|
|
809
811
|
...props
|
|
@@ -898,7 +900,7 @@ function PlayerCanvasControls({
|
|
|
898
900
|
{
|
|
899
901
|
"data-slot": "player-canvas-controls",
|
|
900
902
|
className: cn(
|
|
901
|
-
"flex items-center gap-2 px-1.5 py-1.5 rounded-full bg-
|
|
903
|
+
"flex items-center gap-2 px-1.5 py-1.5 rounded-full bg-background border border-input",
|
|
902
904
|
className
|
|
903
905
|
),
|
|
904
906
|
...props
|
|
@@ -939,7 +941,7 @@ function PlayerCanvasPlayButton({
|
|
|
939
941
|
className
|
|
940
942
|
),
|
|
941
943
|
style: {
|
|
942
|
-
backgroundColor: "var(--j3m-
|
|
944
|
+
backgroundColor: "var(--j3m-orange-8)",
|
|
943
945
|
...style
|
|
944
946
|
},
|
|
945
947
|
...props,
|
|
@@ -1079,7 +1081,7 @@ function PlayerCanvasProgress({
|
|
|
1079
1081
|
className: "absolute inset-y-0 left-0 rounded-full transition-all duration-200",
|
|
1080
1082
|
style: {
|
|
1081
1083
|
width: `${percentage}%`,
|
|
1082
|
-
backgroundColor: "var(--j3m-
|
|
1084
|
+
backgroundColor: "var(--j3m-orange-8)"
|
|
1083
1085
|
}
|
|
1084
1086
|
}
|
|
1085
1087
|
)
|
|
@@ -1103,7 +1105,7 @@ function Label2({
|
|
|
1103
1105
|
);
|
|
1104
1106
|
}
|
|
1105
1107
|
var Form = FormProvider;
|
|
1106
|
-
var FormFieldContext =
|
|
1108
|
+
var FormFieldContext = React14.createContext(
|
|
1107
1109
|
{}
|
|
1108
1110
|
);
|
|
1109
1111
|
var FormField = ({
|
|
@@ -1112,8 +1114,8 @@ var FormField = ({
|
|
|
1112
1114
|
return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
|
|
1113
1115
|
};
|
|
1114
1116
|
var useFormField = () => {
|
|
1115
|
-
const fieldContext =
|
|
1116
|
-
const itemContext =
|
|
1117
|
+
const fieldContext = React14.useContext(FormFieldContext);
|
|
1118
|
+
const itemContext = React14.useContext(FormItemContext);
|
|
1117
1119
|
const { getFieldState } = useFormContext();
|
|
1118
1120
|
const formState = useFormState({ name: fieldContext.name });
|
|
1119
1121
|
const fieldState = getFieldState(fieldContext.name, formState);
|
|
@@ -1130,11 +1132,11 @@ var useFormField = () => {
|
|
|
1130
1132
|
...fieldState
|
|
1131
1133
|
};
|
|
1132
1134
|
};
|
|
1133
|
-
var FormItemContext =
|
|
1135
|
+
var FormItemContext = React14.createContext(
|
|
1134
1136
|
{}
|
|
1135
1137
|
);
|
|
1136
1138
|
function FormItem({ className, ...props }) {
|
|
1137
|
-
const id =
|
|
1139
|
+
const id = React14.useId();
|
|
1138
1140
|
return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx(
|
|
1139
1141
|
"div",
|
|
1140
1142
|
{
|
|
@@ -1418,7 +1420,7 @@ var cardVariants = cva(
|
|
|
1418
1420
|
{
|
|
1419
1421
|
variants: {
|
|
1420
1422
|
variant: {
|
|
1421
|
-
default: "bg-card border
|
|
1423
|
+
default: "bg-card border",
|
|
1422
1424
|
glass: [
|
|
1423
1425
|
"glass-context",
|
|
1424
1426
|
// Enables glass semantic token overrides for children
|
|
@@ -1673,6 +1675,298 @@ function AvatarFallback({
|
|
|
1673
1675
|
}
|
|
1674
1676
|
);
|
|
1675
1677
|
}
|
|
1678
|
+
function DropdownMenu({
|
|
1679
|
+
...props
|
|
1680
|
+
}) {
|
|
1681
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1682
|
+
}
|
|
1683
|
+
function DropdownMenuPortal({
|
|
1684
|
+
...props
|
|
1685
|
+
}) {
|
|
1686
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
|
|
1687
|
+
}
|
|
1688
|
+
function DropdownMenuTrigger({
|
|
1689
|
+
...props
|
|
1690
|
+
}) {
|
|
1691
|
+
return /* @__PURE__ */ jsx(
|
|
1692
|
+
DropdownMenuPrimitive.Trigger,
|
|
1693
|
+
{
|
|
1694
|
+
"data-slot": "dropdown-menu-trigger",
|
|
1695
|
+
...props
|
|
1696
|
+
}
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1699
|
+
function DropdownMenuContent({
|
|
1700
|
+
className,
|
|
1701
|
+
sideOffset = 4,
|
|
1702
|
+
...props
|
|
1703
|
+
}) {
|
|
1704
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
1705
|
+
DropdownMenuPrimitive.Content,
|
|
1706
|
+
{
|
|
1707
|
+
"data-slot": "dropdown-menu-content",
|
|
1708
|
+
sideOffset,
|
|
1709
|
+
className: cn(
|
|
1710
|
+
"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",
|
|
1711
|
+
className
|
|
1712
|
+
),
|
|
1713
|
+
...props
|
|
1714
|
+
}
|
|
1715
|
+
) });
|
|
1716
|
+
}
|
|
1717
|
+
function DropdownMenuGroup({
|
|
1718
|
+
...props
|
|
1719
|
+
}) {
|
|
1720
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
1721
|
+
}
|
|
1722
|
+
function DropdownMenuItem({
|
|
1723
|
+
className,
|
|
1724
|
+
inset,
|
|
1725
|
+
variant = "default",
|
|
1726
|
+
...props
|
|
1727
|
+
}) {
|
|
1728
|
+
return /* @__PURE__ */ jsx(
|
|
1729
|
+
DropdownMenuPrimitive.Item,
|
|
1730
|
+
{
|
|
1731
|
+
"data-slot": "dropdown-menu-item",
|
|
1732
|
+
"data-inset": inset,
|
|
1733
|
+
"data-variant": variant,
|
|
1734
|
+
className: cn(
|
|
1735
|
+
"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",
|
|
1736
|
+
className
|
|
1737
|
+
),
|
|
1738
|
+
...props
|
|
1739
|
+
}
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
function DropdownMenuCheckboxItem({
|
|
1743
|
+
className,
|
|
1744
|
+
children,
|
|
1745
|
+
checked,
|
|
1746
|
+
...props
|
|
1747
|
+
}) {
|
|
1748
|
+
return /* @__PURE__ */ jsxs(
|
|
1749
|
+
DropdownMenuPrimitive.CheckboxItem,
|
|
1750
|
+
{
|
|
1751
|
+
"data-slot": "dropdown-menu-checkbox-item",
|
|
1752
|
+
className: cn(
|
|
1753
|
+
"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",
|
|
1754
|
+
className
|
|
1755
|
+
),
|
|
1756
|
+
checked,
|
|
1757
|
+
...props,
|
|
1758
|
+
children: [
|
|
1759
|
+
/* @__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" }) }) }),
|
|
1760
|
+
children
|
|
1761
|
+
]
|
|
1762
|
+
}
|
|
1763
|
+
);
|
|
1764
|
+
}
|
|
1765
|
+
function DropdownMenuRadioGroup({
|
|
1766
|
+
...props
|
|
1767
|
+
}) {
|
|
1768
|
+
return /* @__PURE__ */ jsx(
|
|
1769
|
+
DropdownMenuPrimitive.RadioGroup,
|
|
1770
|
+
{
|
|
1771
|
+
"data-slot": "dropdown-menu-radio-group",
|
|
1772
|
+
...props
|
|
1773
|
+
}
|
|
1774
|
+
);
|
|
1775
|
+
}
|
|
1776
|
+
function DropdownMenuRadioItem({
|
|
1777
|
+
className,
|
|
1778
|
+
children,
|
|
1779
|
+
...props
|
|
1780
|
+
}) {
|
|
1781
|
+
return /* @__PURE__ */ jsxs(
|
|
1782
|
+
DropdownMenuPrimitive.RadioItem,
|
|
1783
|
+
{
|
|
1784
|
+
"data-slot": "dropdown-menu-radio-item",
|
|
1785
|
+
className: cn(
|
|
1786
|
+
"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",
|
|
1787
|
+
className
|
|
1788
|
+
),
|
|
1789
|
+
...props,
|
|
1790
|
+
children: [
|
|
1791
|
+
/* @__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" }) }) }),
|
|
1792
|
+
children
|
|
1793
|
+
]
|
|
1794
|
+
}
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
function DropdownMenuLabel({
|
|
1798
|
+
className,
|
|
1799
|
+
inset,
|
|
1800
|
+
...props
|
|
1801
|
+
}) {
|
|
1802
|
+
return /* @__PURE__ */ jsx(
|
|
1803
|
+
DropdownMenuPrimitive.Label,
|
|
1804
|
+
{
|
|
1805
|
+
"data-slot": "dropdown-menu-label",
|
|
1806
|
+
"data-inset": inset,
|
|
1807
|
+
className: cn(
|
|
1808
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
1809
|
+
className
|
|
1810
|
+
),
|
|
1811
|
+
...props
|
|
1812
|
+
}
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
function DropdownMenuSeparator({
|
|
1816
|
+
className,
|
|
1817
|
+
...props
|
|
1818
|
+
}) {
|
|
1819
|
+
return /* @__PURE__ */ jsx(
|
|
1820
|
+
DropdownMenuPrimitive.Separator,
|
|
1821
|
+
{
|
|
1822
|
+
"data-slot": "dropdown-menu-separator",
|
|
1823
|
+
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
1824
|
+
...props
|
|
1825
|
+
}
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
function DropdownMenuShortcut({
|
|
1829
|
+
className,
|
|
1830
|
+
...props
|
|
1831
|
+
}) {
|
|
1832
|
+
return /* @__PURE__ */ jsx(
|
|
1833
|
+
"span",
|
|
1834
|
+
{
|
|
1835
|
+
"data-slot": "dropdown-menu-shortcut",
|
|
1836
|
+
className: cn(
|
|
1837
|
+
"text-muted-foreground ml-auto text-xs tracking-widest",
|
|
1838
|
+
className
|
|
1839
|
+
),
|
|
1840
|
+
...props
|
|
1841
|
+
}
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
function DropdownMenuSub({
|
|
1845
|
+
...props
|
|
1846
|
+
}) {
|
|
1847
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
1848
|
+
}
|
|
1849
|
+
function DropdownMenuSubTrigger({
|
|
1850
|
+
className,
|
|
1851
|
+
inset,
|
|
1852
|
+
children,
|
|
1853
|
+
...props
|
|
1854
|
+
}) {
|
|
1855
|
+
return /* @__PURE__ */ jsxs(
|
|
1856
|
+
DropdownMenuPrimitive.SubTrigger,
|
|
1857
|
+
{
|
|
1858
|
+
"data-slot": "dropdown-menu-sub-trigger",
|
|
1859
|
+
"data-inset": inset,
|
|
1860
|
+
className: cn(
|
|
1861
|
+
"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",
|
|
1862
|
+
className
|
|
1863
|
+
),
|
|
1864
|
+
...props,
|
|
1865
|
+
children: [
|
|
1866
|
+
children,
|
|
1867
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
1868
|
+
]
|
|
1869
|
+
}
|
|
1870
|
+
);
|
|
1871
|
+
}
|
|
1872
|
+
function DropdownMenuSubContent({
|
|
1873
|
+
className,
|
|
1874
|
+
...props
|
|
1875
|
+
}) {
|
|
1876
|
+
return /* @__PURE__ */ jsx(
|
|
1877
|
+
DropdownMenuPrimitive.SubContent,
|
|
1878
|
+
{
|
|
1879
|
+
"data-slot": "dropdown-menu-sub-content",
|
|
1880
|
+
className: cn(
|
|
1881
|
+
"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",
|
|
1882
|
+
className
|
|
1883
|
+
),
|
|
1884
|
+
...props
|
|
1885
|
+
}
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
function UserAvatarsDropdown({
|
|
1889
|
+
users,
|
|
1890
|
+
selectedUserId,
|
|
1891
|
+
onSelect,
|
|
1892
|
+
maxVisible = 2,
|
|
1893
|
+
label = "All",
|
|
1894
|
+
className
|
|
1895
|
+
}) {
|
|
1896
|
+
const visibleUsers = users.slice(0, maxVisible);
|
|
1897
|
+
const overflowCount = Math.max(0, users.length - maxVisible);
|
|
1898
|
+
const getInitials = (name) => {
|
|
1899
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
1900
|
+
};
|
|
1901
|
+
const selectedUser = users.find((u) => u.id === selectedUserId);
|
|
1902
|
+
const displayLabel = selectedUserId ? selectedUser?.name || "User" : label;
|
|
1903
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
1904
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1905
|
+
"button",
|
|
1906
|
+
{
|
|
1907
|
+
type: "button",
|
|
1908
|
+
className: cn(
|
|
1909
|
+
"flex items-center gap-2 rounded border border-border bg-background px-3 py-1.5 text-sm transition-colors",
|
|
1910
|
+
"hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1911
|
+
className
|
|
1912
|
+
),
|
|
1913
|
+
children: [
|
|
1914
|
+
/* @__PURE__ */ jsxs("div", { className: "flex -space-x-2", children: [
|
|
1915
|
+
visibleUsers.map((user) => /* @__PURE__ */ jsxs(
|
|
1916
|
+
Avatar,
|
|
1917
|
+
{
|
|
1918
|
+
className: "size-6 border-2 border-background",
|
|
1919
|
+
children: [
|
|
1920
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }),
|
|
1921
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px]", children: getInitials(user.name) })
|
|
1922
|
+
]
|
|
1923
|
+
},
|
|
1924
|
+
user.id
|
|
1925
|
+
)),
|
|
1926
|
+
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: [
|
|
1927
|
+
"+",
|
|
1928
|
+
overflowCount
|
|
1929
|
+
] })
|
|
1930
|
+
] }),
|
|
1931
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: displayLabel }),
|
|
1932
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 text-muted-foreground" })
|
|
1933
|
+
]
|
|
1934
|
+
}
|
|
1935
|
+
) }),
|
|
1936
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-48", children: [
|
|
1937
|
+
/* @__PURE__ */ jsxs(
|
|
1938
|
+
DropdownMenuItem,
|
|
1939
|
+
{
|
|
1940
|
+
onClick: () => onSelect(null),
|
|
1941
|
+
className: "flex items-center justify-between",
|
|
1942
|
+
children: [
|
|
1943
|
+
/* @__PURE__ */ jsx("span", { children: "All users" }),
|
|
1944
|
+
selectedUserId === null && /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" })
|
|
1945
|
+
]
|
|
1946
|
+
}
|
|
1947
|
+
),
|
|
1948
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
1949
|
+
users.map((user) => /* @__PURE__ */ jsxs(
|
|
1950
|
+
DropdownMenuItem,
|
|
1951
|
+
{
|
|
1952
|
+
onClick: () => onSelect(user.id),
|
|
1953
|
+
className: "flex items-center justify-between",
|
|
1954
|
+
children: [
|
|
1955
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1956
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-5", children: [
|
|
1957
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.image, alt: user.name }),
|
|
1958
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[8px]", children: getInitials(user.name) })
|
|
1959
|
+
] }),
|
|
1960
|
+
/* @__PURE__ */ jsx("span", { children: user.name })
|
|
1961
|
+
] }),
|
|
1962
|
+
selectedUserId === user.id && /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" })
|
|
1963
|
+
]
|
|
1964
|
+
},
|
|
1965
|
+
user.id
|
|
1966
|
+
))
|
|
1967
|
+
] })
|
|
1968
|
+
] });
|
|
1969
|
+
}
|
|
1676
1970
|
function Skeleton({ className, ...props }) {
|
|
1677
1971
|
return /* @__PURE__ */ jsx(
|
|
1678
1972
|
"div",
|
|
@@ -1759,7 +2053,7 @@ function TabsList({
|
|
|
1759
2053
|
{
|
|
1760
2054
|
"data-slot": "tabs-list",
|
|
1761
2055
|
className: cn(
|
|
1762
|
-
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
|
2056
|
+
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px] dark:bg-[#1a1a1a]",
|
|
1763
2057
|
className
|
|
1764
2058
|
),
|
|
1765
2059
|
...props
|
|
@@ -1775,7 +2069,7 @@ function TabsTrigger({
|
|
|
1775
2069
|
{
|
|
1776
2070
|
"data-slot": "tabs-trigger",
|
|
1777
2071
|
className: cn(
|
|
1778
|
-
"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]:
|
|
2072
|
+
"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",
|
|
1779
2073
|
className
|
|
1780
2074
|
),
|
|
1781
2075
|
...props
|
|
@@ -1944,8 +2238,8 @@ function CalendarDayButton({
|
|
|
1944
2238
|
modifiers,
|
|
1945
2239
|
...props
|
|
1946
2240
|
}) {
|
|
1947
|
-
const ref =
|
|
1948
|
-
|
|
2241
|
+
const ref = React14.useRef(null);
|
|
2242
|
+
React14.useEffect(() => {
|
|
1949
2243
|
if (modifiers.focused) ref.current?.focus();
|
|
1950
2244
|
}, [modifiers.focused]);
|
|
1951
2245
|
return /* @__PURE__ */ jsx(
|
|
@@ -1966,9 +2260,9 @@ function CalendarDayButton({
|
|
|
1966
2260
|
}
|
|
1967
2261
|
);
|
|
1968
2262
|
}
|
|
1969
|
-
var CarouselContext =
|
|
2263
|
+
var CarouselContext = React14.createContext(null);
|
|
1970
2264
|
function useCarousel() {
|
|
1971
|
-
const context =
|
|
2265
|
+
const context = React14.useContext(CarouselContext);
|
|
1972
2266
|
if (!context) {
|
|
1973
2267
|
throw new Error("useCarousel must be used within a <Carousel />");
|
|
1974
2268
|
}
|
|
@@ -1990,20 +2284,20 @@ function Carousel({
|
|
|
1990
2284
|
},
|
|
1991
2285
|
plugins
|
|
1992
2286
|
);
|
|
1993
|
-
const [canScrollPrev, setCanScrollPrev] =
|
|
1994
|
-
const [canScrollNext, setCanScrollNext] =
|
|
1995
|
-
const onSelect =
|
|
2287
|
+
const [canScrollPrev, setCanScrollPrev] = React14.useState(false);
|
|
2288
|
+
const [canScrollNext, setCanScrollNext] = React14.useState(false);
|
|
2289
|
+
const onSelect = React14.useCallback((api2) => {
|
|
1996
2290
|
if (!api2) return;
|
|
1997
2291
|
setCanScrollPrev(api2.canScrollPrev());
|
|
1998
2292
|
setCanScrollNext(api2.canScrollNext());
|
|
1999
2293
|
}, []);
|
|
2000
|
-
const scrollPrev =
|
|
2294
|
+
const scrollPrev = React14.useCallback(() => {
|
|
2001
2295
|
api?.scrollPrev();
|
|
2002
2296
|
}, [api]);
|
|
2003
|
-
const scrollNext =
|
|
2297
|
+
const scrollNext = React14.useCallback(() => {
|
|
2004
2298
|
api?.scrollNext();
|
|
2005
2299
|
}, [api]);
|
|
2006
|
-
const handleKeyDown =
|
|
2300
|
+
const handleKeyDown = React14.useCallback(
|
|
2007
2301
|
(event) => {
|
|
2008
2302
|
if (event.key === "ArrowLeft") {
|
|
2009
2303
|
event.preventDefault();
|
|
@@ -2015,11 +2309,11 @@ function Carousel({
|
|
|
2015
2309
|
},
|
|
2016
2310
|
[scrollPrev, scrollNext]
|
|
2017
2311
|
);
|
|
2018
|
-
|
|
2312
|
+
React14.useEffect(() => {
|
|
2019
2313
|
if (!api || !setApi) return;
|
|
2020
2314
|
setApi(api);
|
|
2021
2315
|
}, [api, setApi]);
|
|
2022
|
-
|
|
2316
|
+
React14.useEffect(() => {
|
|
2023
2317
|
if (!api) return;
|
|
2024
2318
|
onSelect(api);
|
|
2025
2319
|
api.on("reInit", onSelect);
|
|
@@ -2152,9 +2446,9 @@ function CarouselNext({
|
|
|
2152
2446
|
);
|
|
2153
2447
|
}
|
|
2154
2448
|
var THEMES = { light: "", dark: ".dark" };
|
|
2155
|
-
var ChartContext =
|
|
2449
|
+
var ChartContext = React14.createContext(null);
|
|
2156
2450
|
function useChart() {
|
|
2157
|
-
const context =
|
|
2451
|
+
const context = React14.useContext(ChartContext);
|
|
2158
2452
|
if (!context) {
|
|
2159
2453
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
2160
2454
|
}
|
|
@@ -2167,7 +2461,7 @@ function ChartContainer({
|
|
|
2167
2461
|
config,
|
|
2168
2462
|
...props
|
|
2169
2463
|
}) {
|
|
2170
|
-
const uniqueId =
|
|
2464
|
+
const uniqueId = React14.useId();
|
|
2171
2465
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
2172
2466
|
return /* @__PURE__ */ jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs(
|
|
2173
2467
|
"div",
|
|
@@ -2228,7 +2522,7 @@ function ChartTooltipContent({
|
|
|
2228
2522
|
labelKey
|
|
2229
2523
|
}) {
|
|
2230
2524
|
const { config } = useChart();
|
|
2231
|
-
const tooltipLabel =
|
|
2525
|
+
const tooltipLabel = React14.useMemo(() => {
|
|
2232
2526
|
if (hideLabel || !payload?.length) {
|
|
2233
2527
|
return null;
|
|
2234
2528
|
}
|
|
@@ -2522,7 +2816,7 @@ var itemVariants = cva(
|
|
|
2522
2816
|
}
|
|
2523
2817
|
}
|
|
2524
2818
|
);
|
|
2525
|
-
function
|
|
2819
|
+
function Item6({
|
|
2526
2820
|
className,
|
|
2527
2821
|
variant = "default",
|
|
2528
2822
|
size = "default",
|
|
@@ -2930,40 +3224,27 @@ function TooltipContent({
|
|
|
2930
3224
|
}
|
|
2931
3225
|
) });
|
|
2932
3226
|
}
|
|
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();
|
|
3227
|
+
function useDetectTheme() {
|
|
3228
|
+
const [theme, setTheme] = React14.useState("light");
|
|
3229
|
+
React14.useEffect(() => {
|
|
3230
|
+
const isDark = document.documentElement.classList.contains("dark");
|
|
3231
|
+
setTheme(isDark ? "dark" : "light");
|
|
3232
|
+
const observer = new MutationObserver((mutations) => {
|
|
3233
|
+
mutations.forEach((mutation) => {
|
|
3234
|
+
if (mutation.attributeName === "class") {
|
|
3235
|
+
const isDark2 = document.documentElement.classList.contains("dark");
|
|
3236
|
+
setTheme(isDark2 ? "dark" : "light");
|
|
3237
|
+
}
|
|
3238
|
+
});
|
|
3239
|
+
});
|
|
3240
|
+
observer.observe(document.documentElement, { attributes: true });
|
|
3241
|
+
return () => observer.disconnect();
|
|
3242
|
+
}, []);
|
|
3243
|
+
return theme;
|
|
3244
|
+
}
|
|
3245
|
+
var Toaster = ({ theme: themeProp, ...props }) => {
|
|
3246
|
+
const detectedTheme = useDetectTheme();
|
|
3247
|
+
const theme = themeProp ?? detectedTheme;
|
|
2967
3248
|
return /* @__PURE__ */ jsx(
|
|
2968
3249
|
Toaster$1,
|
|
2969
3250
|
{
|
|
@@ -3466,215 +3747,52 @@ function CommandShortcut({
|
|
|
3466
3747
|
}
|
|
3467
3748
|
);
|
|
3468
3749
|
}
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
}
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
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
|
-
);
|
|
3750
|
+
var SearchTrigger = React14.forwardRef(
|
|
3751
|
+
({
|
|
3752
|
+
className,
|
|
3753
|
+
placeholder = "Search...",
|
|
3754
|
+
showShortcut = true,
|
|
3755
|
+
shortcutKey = "K",
|
|
3756
|
+
shortcutModifier = "\u2318",
|
|
3757
|
+
...props
|
|
3758
|
+
}, ref) => {
|
|
3759
|
+
return /* @__PURE__ */ jsxs(
|
|
3760
|
+
Button,
|
|
3761
|
+
{
|
|
3762
|
+
ref,
|
|
3763
|
+
variant: "outline",
|
|
3764
|
+
"data-slot": "search-trigger",
|
|
3765
|
+
className: cn(
|
|
3766
|
+
"relative h-9 w-full justify-start rounded-full bg-background text-sm text-muted-foreground",
|
|
3767
|
+
"sm:w-64 sm:max-w-[280px]",
|
|
3768
|
+
className
|
|
3769
|
+
),
|
|
3770
|
+
...props,
|
|
3771
|
+
children: [
|
|
3772
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "mr-2 h-4 w-4 shrink-0" }),
|
|
3773
|
+
/* @__PURE__ */ jsx("span", { className: "hidden truncate sm:inline-flex", children: placeholder }),
|
|
3774
|
+
/* @__PURE__ */ jsx("span", { className: "truncate sm:hidden", children: "Search" }),
|
|
3775
|
+
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: [
|
|
3776
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: shortcutModifier }),
|
|
3777
|
+
shortcutKey
|
|
3778
|
+
] })
|
|
3779
|
+
]
|
|
3780
|
+
}
|
|
3781
|
+
);
|
|
3782
|
+
}
|
|
3783
|
+
);
|
|
3784
|
+
SearchTrigger.displayName = "SearchTrigger";
|
|
3785
|
+
function useSearchShortcut(onOpen, key = "k") {
|
|
3786
|
+
React14.useEffect(() => {
|
|
3787
|
+
const down = (e) => {
|
|
3788
|
+
if (e.key.toLowerCase() === key.toLowerCase() && (e.metaKey || e.ctrlKey)) {
|
|
3789
|
+
e.preventDefault();
|
|
3790
|
+
onOpen();
|
|
3791
|
+
}
|
|
3792
|
+
};
|
|
3793
|
+
document.addEventListener("keydown", down);
|
|
3794
|
+
return () => document.removeEventListener("keydown", down);
|
|
3795
|
+
}, [onOpen, key]);
|
|
3678
3796
|
}
|
|
3679
3797
|
function Menubar({
|
|
3680
3798
|
className,
|
|
@@ -4693,9 +4811,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
4693
4811
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
4694
4812
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
4695
4813
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
4696
|
-
var SidebarContext =
|
|
4814
|
+
var SidebarContext = React14.createContext(null);
|
|
4697
4815
|
function useSidebar() {
|
|
4698
|
-
const context =
|
|
4816
|
+
const context = React14.useContext(SidebarContext);
|
|
4699
4817
|
if (!context) {
|
|
4700
4818
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
4701
4819
|
}
|
|
@@ -4711,10 +4829,10 @@ function SidebarProvider({
|
|
|
4711
4829
|
...props
|
|
4712
4830
|
}) {
|
|
4713
4831
|
const isMobile = useIsMobile();
|
|
4714
|
-
const [openMobile, setOpenMobile] =
|
|
4715
|
-
const [_open, _setOpen] =
|
|
4832
|
+
const [openMobile, setOpenMobile] = React14.useState(false);
|
|
4833
|
+
const [_open, _setOpen] = React14.useState(defaultOpen);
|
|
4716
4834
|
const open = openProp ?? _open;
|
|
4717
|
-
const setOpen =
|
|
4835
|
+
const setOpen = React14.useCallback(
|
|
4718
4836
|
(value) => {
|
|
4719
4837
|
const openState = typeof value === "function" ? value(open) : value;
|
|
4720
4838
|
if (setOpenProp) {
|
|
@@ -4726,10 +4844,10 @@ function SidebarProvider({
|
|
|
4726
4844
|
},
|
|
4727
4845
|
[setOpenProp, open]
|
|
4728
4846
|
);
|
|
4729
|
-
const toggleSidebar =
|
|
4847
|
+
const toggleSidebar = React14.useCallback(() => {
|
|
4730
4848
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
4731
4849
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
4732
|
-
|
|
4850
|
+
React14.useEffect(() => {
|
|
4733
4851
|
const handleKeyDown = (event) => {
|
|
4734
4852
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
4735
4853
|
event.preventDefault();
|
|
@@ -4740,7 +4858,7 @@ function SidebarProvider({
|
|
|
4740
4858
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
4741
4859
|
}, [toggleSidebar]);
|
|
4742
4860
|
const state = open ? "expanded" : "collapsed";
|
|
4743
|
-
const contextValue =
|
|
4861
|
+
const contextValue = React14.useMemo(
|
|
4744
4862
|
() => ({
|
|
4745
4863
|
state,
|
|
4746
4864
|
open,
|
|
@@ -5198,7 +5316,7 @@ function SidebarMenuSkeleton({
|
|
|
5198
5316
|
showIcon = false,
|
|
5199
5317
|
...props
|
|
5200
5318
|
}) {
|
|
5201
|
-
const width =
|
|
5319
|
+
const width = React14.useMemo(() => {
|
|
5202
5320
|
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
5203
5321
|
}, []);
|
|
5204
5322
|
return /* @__PURE__ */ jsxs(
|
|
@@ -5296,8 +5414,7 @@ var sectionVariants = cva(
|
|
|
5296
5414
|
default: [
|
|
5297
5415
|
"bg-[var(--color-bg-surface)]",
|
|
5298
5416
|
"border border-[var(--color-border-subtle)]",
|
|
5299
|
-
"text-[var(--color-text-main)]"
|
|
5300
|
-
"shadow-sm"
|
|
5417
|
+
"text-[var(--color-text-main)]"
|
|
5301
5418
|
].join(" "),
|
|
5302
5419
|
// Glass Light - frosted glass for dark or image backgrounds
|
|
5303
5420
|
"glass-light": [
|
|
@@ -5342,7 +5459,7 @@ var sectionVariants = cva(
|
|
|
5342
5459
|
}
|
|
5343
5460
|
);
|
|
5344
5461
|
var isGlassVariant = (variant) => variant?.startsWith("glass-") ?? false;
|
|
5345
|
-
var Section =
|
|
5462
|
+
var Section = React14.forwardRef(
|
|
5346
5463
|
({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5347
5464
|
"section",
|
|
5348
5465
|
{
|
|
@@ -5354,7 +5471,7 @@ var Section = React7.forwardRef(
|
|
|
5354
5471
|
)
|
|
5355
5472
|
);
|
|
5356
5473
|
Section.displayName = "Section";
|
|
5357
|
-
var SectionHeader =
|
|
5474
|
+
var SectionHeader = React14.forwardRef(
|
|
5358
5475
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5359
5476
|
"div",
|
|
5360
5477
|
{
|
|
@@ -5369,7 +5486,7 @@ var SectionHeader = React7.forwardRef(
|
|
|
5369
5486
|
)
|
|
5370
5487
|
);
|
|
5371
5488
|
SectionHeader.displayName = "SectionHeader";
|
|
5372
|
-
var SectionTitle =
|
|
5489
|
+
var SectionTitle = React14.forwardRef(
|
|
5373
5490
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5374
5491
|
"h2",
|
|
5375
5492
|
{
|
|
@@ -5383,7 +5500,7 @@ var SectionTitle = React7.forwardRef(
|
|
|
5383
5500
|
)
|
|
5384
5501
|
);
|
|
5385
5502
|
SectionTitle.displayName = "SectionTitle";
|
|
5386
|
-
var SectionDescription =
|
|
5503
|
+
var SectionDescription = React14.forwardRef(
|
|
5387
5504
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5388
5505
|
"p",
|
|
5389
5506
|
{
|
|
@@ -5397,7 +5514,7 @@ var SectionDescription = React7.forwardRef(
|
|
|
5397
5514
|
)
|
|
5398
5515
|
);
|
|
5399
5516
|
SectionDescription.displayName = "SectionDescription";
|
|
5400
|
-
var SectionContent =
|
|
5517
|
+
var SectionContent = React14.forwardRef(
|
|
5401
5518
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5402
5519
|
"div",
|
|
5403
5520
|
{
|
|
@@ -5411,7 +5528,7 @@ var SectionContent = React7.forwardRef(
|
|
|
5411
5528
|
)
|
|
5412
5529
|
);
|
|
5413
5530
|
SectionContent.displayName = "SectionContent";
|
|
5414
|
-
var SectionFooter =
|
|
5531
|
+
var SectionFooter = React14.forwardRef(
|
|
5415
5532
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
5416
5533
|
"div",
|
|
5417
5534
|
{
|
|
@@ -5427,7 +5544,3182 @@ var SectionFooter = React7.forwardRef(
|
|
|
5427
5544
|
)
|
|
5428
5545
|
);
|
|
5429
5546
|
SectionFooter.displayName = "SectionFooter";
|
|
5547
|
+
function SearchForm({ ...props }) {
|
|
5548
|
+
return /* @__PURE__ */ jsx("form", { ...props, children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
5549
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "search", className: "sr-only", children: "Search" }),
|
|
5550
|
+
/* @__PURE__ */ jsx(
|
|
5551
|
+
SidebarInput,
|
|
5552
|
+
{
|
|
5553
|
+
id: "search",
|
|
5554
|
+
placeholder: "Type to search...",
|
|
5555
|
+
className: "h-8 pl-7"
|
|
5556
|
+
}
|
|
5557
|
+
),
|
|
5558
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute top-1/2 left-2 size-4 -translate-y-1/2 opacity-50 select-none" })
|
|
5559
|
+
] }) });
|
|
5560
|
+
}
|
|
5561
|
+
function SiteHeader({
|
|
5562
|
+
trigger,
|
|
5563
|
+
breadcrumbs = [
|
|
5564
|
+
{ label: "Building Your Application", href: "#" },
|
|
5565
|
+
{ label: "Data Fetching" }
|
|
5566
|
+
],
|
|
5567
|
+
showSearch = true,
|
|
5568
|
+
className,
|
|
5569
|
+
children
|
|
5570
|
+
}) {
|
|
5571
|
+
return /* @__PURE__ */ jsx(
|
|
5572
|
+
"header",
|
|
5573
|
+
{
|
|
5574
|
+
"data-slot": "site-header",
|
|
5575
|
+
className: cn(
|
|
5576
|
+
"bg-sidebar text-sidebar-foreground sticky top-0 z-50 flex w-full items-center border-b border-sidebar-border",
|
|
5577
|
+
className
|
|
5578
|
+
),
|
|
5579
|
+
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: [
|
|
5580
|
+
trigger,
|
|
5581
|
+
trigger && /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mr-[var(--j3m-spacing-s)] h-4" }),
|
|
5582
|
+
/* @__PURE__ */ jsx(Breadcrumb, { className: "hidden sm:block", children: /* @__PURE__ */ jsx(BreadcrumbList, { children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxs(React14.Fragment, { children: [
|
|
5583
|
+
index > 0 && /* @__PURE__ */ jsx(BreadcrumbSeparator, {}),
|
|
5584
|
+
/* @__PURE__ */ jsx(BreadcrumbItem, { children: item.href ? /* @__PURE__ */ jsx(BreadcrumbLink, { href: item.href, children: item.label }) : /* @__PURE__ */ jsx(BreadcrumbPage, { children: item.label }) })
|
|
5585
|
+
] }, index)) }) }),
|
|
5586
|
+
showSearch && /* @__PURE__ */ jsx(SearchForm, { className: "w-full sm:ml-auto sm:w-auto" }),
|
|
5587
|
+
children
|
|
5588
|
+
] })
|
|
5589
|
+
}
|
|
5590
|
+
);
|
|
5591
|
+
}
|
|
5592
|
+
function NavMain({ items, label = "Platform" }) {
|
|
5593
|
+
return /* @__PURE__ */ jsxs(SidebarGroup, { children: [
|
|
5594
|
+
/* @__PURE__ */ jsx(SidebarGroupLabel, { children: label }),
|
|
5595
|
+
/* @__PURE__ */ jsx(SidebarMenu, { children: items.map((item) => /* @__PURE__ */ jsx(Collapsible, { asChild: true, defaultOpen: item.isActive, children: /* @__PURE__ */ jsxs(SidebarMenuItem, { children: [
|
|
5596
|
+
/* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, tooltip: item.title, children: /* @__PURE__ */ jsxs("a", { href: item.url, children: [
|
|
5597
|
+
item.icon && /* @__PURE__ */ jsx(item.icon, {}),
|
|
5598
|
+
/* @__PURE__ */ jsx("span", { children: item.title })
|
|
5599
|
+
] }) }),
|
|
5600
|
+
item.items?.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5601
|
+
/* @__PURE__ */ jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs(SidebarMenuAction, { className: "data-[state=open]:rotate-90", children: [
|
|
5602
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, {}),
|
|
5603
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle" })
|
|
5604
|
+
] }) }),
|
|
5605
|
+
/* @__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)) }) })
|
|
5606
|
+
] }) : null
|
|
5607
|
+
] }) }, item.title)) })
|
|
5608
|
+
] });
|
|
5609
|
+
}
|
|
5610
|
+
function NavProjects({ projects, label = "Projects" }) {
|
|
5611
|
+
return /* @__PURE__ */ jsxs(SidebarGroup, { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
5612
|
+
/* @__PURE__ */ jsx(SidebarGroupLabel, { children: label }),
|
|
5613
|
+
/* @__PURE__ */ jsxs(SidebarMenu, { children: [
|
|
5614
|
+
projects.map((item) => /* @__PURE__ */ jsxs(SidebarMenuItem, { children: [
|
|
5615
|
+
/* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxs("a", { href: item.url, children: [
|
|
5616
|
+
/* @__PURE__ */ jsx(item.icon, {}),
|
|
5617
|
+
/* @__PURE__ */ jsx("span", { children: item.name })
|
|
5618
|
+
] }) }),
|
|
5619
|
+
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
5620
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(SidebarMenuAction, { showOnHover: true, children: [
|
|
5621
|
+
/* @__PURE__ */ jsx(MoreHorizontalIcon, {}),
|
|
5622
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "More" })
|
|
5623
|
+
] }) }),
|
|
5624
|
+
/* @__PURE__ */ jsxs(
|
|
5625
|
+
DropdownMenuContent,
|
|
5626
|
+
{
|
|
5627
|
+
className: "w-48 rounded-[var(--j3m-radius-m)]",
|
|
5628
|
+
side: "right",
|
|
5629
|
+
align: "start",
|
|
5630
|
+
sideOffset: 8,
|
|
5631
|
+
children: [
|
|
5632
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5633
|
+
/* @__PURE__ */ jsx(FolderIcon, { className: "text-muted-foreground" }),
|
|
5634
|
+
/* @__PURE__ */ jsx("span", { children: "View Project" })
|
|
5635
|
+
] }),
|
|
5636
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5637
|
+
/* @__PURE__ */ jsx(ShareIcon, { className: "text-muted-foreground" }),
|
|
5638
|
+
/* @__PURE__ */ jsx("span", { children: "Share Project" })
|
|
5639
|
+
] }),
|
|
5640
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5641
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5642
|
+
/* @__PURE__ */ jsx(TrashIcon, { className: "text-muted-foreground" }),
|
|
5643
|
+
/* @__PURE__ */ jsx("span", { children: "Delete Project" })
|
|
5644
|
+
] })
|
|
5645
|
+
]
|
|
5646
|
+
}
|
|
5647
|
+
)
|
|
5648
|
+
] })
|
|
5649
|
+
] }, item.name)),
|
|
5650
|
+
/* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(SidebarMenuButton, { className: "text-sidebar-foreground/70", children: [
|
|
5651
|
+
/* @__PURE__ */ jsx(MoreHorizontalIcon, { className: "text-sidebar-foreground/70" }),
|
|
5652
|
+
/* @__PURE__ */ jsx("span", { children: "More" })
|
|
5653
|
+
] }) })
|
|
5654
|
+
] })
|
|
5655
|
+
] });
|
|
5656
|
+
}
|
|
5657
|
+
function NavSecondary({ items, ...props }) {
|
|
5658
|
+
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: [
|
|
5659
|
+
/* @__PURE__ */ jsx(item.icon, {}),
|
|
5660
|
+
/* @__PURE__ */ jsx("span", { children: item.title })
|
|
5661
|
+
] }) }) }, item.title)) }) }) });
|
|
5662
|
+
}
|
|
5663
|
+
function NavUser({ user }) {
|
|
5664
|
+
return /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
5665
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
5666
|
+
SidebarMenuButton,
|
|
5667
|
+
{
|
|
5668
|
+
size: "lg",
|
|
5669
|
+
className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
|
|
5670
|
+
children: [
|
|
5671
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
5672
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
5673
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
5674
|
+
] }),
|
|
5675
|
+
/* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
5676
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
5677
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs", children: user.email })
|
|
5678
|
+
] }),
|
|
5679
|
+
/* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "ml-auto size-4" })
|
|
5680
|
+
]
|
|
5681
|
+
}
|
|
5682
|
+
) }),
|
|
5683
|
+
/* @__PURE__ */ jsxs(
|
|
5684
|
+
DropdownMenuContent,
|
|
5685
|
+
{
|
|
5686
|
+
className: "w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-[var(--j3m-radius-m)]",
|
|
5687
|
+
side: "right",
|
|
5688
|
+
align: "end",
|
|
5689
|
+
sideOffset: 8,
|
|
5690
|
+
children: [
|
|
5691
|
+
/* @__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: [
|
|
5692
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [
|
|
5693
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
|
|
5694
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg", children: user.name.slice(0, 2).toUpperCase() })
|
|
5695
|
+
] }),
|
|
5696
|
+
/* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
|
|
5697
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: user.name }),
|
|
5698
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs", children: user.email })
|
|
5699
|
+
] })
|
|
5700
|
+
] }) }),
|
|
5701
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5702
|
+
/* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5703
|
+
/* @__PURE__ */ jsx(SparklesIcon, {}),
|
|
5704
|
+
"Upgrade to Pro"
|
|
5705
|
+
] }) }),
|
|
5706
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5707
|
+
/* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
5708
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5709
|
+
/* @__PURE__ */ jsx(BadgeCheckIcon, {}),
|
|
5710
|
+
"Account"
|
|
5711
|
+
] }),
|
|
5712
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5713
|
+
/* @__PURE__ */ jsx(CreditCardIcon, {}),
|
|
5714
|
+
"Billing"
|
|
5715
|
+
] }),
|
|
5716
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5717
|
+
/* @__PURE__ */ jsx(BellIcon, {}),
|
|
5718
|
+
"Notifications"
|
|
5719
|
+
] })
|
|
5720
|
+
] }),
|
|
5721
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
5722
|
+
/* @__PURE__ */ jsxs(DropdownMenuItem, { children: [
|
|
5723
|
+
/* @__PURE__ */ jsx(LogOutIcon, {}),
|
|
5724
|
+
"Log out"
|
|
5725
|
+
] })
|
|
5726
|
+
]
|
|
5727
|
+
}
|
|
5728
|
+
)
|
|
5729
|
+
] }) }) });
|
|
5730
|
+
}
|
|
5731
|
+
|
|
5732
|
+
// src/components/event-calendar/types.ts
|
|
5733
|
+
var DEFAULT_WORKING_HOURS = {
|
|
5734
|
+
0: { from: 0, to: 0 },
|
|
5735
|
+
// Sunday - closed
|
|
5736
|
+
1: { from: 9, to: 17 },
|
|
5737
|
+
// Monday
|
|
5738
|
+
2: { from: 9, to: 17 },
|
|
5739
|
+
// Tuesday
|
|
5740
|
+
3: { from: 9, to: 17 },
|
|
5741
|
+
// Wednesday
|
|
5742
|
+
4: { from: 9, to: 17 },
|
|
5743
|
+
// Thursday
|
|
5744
|
+
5: { from: 9, to: 17 },
|
|
5745
|
+
// Friday
|
|
5746
|
+
6: { from: 0, to: 0 }
|
|
5747
|
+
// Saturday - closed
|
|
5748
|
+
};
|
|
5749
|
+
var DEFAULT_VISIBLE_HOURS = { from: 0, to: 24 };
|
|
5750
|
+
var EVENT_COLORS = {
|
|
5751
|
+
blue: {
|
|
5752
|
+
bg: "bg-blue-500/20",
|
|
5753
|
+
text: "text-blue-700 dark:text-blue-300",
|
|
5754
|
+
border: "border-blue-500"
|
|
5755
|
+
},
|
|
5756
|
+
green: {
|
|
5757
|
+
bg: "bg-green-500/20",
|
|
5758
|
+
text: "text-green-700 dark:text-green-300",
|
|
5759
|
+
border: "border-green-500"
|
|
5760
|
+
},
|
|
5761
|
+
red: {
|
|
5762
|
+
bg: "bg-red-500/20",
|
|
5763
|
+
text: "text-red-700 dark:text-red-300",
|
|
5764
|
+
border: "border-red-500"
|
|
5765
|
+
},
|
|
5766
|
+
yellow: {
|
|
5767
|
+
bg: "bg-yellow-500/20",
|
|
5768
|
+
text: "text-yellow-700 dark:text-yellow-300",
|
|
5769
|
+
border: "border-yellow-500"
|
|
5770
|
+
},
|
|
5771
|
+
purple: {
|
|
5772
|
+
bg: "bg-purple-500/20",
|
|
5773
|
+
text: "text-purple-700 dark:text-purple-300",
|
|
5774
|
+
border: "border-purple-500"
|
|
5775
|
+
},
|
|
5776
|
+
orange: {
|
|
5777
|
+
bg: "bg-primary/20",
|
|
5778
|
+
text: "text-primary dark:text-orange-300",
|
|
5779
|
+
border: "border-primary"
|
|
5780
|
+
}
|
|
5781
|
+
};
|
|
5782
|
+
var VIEW_LABELS = {
|
|
5783
|
+
month: "Month",
|
|
5784
|
+
week: "Week",
|
|
5785
|
+
day: "Day",
|
|
5786
|
+
year: "Year",
|
|
5787
|
+
agenda: "Agenda"
|
|
5788
|
+
};
|
|
5789
|
+
var BADGE_VARIANT_LABELS = {
|
|
5790
|
+
dot: "Dot",
|
|
5791
|
+
colored: "Colored",
|
|
5792
|
+
mixed: "Mixed"
|
|
5793
|
+
};
|
|
5794
|
+
var CalendarContext = React14.createContext(null);
|
|
5795
|
+
function EventCalendarProvider({
|
|
5796
|
+
children,
|
|
5797
|
+
events: initialEvents = [],
|
|
5798
|
+
users: initialUsers = [],
|
|
5799
|
+
defaultDate = /* @__PURE__ */ new Date(),
|
|
5800
|
+
defaultView = "month",
|
|
5801
|
+
defaultBadgeVariant = "colored",
|
|
5802
|
+
defaultUserId = null,
|
|
5803
|
+
defaultWorkingHours = DEFAULT_WORKING_HOURS,
|
|
5804
|
+
defaultVisibleHours = DEFAULT_VISIBLE_HOURS,
|
|
5805
|
+
onEventAdd,
|
|
5806
|
+
onEventUpdate,
|
|
5807
|
+
onEventDelete
|
|
5808
|
+
}) {
|
|
5809
|
+
const [selectedDate, setSelectedDate] = React14.useState(defaultDate);
|
|
5810
|
+
const [selectedUserId, setSelectedUserId] = React14.useState(defaultUserId);
|
|
5811
|
+
const [events, setEventsState] = React14.useState(initialEvents);
|
|
5812
|
+
const [users] = React14.useState(initialUsers);
|
|
5813
|
+
const [badgeVariant, setBadgeVariant] = React14.useState(defaultBadgeVariant);
|
|
5814
|
+
const [view, setView] = React14.useState(defaultView);
|
|
5815
|
+
const [workingHours, setWorkingHours] = React14.useState(defaultWorkingHours);
|
|
5816
|
+
const [visibleHours, setVisibleHours] = React14.useState(defaultVisibleHours);
|
|
5817
|
+
React14.useEffect(() => {
|
|
5818
|
+
setEventsState(initialEvents);
|
|
5819
|
+
}, [initialEvents]);
|
|
5820
|
+
const setEvents = React14.useCallback((newEvents) => {
|
|
5821
|
+
setEventsState(newEvents);
|
|
5822
|
+
}, []);
|
|
5823
|
+
const addEvent = React14.useCallback((event) => {
|
|
5824
|
+
setEventsState((prev) => [...prev, event]);
|
|
5825
|
+
onEventAdd?.(event);
|
|
5826
|
+
}, [onEventAdd]);
|
|
5827
|
+
const updateEvent = React14.useCallback((event) => {
|
|
5828
|
+
setEventsState(
|
|
5829
|
+
(prev) => prev.map((e) => e.id === event.id ? event : e)
|
|
5830
|
+
);
|
|
5831
|
+
onEventUpdate?.(event);
|
|
5832
|
+
}, [onEventUpdate]);
|
|
5833
|
+
const deleteEvent = React14.useCallback((eventId) => {
|
|
5834
|
+
setEventsState((prev) => prev.filter((e) => e.id !== eventId));
|
|
5835
|
+
onEventDelete?.(eventId);
|
|
5836
|
+
}, [onEventDelete]);
|
|
5837
|
+
const goToToday = React14.useCallback(() => {
|
|
5838
|
+
setSelectedDate(/* @__PURE__ */ new Date());
|
|
5839
|
+
}, []);
|
|
5840
|
+
const goToPrevious = React14.useCallback(() => {
|
|
5841
|
+
setSelectedDate((current) => {
|
|
5842
|
+
switch (view) {
|
|
5843
|
+
case "day":
|
|
5844
|
+
return subDays(current, 1);
|
|
5845
|
+
case "week":
|
|
5846
|
+
return subWeeks(current, 1);
|
|
5847
|
+
case "month":
|
|
5848
|
+
return subMonths(current, 1);
|
|
5849
|
+
case "year":
|
|
5850
|
+
return subYears(current, 1);
|
|
5851
|
+
case "agenda":
|
|
5852
|
+
return subMonths(current, 1);
|
|
5853
|
+
default:
|
|
5854
|
+
return current;
|
|
5855
|
+
}
|
|
5856
|
+
});
|
|
5857
|
+
}, [view]);
|
|
5858
|
+
const goToNext = React14.useCallback(() => {
|
|
5859
|
+
setSelectedDate((current) => {
|
|
5860
|
+
switch (view) {
|
|
5861
|
+
case "day":
|
|
5862
|
+
return addDays(current, 1);
|
|
5863
|
+
case "week":
|
|
5864
|
+
return addWeeks(current, 1);
|
|
5865
|
+
case "month":
|
|
5866
|
+
return addMonths(current, 1);
|
|
5867
|
+
case "year":
|
|
5868
|
+
return addYears(current, 1);
|
|
5869
|
+
case "agenda":
|
|
5870
|
+
return addMonths(current, 1);
|
|
5871
|
+
default:
|
|
5872
|
+
return current;
|
|
5873
|
+
}
|
|
5874
|
+
});
|
|
5875
|
+
}, [view]);
|
|
5876
|
+
const contextValue = React14.useMemo(
|
|
5877
|
+
() => ({
|
|
5878
|
+
// State
|
|
5879
|
+
selectedDate,
|
|
5880
|
+
selectedUserId,
|
|
5881
|
+
events,
|
|
5882
|
+
users,
|
|
5883
|
+
badgeVariant,
|
|
5884
|
+
view,
|
|
5885
|
+
workingHours,
|
|
5886
|
+
visibleHours,
|
|
5887
|
+
// Actions
|
|
5888
|
+
setSelectedDate,
|
|
5889
|
+
setSelectedUserId,
|
|
5890
|
+
setEvents,
|
|
5891
|
+
addEvent,
|
|
5892
|
+
updateEvent,
|
|
5893
|
+
deleteEvent,
|
|
5894
|
+
setBadgeVariant,
|
|
5895
|
+
setView,
|
|
5896
|
+
setWorkingHours,
|
|
5897
|
+
setVisibleHours,
|
|
5898
|
+
goToToday,
|
|
5899
|
+
goToPrevious,
|
|
5900
|
+
goToNext
|
|
5901
|
+
}),
|
|
5902
|
+
[
|
|
5903
|
+
selectedDate,
|
|
5904
|
+
selectedUserId,
|
|
5905
|
+
events,
|
|
5906
|
+
users,
|
|
5907
|
+
badgeVariant,
|
|
5908
|
+
view,
|
|
5909
|
+
workingHours,
|
|
5910
|
+
visibleHours,
|
|
5911
|
+
setEvents,
|
|
5912
|
+
addEvent,
|
|
5913
|
+
updateEvent,
|
|
5914
|
+
deleteEvent,
|
|
5915
|
+
goToToday,
|
|
5916
|
+
goToPrevious,
|
|
5917
|
+
goToNext
|
|
5918
|
+
]
|
|
5919
|
+
);
|
|
5920
|
+
return /* @__PURE__ */ jsx(CalendarContext.Provider, { value: contextValue, children });
|
|
5921
|
+
}
|
|
5922
|
+
function useEventCalendar() {
|
|
5923
|
+
const context = React14.useContext(CalendarContext);
|
|
5924
|
+
if (!context) {
|
|
5925
|
+
throw new Error("useEventCalendar must be used within an EventCalendarProvider");
|
|
5926
|
+
}
|
|
5927
|
+
return context;
|
|
5928
|
+
}
|
|
5929
|
+
function useFilteredEvents() {
|
|
5930
|
+
const { events, selectedUserId } = useEventCalendar();
|
|
5931
|
+
return React14.useMemo(() => {
|
|
5932
|
+
if (!selectedUserId) return events;
|
|
5933
|
+
return events.filter((event) => event.user.id === selectedUserId);
|
|
5934
|
+
}, [events, selectedUserId]);
|
|
5935
|
+
}
|
|
5936
|
+
function useEventsInRange(startDate, endDate) {
|
|
5937
|
+
const filteredEvents = useFilteredEvents();
|
|
5938
|
+
return React14.useMemo(() => {
|
|
5939
|
+
return filteredEvents.filter((event) => {
|
|
5940
|
+
const eventStart = new Date(event.startDate);
|
|
5941
|
+
const eventEnd = new Date(event.endDate);
|
|
5942
|
+
return eventStart <= endDate && eventEnd >= startDate;
|
|
5943
|
+
});
|
|
5944
|
+
}, [filteredEvents, startDate, endDate]);
|
|
5945
|
+
}
|
|
5946
|
+
function rangeText(view, date) {
|
|
5947
|
+
const formatString = "MMM d, yyyy";
|
|
5948
|
+
let start;
|
|
5949
|
+
let end;
|
|
5950
|
+
switch (view) {
|
|
5951
|
+
case "agenda":
|
|
5952
|
+
start = startOfMonth(date);
|
|
5953
|
+
end = endOfMonth(date);
|
|
5954
|
+
break;
|
|
5955
|
+
case "year":
|
|
5956
|
+
start = startOfYear(date);
|
|
5957
|
+
end = endOfYear(date);
|
|
5958
|
+
break;
|
|
5959
|
+
case "month":
|
|
5960
|
+
start = startOfMonth(date);
|
|
5961
|
+
end = endOfMonth(date);
|
|
5962
|
+
break;
|
|
5963
|
+
case "week":
|
|
5964
|
+
start = startOfWeek(date);
|
|
5965
|
+
end = endOfWeek(date);
|
|
5966
|
+
break;
|
|
5967
|
+
case "day":
|
|
5968
|
+
return format(date, formatString);
|
|
5969
|
+
default:
|
|
5970
|
+
return "Error while formatting";
|
|
5971
|
+
}
|
|
5972
|
+
return `${format(start, formatString)} - ${format(end, formatString)}`;
|
|
5973
|
+
}
|
|
5974
|
+
function navigateDate(date, view, direction) {
|
|
5975
|
+
const operations = {
|
|
5976
|
+
agenda: direction === "next" ? addMonths : subMonths,
|
|
5977
|
+
year: direction === "next" ? addYears : subYears,
|
|
5978
|
+
month: direction === "next" ? addMonths : subMonths,
|
|
5979
|
+
week: direction === "next" ? addWeeks : subWeeks,
|
|
5980
|
+
day: direction === "next" ? addDays : subDays
|
|
5981
|
+
};
|
|
5982
|
+
return operations[view](date, 1);
|
|
5983
|
+
}
|
|
5984
|
+
function getEventsCount(events, date, view) {
|
|
5985
|
+
const compareFns = {
|
|
5986
|
+
agenda: isSameMonth,
|
|
5987
|
+
year: isSameYear,
|
|
5988
|
+
day: isSameDay,
|
|
5989
|
+
week: isSameWeek,
|
|
5990
|
+
month: isSameMonth
|
|
5991
|
+
};
|
|
5992
|
+
return events.filter(
|
|
5993
|
+
(event) => compareFns[view](new Date(event.startDate), date)
|
|
5994
|
+
).length;
|
|
5995
|
+
}
|
|
5996
|
+
function getCurrentEvents(events) {
|
|
5997
|
+
const now = /* @__PURE__ */ new Date();
|
|
5998
|
+
return events.filter(
|
|
5999
|
+
(event) => isWithinInterval(now, {
|
|
6000
|
+
start: parseISO(event.startDate),
|
|
6001
|
+
end: parseISO(event.endDate)
|
|
6002
|
+
})
|
|
6003
|
+
) || [];
|
|
6004
|
+
}
|
|
6005
|
+
function groupEvents(dayEvents) {
|
|
6006
|
+
const sortedEvents = dayEvents.sort(
|
|
6007
|
+
(a, b) => parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime()
|
|
6008
|
+
);
|
|
6009
|
+
const groups = [];
|
|
6010
|
+
for (const event of sortedEvents) {
|
|
6011
|
+
const eventStart = parseISO(event.startDate);
|
|
6012
|
+
let placed = false;
|
|
6013
|
+
for (const group of groups) {
|
|
6014
|
+
const lastEventInGroup = group[group.length - 1];
|
|
6015
|
+
const lastEventEnd = parseISO(lastEventInGroup.endDate);
|
|
6016
|
+
if (eventStart >= lastEventEnd) {
|
|
6017
|
+
group.push(event);
|
|
6018
|
+
placed = true;
|
|
6019
|
+
break;
|
|
6020
|
+
}
|
|
6021
|
+
}
|
|
6022
|
+
if (!placed) groups.push([event]);
|
|
6023
|
+
}
|
|
6024
|
+
return groups;
|
|
6025
|
+
}
|
|
6026
|
+
function getEventBlockStyle(event, day, groupIndex, groupSize, visibleHoursRange, hourHeight = 96) {
|
|
6027
|
+
const startDate = parseISO(event.startDate);
|
|
6028
|
+
const endDate = parseISO(event.endDate);
|
|
6029
|
+
const dayStart = new Date(day);
|
|
6030
|
+
dayStart.setHours(0, 0, 0, 0);
|
|
6031
|
+
const eventStart = startDate < dayStart ? dayStart : startDate;
|
|
6032
|
+
const startMinutes = differenceInMinutes(eventStart, dayStart);
|
|
6033
|
+
const durationMinutes = differenceInMinutes(endDate, eventStart);
|
|
6034
|
+
const visibleStartMinutes = (visibleHoursRange?.from ?? 0) * 60;
|
|
6035
|
+
const topMinutes = startMinutes - visibleStartMinutes;
|
|
6036
|
+
const topPx = topMinutes / 60 * hourHeight;
|
|
6037
|
+
const heightPx = Math.max(durationMinutes / 60 * hourHeight, hourHeight / 4);
|
|
6038
|
+
const width = 100 / groupSize;
|
|
6039
|
+
const left = groupIndex * width;
|
|
6040
|
+
return {
|
|
6041
|
+
top: `${topPx}px`,
|
|
6042
|
+
height: `${heightPx}px`,
|
|
6043
|
+
width: `${width}%`,
|
|
6044
|
+
left: `${left}%`
|
|
6045
|
+
};
|
|
6046
|
+
}
|
|
6047
|
+
function isWorkingHour(day, hour, workingHours) {
|
|
6048
|
+
const dayIndex = day.getDay();
|
|
6049
|
+
const dayHours = workingHours[dayIndex];
|
|
6050
|
+
return hour >= dayHours.from && hour < dayHours.to;
|
|
6051
|
+
}
|
|
6052
|
+
function getVisibleHours(visibleHours, singleDayEvents) {
|
|
6053
|
+
let earliestEventHour = visibleHours.from;
|
|
6054
|
+
let latestEventHour = visibleHours.to;
|
|
6055
|
+
singleDayEvents.forEach((event) => {
|
|
6056
|
+
const startHour = parseISO(event.startDate).getHours();
|
|
6057
|
+
const endTime = parseISO(event.endDate);
|
|
6058
|
+
const endHour = endTime.getHours() + (endTime.getMinutes() > 0 ? 1 : 0);
|
|
6059
|
+
if (startHour < earliestEventHour) earliestEventHour = startHour;
|
|
6060
|
+
if (endHour > latestEventHour) latestEventHour = endHour;
|
|
6061
|
+
});
|
|
6062
|
+
latestEventHour = Math.min(latestEventHour, 24);
|
|
6063
|
+
const hours = Array.from(
|
|
6064
|
+
{ length: latestEventHour - earliestEventHour },
|
|
6065
|
+
(_, i) => i + earliestEventHour
|
|
6066
|
+
);
|
|
6067
|
+
return { hours, earliestEventHour, latestEventHour };
|
|
6068
|
+
}
|
|
6069
|
+
function getCalendarCells(selectedDate) {
|
|
6070
|
+
const currentYear = selectedDate.getFullYear();
|
|
6071
|
+
const currentMonth = selectedDate.getMonth();
|
|
6072
|
+
const getDaysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
6073
|
+
const getFirstDayOfMonth = (year, month) => new Date(year, month, 1).getDay();
|
|
6074
|
+
const daysInMonth = getDaysInMonth(currentYear, currentMonth);
|
|
6075
|
+
const firstDayOfMonth = getFirstDayOfMonth(currentYear, currentMonth);
|
|
6076
|
+
const daysInPrevMonth = getDaysInMonth(currentYear, currentMonth - 1);
|
|
6077
|
+
const totalDays = firstDayOfMonth + daysInMonth;
|
|
6078
|
+
const prevMonthCells = Array.from({ length: firstDayOfMonth }, (_, i) => ({
|
|
6079
|
+
day: daysInPrevMonth - firstDayOfMonth + i + 1,
|
|
6080
|
+
currentMonth: false,
|
|
6081
|
+
date: new Date(
|
|
6082
|
+
currentYear,
|
|
6083
|
+
currentMonth - 1,
|
|
6084
|
+
daysInPrevMonth - firstDayOfMonth + i + 1
|
|
6085
|
+
)
|
|
6086
|
+
}));
|
|
6087
|
+
const currentMonthCells = Array.from({ length: daysInMonth }, (_, i) => ({
|
|
6088
|
+
day: i + 1,
|
|
6089
|
+
currentMonth: true,
|
|
6090
|
+
date: new Date(currentYear, currentMonth, i + 1)
|
|
6091
|
+
}));
|
|
6092
|
+
const nextMonthCells = Array.from(
|
|
6093
|
+
{ length: (7 - totalDays % 7) % 7 },
|
|
6094
|
+
(_, i) => ({
|
|
6095
|
+
day: i + 1,
|
|
6096
|
+
currentMonth: false,
|
|
6097
|
+
date: new Date(currentYear, currentMonth + 1, i + 1)
|
|
6098
|
+
})
|
|
6099
|
+
);
|
|
6100
|
+
return [...prevMonthCells, ...currentMonthCells, ...nextMonthCells];
|
|
6101
|
+
}
|
|
6102
|
+
function calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate) {
|
|
6103
|
+
const monthStart = startOfMonth(selectedDate);
|
|
6104
|
+
const monthEnd = endOfMonth(selectedDate);
|
|
6105
|
+
const eventPositions = {};
|
|
6106
|
+
const occupiedPositions = {};
|
|
6107
|
+
eachDayOfInterval({ start: monthStart, end: monthEnd }).forEach((day) => {
|
|
6108
|
+
occupiedPositions[day.toISOString()] = [false, false, false];
|
|
6109
|
+
});
|
|
6110
|
+
const sortedEvents = [
|
|
6111
|
+
...multiDayEvents.sort((a, b) => {
|
|
6112
|
+
const aDuration = differenceInDays(
|
|
6113
|
+
parseISO(a.endDate),
|
|
6114
|
+
parseISO(a.startDate)
|
|
6115
|
+
);
|
|
6116
|
+
const bDuration = differenceInDays(
|
|
6117
|
+
parseISO(b.endDate),
|
|
6118
|
+
parseISO(b.startDate)
|
|
6119
|
+
);
|
|
6120
|
+
return bDuration - aDuration || parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime();
|
|
6121
|
+
}),
|
|
6122
|
+
...singleDayEvents.sort(
|
|
6123
|
+
(a, b) => parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime()
|
|
6124
|
+
)
|
|
6125
|
+
];
|
|
6126
|
+
sortedEvents.forEach((event) => {
|
|
6127
|
+
const eventStart = parseISO(event.startDate);
|
|
6128
|
+
const eventEnd = parseISO(event.endDate);
|
|
6129
|
+
const eventDays = eachDayOfInterval({
|
|
6130
|
+
start: eventStart < monthStart ? monthStart : eventStart,
|
|
6131
|
+
end: eventEnd > monthEnd ? monthEnd : eventEnd
|
|
6132
|
+
});
|
|
6133
|
+
let position = -1;
|
|
6134
|
+
for (let i = 0; i < 3; i++) {
|
|
6135
|
+
if (eventDays.every((day) => {
|
|
6136
|
+
const dayPositions = occupiedPositions[startOfDay(day).toISOString()];
|
|
6137
|
+
return dayPositions && !dayPositions[i];
|
|
6138
|
+
})) {
|
|
6139
|
+
position = i;
|
|
6140
|
+
break;
|
|
6141
|
+
}
|
|
6142
|
+
}
|
|
6143
|
+
if (position !== -1) {
|
|
6144
|
+
eventDays.forEach((day) => {
|
|
6145
|
+
const dayKey = startOfDay(day).toISOString();
|
|
6146
|
+
occupiedPositions[dayKey][position] = true;
|
|
6147
|
+
});
|
|
6148
|
+
eventPositions[event.id] = position;
|
|
6149
|
+
}
|
|
6150
|
+
});
|
|
6151
|
+
return eventPositions;
|
|
6152
|
+
}
|
|
6153
|
+
function getMonthCellEvents(date, events, eventPositions) {
|
|
6154
|
+
const eventsForDate = events.filter((event) => {
|
|
6155
|
+
const eventStart = parseISO(event.startDate);
|
|
6156
|
+
const eventEnd = parseISO(event.endDate);
|
|
6157
|
+
return date >= eventStart && date <= eventEnd || isSameDay(date, eventStart) || isSameDay(date, eventEnd);
|
|
6158
|
+
});
|
|
6159
|
+
return eventsForDate.map((event) => ({
|
|
6160
|
+
...event,
|
|
6161
|
+
position: eventPositions[event.id] ?? -1,
|
|
6162
|
+
isMultiDay: event.startDate !== event.endDate
|
|
6163
|
+
})).sort((a, b) => {
|
|
6164
|
+
if (a.isMultiDay && !b.isMultiDay) return -1;
|
|
6165
|
+
if (!a.isMultiDay && b.isMultiDay) return 1;
|
|
6166
|
+
return a.position - b.position;
|
|
6167
|
+
});
|
|
6168
|
+
}
|
|
6169
|
+
function getMonthDays(date, weekStartsOn = 0) {
|
|
6170
|
+
const start = startOfWeek(startOfMonth(date), { weekStartsOn });
|
|
6171
|
+
const end = endOfWeek(endOfMonth(date), { weekStartsOn });
|
|
6172
|
+
return eachDayOfInterval({ start, end });
|
|
6173
|
+
}
|
|
6174
|
+
function getWeekDays(date, weekStartsOn = 0) {
|
|
6175
|
+
const start = startOfWeek(date, { weekStartsOn });
|
|
6176
|
+
const end = endOfWeek(date, { weekStartsOn });
|
|
6177
|
+
return eachDayOfInterval({ start, end });
|
|
6178
|
+
}
|
|
6179
|
+
function getDayHours(date, start = 0, end = 24) {
|
|
6180
|
+
const dayStart = setMinutes(setHours(date, start), 0);
|
|
6181
|
+
const dayEnd = setMinutes(setHours(date, end - 1), 59);
|
|
6182
|
+
return eachHourOfInterval({ start: dayStart, end: dayEnd });
|
|
6183
|
+
}
|
|
6184
|
+
function getYearMonths(date) {
|
|
6185
|
+
const start = startOfYear(date);
|
|
6186
|
+
const months = [];
|
|
6187
|
+
for (let i = 0; i < 12; i++) {
|
|
6188
|
+
months.push(new Date(start.getFullYear(), i, 1));
|
|
6189
|
+
}
|
|
6190
|
+
return months;
|
|
6191
|
+
}
|
|
6192
|
+
function getEventsForDate(events, date) {
|
|
6193
|
+
return events.filter((event) => {
|
|
6194
|
+
const eventStart = parseISO(event.startDate);
|
|
6195
|
+
const eventEnd = parseISO(event.endDate);
|
|
6196
|
+
return isWithinInterval(date, {
|
|
6197
|
+
start: startOfDay(eventStart),
|
|
6198
|
+
end: endOfDay(eventEnd)
|
|
6199
|
+
}) || isSameDay(eventStart, date) || isSameDay(eventEnd, date);
|
|
6200
|
+
});
|
|
6201
|
+
}
|
|
6202
|
+
function getEventsInRange(events, start, end) {
|
|
6203
|
+
return events.filter((event) => {
|
|
6204
|
+
const eventStart = parseISO(event.startDate);
|
|
6205
|
+
const eventEnd = parseISO(event.endDate);
|
|
6206
|
+
return eventStart >= start && eventStart <= end || eventEnd >= start && eventEnd <= end || eventStart <= start && eventEnd >= end;
|
|
6207
|
+
});
|
|
6208
|
+
}
|
|
6209
|
+
function splitEventsByDuration(events) {
|
|
6210
|
+
const singleDayEvents = [];
|
|
6211
|
+
const multiDayEvents = [];
|
|
6212
|
+
events.forEach((event) => {
|
|
6213
|
+
const start = parseISO(event.startDate);
|
|
6214
|
+
const end = parseISO(event.endDate);
|
|
6215
|
+
if (isSameDay(start, end)) {
|
|
6216
|
+
singleDayEvents.push(event);
|
|
6217
|
+
} else {
|
|
6218
|
+
multiDayEvents.push(event);
|
|
6219
|
+
}
|
|
6220
|
+
});
|
|
6221
|
+
return { singleDayEvents, multiDayEvents };
|
|
6222
|
+
}
|
|
6223
|
+
function isMultiDayEvent(event) {
|
|
6224
|
+
const start = parseISO(event.startDate);
|
|
6225
|
+
const end = parseISO(event.endDate);
|
|
6226
|
+
return !isSameDay(start, end);
|
|
6227
|
+
}
|
|
6228
|
+
function getEventDuration(event) {
|
|
6229
|
+
const start = parseISO(event.startDate);
|
|
6230
|
+
const end = parseISO(event.endDate);
|
|
6231
|
+
return differenceInDays(end, start) + 1;
|
|
6232
|
+
}
|
|
6233
|
+
function getEventDurationMinutes(event) {
|
|
6234
|
+
const start = parseISO(event.startDate);
|
|
6235
|
+
const end = parseISO(event.endDate);
|
|
6236
|
+
return differenceInMinutes(end, start);
|
|
6237
|
+
}
|
|
6238
|
+
function sortEvents(events) {
|
|
6239
|
+
return [...events].sort((a, b) => {
|
|
6240
|
+
const startDiff = parseISO(a.startDate).getTime() - parseISO(b.startDate).getTime();
|
|
6241
|
+
if (startDiff !== 0) return startDiff;
|
|
6242
|
+
return getEventDuration(b) - getEventDuration(a);
|
|
6243
|
+
});
|
|
6244
|
+
}
|
|
6245
|
+
function getTimePosition(event, visibleHoursRange) {
|
|
6246
|
+
const start = parseISO(event.startDate);
|
|
6247
|
+
const hours = getHours(start);
|
|
6248
|
+
const minutes = getMinutes(start);
|
|
6249
|
+
const startHour = visibleHoursRange?.from ?? 0;
|
|
6250
|
+
const totalMinutes = (hours - startHour) * 60 + minutes;
|
|
6251
|
+
const totalDayMinutes = ((visibleHoursRange?.to ?? 24) - startHour) * 60;
|
|
6252
|
+
return totalMinutes / totalDayMinutes * 100;
|
|
6253
|
+
}
|
|
6254
|
+
function getTimeHeight(event, visibleHoursRange) {
|
|
6255
|
+
const duration = getEventDurationMinutes(event);
|
|
6256
|
+
const totalDayMinutes = ((visibleHoursRange?.to ?? 24) - (visibleHoursRange?.from ?? 0)) * 60;
|
|
6257
|
+
return Math.min(duration / totalDayMinutes * 100, 100);
|
|
6258
|
+
}
|
|
6259
|
+
function formatTime(date, use24h = false) {
|
|
6260
|
+
return format(date, use24h ? "HH:mm" : "h:mm a");
|
|
6261
|
+
}
|
|
6262
|
+
function getWeekDayNames(weekStartsOn = 0, shortNames = true) {
|
|
6263
|
+
const days = [
|
|
6264
|
+
"Sunday",
|
|
6265
|
+
"Monday",
|
|
6266
|
+
"Tuesday",
|
|
6267
|
+
"Wednesday",
|
|
6268
|
+
"Thursday",
|
|
6269
|
+
"Friday",
|
|
6270
|
+
"Saturday"
|
|
6271
|
+
];
|
|
6272
|
+
const rotated = [...days.slice(weekStartsOn), ...days.slice(0, weekStartsOn)];
|
|
6273
|
+
return shortNames ? rotated.map((d) => d.slice(0, 3)) : rotated;
|
|
6274
|
+
}
|
|
6275
|
+
function getHeaderLabel(date, view) {
|
|
6276
|
+
switch (view) {
|
|
6277
|
+
case "day":
|
|
6278
|
+
return format(date, "EEEE, MMMM d, yyyy");
|
|
6279
|
+
case "week":
|
|
6280
|
+
const weekStart = startOfWeek(date);
|
|
6281
|
+
const weekEnd = endOfWeek(date);
|
|
6282
|
+
if (weekStart.getMonth() === weekEnd.getMonth()) {
|
|
6283
|
+
return format(weekStart, "MMMM d") + " - " + format(weekEnd, "d, yyyy");
|
|
6284
|
+
}
|
|
6285
|
+
return format(weekStart, "MMM d") + " - " + format(weekEnd, "MMM d, yyyy");
|
|
6286
|
+
case "month":
|
|
6287
|
+
return format(date, "MMMM yyyy");
|
|
6288
|
+
case "year":
|
|
6289
|
+
return format(date, "yyyy");
|
|
6290
|
+
case "agenda":
|
|
6291
|
+
return format(date, "MMMM yyyy");
|
|
6292
|
+
default:
|
|
6293
|
+
return format(date, "MMMM yyyy");
|
|
6294
|
+
}
|
|
6295
|
+
}
|
|
6296
|
+
function getViewDateRange(date, view) {
|
|
6297
|
+
switch (view) {
|
|
6298
|
+
case "day":
|
|
6299
|
+
return { start: startOfDay(date), end: endOfDay(date) };
|
|
6300
|
+
case "week":
|
|
6301
|
+
return { start: startOfWeek(date), end: endOfWeek(date) };
|
|
6302
|
+
case "month":
|
|
6303
|
+
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6304
|
+
case "year":
|
|
6305
|
+
return { start: startOfYear(date), end: endOfYear(date) };
|
|
6306
|
+
case "agenda":
|
|
6307
|
+
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6308
|
+
default:
|
|
6309
|
+
return { start: startOfMonth(date), end: endOfMonth(date) };
|
|
6310
|
+
}
|
|
6311
|
+
}
|
|
6312
|
+
function formatDateRange(start, end) {
|
|
6313
|
+
if (isSameDay(start, end)) {
|
|
6314
|
+
return format(start, "MMM d, yyyy");
|
|
6315
|
+
}
|
|
6316
|
+
if (start.getFullYear() === end.getFullYear()) {
|
|
6317
|
+
if (start.getMonth() === end.getMonth()) {
|
|
6318
|
+
return format(start, "MMM d") + " - " + format(end, "d, yyyy");
|
|
6319
|
+
}
|
|
6320
|
+
return format(start, "MMM d") + " - " + format(end, "MMM d, yyyy");
|
|
6321
|
+
}
|
|
6322
|
+
return format(start, "MMM d, yyyy") + " - " + format(end, "MMM d, yyyy");
|
|
6323
|
+
}
|
|
6324
|
+
function createDefaultEvent(startDate, duration = 60) {
|
|
6325
|
+
return {
|
|
6326
|
+
title: "",
|
|
6327
|
+
description: "",
|
|
6328
|
+
startDate: startDate.toISOString(),
|
|
6329
|
+
endDate: addMinutes(startDate, duration).toISOString(),
|
|
6330
|
+
color: "blue",
|
|
6331
|
+
user: {
|
|
6332
|
+
id: "",
|
|
6333
|
+
name: ""
|
|
6334
|
+
}
|
|
6335
|
+
};
|
|
6336
|
+
}
|
|
6337
|
+
function generateEventId() {
|
|
6338
|
+
return `event_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
6339
|
+
}
|
|
6340
|
+
function calculateDropDates(event, newStartDate) {
|
|
6341
|
+
const originalStart = parseISO(event.startDate);
|
|
6342
|
+
const originalEnd = parseISO(event.endDate);
|
|
6343
|
+
const duration = differenceInMinutes(originalEnd, originalStart);
|
|
6344
|
+
const newStart = newStartDate;
|
|
6345
|
+
const newEnd = addMinutes(newStart, duration);
|
|
6346
|
+
return {
|
|
6347
|
+
startDate: newStart.toISOString(),
|
|
6348
|
+
endDate: newEnd.toISOString()
|
|
6349
|
+
};
|
|
6350
|
+
}
|
|
6351
|
+
function snapToInterval(date, intervalMinutes = 15) {
|
|
6352
|
+
const minutes = getMinutes(date);
|
|
6353
|
+
const snappedMinutes = Math.round(minutes / intervalMinutes) * intervalMinutes;
|
|
6354
|
+
return setMinutes(date, snappedMinutes);
|
|
6355
|
+
}
|
|
6356
|
+
var colorClasses = {
|
|
6357
|
+
blue: {
|
|
6358
|
+
dot: "bg-blue-500",
|
|
6359
|
+
bg: "bg-blue-50 dark:bg-blue-950/50",
|
|
6360
|
+
text: "text-blue-600 dark:text-blue-400",
|
|
6361
|
+
border: "border-l-blue-500",
|
|
6362
|
+
solid: "bg-blue-500"
|
|
6363
|
+
},
|
|
6364
|
+
green: {
|
|
6365
|
+
dot: "bg-green-500",
|
|
6366
|
+
bg: "bg-green-50 dark:bg-green-950/50",
|
|
6367
|
+
text: "text-green-600 dark:text-green-400",
|
|
6368
|
+
border: "border-l-green-500",
|
|
6369
|
+
solid: "bg-green-500"
|
|
6370
|
+
},
|
|
6371
|
+
red: {
|
|
6372
|
+
dot: "bg-red-500",
|
|
6373
|
+
bg: "bg-red-50 dark:bg-red-950/50",
|
|
6374
|
+
text: "text-red-600 dark:text-red-400",
|
|
6375
|
+
border: "border-l-red-500",
|
|
6376
|
+
solid: "bg-red-500"
|
|
6377
|
+
},
|
|
6378
|
+
yellow: {
|
|
6379
|
+
dot: "bg-yellow-500",
|
|
6380
|
+
bg: "bg-yellow-50 dark:bg-yellow-950/50",
|
|
6381
|
+
text: "text-yellow-600 dark:text-yellow-400",
|
|
6382
|
+
border: "border-l-yellow-500",
|
|
6383
|
+
solid: "bg-yellow-500"
|
|
6384
|
+
},
|
|
6385
|
+
purple: {
|
|
6386
|
+
dot: "bg-purple-500",
|
|
6387
|
+
bg: "bg-purple-50 dark:bg-purple-950/50",
|
|
6388
|
+
text: "text-purple-600 dark:text-purple-400",
|
|
6389
|
+
border: "border-l-purple-500",
|
|
6390
|
+
solid: "bg-purple-500"
|
|
6391
|
+
},
|
|
6392
|
+
orange: {
|
|
6393
|
+
dot: "bg-primary",
|
|
6394
|
+
bg: "bg-orange-50 dark:bg-orange-950/50",
|
|
6395
|
+
text: "text-primary dark:text-orange-400",
|
|
6396
|
+
border: "border-l-primary",
|
|
6397
|
+
solid: "bg-primary"
|
|
6398
|
+
}
|
|
6399
|
+
};
|
|
6400
|
+
function EventBadge({
|
|
6401
|
+
event,
|
|
6402
|
+
variant = "colored",
|
|
6403
|
+
className,
|
|
6404
|
+
showTime = false,
|
|
6405
|
+
compact = false,
|
|
6406
|
+
isDragging = false,
|
|
6407
|
+
onClick
|
|
6408
|
+
}) {
|
|
6409
|
+
const colors = colorClasses[event.color];
|
|
6410
|
+
const startTime = format(parseISO(event.startDate), "h:mm a");
|
|
6411
|
+
const handleClick = (e) => {
|
|
6412
|
+
e.stopPropagation();
|
|
6413
|
+
onClick?.(event, e);
|
|
6414
|
+
};
|
|
6415
|
+
if (variant === "dot") {
|
|
6416
|
+
return /* @__PURE__ */ jsxs(
|
|
6417
|
+
"button",
|
|
6418
|
+
{
|
|
6419
|
+
type: "button",
|
|
6420
|
+
onClick: handleClick,
|
|
6421
|
+
className: cn(
|
|
6422
|
+
"flex items-center gap-1.5 rounded-sm px-1.5 py-0.5 text-left text-xs transition-colors",
|
|
6423
|
+
"hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6424
|
+
isDragging && "opacity-50",
|
|
6425
|
+
className
|
|
6426
|
+
),
|
|
6427
|
+
children: [
|
|
6428
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-2 shrink-0 rounded-full", colors.dot) }),
|
|
6429
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: event.title }),
|
|
6430
|
+
showTime && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: startTime })
|
|
6431
|
+
]
|
|
6432
|
+
}
|
|
6433
|
+
);
|
|
6434
|
+
}
|
|
6435
|
+
if (variant === "mixed") {
|
|
6436
|
+
return /* @__PURE__ */ jsxs(
|
|
6437
|
+
"button",
|
|
6438
|
+
{
|
|
6439
|
+
type: "button",
|
|
6440
|
+
onClick: handleClick,
|
|
6441
|
+
className: cn(
|
|
6442
|
+
"flex items-center gap-1.5 rounded-sm border-l-2 px-1.5 py-0.5 text-left text-xs transition-colors",
|
|
6443
|
+
"hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6444
|
+
colors.border,
|
|
6445
|
+
isDragging && "opacity-50",
|
|
6446
|
+
className
|
|
6447
|
+
),
|
|
6448
|
+
children: [
|
|
6449
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: event.title }),
|
|
6450
|
+
showTime && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: startTime })
|
|
6451
|
+
]
|
|
6452
|
+
}
|
|
6453
|
+
);
|
|
6454
|
+
}
|
|
6455
|
+
return /* @__PURE__ */ jsxs(
|
|
6456
|
+
"button",
|
|
6457
|
+
{
|
|
6458
|
+
type: "button",
|
|
6459
|
+
onClick: handleClick,
|
|
6460
|
+
className: cn(
|
|
6461
|
+
"flex flex-col items-start rounded-sm border-l-[3px] text-left text-xs transition-colors",
|
|
6462
|
+
"hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6463
|
+
colors.border,
|
|
6464
|
+
colors.bg,
|
|
6465
|
+
colors.text,
|
|
6466
|
+
compact ? "px-1.5 py-0.5" : "px-2 py-1",
|
|
6467
|
+
isDragging && "opacity-50 shadow-lg",
|
|
6468
|
+
className
|
|
6469
|
+
),
|
|
6470
|
+
children: [
|
|
6471
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium max-w-full", children: event.title }),
|
|
6472
|
+
showTime && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: startTime })
|
|
6473
|
+
]
|
|
6474
|
+
}
|
|
6475
|
+
);
|
|
6476
|
+
}
|
|
6477
|
+
function MoreEvents({ count, onClick, className }) {
|
|
6478
|
+
return /* @__PURE__ */ jsxs(
|
|
6479
|
+
"button",
|
|
6480
|
+
{
|
|
6481
|
+
type: "button",
|
|
6482
|
+
onClick,
|
|
6483
|
+
className: cn(
|
|
6484
|
+
"w-full rounded-sm px-2 py-0.5 text-left text-xs text-muted-foreground transition-colors",
|
|
6485
|
+
"hover:bg-muted hover:text-foreground",
|
|
6486
|
+
className
|
|
6487
|
+
),
|
|
6488
|
+
children: [
|
|
6489
|
+
count,
|
|
6490
|
+
" more..."
|
|
6491
|
+
]
|
|
6492
|
+
}
|
|
6493
|
+
);
|
|
6494
|
+
}
|
|
6495
|
+
function TimeIndicator({ className }) {
|
|
6496
|
+
const [now, setNow] = React14.useState(/* @__PURE__ */ new Date());
|
|
6497
|
+
React14.useEffect(() => {
|
|
6498
|
+
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
6499
|
+
return () => clearInterval(interval);
|
|
6500
|
+
}, []);
|
|
6501
|
+
const hours = now.getHours();
|
|
6502
|
+
const minutes = now.getMinutes();
|
|
6503
|
+
const topPercent = (hours * 60 + minutes) / (24 * 60) * 100;
|
|
6504
|
+
return /* @__PURE__ */ jsxs(
|
|
6505
|
+
"div",
|
|
6506
|
+
{
|
|
6507
|
+
className: cn(
|
|
6508
|
+
"pointer-events-none absolute left-0 right-0 z-20 flex items-center",
|
|
6509
|
+
className
|
|
6510
|
+
),
|
|
6511
|
+
style: { top: `${topPercent}%` },
|
|
6512
|
+
children: [
|
|
6513
|
+
/* @__PURE__ */ jsx("div", { className: "size-2.5 -translate-x-1/2 rounded-full bg-red-500" }),
|
|
6514
|
+
/* @__PURE__ */ jsx("div", { className: "h-0.5 flex-1 bg-red-500" })
|
|
6515
|
+
]
|
|
6516
|
+
}
|
|
6517
|
+
);
|
|
6518
|
+
}
|
|
6519
|
+
function DateBadge({ date, className }) {
|
|
6520
|
+
return /* @__PURE__ */ jsxs(
|
|
6521
|
+
"div",
|
|
6522
|
+
{
|
|
6523
|
+
className: cn(
|
|
6524
|
+
"flex flex-col w-14 overflow-hidden border border-border rounded-md",
|
|
6525
|
+
className
|
|
6526
|
+
),
|
|
6527
|
+
children: [
|
|
6528
|
+
/* @__PURE__ */ jsx("div", { className: "bg-foreground text-background text-[10px] font-bold text-center py-1.5 uppercase tracking-wider", children: format(date, "MMM") }),
|
|
6529
|
+
/* @__PURE__ */ jsx("div", { className: "bg-background text-foreground text-2xl font-bold text-center py-2.5", children: format(date, "d") })
|
|
6530
|
+
]
|
|
6531
|
+
}
|
|
6532
|
+
);
|
|
6533
|
+
}
|
|
6534
|
+
var DragContext = React14.createContext(null);
|
|
6535
|
+
function DragProvider({
|
|
6536
|
+
children,
|
|
6537
|
+
snapMinutes = 15,
|
|
6538
|
+
onDragStart,
|
|
6539
|
+
onDragEnd
|
|
6540
|
+
}) {
|
|
6541
|
+
const [draggedEvent, setDraggedEventState] = React14.useState(null);
|
|
6542
|
+
const [isDragging, setIsDragging] = React14.useState(false);
|
|
6543
|
+
const { updateEvent } = useEventCalendar();
|
|
6544
|
+
const setDraggedEvent = React14.useCallback((event) => {
|
|
6545
|
+
setDraggedEventState(event);
|
|
6546
|
+
setIsDragging(!!event);
|
|
6547
|
+
if (event) {
|
|
6548
|
+
onDragStart?.(event);
|
|
6549
|
+
}
|
|
6550
|
+
}, [onDragStart]);
|
|
6551
|
+
const handleDrop = React14.useCallback((newStartDate) => {
|
|
6552
|
+
if (!draggedEvent) return;
|
|
6553
|
+
const snappedDate = snapToInterval(newStartDate, snapMinutes);
|
|
6554
|
+
const { startDate, endDate } = calculateDropDates(draggedEvent, snappedDate);
|
|
6555
|
+
const updatedEvent = {
|
|
6556
|
+
...draggedEvent,
|
|
6557
|
+
startDate,
|
|
6558
|
+
endDate
|
|
6559
|
+
};
|
|
6560
|
+
updateEvent(updatedEvent);
|
|
6561
|
+
onDragEnd?.(updatedEvent, new Date(startDate), new Date(endDate));
|
|
6562
|
+
setDraggedEvent(null);
|
|
6563
|
+
}, [draggedEvent, snapMinutes, updateEvent, onDragEnd, setDraggedEvent]);
|
|
6564
|
+
const contextValue = React14.useMemo(
|
|
6565
|
+
() => ({
|
|
6566
|
+
draggedEvent,
|
|
6567
|
+
setDraggedEvent,
|
|
6568
|
+
isDragging
|
|
6569
|
+
}),
|
|
6570
|
+
[draggedEvent, setDraggedEvent, isDragging]
|
|
6571
|
+
);
|
|
6572
|
+
return /* @__PURE__ */ jsx(DragContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(DragDropHandler, { onDrop: handleDrop, children }) });
|
|
6573
|
+
}
|
|
6574
|
+
function useDrag() {
|
|
6575
|
+
const context = React14.useContext(DragContext);
|
|
6576
|
+
if (!context) {
|
|
6577
|
+
throw new Error("useDrag must be used within a DragProvider");
|
|
6578
|
+
}
|
|
6579
|
+
return context;
|
|
6580
|
+
}
|
|
6581
|
+
function DragDropHandler({ children, onDrop }) {
|
|
6582
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
6583
|
+
}
|
|
6584
|
+
function DraggableEvent({
|
|
6585
|
+
event,
|
|
6586
|
+
children,
|
|
6587
|
+
disabled = false
|
|
6588
|
+
}) {
|
|
6589
|
+
const { setDraggedEvent, isDragging, draggedEvent } = useDrag();
|
|
6590
|
+
const isDragged = draggedEvent?.id === event.id;
|
|
6591
|
+
const handleDragStart = (e) => {
|
|
6592
|
+
if (disabled) return;
|
|
6593
|
+
e.dataTransfer.effectAllowed = "move";
|
|
6594
|
+
e.dataTransfer.setData("text/plain", event.id);
|
|
6595
|
+
setDraggedEvent(event);
|
|
6596
|
+
};
|
|
6597
|
+
const handleDragEnd = () => {
|
|
6598
|
+
setDraggedEvent(null);
|
|
6599
|
+
};
|
|
6600
|
+
return /* @__PURE__ */ jsx(
|
|
6601
|
+
"div",
|
|
6602
|
+
{
|
|
6603
|
+
draggable: !disabled,
|
|
6604
|
+
onDragStart: handleDragStart,
|
|
6605
|
+
onDragEnd: handleDragEnd,
|
|
6606
|
+
className: isDragged ? "opacity-50" : "",
|
|
6607
|
+
style: { cursor: disabled ? "default" : "grab" },
|
|
6608
|
+
children
|
|
6609
|
+
}
|
|
6610
|
+
);
|
|
6611
|
+
}
|
|
6612
|
+
function DroppableZone({
|
|
6613
|
+
date,
|
|
6614
|
+
children,
|
|
6615
|
+
onDrop,
|
|
6616
|
+
className
|
|
6617
|
+
}) {
|
|
6618
|
+
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6619
|
+
const { updateEvent } = useEventCalendar();
|
|
6620
|
+
const [isOver, setIsOver] = React14.useState(false);
|
|
6621
|
+
const handleDragOver = (e) => {
|
|
6622
|
+
e.preventDefault();
|
|
6623
|
+
e.dataTransfer.dropEffect = "move";
|
|
6624
|
+
setIsOver(true);
|
|
6625
|
+
};
|
|
6626
|
+
const handleDragLeave = () => {
|
|
6627
|
+
setIsOver(false);
|
|
6628
|
+
};
|
|
6629
|
+
const handleDrop = (e) => {
|
|
6630
|
+
e.preventDefault();
|
|
6631
|
+
setIsOver(false);
|
|
6632
|
+
if (!draggedEvent) return;
|
|
6633
|
+
const { startDate, endDate } = calculateDropDates(draggedEvent, date);
|
|
6634
|
+
const updatedEvent = {
|
|
6635
|
+
...draggedEvent,
|
|
6636
|
+
startDate,
|
|
6637
|
+
endDate
|
|
6638
|
+
};
|
|
6639
|
+
updateEvent(updatedEvent);
|
|
6640
|
+
onDrop?.(updatedEvent, date);
|
|
6641
|
+
setDraggedEvent(null);
|
|
6642
|
+
};
|
|
6643
|
+
return /* @__PURE__ */ jsx(
|
|
6644
|
+
"div",
|
|
6645
|
+
{
|
|
6646
|
+
onDragOver: handleDragOver,
|
|
6647
|
+
onDragLeave: handleDragLeave,
|
|
6648
|
+
onDrop: handleDrop,
|
|
6649
|
+
className,
|
|
6650
|
+
"data-drag-over": isOver,
|
|
6651
|
+
children
|
|
6652
|
+
}
|
|
6653
|
+
);
|
|
6654
|
+
}
|
|
6655
|
+
function useDroppable({ date, hour, minute = 0, onDrop }) {
|
|
6656
|
+
const { draggedEvent, setDraggedEvent } = useDrag();
|
|
6657
|
+
const { updateEvent } = useEventCalendar();
|
|
6658
|
+
const [isOver, setIsOver] = React14.useState(false);
|
|
6659
|
+
const dropTargetDate = React14.useMemo(() => {
|
|
6660
|
+
const targetDate = new Date(date);
|
|
6661
|
+
if (hour !== void 0) {
|
|
6662
|
+
targetDate.setHours(hour, minute, 0, 0);
|
|
6663
|
+
}
|
|
6664
|
+
return targetDate;
|
|
6665
|
+
}, [date, hour, minute]);
|
|
6666
|
+
const handleDragOver = React14.useCallback((e) => {
|
|
6667
|
+
e.preventDefault();
|
|
6668
|
+
e.dataTransfer.dropEffect = "move";
|
|
6669
|
+
if (!isOver) setIsOver(true);
|
|
6670
|
+
}, [isOver]);
|
|
6671
|
+
const handleDragLeave = React14.useCallback(() => {
|
|
6672
|
+
setIsOver(false);
|
|
6673
|
+
}, []);
|
|
6674
|
+
const handleDrop = React14.useCallback((e) => {
|
|
6675
|
+
e.preventDefault();
|
|
6676
|
+
setIsOver(false);
|
|
6677
|
+
if (!draggedEvent) return;
|
|
6678
|
+
const { startDate, endDate } = calculateDropDates(draggedEvent, dropTargetDate);
|
|
6679
|
+
const updatedEvent = {
|
|
6680
|
+
...draggedEvent,
|
|
6681
|
+
startDate,
|
|
6682
|
+
endDate
|
|
6683
|
+
};
|
|
6684
|
+
updateEvent(updatedEvent);
|
|
6685
|
+
onDrop?.(updatedEvent, dropTargetDate);
|
|
6686
|
+
setDraggedEvent(null);
|
|
6687
|
+
}, [draggedEvent, dropTargetDate, updateEvent, onDrop, setDraggedEvent]);
|
|
6688
|
+
return {
|
|
6689
|
+
isOver,
|
|
6690
|
+
dropProps: {
|
|
6691
|
+
onDragOver: handleDragOver,
|
|
6692
|
+
onDragLeave: handleDragLeave,
|
|
6693
|
+
onDrop: handleDrop,
|
|
6694
|
+
"data-drag-over": isOver
|
|
6695
|
+
}
|
|
6696
|
+
};
|
|
6697
|
+
}
|
|
6698
|
+
function useDraggable(event, disabled = false) {
|
|
6699
|
+
const { setDraggedEvent, draggedEvent } = useDrag();
|
|
6700
|
+
const isDragged = draggedEvent?.id === event.id;
|
|
6701
|
+
const handleDragStart = React14.useCallback((e) => {
|
|
6702
|
+
if (disabled) return;
|
|
6703
|
+
e.dataTransfer.effectAllowed = "move";
|
|
6704
|
+
e.dataTransfer.setData("text/plain", event.id);
|
|
6705
|
+
setDraggedEvent(event);
|
|
6706
|
+
}, [disabled, event, setDraggedEvent]);
|
|
6707
|
+
const handleDragEnd = React14.useCallback(() => {
|
|
6708
|
+
setDraggedEvent(null);
|
|
6709
|
+
}, [setDraggedEvent]);
|
|
6710
|
+
return {
|
|
6711
|
+
isDragged,
|
|
6712
|
+
dragProps: {
|
|
6713
|
+
draggable: !disabled,
|
|
6714
|
+
onDragStart: handleDragStart,
|
|
6715
|
+
onDragEnd: handleDragEnd,
|
|
6716
|
+
style: { cursor: disabled ? "default" : "grab" }
|
|
6717
|
+
}
|
|
6718
|
+
};
|
|
6719
|
+
}
|
|
6720
|
+
var WEEK_DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
6721
|
+
function DraggableEventWrapper({
|
|
6722
|
+
event,
|
|
6723
|
+
children
|
|
6724
|
+
}) {
|
|
6725
|
+
const { isDragged, dragProps } = useDraggable(event);
|
|
6726
|
+
return /* @__PURE__ */ jsx(
|
|
6727
|
+
"div",
|
|
6728
|
+
{
|
|
6729
|
+
...dragProps,
|
|
6730
|
+
className: cn(
|
|
6731
|
+
"transition-opacity",
|
|
6732
|
+
isDragged && "opacity-50"
|
|
6733
|
+
),
|
|
6734
|
+
children
|
|
6735
|
+
}
|
|
6736
|
+
);
|
|
6737
|
+
}
|
|
6738
|
+
function MonthView({
|
|
6739
|
+
className,
|
|
6740
|
+
maxEventsPerDay = 3,
|
|
6741
|
+
weekStartsOn = 0,
|
|
6742
|
+
onEventClick,
|
|
6743
|
+
onDateClick,
|
|
6744
|
+
onMoreClick
|
|
6745
|
+
}) {
|
|
6746
|
+
const { selectedDate, badgeVariant, setSelectedDate, setView } = useEventCalendar();
|
|
6747
|
+
const filteredEvents = useFilteredEvents();
|
|
6748
|
+
const { singleDayEvents, multiDayEvents } = React14.useMemo(
|
|
6749
|
+
() => splitEventsByDuration(filteredEvents),
|
|
6750
|
+
[filteredEvents]
|
|
6751
|
+
);
|
|
6752
|
+
const cells = React14.useMemo(
|
|
6753
|
+
() => getCalendarCells(selectedDate),
|
|
6754
|
+
[selectedDate]
|
|
6755
|
+
);
|
|
6756
|
+
const eventPositions = React14.useMemo(
|
|
6757
|
+
() => calculateMonthEventPositions(multiDayEvents, singleDayEvents, selectedDate),
|
|
6758
|
+
[multiDayEvents, singleDayEvents, selectedDate]
|
|
6759
|
+
);
|
|
6760
|
+
const allEvents = [...multiDayEvents, ...singleDayEvents];
|
|
6761
|
+
const handleDateClick = (date) => {
|
|
6762
|
+
setSelectedDate(date);
|
|
6763
|
+
setView("day");
|
|
6764
|
+
onDateClick?.(date);
|
|
6765
|
+
};
|
|
6766
|
+
const handleMoreClick = (date, events) => {
|
|
6767
|
+
setSelectedDate(date);
|
|
6768
|
+
setView("day");
|
|
6769
|
+
onMoreClick?.(date, events);
|
|
6770
|
+
};
|
|
6771
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("", className), children: [
|
|
6772
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 divide-x divide-border/50", children: WEEK_DAYS.map((day) => /* @__PURE__ */ jsx(
|
|
6773
|
+
"div",
|
|
6774
|
+
{
|
|
6775
|
+
className: "flex items-center justify-center py-2",
|
|
6776
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-muted-foreground", children: day })
|
|
6777
|
+
},
|
|
6778
|
+
day
|
|
6779
|
+
)) }),
|
|
6780
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 overflow-hidden", children: cells.map((cell) => /* @__PURE__ */ jsx(
|
|
6781
|
+
DayCell,
|
|
6782
|
+
{
|
|
6783
|
+
cell,
|
|
6784
|
+
events: allEvents,
|
|
6785
|
+
eventPositions,
|
|
6786
|
+
selectedDate,
|
|
6787
|
+
badgeVariant,
|
|
6788
|
+
maxEvents: maxEventsPerDay,
|
|
6789
|
+
onDateClick: handleDateClick,
|
|
6790
|
+
onEventClick,
|
|
6791
|
+
onMoreClick: handleMoreClick
|
|
6792
|
+
},
|
|
6793
|
+
cell.date.toISOString()
|
|
6794
|
+
)) })
|
|
6795
|
+
] });
|
|
6796
|
+
}
|
|
6797
|
+
function DayCell({
|
|
6798
|
+
cell,
|
|
6799
|
+
events,
|
|
6800
|
+
eventPositions,
|
|
6801
|
+
selectedDate,
|
|
6802
|
+
badgeVariant,
|
|
6803
|
+
maxEvents,
|
|
6804
|
+
onDateClick,
|
|
6805
|
+
onEventClick,
|
|
6806
|
+
onMoreClick
|
|
6807
|
+
}) {
|
|
6808
|
+
const { date, currentMonth } = cell;
|
|
6809
|
+
const isCurrentDay = isToday(date);
|
|
6810
|
+
const isSelectedDay = isSameDay(date, selectedDate);
|
|
6811
|
+
const { isOver, dropProps } = useDroppable({ date });
|
|
6812
|
+
const cellEvents = getMonthCellEvents(date, events, eventPositions);
|
|
6813
|
+
const positionedEvents = cellEvents.filter((e) => e.position !== -1);
|
|
6814
|
+
const hiddenEvents = cellEvents.filter((e) => e.position === -1);
|
|
6815
|
+
const slots = [null, null, null];
|
|
6816
|
+
positionedEvents.forEach((event) => {
|
|
6817
|
+
if (event.position >= 0 && event.position < 3) {
|
|
6818
|
+
slots[event.position] = event;
|
|
6819
|
+
}
|
|
6820
|
+
});
|
|
6821
|
+
const hiddenCount = hiddenEvents.length + positionedEvents.filter((e) => e.position >= 3).length;
|
|
6822
|
+
const isEventStart = (event) => isSameDay(parseISO(event.startDate), date);
|
|
6823
|
+
return /* @__PURE__ */ jsxs(
|
|
6824
|
+
"div",
|
|
6825
|
+
{
|
|
6826
|
+
...dropProps,
|
|
6827
|
+
className: cn(
|
|
6828
|
+
"relative min-h-[120px] border-b border-r border-border/50 p-1 transition-colors",
|
|
6829
|
+
!currentMonth && "bg-muted/30",
|
|
6830
|
+
isOver && "bg-primary/10 ring-2 ring-primary/50 ring-inset"
|
|
6831
|
+
),
|
|
6832
|
+
children: [
|
|
6833
|
+
/* @__PURE__ */ jsx(
|
|
6834
|
+
"button",
|
|
6835
|
+
{
|
|
6836
|
+
type: "button",
|
|
6837
|
+
onClick: () => onDateClick(date),
|
|
6838
|
+
className: cn(
|
|
6839
|
+
"mb-1 flex size-7 items-center justify-center text-sm transition-colors",
|
|
6840
|
+
"hover:bg-muted rounded-sm",
|
|
6841
|
+
isCurrentDay && "bg-primary text-primary-foreground hover:bg-primary/90 rounded-sm",
|
|
6842
|
+
isSelectedDay && !isCurrentDay && "bg-muted font-semibold rounded-sm",
|
|
6843
|
+
!currentMonth && "text-muted-foreground"
|
|
6844
|
+
),
|
|
6845
|
+
children: cell.day
|
|
6846
|
+
}
|
|
6847
|
+
),
|
|
6848
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
6849
|
+
slots.map((event, index) => {
|
|
6850
|
+
if (!event) {
|
|
6851
|
+
return /* @__PURE__ */ jsx("div", { className: "h-5" }, `empty-${index}`);
|
|
6852
|
+
}
|
|
6853
|
+
const showTitle = isEventStart(event) || startOfDay(date).getDay() === 0;
|
|
6854
|
+
return /* @__PURE__ */ jsx(DraggableEventWrapper, { event, children: /* @__PURE__ */ jsx(
|
|
6855
|
+
EventBadge,
|
|
6856
|
+
{
|
|
6857
|
+
event,
|
|
6858
|
+
variant: badgeVariant,
|
|
6859
|
+
compact: true,
|
|
6860
|
+
showTime: showTitle,
|
|
6861
|
+
onClick: (e) => onEventClick?.(e),
|
|
6862
|
+
className: cn(
|
|
6863
|
+
"w-full",
|
|
6864
|
+
// If not showing title, make it appear as a continuation
|
|
6865
|
+
!showTitle && "rounded-l-none border-l-0"
|
|
6866
|
+
)
|
|
6867
|
+
}
|
|
6868
|
+
) }, event.id);
|
|
6869
|
+
}),
|
|
6870
|
+
hiddenCount > 0 && /* @__PURE__ */ jsx(
|
|
6871
|
+
MoreEvents,
|
|
6872
|
+
{
|
|
6873
|
+
count: hiddenCount,
|
|
6874
|
+
onClick: () => onMoreClick(date, cellEvents)
|
|
6875
|
+
}
|
|
6876
|
+
)
|
|
6877
|
+
] })
|
|
6878
|
+
]
|
|
6879
|
+
}
|
|
6880
|
+
);
|
|
6881
|
+
}
|
|
6882
|
+
function DraggableEventWrapper2({
|
|
6883
|
+
event,
|
|
6884
|
+
children,
|
|
6885
|
+
className,
|
|
6886
|
+
style
|
|
6887
|
+
}) {
|
|
6888
|
+
const { isDragged, dragProps } = useDraggable(event);
|
|
6889
|
+
return /* @__PURE__ */ jsx(
|
|
6890
|
+
"div",
|
|
6891
|
+
{
|
|
6892
|
+
...dragProps,
|
|
6893
|
+
className: cn(
|
|
6894
|
+
className,
|
|
6895
|
+
"transition-opacity",
|
|
6896
|
+
isDragged && "opacity-50"
|
|
6897
|
+
),
|
|
6898
|
+
style,
|
|
6899
|
+
children
|
|
6900
|
+
}
|
|
6901
|
+
);
|
|
6902
|
+
}
|
|
6903
|
+
function DroppableTimeSlot({
|
|
6904
|
+
date,
|
|
6905
|
+
hour,
|
|
6906
|
+
minute,
|
|
6907
|
+
className,
|
|
6908
|
+
onClick
|
|
6909
|
+
}) {
|
|
6910
|
+
const { isOver, dropProps } = useDroppable({ date, hour, minute });
|
|
6911
|
+
return /* @__PURE__ */ jsx(
|
|
6912
|
+
"div",
|
|
6913
|
+
{
|
|
6914
|
+
...dropProps,
|
|
6915
|
+
onClick,
|
|
6916
|
+
className: cn(
|
|
6917
|
+
className,
|
|
6918
|
+
"cursor-pointer transition-colors hover:bg-accent",
|
|
6919
|
+
isOver && "bg-primary/20"
|
|
6920
|
+
)
|
|
6921
|
+
}
|
|
6922
|
+
);
|
|
6923
|
+
}
|
|
6924
|
+
function WeekView({
|
|
6925
|
+
className,
|
|
6926
|
+
weekStartsOn = 0,
|
|
6927
|
+
onEventClick,
|
|
6928
|
+
onDateClick,
|
|
6929
|
+
onTimeClick
|
|
6930
|
+
}) {
|
|
6931
|
+
const {
|
|
6932
|
+
selectedDate,
|
|
6933
|
+
badgeVariant,
|
|
6934
|
+
workingHours,
|
|
6935
|
+
visibleHours
|
|
6936
|
+
} = useEventCalendar();
|
|
6937
|
+
const filteredEvents = useFilteredEvents();
|
|
6938
|
+
const { singleDayEvents, multiDayEvents } = React14.useMemo(
|
|
6939
|
+
() => splitEventsByDuration(filteredEvents),
|
|
6940
|
+
[filteredEvents]
|
|
6941
|
+
);
|
|
6942
|
+
const { hours, earliestEventHour, latestEventHour } = getVisibleHours(
|
|
6943
|
+
visibleHours,
|
|
6944
|
+
singleDayEvents
|
|
6945
|
+
);
|
|
6946
|
+
const weekStart = startOfWeek(selectedDate, { weekStartsOn });
|
|
6947
|
+
const weekDays = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
|
|
6948
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6949
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center border-b py-4 text-sm text-muted-foreground sm:hidden", children: [
|
|
6950
|
+
/* @__PURE__ */ jsx("p", { children: "Weekly view is not available on smaller devices." }),
|
|
6951
|
+
/* @__PURE__ */ jsx("p", { children: "Please switch to daily or monthly view." })
|
|
6952
|
+
] }),
|
|
6953
|
+
/* @__PURE__ */ jsxs("div", { className: cn("hidden flex-col sm:flex", className), children: [
|
|
6954
|
+
/* @__PURE__ */ jsx(
|
|
6955
|
+
WeekViewMultiDayEventsRow,
|
|
6956
|
+
{
|
|
6957
|
+
selectedDate,
|
|
6958
|
+
multiDayEvents
|
|
6959
|
+
}
|
|
6960
|
+
),
|
|
6961
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-20 flex border-b border-border/50", children: [
|
|
6962
|
+
/* @__PURE__ */ jsx("div", { className: "w-18" }),
|
|
6963
|
+
/* @__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(
|
|
6964
|
+
"span",
|
|
6965
|
+
{
|
|
6966
|
+
className: "py-2 text-center text-xs font-medium text-muted-foreground",
|
|
6967
|
+
children: [
|
|
6968
|
+
format(day, "EE"),
|
|
6969
|
+
" ",
|
|
6970
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1 font-semibold text-foreground", children: format(day, "d") })
|
|
6971
|
+
]
|
|
6972
|
+
},
|
|
6973
|
+
index
|
|
6974
|
+
)) })
|
|
6975
|
+
] }),
|
|
6976
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "h-[736px]", type: "always", children: /* @__PURE__ */ jsxs("div", { className: "flex overflow-hidden", children: [
|
|
6977
|
+
/* @__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)) }),
|
|
6978
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 border-l border-border/50", children: [
|
|
6979
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 divide-x divide-border/50", children: weekDays.map((day, dayIndex) => {
|
|
6980
|
+
const dayEvents = singleDayEvents.filter(
|
|
6981
|
+
(event) => isSameDay(parseISO(event.startDate), day) || isSameDay(parseISO(event.endDate), day)
|
|
6982
|
+
);
|
|
6983
|
+
const groupedEvents = groupEvents(dayEvents);
|
|
6984
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
6985
|
+
hours.map((hour, index) => {
|
|
6986
|
+
const isDisabled = !isWorkingHour(day, hour, workingHours);
|
|
6987
|
+
return /* @__PURE__ */ jsxs(
|
|
6988
|
+
"div",
|
|
6989
|
+
{
|
|
6990
|
+
className: cn(
|
|
6991
|
+
"relative",
|
|
6992
|
+
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)]"
|
|
6993
|
+
),
|
|
6994
|
+
style: { height: "96px" },
|
|
6995
|
+
children: [
|
|
6996
|
+
index !== 0 && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 border-b border-border/40" }),
|
|
6997
|
+
/* @__PURE__ */ jsx(
|
|
6998
|
+
DroppableTimeSlot,
|
|
6999
|
+
{
|
|
7000
|
+
date: day,
|
|
7001
|
+
hour,
|
|
7002
|
+
minute: 0,
|
|
7003
|
+
className: "absolute inset-x-0 top-0 h-[24px]",
|
|
7004
|
+
onClick: () => onTimeClick?.(day, hour, 0)
|
|
7005
|
+
}
|
|
7006
|
+
),
|
|
7007
|
+
/* @__PURE__ */ jsx(
|
|
7008
|
+
DroppableTimeSlot,
|
|
7009
|
+
{
|
|
7010
|
+
date: day,
|
|
7011
|
+
hour,
|
|
7012
|
+
minute: 15,
|
|
7013
|
+
className: "absolute inset-x-0 top-[24px] h-[24px]",
|
|
7014
|
+
onClick: () => onTimeClick?.(day, hour, 15)
|
|
7015
|
+
}
|
|
7016
|
+
),
|
|
7017
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-1/2 border-b border-dashed border-border/30" }),
|
|
7018
|
+
/* @__PURE__ */ jsx(
|
|
7019
|
+
DroppableTimeSlot,
|
|
7020
|
+
{
|
|
7021
|
+
date: day,
|
|
7022
|
+
hour,
|
|
7023
|
+
minute: 30,
|
|
7024
|
+
className: "absolute inset-x-0 top-[48px] h-[24px]",
|
|
7025
|
+
onClick: () => onTimeClick?.(day, hour, 30)
|
|
7026
|
+
}
|
|
7027
|
+
),
|
|
7028
|
+
/* @__PURE__ */ jsx(
|
|
7029
|
+
DroppableTimeSlot,
|
|
7030
|
+
{
|
|
7031
|
+
date: day,
|
|
7032
|
+
hour,
|
|
7033
|
+
minute: 45,
|
|
7034
|
+
className: "absolute inset-x-0 top-[72px] h-[24px]",
|
|
7035
|
+
onClick: () => onTimeClick?.(day, hour, 45)
|
|
7036
|
+
}
|
|
7037
|
+
)
|
|
7038
|
+
]
|
|
7039
|
+
},
|
|
7040
|
+
hour
|
|
7041
|
+
);
|
|
7042
|
+
}),
|
|
7043
|
+
groupedEvents.map(
|
|
7044
|
+
(group, groupIndex) => group.map((event) => {
|
|
7045
|
+
let style = getEventBlockStyle(
|
|
7046
|
+
event,
|
|
7047
|
+
day,
|
|
7048
|
+
groupIndex,
|
|
7049
|
+
groupedEvents.length,
|
|
7050
|
+
{ from: earliestEventHour}
|
|
7051
|
+
);
|
|
7052
|
+
const hasOverlap = groupedEvents.some(
|
|
7053
|
+
(otherGroup, otherIndex) => otherIndex !== groupIndex && otherGroup.some(
|
|
7054
|
+
(otherEvent) => areIntervalsOverlapping(
|
|
7055
|
+
{
|
|
7056
|
+
start: parseISO(event.startDate),
|
|
7057
|
+
end: parseISO(event.endDate)
|
|
7058
|
+
},
|
|
7059
|
+
{
|
|
7060
|
+
start: parseISO(otherEvent.startDate),
|
|
7061
|
+
end: parseISO(otherEvent.endDate)
|
|
7062
|
+
}
|
|
7063
|
+
)
|
|
7064
|
+
)
|
|
7065
|
+
);
|
|
7066
|
+
if (!hasOverlap) {
|
|
7067
|
+
style = { ...style, width: "100%", left: "0%" };
|
|
7068
|
+
}
|
|
7069
|
+
return /* @__PURE__ */ jsx(
|
|
7070
|
+
DraggableEventWrapper2,
|
|
7071
|
+
{
|
|
7072
|
+
event,
|
|
7073
|
+
className: "absolute px-0.5 py-0.5",
|
|
7074
|
+
style,
|
|
7075
|
+
children: /* @__PURE__ */ jsx(
|
|
7076
|
+
EventBadge,
|
|
7077
|
+
{
|
|
7078
|
+
event,
|
|
7079
|
+
variant: badgeVariant,
|
|
7080
|
+
showTime: true,
|
|
7081
|
+
onClick: (e) => onEventClick?.(e),
|
|
7082
|
+
className: "h-full w-full"
|
|
7083
|
+
}
|
|
7084
|
+
)
|
|
7085
|
+
},
|
|
7086
|
+
event.id
|
|
7087
|
+
);
|
|
7088
|
+
})
|
|
7089
|
+
)
|
|
7090
|
+
] }, dayIndex);
|
|
7091
|
+
}) }),
|
|
7092
|
+
weekDays.some((day) => isToday(day)) && /* @__PURE__ */ jsx(
|
|
7093
|
+
CalendarTimeline,
|
|
7094
|
+
{
|
|
7095
|
+
firstVisibleHour: earliestEventHour,
|
|
7096
|
+
lastVisibleHour: latestEventHour
|
|
7097
|
+
}
|
|
7098
|
+
)
|
|
7099
|
+
] })
|
|
7100
|
+
] }) })
|
|
7101
|
+
] })
|
|
7102
|
+
] });
|
|
7103
|
+
}
|
|
7104
|
+
function WeekViewMultiDayEventsRow({
|
|
7105
|
+
selectedDate,
|
|
7106
|
+
multiDayEvents
|
|
7107
|
+
}) {
|
|
7108
|
+
const { badgeVariant } = useEventCalendar();
|
|
7109
|
+
if (multiDayEvents.length === 0) return null;
|
|
7110
|
+
const weekStart = startOfWeek(selectedDate);
|
|
7111
|
+
const weekDays = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i));
|
|
7112
|
+
return /* @__PURE__ */ jsxs("div", { className: "hidden border-b sm:flex", children: [
|
|
7113
|
+
/* @__PURE__ */ jsx("div", { className: "w-18 shrink-0" }),
|
|
7114
|
+
/* @__PURE__ */ jsx("div", { className: "grid flex-1 grid-cols-7 divide-x border-l", children: weekDays.map((day, index) => {
|
|
7115
|
+
const dayMultiEvents = multiDayEvents.filter((event) => {
|
|
7116
|
+
const start = parseISO(event.startDate);
|
|
7117
|
+
const end = parseISO(event.endDate);
|
|
7118
|
+
return day >= start && day <= end;
|
|
7119
|
+
});
|
|
7120
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-h-[32px] space-y-1 p-1", children: [
|
|
7121
|
+
dayMultiEvents.slice(0, 2).map((event) => /* @__PURE__ */ jsx(
|
|
7122
|
+
EventBadge,
|
|
7123
|
+
{
|
|
7124
|
+
event,
|
|
7125
|
+
variant: badgeVariant,
|
|
7126
|
+
compact: true,
|
|
7127
|
+
className: "w-full"
|
|
7128
|
+
},
|
|
7129
|
+
event.id
|
|
7130
|
+
)),
|
|
7131
|
+
dayMultiEvents.length > 2 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground text-center", children: [
|
|
7132
|
+
"+",
|
|
7133
|
+
dayMultiEvents.length - 2,
|
|
7134
|
+
" more"
|
|
7135
|
+
] })
|
|
7136
|
+
] }, index);
|
|
7137
|
+
}) })
|
|
7138
|
+
] });
|
|
7139
|
+
}
|
|
7140
|
+
function CalendarTimeline({
|
|
7141
|
+
firstVisibleHour,
|
|
7142
|
+
lastVisibleHour
|
|
7143
|
+
}) {
|
|
7144
|
+
const [currentTime, setCurrentTime] = React14.useState(/* @__PURE__ */ new Date());
|
|
7145
|
+
React14.useEffect(() => {
|
|
7146
|
+
const interval = setInterval(() => {
|
|
7147
|
+
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7148
|
+
}, 6e4);
|
|
7149
|
+
return () => clearInterval(interval);
|
|
7150
|
+
}, []);
|
|
7151
|
+
const currentHour = currentTime.getHours();
|
|
7152
|
+
const currentMinute = currentTime.getMinutes();
|
|
7153
|
+
if (currentHour < firstVisibleHour || currentHour >= lastVisibleHour) {
|
|
7154
|
+
return null;
|
|
7155
|
+
}
|
|
7156
|
+
const minutesSinceStart = (currentHour - firstVisibleHour) * 60 + currentMinute;
|
|
7157
|
+
const totalMinutes = (lastVisibleHour - firstVisibleHour) * 60;
|
|
7158
|
+
const topPercent = minutesSinceStart / totalMinutes * 100;
|
|
7159
|
+
return /* @__PURE__ */ jsxs(
|
|
7160
|
+
"div",
|
|
7161
|
+
{
|
|
7162
|
+
className: "pointer-events-none absolute inset-x-0 z-30 flex items-center",
|
|
7163
|
+
style: { top: `${topPercent}%` },
|
|
7164
|
+
children: [
|
|
7165
|
+
/* @__PURE__ */ jsx("div", { className: "size-3 -translate-x-1/2 rounded-full bg-red-500" }),
|
|
7166
|
+
/* @__PURE__ */ jsx("div", { className: "h-0.5 flex-1 bg-red-500" })
|
|
7167
|
+
]
|
|
7168
|
+
}
|
|
7169
|
+
);
|
|
7170
|
+
}
|
|
7171
|
+
function DraggableEventWrapper3({
|
|
7172
|
+
event,
|
|
7173
|
+
children,
|
|
7174
|
+
className,
|
|
7175
|
+
style
|
|
7176
|
+
}) {
|
|
7177
|
+
const { isDragged, dragProps } = useDraggable(event);
|
|
7178
|
+
return /* @__PURE__ */ jsx(
|
|
7179
|
+
"div",
|
|
7180
|
+
{
|
|
7181
|
+
...dragProps,
|
|
7182
|
+
className: cn(
|
|
7183
|
+
className,
|
|
7184
|
+
"transition-opacity",
|
|
7185
|
+
isDragged && "opacity-50"
|
|
7186
|
+
),
|
|
7187
|
+
style,
|
|
7188
|
+
children
|
|
7189
|
+
}
|
|
7190
|
+
);
|
|
7191
|
+
}
|
|
7192
|
+
function DroppableTimeSlot2({
|
|
7193
|
+
date,
|
|
7194
|
+
hour,
|
|
7195
|
+
minute,
|
|
7196
|
+
className,
|
|
7197
|
+
onClick
|
|
7198
|
+
}) {
|
|
7199
|
+
const { isOver, dropProps } = useDroppable({ date, hour, minute });
|
|
7200
|
+
return /* @__PURE__ */ jsx(
|
|
7201
|
+
"div",
|
|
7202
|
+
{
|
|
7203
|
+
...dropProps,
|
|
7204
|
+
onClick,
|
|
7205
|
+
className: cn(
|
|
7206
|
+
className,
|
|
7207
|
+
"cursor-pointer transition-colors hover:bg-accent",
|
|
7208
|
+
isOver && "bg-primary/20"
|
|
7209
|
+
)
|
|
7210
|
+
}
|
|
7211
|
+
);
|
|
7212
|
+
}
|
|
7213
|
+
function DayView({
|
|
7214
|
+
className,
|
|
7215
|
+
showSidebar = true,
|
|
7216
|
+
onEventClick,
|
|
7217
|
+
onTimeClick
|
|
7218
|
+
}) {
|
|
7219
|
+
const {
|
|
7220
|
+
selectedDate,
|
|
7221
|
+
setSelectedDate,
|
|
7222
|
+
badgeVariant,
|
|
7223
|
+
users,
|
|
7224
|
+
workingHours,
|
|
7225
|
+
visibleHours
|
|
7226
|
+
} = useEventCalendar();
|
|
7227
|
+
const filteredEvents = useFilteredEvents();
|
|
7228
|
+
const { singleDayEvents, multiDayEvents } = React14.useMemo(
|
|
7229
|
+
() => splitEventsByDuration(filteredEvents),
|
|
7230
|
+
[filteredEvents]
|
|
7231
|
+
);
|
|
7232
|
+
const { hours, earliestEventHour, latestEventHour } = getVisibleHours(
|
|
7233
|
+
visibleHours,
|
|
7234
|
+
singleDayEvents
|
|
7235
|
+
);
|
|
7236
|
+
const currentEvents = React14.useMemo(() => {
|
|
7237
|
+
if (!isToday(selectedDate)) return [];
|
|
7238
|
+
return getCurrentEvents(singleDayEvents);
|
|
7239
|
+
}, [singleDayEvents, selectedDate]);
|
|
7240
|
+
const dayEvents = singleDayEvents.filter((event) => {
|
|
7241
|
+
const eventDate = parseISO(event.startDate);
|
|
7242
|
+
return eventDate.getDate() === selectedDate.getDate() && eventDate.getMonth() === selectedDate.getMonth() && eventDate.getFullYear() === selectedDate.getFullYear();
|
|
7243
|
+
});
|
|
7244
|
+
const groupedEvents = groupEvents(dayEvents);
|
|
7245
|
+
const handleDateSelect = (date) => {
|
|
7246
|
+
if (date) {
|
|
7247
|
+
setSelectedDate(date);
|
|
7248
|
+
}
|
|
7249
|
+
};
|
|
7250
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex", className), children: [
|
|
7251
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col", children: [
|
|
7252
|
+
multiDayEvents.length > 0 && /* @__PURE__ */ jsx(
|
|
7253
|
+
DayViewMultiDayEventsRow,
|
|
7254
|
+
{
|
|
7255
|
+
selectedDate,
|
|
7256
|
+
multiDayEvents
|
|
7257
|
+
}
|
|
7258
|
+
),
|
|
7259
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-20 flex border-b border-border/50", children: [
|
|
7260
|
+
/* @__PURE__ */ jsx("div", { className: "w-18" }),
|
|
7261
|
+
/* @__PURE__ */ jsxs("span", { className: "flex-1 border-l border-border/50 py-2 text-center text-xs font-medium text-muted-foreground", children: [
|
|
7262
|
+
format(selectedDate, "EE"),
|
|
7263
|
+
" ",
|
|
7264
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: format(selectedDate, "d") })
|
|
7265
|
+
] })
|
|
7266
|
+
] }),
|
|
7267
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "h-[800px]", type: "always", children: /* @__PURE__ */ jsxs("div", { className: "flex", children: [
|
|
7268
|
+
/* @__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)) }),
|
|
7269
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 border-l border-border/50", children: [
|
|
7270
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
7271
|
+
hours.map((hour, index) => {
|
|
7272
|
+
const isDisabled = !isWorkingHour(selectedDate, hour, workingHours);
|
|
7273
|
+
return /* @__PURE__ */ jsxs(
|
|
7274
|
+
"div",
|
|
7275
|
+
{
|
|
7276
|
+
className: cn(
|
|
7277
|
+
"relative",
|
|
7278
|
+
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)]"
|
|
7279
|
+
),
|
|
7280
|
+
style: { height: "96px" },
|
|
7281
|
+
children: [
|
|
7282
|
+
index !== 0 && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 border-b border-border/40" }),
|
|
7283
|
+
/* @__PURE__ */ jsx(
|
|
7284
|
+
DroppableTimeSlot2,
|
|
7285
|
+
{
|
|
7286
|
+
date: selectedDate,
|
|
7287
|
+
hour,
|
|
7288
|
+
minute: 0,
|
|
7289
|
+
className: "absolute inset-x-0 top-0 h-[24px]",
|
|
7290
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 0)
|
|
7291
|
+
}
|
|
7292
|
+
),
|
|
7293
|
+
/* @__PURE__ */ jsx(
|
|
7294
|
+
DroppableTimeSlot2,
|
|
7295
|
+
{
|
|
7296
|
+
date: selectedDate,
|
|
7297
|
+
hour,
|
|
7298
|
+
minute: 15,
|
|
7299
|
+
className: "absolute inset-x-0 top-[24px] h-[24px]",
|
|
7300
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 15)
|
|
7301
|
+
}
|
|
7302
|
+
),
|
|
7303
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-1/2 border-b border-dashed border-border/30" }),
|
|
7304
|
+
/* @__PURE__ */ jsx(
|
|
7305
|
+
DroppableTimeSlot2,
|
|
7306
|
+
{
|
|
7307
|
+
date: selectedDate,
|
|
7308
|
+
hour,
|
|
7309
|
+
minute: 30,
|
|
7310
|
+
className: "absolute inset-x-0 top-[48px] h-[24px]",
|
|
7311
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 30)
|
|
7312
|
+
}
|
|
7313
|
+
),
|
|
7314
|
+
/* @__PURE__ */ jsx(
|
|
7315
|
+
DroppableTimeSlot2,
|
|
7316
|
+
{
|
|
7317
|
+
date: selectedDate,
|
|
7318
|
+
hour,
|
|
7319
|
+
minute: 45,
|
|
7320
|
+
className: "absolute inset-x-0 top-[72px] h-[24px]",
|
|
7321
|
+
onClick: () => onTimeClick?.(selectedDate, hour, 45)
|
|
7322
|
+
}
|
|
7323
|
+
)
|
|
7324
|
+
]
|
|
7325
|
+
},
|
|
7326
|
+
hour
|
|
7327
|
+
);
|
|
7328
|
+
}),
|
|
7329
|
+
groupedEvents.map(
|
|
7330
|
+
(group, groupIndex) => group.map((event) => {
|
|
7331
|
+
let style = getEventBlockStyle(
|
|
7332
|
+
event,
|
|
7333
|
+
selectedDate,
|
|
7334
|
+
groupIndex,
|
|
7335
|
+
groupedEvents.length,
|
|
7336
|
+
{ from: earliestEventHour}
|
|
7337
|
+
);
|
|
7338
|
+
const hasOverlap = groupedEvents.some(
|
|
7339
|
+
(otherGroup, otherIndex) => otherIndex !== groupIndex && otherGroup.some(
|
|
7340
|
+
(otherEvent) => areIntervalsOverlapping(
|
|
7341
|
+
{
|
|
7342
|
+
start: parseISO(event.startDate),
|
|
7343
|
+
end: parseISO(event.endDate)
|
|
7344
|
+
},
|
|
7345
|
+
{
|
|
7346
|
+
start: parseISO(otherEvent.startDate),
|
|
7347
|
+
end: parseISO(otherEvent.endDate)
|
|
7348
|
+
}
|
|
7349
|
+
)
|
|
7350
|
+
)
|
|
7351
|
+
);
|
|
7352
|
+
if (!hasOverlap) {
|
|
7353
|
+
style = { ...style, width: "100%", left: "0%" };
|
|
7354
|
+
}
|
|
7355
|
+
return /* @__PURE__ */ jsx(
|
|
7356
|
+
DraggableEventWrapper3,
|
|
7357
|
+
{
|
|
7358
|
+
event,
|
|
7359
|
+
className: "absolute px-1 py-0.5",
|
|
7360
|
+
style,
|
|
7361
|
+
children: /* @__PURE__ */ jsx(
|
|
7362
|
+
EventBadge,
|
|
7363
|
+
{
|
|
7364
|
+
event,
|
|
7365
|
+
variant: badgeVariant,
|
|
7366
|
+
showTime: true,
|
|
7367
|
+
onClick: (e) => onEventClick?.(e),
|
|
7368
|
+
className: "h-full w-full"
|
|
7369
|
+
}
|
|
7370
|
+
)
|
|
7371
|
+
},
|
|
7372
|
+
event.id
|
|
7373
|
+
);
|
|
7374
|
+
})
|
|
7375
|
+
)
|
|
7376
|
+
] }),
|
|
7377
|
+
isToday(selectedDate) && /* @__PURE__ */ jsx(
|
|
7378
|
+
CalendarTimeline2,
|
|
7379
|
+
{
|
|
7380
|
+
firstVisibleHour: earliestEventHour,
|
|
7381
|
+
lastVisibleHour: latestEventHour
|
|
7382
|
+
}
|
|
7383
|
+
)
|
|
7384
|
+
] })
|
|
7385
|
+
] }) })
|
|
7386
|
+
] }),
|
|
7387
|
+
showSidebar && /* @__PURE__ */ jsxs("div", { className: "hidden w-64 divide-y border-l md:block", children: [
|
|
7388
|
+
/* @__PURE__ */ jsx(
|
|
7389
|
+
Calendar,
|
|
7390
|
+
{
|
|
7391
|
+
className: "mx-auto w-fit",
|
|
7392
|
+
mode: "single",
|
|
7393
|
+
selected: selectedDate,
|
|
7394
|
+
onSelect: handleDateSelect
|
|
7395
|
+
}
|
|
7396
|
+
),
|
|
7397
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-3", children: [
|
|
7398
|
+
currentEvents.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 px-4 pt-4", children: [
|
|
7399
|
+
/* @__PURE__ */ jsxs("span", { className: "relative mt-[5px] flex size-2.5", children: [
|
|
7400
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-full animate-ping rounded-full bg-green-400 opacity-75" }),
|
|
7401
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex size-2.5 rounded-full bg-green-600" })
|
|
7402
|
+
] }),
|
|
7403
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-foreground", children: "Happening now" })
|
|
7404
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "p-4 text-center text-sm italic text-muted-foreground", children: "No appointments or consultations at the moment" }),
|
|
7405
|
+
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) => {
|
|
7406
|
+
const user = users.find((u) => u.id === event.user.id);
|
|
7407
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
7408
|
+
/* @__PURE__ */ jsx("p", { className: "line-clamp-2 text-sm font-semibold", children: event.title }),
|
|
7409
|
+
user && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
7410
|
+
/* @__PURE__ */ jsx(User, { className: "size-3.5" }),
|
|
7411
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: user.name })
|
|
7412
|
+
] }),
|
|
7413
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
7414
|
+
/* @__PURE__ */ jsx(Calendar$1, { className: "size-3.5" }),
|
|
7415
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: format(/* @__PURE__ */ new Date(), "MMM d, yyyy") })
|
|
7416
|
+
] }),
|
|
7417
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
7418
|
+
/* @__PURE__ */ jsx(Clock, { className: "size-3.5" }),
|
|
7419
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm", children: [
|
|
7420
|
+
format(parseISO(event.startDate), "h:mm a"),
|
|
7421
|
+
" -",
|
|
7422
|
+
" ",
|
|
7423
|
+
format(parseISO(event.endDate), "h:mm a")
|
|
7424
|
+
] })
|
|
7425
|
+
] })
|
|
7426
|
+
] }, event.id);
|
|
7427
|
+
}) }) })
|
|
7428
|
+
] })
|
|
7429
|
+
] })
|
|
7430
|
+
] });
|
|
7431
|
+
}
|
|
7432
|
+
function DayViewMultiDayEventsRow({
|
|
7433
|
+
selectedDate,
|
|
7434
|
+
multiDayEvents
|
|
7435
|
+
}) {
|
|
7436
|
+
const { badgeVariant } = useEventCalendar();
|
|
7437
|
+
const relevantEvents = multiDayEvents.filter((event) => {
|
|
7438
|
+
const start = parseISO(event.startDate);
|
|
7439
|
+
const end = parseISO(event.endDate);
|
|
7440
|
+
return selectedDate >= start && selectedDate <= end;
|
|
7441
|
+
});
|
|
7442
|
+
if (relevantEvents.length === 0) return null;
|
|
7443
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex border-b", children: [
|
|
7444
|
+
/* @__PURE__ */ jsx("div", { className: "w-18 shrink-0" }),
|
|
7445
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 space-y-1 border-l p-2", children: relevantEvents.map((event) => /* @__PURE__ */ jsx(
|
|
7446
|
+
EventBadge,
|
|
7447
|
+
{
|
|
7448
|
+
event,
|
|
7449
|
+
variant: badgeVariant,
|
|
7450
|
+
className: "w-full"
|
|
7451
|
+
},
|
|
7452
|
+
event.id
|
|
7453
|
+
)) })
|
|
7454
|
+
] });
|
|
7455
|
+
}
|
|
7456
|
+
function CalendarTimeline2({
|
|
7457
|
+
firstVisibleHour,
|
|
7458
|
+
lastVisibleHour
|
|
7459
|
+
}) {
|
|
7460
|
+
const [currentTime, setCurrentTime] = React14.useState(/* @__PURE__ */ new Date());
|
|
7461
|
+
React14.useEffect(() => {
|
|
7462
|
+
const interval = setInterval(() => {
|
|
7463
|
+
setCurrentTime(/* @__PURE__ */ new Date());
|
|
7464
|
+
}, 6e4);
|
|
7465
|
+
return () => clearInterval(interval);
|
|
7466
|
+
}, []);
|
|
7467
|
+
const currentHour = currentTime.getHours();
|
|
7468
|
+
const currentMinute = currentTime.getMinutes();
|
|
7469
|
+
if (currentHour < firstVisibleHour || currentHour >= lastVisibleHour) {
|
|
7470
|
+
return null;
|
|
7471
|
+
}
|
|
7472
|
+
const minutesSinceStart = (currentHour - firstVisibleHour) * 60 + currentMinute;
|
|
7473
|
+
const totalMinutes = (lastVisibleHour - firstVisibleHour) * 60;
|
|
7474
|
+
const topPercent = minutesSinceStart / totalMinutes * 100;
|
|
7475
|
+
return /* @__PURE__ */ jsxs(
|
|
7476
|
+
"div",
|
|
7477
|
+
{
|
|
7478
|
+
className: "pointer-events-none absolute inset-x-0 z-30 flex items-center",
|
|
7479
|
+
style: { top: `${topPercent}%` },
|
|
7480
|
+
children: [
|
|
7481
|
+
/* @__PURE__ */ jsx("div", { className: "size-3 -translate-x-1/2 rounded-full bg-red-500" }),
|
|
7482
|
+
/* @__PURE__ */ jsx("div", { className: "h-0.5 flex-1 bg-red-500" })
|
|
7483
|
+
]
|
|
7484
|
+
}
|
|
7485
|
+
);
|
|
7486
|
+
}
|
|
7487
|
+
function YearView({
|
|
7488
|
+
className,
|
|
7489
|
+
weekStartsOn = 0,
|
|
7490
|
+
onMonthClick,
|
|
7491
|
+
onDateClick
|
|
7492
|
+
}) {
|
|
7493
|
+
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7494
|
+
const filteredEvents = useFilteredEvents();
|
|
7495
|
+
const months = React14.useMemo(() => {
|
|
7496
|
+
const yearStart = startOfYear(selectedDate);
|
|
7497
|
+
return Array.from({ length: 12 }, (_, i) => addMonths(yearStart, i));
|
|
7498
|
+
}, [selectedDate]);
|
|
7499
|
+
const handleMonthClick = (date) => {
|
|
7500
|
+
setSelectedDate(date);
|
|
7501
|
+
setView("month");
|
|
7502
|
+
onMonthClick?.(date);
|
|
7503
|
+
};
|
|
7504
|
+
const handleDateClick = (date) => {
|
|
7505
|
+
setSelectedDate(date);
|
|
7506
|
+
setView("day");
|
|
7507
|
+
onDateClick?.(date);
|
|
7508
|
+
};
|
|
7509
|
+
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(
|
|
7510
|
+
YearViewMonth,
|
|
7511
|
+
{
|
|
7512
|
+
month,
|
|
7513
|
+
events: filteredEvents,
|
|
7514
|
+
onMonthClick: () => handleMonthClick(month),
|
|
7515
|
+
onDateClick: handleDateClick
|
|
7516
|
+
},
|
|
7517
|
+
month.toString()
|
|
7518
|
+
)) }) }) });
|
|
7519
|
+
}
|
|
7520
|
+
function YearViewMonth({
|
|
7521
|
+
month,
|
|
7522
|
+
events,
|
|
7523
|
+
onMonthClick,
|
|
7524
|
+
onDateClick
|
|
7525
|
+
}) {
|
|
7526
|
+
const cells = getCalendarCells(month);
|
|
7527
|
+
const monthEvents = events.filter((event) => {
|
|
7528
|
+
const eventStart = parseISO(event.startDate);
|
|
7529
|
+
return isSameMonth(eventStart, month);
|
|
7530
|
+
});
|
|
7531
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-sm border border-border/50 bg-card p-3", children: [
|
|
7532
|
+
/* @__PURE__ */ jsxs(
|
|
7533
|
+
"button",
|
|
7534
|
+
{
|
|
7535
|
+
type: "button",
|
|
7536
|
+
onClick: onMonthClick,
|
|
7537
|
+
className: "mb-2 w-full text-left text-sm font-semibold transition-colors hover:text-primary",
|
|
7538
|
+
children: [
|
|
7539
|
+
format(month, "MMMM"),
|
|
7540
|
+
monthEvents.length > 0 && /* @__PURE__ */ jsxs("span", { className: "ml-2 text-xs font-normal text-muted-foreground", children: [
|
|
7541
|
+
"(",
|
|
7542
|
+
monthEvents.length,
|
|
7543
|
+
")"
|
|
7544
|
+
] })
|
|
7545
|
+
]
|
|
7546
|
+
}
|
|
7547
|
+
),
|
|
7548
|
+
/* @__PURE__ */ jsx("div", { className: "mb-1 grid grid-cols-7", children: ["S", "M", "T", "W", "T", "F", "S"].map((day, i) => /* @__PURE__ */ jsx(
|
|
7549
|
+
"div",
|
|
7550
|
+
{
|
|
7551
|
+
className: "text-center text-[10px] font-medium text-muted-foreground",
|
|
7552
|
+
children: day
|
|
7553
|
+
},
|
|
7554
|
+
i
|
|
7555
|
+
)) }),
|
|
7556
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7", children: cells.map((cell) => /* @__PURE__ */ jsx(
|
|
7557
|
+
YearViewDayCell,
|
|
7558
|
+
{
|
|
7559
|
+
cell,
|
|
7560
|
+
month,
|
|
7561
|
+
events,
|
|
7562
|
+
onDateClick
|
|
7563
|
+
},
|
|
7564
|
+
cell.date.toISOString()
|
|
7565
|
+
)) })
|
|
7566
|
+
] });
|
|
7567
|
+
}
|
|
7568
|
+
function YearViewDayCell({
|
|
7569
|
+
cell,
|
|
7570
|
+
month,
|
|
7571
|
+
events,
|
|
7572
|
+
onDateClick
|
|
7573
|
+
}) {
|
|
7574
|
+
const { date, currentMonth } = cell;
|
|
7575
|
+
const isCurrentDay = isToday(date);
|
|
7576
|
+
const dayEvents = events.filter((event) => {
|
|
7577
|
+
const eventStart = parseISO(event.startDate);
|
|
7578
|
+
const eventEnd = parseISO(event.endDate);
|
|
7579
|
+
return date >= eventStart && date <= eventEnd || isSameDay(eventStart, date) || isSameDay(eventEnd, date);
|
|
7580
|
+
});
|
|
7581
|
+
const hasEvents = dayEvents.length > 0;
|
|
7582
|
+
if (!currentMonth) {
|
|
7583
|
+
return /* @__PURE__ */ jsx("div", { className: "aspect-square" });
|
|
7584
|
+
}
|
|
7585
|
+
return /* @__PURE__ */ jsxs(
|
|
7586
|
+
"button",
|
|
7587
|
+
{
|
|
7588
|
+
type: "button",
|
|
7589
|
+
onClick: () => onDateClick(date),
|
|
7590
|
+
className: cn(
|
|
7591
|
+
"relative flex aspect-square items-center justify-center text-[11px] transition-colors",
|
|
7592
|
+
"hover:bg-muted rounded-sm",
|
|
7593
|
+
isCurrentDay && "bg-primary text-primary-foreground rounded-sm hover:bg-primary/90"
|
|
7594
|
+
),
|
|
7595
|
+
children: [
|
|
7596
|
+
cell.day,
|
|
7597
|
+
hasEvents && !isCurrentDay && /* @__PURE__ */ jsx("span", { className: "absolute bottom-0.5 left-1/2 size-1 -translate-x-1/2 rounded-full bg-primary" })
|
|
7598
|
+
]
|
|
7599
|
+
}
|
|
7600
|
+
);
|
|
7601
|
+
}
|
|
7602
|
+
var colorClasses2 = {
|
|
7603
|
+
blue: { border: "border-l-blue-500", bg: "bg-blue-50 dark:bg-blue-950/20" },
|
|
7604
|
+
green: { border: "border-l-green-500", bg: "bg-green-50 dark:bg-green-950/20" },
|
|
7605
|
+
red: { border: "border-l-red-500", bg: "bg-red-50 dark:bg-red-950/20" },
|
|
7606
|
+
yellow: { border: "border-l-yellow-500", bg: "bg-yellow-50 dark:bg-yellow-950/20" },
|
|
7607
|
+
purple: { border: "border-l-purple-500", bg: "bg-purple-50 dark:bg-purple-950/20" },
|
|
7608
|
+
orange: { border: "border-l-primary", bg: "bg-orange-50 dark:bg-orange-950/20" }
|
|
7609
|
+
};
|
|
7610
|
+
function AgendaView({
|
|
7611
|
+
className,
|
|
7612
|
+
emptyMessage = "No events scheduled for the selected month",
|
|
7613
|
+
onEventClick,
|
|
7614
|
+
onDateClick
|
|
7615
|
+
}) {
|
|
7616
|
+
const { selectedDate, setSelectedDate, setView } = useEventCalendar();
|
|
7617
|
+
const filteredEvents = useFilteredEvents();
|
|
7618
|
+
const { singleDayEvents, multiDayEvents } = React14.useMemo(
|
|
7619
|
+
() => splitEventsByDuration(filteredEvents),
|
|
7620
|
+
[filteredEvents]
|
|
7621
|
+
);
|
|
7622
|
+
const eventsByDay = React14.useMemo(() => {
|
|
7623
|
+
const allDates = /* @__PURE__ */ new Map();
|
|
7624
|
+
singleDayEvents.forEach((event) => {
|
|
7625
|
+
const eventDate = parseISO(event.startDate);
|
|
7626
|
+
if (!isSameMonth(eventDate, selectedDate)) return;
|
|
7627
|
+
const dateKey = format(eventDate, "yyyy-MM-dd");
|
|
7628
|
+
if (!allDates.has(dateKey)) {
|
|
7629
|
+
allDates.set(dateKey, {
|
|
7630
|
+
date: startOfDay(eventDate),
|
|
7631
|
+
events: [],
|
|
7632
|
+
multiDayEvents: []
|
|
7633
|
+
});
|
|
7634
|
+
}
|
|
7635
|
+
allDates.get(dateKey)?.events.push(event);
|
|
7636
|
+
});
|
|
7637
|
+
multiDayEvents.forEach((event) => {
|
|
7638
|
+
const eventStart = parseISO(event.startDate);
|
|
7639
|
+
const eventEnd = parseISO(event.endDate);
|
|
7640
|
+
let currentDate = startOfDay(eventStart);
|
|
7641
|
+
const lastDate = endOfDay(eventEnd);
|
|
7642
|
+
while (currentDate <= lastDate) {
|
|
7643
|
+
if (isSameMonth(currentDate, selectedDate)) {
|
|
7644
|
+
const dateKey = format(currentDate, "yyyy-MM-dd");
|
|
7645
|
+
if (!allDates.has(dateKey)) {
|
|
7646
|
+
allDates.set(dateKey, {
|
|
7647
|
+
date: new Date(currentDate),
|
|
7648
|
+
events: [],
|
|
7649
|
+
multiDayEvents: []
|
|
7650
|
+
});
|
|
7651
|
+
}
|
|
7652
|
+
allDates.get(dateKey)?.multiDayEvents.push(event);
|
|
7653
|
+
}
|
|
7654
|
+
currentDate = new Date(currentDate.setDate(currentDate.getDate() + 1));
|
|
7655
|
+
}
|
|
7656
|
+
});
|
|
7657
|
+
return Array.from(allDates.values()).sort(
|
|
7658
|
+
(a, b) => a.date.getTime() - b.date.getTime()
|
|
7659
|
+
);
|
|
7660
|
+
}, [singleDayEvents, multiDayEvents, selectedDate]);
|
|
7661
|
+
const hasAnyEvents = singleDayEvents.length > 0 || multiDayEvents.length > 0;
|
|
7662
|
+
const handleDateClick = (date) => {
|
|
7663
|
+
setSelectedDate(date);
|
|
7664
|
+
setView("day");
|
|
7665
|
+
onDateClick?.(date);
|
|
7666
|
+
};
|
|
7667
|
+
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: [
|
|
7668
|
+
eventsByDay.map((dayGroup) => /* @__PURE__ */ jsx(
|
|
7669
|
+
AgendaDayGroup,
|
|
7670
|
+
{
|
|
7671
|
+
date: dayGroup.date,
|
|
7672
|
+
events: dayGroup.events,
|
|
7673
|
+
multiDayEvents: dayGroup.multiDayEvents,
|
|
7674
|
+
onDateClick: handleDateClick,
|
|
7675
|
+
onEventClick
|
|
7676
|
+
},
|
|
7677
|
+
format(dayGroup.date, "yyyy-MM-dd")
|
|
7678
|
+
)),
|
|
7679
|
+
!hasAnyEvents && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2 py-20 text-muted-foreground", children: [
|
|
7680
|
+
/* @__PURE__ */ jsx(CalendarX2, { className: "size-10" }),
|
|
7681
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm md:text-base", children: emptyMessage })
|
|
7682
|
+
] })
|
|
7683
|
+
] }) }) });
|
|
7684
|
+
}
|
|
7685
|
+
function AgendaDayGroup({
|
|
7686
|
+
date,
|
|
7687
|
+
events,
|
|
7688
|
+
multiDayEvents,
|
|
7689
|
+
onDateClick,
|
|
7690
|
+
onEventClick
|
|
7691
|
+
}) {
|
|
7692
|
+
const isCurrentDay = isToday(date);
|
|
7693
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
7694
|
+
/* @__PURE__ */ jsxs(
|
|
7695
|
+
"button",
|
|
7696
|
+
{
|
|
7697
|
+
type: "button",
|
|
7698
|
+
onClick: () => onDateClick(date),
|
|
7699
|
+
className: cn(
|
|
7700
|
+
"mb-3 flex items-center gap-2 text-left transition-colors hover:text-primary",
|
|
7701
|
+
isCurrentDay && "text-primary"
|
|
7702
|
+
),
|
|
7703
|
+
children: [
|
|
7704
|
+
/* @__PURE__ */ jsx(
|
|
7705
|
+
"span",
|
|
7706
|
+
{
|
|
7707
|
+
className: cn(
|
|
7708
|
+
"flex size-8 items-center justify-center rounded-full text-sm font-bold",
|
|
7709
|
+
isCurrentDay && "bg-primary text-primary-foreground"
|
|
7710
|
+
),
|
|
7711
|
+
children: format(date, "d")
|
|
7712
|
+
}
|
|
7713
|
+
),
|
|
7714
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
7715
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: format(date, "EEEE") }),
|
|
7716
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 text-muted-foreground", children: format(date, "MMMM d, yyyy") })
|
|
7717
|
+
] })
|
|
7718
|
+
]
|
|
7719
|
+
}
|
|
7720
|
+
),
|
|
7721
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 pl-10", children: [
|
|
7722
|
+
multiDayEvents.map((event) => /* @__PURE__ */ jsx(
|
|
7723
|
+
AgendaEventCard,
|
|
7724
|
+
{
|
|
7725
|
+
event,
|
|
7726
|
+
isMultiDay: true,
|
|
7727
|
+
onClick: () => onEventClick?.(event)
|
|
7728
|
+
},
|
|
7729
|
+
`multi-${event.id}`
|
|
7730
|
+
)),
|
|
7731
|
+
events.map((event) => /* @__PURE__ */ jsx(
|
|
7732
|
+
AgendaEventCard,
|
|
7733
|
+
{
|
|
7734
|
+
event,
|
|
7735
|
+
onClick: () => onEventClick?.(event)
|
|
7736
|
+
},
|
|
7737
|
+
event.id
|
|
7738
|
+
))
|
|
7739
|
+
] })
|
|
7740
|
+
] });
|
|
7741
|
+
}
|
|
7742
|
+
function AgendaEventCard({ event, isMultiDay, onClick }) {
|
|
7743
|
+
const colors = colorClasses2[event.color];
|
|
7744
|
+
const startTime = format(parseISO(event.startDate), "h:mm a");
|
|
7745
|
+
const endTime = format(parseISO(event.endDate), "h:mm a");
|
|
7746
|
+
const getInitials = (name) => {
|
|
7747
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
7748
|
+
};
|
|
7749
|
+
return /* @__PURE__ */ jsxs(
|
|
7750
|
+
"button",
|
|
7751
|
+
{
|
|
7752
|
+
type: "button",
|
|
7753
|
+
onClick,
|
|
7754
|
+
className: cn(
|
|
7755
|
+
"flex w-full items-start gap-3 rounded-lg border-l-4 p-3 text-left transition-colors",
|
|
7756
|
+
"hover:opacity-90",
|
|
7757
|
+
colors.border,
|
|
7758
|
+
colors.bg
|
|
7759
|
+
),
|
|
7760
|
+
children: [
|
|
7761
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-10 shrink-0", children: [
|
|
7762
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: event.user.picturePath, alt: event.user.name }),
|
|
7763
|
+
/* @__PURE__ */ jsx(AvatarFallback, { children: getInitials(event.user.name) })
|
|
7764
|
+
] }),
|
|
7765
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
7766
|
+
isMultiDay && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Multi-day event" }),
|
|
7767
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold truncate", children: event.title }),
|
|
7768
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: event.user.name }),
|
|
7769
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
7770
|
+
startTime,
|
|
7771
|
+
" - ",
|
|
7772
|
+
endTime
|
|
7773
|
+
] }),
|
|
7774
|
+
event.description && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground line-clamp-2", children: event.description })
|
|
7775
|
+
] })
|
|
7776
|
+
]
|
|
7777
|
+
}
|
|
7778
|
+
);
|
|
7779
|
+
}
|
|
7780
|
+
var VIEW_CONFIG = [
|
|
7781
|
+
{ view: "day", icon: List, label: "View by day" },
|
|
7782
|
+
{ view: "week", icon: Columns, label: "View by week" },
|
|
7783
|
+
{ view: "month", icon: Grid2x2, label: "View by month" },
|
|
7784
|
+
{ view: "year", icon: Grid3x3, label: "View by year" },
|
|
7785
|
+
{ view: "agenda", icon: CalendarRange, label: "View by agenda" }
|
|
7786
|
+
];
|
|
7787
|
+
function CalendarHeader({
|
|
7788
|
+
className,
|
|
7789
|
+
showViewSwitcher = true,
|
|
7790
|
+
showUserFilter = true,
|
|
7791
|
+
showBadgeVariant = false,
|
|
7792
|
+
// Hidden by default, controlled via settings
|
|
7793
|
+
showToday = true,
|
|
7794
|
+
showAddButton = true,
|
|
7795
|
+
onAddClick
|
|
7796
|
+
}) {
|
|
7797
|
+
const {
|
|
7798
|
+
selectedDate,
|
|
7799
|
+
view,
|
|
7800
|
+
setView,
|
|
7801
|
+
setSelectedDate,
|
|
7802
|
+
selectedUserId,
|
|
7803
|
+
setSelectedUserId,
|
|
7804
|
+
users,
|
|
7805
|
+
badgeVariant,
|
|
7806
|
+
setBadgeVariant,
|
|
7807
|
+
goToPrevious,
|
|
7808
|
+
goToNext
|
|
7809
|
+
} = useEventCalendar();
|
|
7810
|
+
const filteredEvents = useFilteredEvents();
|
|
7811
|
+
const eventCount = filteredEvents.length;
|
|
7812
|
+
const { start: rangeStart, end: rangeEnd } = getViewDateRange(selectedDate, view);
|
|
7813
|
+
const dateRangeLabel = formatDateRange(rangeStart, rangeEnd);
|
|
7814
|
+
const getInitials = (name) => {
|
|
7815
|
+
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
7816
|
+
};
|
|
7817
|
+
const handleTodayClick = () => {
|
|
7818
|
+
setSelectedDate(/* @__PURE__ */ new Date());
|
|
7819
|
+
};
|
|
7820
|
+
const today = /* @__PURE__ */ new Date();
|
|
7821
|
+
return /* @__PURE__ */ jsxs(
|
|
7822
|
+
"div",
|
|
7823
|
+
{
|
|
7824
|
+
className: cn(
|
|
7825
|
+
"flex flex-col gap-4 border-b border-border p-4 lg:flex-row lg:items-center lg:justify-between",
|
|
7826
|
+
className
|
|
7827
|
+
),
|
|
7828
|
+
children: [
|
|
7829
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
7830
|
+
/* @__PURE__ */ jsxs(
|
|
7831
|
+
"button",
|
|
7832
|
+
{
|
|
7833
|
+
type: "button",
|
|
7834
|
+
onClick: handleTodayClick,
|
|
7835
|
+
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",
|
|
7836
|
+
children: [
|
|
7837
|
+
/* @__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() }),
|
|
7838
|
+
/* @__PURE__ */ jsx("p", { className: "flex w-full flex-1 items-center justify-center text-lg font-bold", children: today.getDate() })
|
|
7839
|
+
]
|
|
7840
|
+
}
|
|
7841
|
+
),
|
|
7842
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
7843
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7844
|
+
/* @__PURE__ */ jsxs("span", { className: "text-lg font-semibold", children: [
|
|
7845
|
+
format(selectedDate, "MMMM"),
|
|
7846
|
+
" ",
|
|
7847
|
+
selectedDate.getFullYear()
|
|
7848
|
+
] }),
|
|
7849
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "px-1.5", children: [
|
|
7850
|
+
eventCount,
|
|
7851
|
+
" event",
|
|
7852
|
+
eventCount !== 1 ? "s" : ""
|
|
7853
|
+
] })
|
|
7854
|
+
] }),
|
|
7855
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7856
|
+
/* @__PURE__ */ jsxs(
|
|
7857
|
+
Button,
|
|
7858
|
+
{
|
|
7859
|
+
variant: "outline",
|
|
7860
|
+
size: "icon",
|
|
7861
|
+
className: "size-7 [&_svg]:size-4",
|
|
7862
|
+
onClick: goToPrevious,
|
|
7863
|
+
children: [
|
|
7864
|
+
/* @__PURE__ */ jsx(ChevronLeft, {}),
|
|
7865
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Previous" })
|
|
7866
|
+
]
|
|
7867
|
+
}
|
|
7868
|
+
),
|
|
7869
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: dateRangeLabel }),
|
|
7870
|
+
/* @__PURE__ */ jsxs(
|
|
7871
|
+
Button,
|
|
7872
|
+
{
|
|
7873
|
+
variant: "outline",
|
|
7874
|
+
size: "icon",
|
|
7875
|
+
className: "size-7 [&_svg]:size-4",
|
|
7876
|
+
onClick: goToNext,
|
|
7877
|
+
children: [
|
|
7878
|
+
/* @__PURE__ */ jsx(ChevronRight, {}),
|
|
7879
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Next" })
|
|
7880
|
+
]
|
|
7881
|
+
}
|
|
7882
|
+
)
|
|
7883
|
+
] })
|
|
7884
|
+
] })
|
|
7885
|
+
] }),
|
|
7886
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1.5 sm:flex-row sm:justify-between", children: [
|
|
7887
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-full items-center gap-1.5", children: [
|
|
7888
|
+
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) => {
|
|
7889
|
+
const Icon2 = config.icon;
|
|
7890
|
+
const isFirst = index === 0;
|
|
7891
|
+
const isLast = index === VIEW_CONFIG.length - 1;
|
|
7892
|
+
const isActive = view === config.view;
|
|
7893
|
+
return /* @__PURE__ */ jsx(
|
|
7894
|
+
Button,
|
|
7895
|
+
{
|
|
7896
|
+
"aria-label": config.label,
|
|
7897
|
+
size: "icon",
|
|
7898
|
+
variant: isActive ? "default" : "ghost",
|
|
7899
|
+
className: cn(
|
|
7900
|
+
"size-8 border-0 [&_svg]:size-4",
|
|
7901
|
+
isFirst && "rounded-l-full rounded-r-sm",
|
|
7902
|
+
isLast && "rounded-r-full rounded-l-sm",
|
|
7903
|
+
!isFirst && !isLast && "rounded-sm"
|
|
7904
|
+
),
|
|
7905
|
+
onClick: () => setView(config.view),
|
|
7906
|
+
children: /* @__PURE__ */ jsx(Icon2, { strokeWidth: 1.8 })
|
|
7907
|
+
},
|
|
7908
|
+
config.view
|
|
7909
|
+
);
|
|
7910
|
+
}) }),
|
|
7911
|
+
showUserFilter && users.length > 0 && /* @__PURE__ */ jsxs(
|
|
7912
|
+
Select,
|
|
7913
|
+
{
|
|
7914
|
+
value: selectedUserId || "all",
|
|
7915
|
+
onValueChange: (value) => setSelectedUserId(value === "all" ? null : value),
|
|
7916
|
+
children: [
|
|
7917
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "flex-1 md:w-48", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
7918
|
+
/* @__PURE__ */ jsxs(SelectContent, { align: "end", children: [
|
|
7919
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "all", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
7920
|
+
/* @__PURE__ */ jsxs("div", { className: "flex -space-x-2", children: [
|
|
7921
|
+
users.slice(0, 2).map((user) => /* @__PURE__ */ jsxs(Avatar, { className: "size-6 border-2 border-background", children: [
|
|
7922
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.picturePath, alt: user.name }),
|
|
7923
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px]", children: getInitials(user.name) })
|
|
7924
|
+
] }, user.id)),
|
|
7925
|
+
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: [
|
|
7926
|
+
"+",
|
|
7927
|
+
users.length - 2
|
|
7928
|
+
] })
|
|
7929
|
+
] }),
|
|
7930
|
+
"All"
|
|
7931
|
+
] }) }),
|
|
7932
|
+
users.map((user) => /* @__PURE__ */ jsx(SelectItem, { value: user.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7933
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-6", children: [
|
|
7934
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: user.picturePath, alt: user.name }),
|
|
7935
|
+
/* @__PURE__ */ jsx(AvatarFallback, { className: "text-[10px]", children: getInitials(user.name) })
|
|
7936
|
+
] }),
|
|
7937
|
+
/* @__PURE__ */ jsx("p", { className: "truncate", children: user.name })
|
|
7938
|
+
] }) }, user.id))
|
|
7939
|
+
] })
|
|
7940
|
+
]
|
|
7941
|
+
}
|
|
7942
|
+
)
|
|
7943
|
+
] }),
|
|
7944
|
+
showAddButton && /* @__PURE__ */ jsxs(Button, { onClick: onAddClick, className: "w-full sm:w-auto", children: [
|
|
7945
|
+
/* @__PURE__ */ jsx(Plus, {}),
|
|
7946
|
+
"Add Event"
|
|
7947
|
+
] })
|
|
7948
|
+
] })
|
|
7949
|
+
]
|
|
7950
|
+
}
|
|
7951
|
+
);
|
|
7952
|
+
}
|
|
7953
|
+
function CalendarHeaderCompact({
|
|
7954
|
+
className,
|
|
7955
|
+
showAddButton = true,
|
|
7956
|
+
onAddClick
|
|
7957
|
+
}) {
|
|
7958
|
+
const {
|
|
7959
|
+
selectedDate,
|
|
7960
|
+
setSelectedDate,
|
|
7961
|
+
view,
|
|
7962
|
+
setView,
|
|
7963
|
+
goToPrevious,
|
|
7964
|
+
goToNext
|
|
7965
|
+
} = useEventCalendar();
|
|
7966
|
+
const filteredEvents = useFilteredEvents();
|
|
7967
|
+
const eventCount = filteredEvents.length;
|
|
7968
|
+
const today = /* @__PURE__ */ new Date();
|
|
7969
|
+
const handleTodayClick = () => {
|
|
7970
|
+
setSelectedDate(/* @__PURE__ */ new Date());
|
|
7971
|
+
};
|
|
7972
|
+
return /* @__PURE__ */ jsxs(
|
|
7973
|
+
"div",
|
|
7974
|
+
{
|
|
7975
|
+
className: cn(
|
|
7976
|
+
"flex items-center justify-between border-b border-border p-3",
|
|
7977
|
+
className
|
|
7978
|
+
),
|
|
7979
|
+
children: [
|
|
7980
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7981
|
+
/* @__PURE__ */ jsxs(
|
|
7982
|
+
"button",
|
|
7983
|
+
{
|
|
7984
|
+
type: "button",
|
|
7985
|
+
onClick: handleTodayClick,
|
|
7986
|
+
className: "flex size-10 flex-col items-start overflow-hidden rounded border focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
7987
|
+
children: [
|
|
7988
|
+
/* @__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() }),
|
|
7989
|
+
/* @__PURE__ */ jsx("p", { className: "flex w-full flex-1 items-center justify-center text-sm font-bold", children: today.getDate() })
|
|
7990
|
+
]
|
|
7991
|
+
}
|
|
7992
|
+
),
|
|
7993
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
7994
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: format(selectedDate, "MMM yyyy") }),
|
|
7995
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
7996
|
+
eventCount,
|
|
7997
|
+
" events"
|
|
7998
|
+
] })
|
|
7999
|
+
] })
|
|
8000
|
+
] }),
|
|
8001
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8002
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", className: "size-8", onClick: goToPrevious, children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4" }) }),
|
|
8003
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", className: "size-8", onClick: goToNext, children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" }) }),
|
|
8004
|
+
/* @__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: [
|
|
8005
|
+
/* @__PURE__ */ jsx(
|
|
8006
|
+
Button,
|
|
8007
|
+
{
|
|
8008
|
+
size: "icon",
|
|
8009
|
+
variant: view === "day" ? "default" : "ghost",
|
|
8010
|
+
className: "size-6 rounded-l-full rounded-r-sm border-0 [&_svg]:size-3",
|
|
8011
|
+
onClick: () => setView("day"),
|
|
8012
|
+
children: /* @__PURE__ */ jsx(List, { strokeWidth: 1.8 })
|
|
8013
|
+
}
|
|
8014
|
+
),
|
|
8015
|
+
/* @__PURE__ */ jsx(
|
|
8016
|
+
Button,
|
|
8017
|
+
{
|
|
8018
|
+
size: "icon",
|
|
8019
|
+
variant: view === "week" ? "default" : "ghost",
|
|
8020
|
+
className: "size-6 rounded-sm border-0 [&_svg]:size-3",
|
|
8021
|
+
onClick: () => setView("week"),
|
|
8022
|
+
children: /* @__PURE__ */ jsx(Columns, { strokeWidth: 1.8 })
|
|
8023
|
+
}
|
|
8024
|
+
),
|
|
8025
|
+
/* @__PURE__ */ jsx(
|
|
8026
|
+
Button,
|
|
8027
|
+
{
|
|
8028
|
+
size: "icon",
|
|
8029
|
+
variant: view === "month" ? "default" : "ghost",
|
|
8030
|
+
className: "size-6 rounded-r-full rounded-l-sm border-0 [&_svg]:size-3",
|
|
8031
|
+
onClick: () => setView("month"),
|
|
8032
|
+
children: /* @__PURE__ */ jsx(Grid2x2, { strokeWidth: 1.8 })
|
|
8033
|
+
}
|
|
8034
|
+
)
|
|
8035
|
+
] }),
|
|
8036
|
+
showAddButton && /* @__PURE__ */ jsx(Button, { size: "sm", onClick: onAddClick, className: "ml-2 size-8 p-0", children: /* @__PURE__ */ jsx(Plus, { className: "size-4" }) })
|
|
8037
|
+
] })
|
|
8038
|
+
]
|
|
8039
|
+
}
|
|
8040
|
+
);
|
|
8041
|
+
}
|
|
8042
|
+
var EVENT_COLORS2 = [
|
|
8043
|
+
{ value: "blue", label: "Blue", className: "bg-blue-500" },
|
|
8044
|
+
{ value: "green", label: "Green", className: "bg-green-500" },
|
|
8045
|
+
{ value: "red", label: "Red", className: "bg-red-500" },
|
|
8046
|
+
{ value: "yellow", label: "Yellow", className: "bg-yellow-500" },
|
|
8047
|
+
{ value: "purple", label: "Purple", className: "bg-purple-500" },
|
|
8048
|
+
{ value: "orange", label: "Orange", className: "bg-primary" }
|
|
8049
|
+
];
|
|
8050
|
+
function EventDialog({
|
|
8051
|
+
open,
|
|
8052
|
+
onOpenChange,
|
|
8053
|
+
mode = "add",
|
|
8054
|
+
event,
|
|
8055
|
+
defaultDate = /* @__PURE__ */ new Date(),
|
|
8056
|
+
defaultUserId
|
|
8057
|
+
}) {
|
|
8058
|
+
const { addEvent, updateEvent, deleteEvent, users } = useEventCalendar();
|
|
8059
|
+
const [title, setTitle] = React14.useState("");
|
|
8060
|
+
const [description, setDescription] = React14.useState("");
|
|
8061
|
+
const [startDate, setStartDate] = React14.useState("");
|
|
8062
|
+
const [startTime, setStartTime] = React14.useState("");
|
|
8063
|
+
const [endDate, setEndDate] = React14.useState("");
|
|
8064
|
+
const [endTime, setEndTime] = React14.useState("");
|
|
8065
|
+
const [color, setColor] = React14.useState("blue");
|
|
8066
|
+
const [userId, setUserId] = React14.useState("");
|
|
8067
|
+
const [isSubmitting, setIsSubmitting] = React14.useState(false);
|
|
8068
|
+
React14.useEffect(() => {
|
|
8069
|
+
if (open) {
|
|
8070
|
+
if (mode === "edit" && event) {
|
|
8071
|
+
const start = parseISO(event.startDate);
|
|
8072
|
+
const end = parseISO(event.endDate);
|
|
8073
|
+
setTitle(event.title);
|
|
8074
|
+
setDescription(event.description || "");
|
|
8075
|
+
setStartDate(format(start, "yyyy-MM-dd"));
|
|
8076
|
+
setStartTime(format(start, "HH:mm"));
|
|
8077
|
+
setEndDate(format(end, "yyyy-MM-dd"));
|
|
8078
|
+
setEndTime(format(end, "HH:mm"));
|
|
8079
|
+
setColor(event.color);
|
|
8080
|
+
setUserId(event.user.id);
|
|
8081
|
+
} else {
|
|
8082
|
+
const start = defaultDate;
|
|
8083
|
+
const end = setMinutes(setHours(defaultDate, defaultDate.getHours() + 1), 0);
|
|
8084
|
+
setTitle("");
|
|
8085
|
+
setDescription("");
|
|
8086
|
+
setStartDate(format(start, "yyyy-MM-dd"));
|
|
8087
|
+
setStartTime(format(start, "HH:mm"));
|
|
8088
|
+
setEndDate(format(end, "yyyy-MM-dd"));
|
|
8089
|
+
setEndTime(format(end, "HH:mm"));
|
|
8090
|
+
setColor("blue");
|
|
8091
|
+
setUserId(defaultUserId || users[0]?.id || "");
|
|
8092
|
+
}
|
|
8093
|
+
}
|
|
8094
|
+
}, [open, mode, event, defaultDate, defaultUserId, users]);
|
|
8095
|
+
const handleSubmit = async (e) => {
|
|
8096
|
+
e.preventDefault();
|
|
8097
|
+
setIsSubmitting(true);
|
|
8098
|
+
try {
|
|
8099
|
+
const [startYear, startMonth, startDay] = startDate.split("-").map(Number);
|
|
8100
|
+
const [startHour, startMinute] = startTime.split(":").map(Number);
|
|
8101
|
+
const [endYear, endMonth, endDay] = endDate.split("-").map(Number);
|
|
8102
|
+
const [endHour, endMinute] = endTime.split(":").map(Number);
|
|
8103
|
+
const startDateTime = new Date(startYear, startMonth - 1, startDay, startHour, startMinute);
|
|
8104
|
+
const endDateTime = new Date(endYear, endMonth - 1, endDay, endHour, endMinute);
|
|
8105
|
+
const selectedUser = users.find((u) => u.id === userId);
|
|
8106
|
+
if (mode === "edit" && event) {
|
|
8107
|
+
const updatedEvent = {
|
|
8108
|
+
...event,
|
|
8109
|
+
title,
|
|
8110
|
+
description,
|
|
8111
|
+
startDate: startDateTime.toISOString(),
|
|
8112
|
+
endDate: endDateTime.toISOString(),
|
|
8113
|
+
color,
|
|
8114
|
+
user: {
|
|
8115
|
+
id: userId,
|
|
8116
|
+
name: selectedUser?.name || "Unknown"
|
|
8117
|
+
}
|
|
8118
|
+
};
|
|
8119
|
+
updateEvent(updatedEvent);
|
|
8120
|
+
} else {
|
|
8121
|
+
const newEvent = {
|
|
8122
|
+
id: generateEventId(),
|
|
8123
|
+
title,
|
|
8124
|
+
description,
|
|
8125
|
+
startDate: startDateTime.toISOString(),
|
|
8126
|
+
endDate: endDateTime.toISOString(),
|
|
8127
|
+
color,
|
|
8128
|
+
user: {
|
|
8129
|
+
id: userId,
|
|
8130
|
+
name: selectedUser?.name || "Unknown"
|
|
8131
|
+
}
|
|
8132
|
+
};
|
|
8133
|
+
addEvent(newEvent);
|
|
8134
|
+
}
|
|
8135
|
+
onOpenChange(false);
|
|
8136
|
+
} catch (error) {
|
|
8137
|
+
console.error("Failed to save event:", error);
|
|
8138
|
+
} finally {
|
|
8139
|
+
setIsSubmitting(false);
|
|
8140
|
+
}
|
|
8141
|
+
};
|
|
8142
|
+
const handleDelete = () => {
|
|
8143
|
+
if (event) {
|
|
8144
|
+
deleteEvent(event.id);
|
|
8145
|
+
onOpenChange(false);
|
|
8146
|
+
}
|
|
8147
|
+
};
|
|
8148
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { className: "sm:max-w-[500px]", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
|
|
8149
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
8150
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: mode === "edit" ? "Edit Event" : "Add Event" }),
|
|
8151
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: mode === "edit" ? "Make changes to your event below." : "Fill in the details for your new event." })
|
|
8152
|
+
] }),
|
|
8153
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 py-4", children: [
|
|
8154
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8155
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "title", children: "Title" }),
|
|
8156
|
+
/* @__PURE__ */ jsx(
|
|
8157
|
+
Input,
|
|
8158
|
+
{
|
|
8159
|
+
id: "title",
|
|
8160
|
+
value: title,
|
|
8161
|
+
onChange: (e) => setTitle(e.target.value),
|
|
8162
|
+
placeholder: "Event title",
|
|
8163
|
+
required: true
|
|
8164
|
+
}
|
|
8165
|
+
)
|
|
8166
|
+
] }),
|
|
8167
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8168
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "description", children: "Description" }),
|
|
8169
|
+
/* @__PURE__ */ jsx(
|
|
8170
|
+
Textarea,
|
|
8171
|
+
{
|
|
8172
|
+
id: "description",
|
|
8173
|
+
value: description,
|
|
8174
|
+
onChange: (e) => setDescription(e.target.value),
|
|
8175
|
+
placeholder: "Event description (optional)",
|
|
8176
|
+
rows: 3
|
|
8177
|
+
}
|
|
8178
|
+
)
|
|
8179
|
+
] }),
|
|
8180
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
8181
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8182
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "startDate", children: "Start Date" }),
|
|
8183
|
+
/* @__PURE__ */ jsx(
|
|
8184
|
+
Input,
|
|
8185
|
+
{
|
|
8186
|
+
id: "startDate",
|
|
8187
|
+
type: "date",
|
|
8188
|
+
value: startDate,
|
|
8189
|
+
onChange: (e) => setStartDate(e.target.value),
|
|
8190
|
+
required: true
|
|
8191
|
+
}
|
|
8192
|
+
)
|
|
8193
|
+
] }),
|
|
8194
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8195
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "startTime", children: "Start Time" }),
|
|
8196
|
+
/* @__PURE__ */ jsx(
|
|
8197
|
+
Input,
|
|
8198
|
+
{
|
|
8199
|
+
id: "startTime",
|
|
8200
|
+
type: "time",
|
|
8201
|
+
value: startTime,
|
|
8202
|
+
onChange: (e) => setStartTime(e.target.value),
|
|
8203
|
+
required: true
|
|
8204
|
+
}
|
|
8205
|
+
)
|
|
8206
|
+
] })
|
|
8207
|
+
] }),
|
|
8208
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
8209
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8210
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "endDate", children: "End Date" }),
|
|
8211
|
+
/* @__PURE__ */ jsx(
|
|
8212
|
+
Input,
|
|
8213
|
+
{
|
|
8214
|
+
id: "endDate",
|
|
8215
|
+
type: "date",
|
|
8216
|
+
value: endDate,
|
|
8217
|
+
onChange: (e) => setEndDate(e.target.value),
|
|
8218
|
+
required: true
|
|
8219
|
+
}
|
|
8220
|
+
)
|
|
8221
|
+
] }),
|
|
8222
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8223
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: "endTime", children: "End Time" }),
|
|
8224
|
+
/* @__PURE__ */ jsx(
|
|
8225
|
+
Input,
|
|
8226
|
+
{
|
|
8227
|
+
id: "endTime",
|
|
8228
|
+
type: "time",
|
|
8229
|
+
value: endTime,
|
|
8230
|
+
onChange: (e) => setEndTime(e.target.value),
|
|
8231
|
+
required: true
|
|
8232
|
+
}
|
|
8233
|
+
)
|
|
8234
|
+
] })
|
|
8235
|
+
] }),
|
|
8236
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
8237
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8238
|
+
/* @__PURE__ */ jsx(Label2, { children: "Color" }),
|
|
8239
|
+
/* @__PURE__ */ jsxs(Select, { value: color, onValueChange: (v) => setColor(v), children: [
|
|
8240
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8241
|
+
/* @__PURE__ */ jsx(
|
|
8242
|
+
"span",
|
|
8243
|
+
{
|
|
8244
|
+
className: cn(
|
|
8245
|
+
"size-3 rounded-full",
|
|
8246
|
+
EVENT_COLORS2.find((c) => c.value === color)?.className
|
|
8247
|
+
)
|
|
8248
|
+
}
|
|
8249
|
+
),
|
|
8250
|
+
EVENT_COLORS2.find((c) => c.value === color)?.label
|
|
8251
|
+
] }) }) }),
|
|
8252
|
+
/* @__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: [
|
|
8253
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-3 rounded-full", c.className) }),
|
|
8254
|
+
c.label
|
|
8255
|
+
] }) }, c.value)) })
|
|
8256
|
+
] })
|
|
8257
|
+
] }),
|
|
8258
|
+
users.length > 0 && /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
8259
|
+
/* @__PURE__ */ jsx(Label2, { children: "Assignee" }),
|
|
8260
|
+
/* @__PURE__ */ jsxs(Select, { value: userId, onValueChange: setUserId, children: [
|
|
8261
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select user" }) }),
|
|
8262
|
+
/* @__PURE__ */ jsx(SelectContent, { children: users.map((user) => /* @__PURE__ */ jsx(SelectItem, { value: user.id, children: user.name }, user.id)) })
|
|
8263
|
+
] })
|
|
8264
|
+
] })
|
|
8265
|
+
] })
|
|
8266
|
+
] }),
|
|
8267
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "flex-row justify-between gap-2", children: [
|
|
8268
|
+
mode === "edit" ? /* @__PURE__ */ jsx(
|
|
8269
|
+
Button,
|
|
8270
|
+
{
|
|
8271
|
+
type: "button",
|
|
8272
|
+
variant: "destructive",
|
|
8273
|
+
onClick: handleDelete,
|
|
8274
|
+
disabled: isSubmitting,
|
|
8275
|
+
children: "Delete"
|
|
8276
|
+
}
|
|
8277
|
+
) : /* @__PURE__ */ jsx("div", {}),
|
|
8278
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8279
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
8280
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting || !title.trim(), children: isSubmitting ? "Saving..." : mode === "edit" ? "Save Changes" : "Add Event" })
|
|
8281
|
+
] })
|
|
8282
|
+
] })
|
|
8283
|
+
] }) }) });
|
|
8284
|
+
}
|
|
8285
|
+
function QuickAddEvent({
|
|
8286
|
+
date,
|
|
8287
|
+
onAdd,
|
|
8288
|
+
onOpenDialog,
|
|
8289
|
+
onClose
|
|
8290
|
+
}) {
|
|
8291
|
+
const [title, setTitle] = React14.useState("");
|
|
8292
|
+
const { users } = useEventCalendar();
|
|
8293
|
+
const handleSubmit = (e) => {
|
|
8294
|
+
e.preventDefault();
|
|
8295
|
+
if (!title.trim()) return;
|
|
8296
|
+
const end = setMinutes(setHours(date, date.getHours() + 1), 0);
|
|
8297
|
+
onAdd({
|
|
8298
|
+
title,
|
|
8299
|
+
description: "",
|
|
8300
|
+
startDate: date.toISOString(),
|
|
8301
|
+
endDate: end.toISOString(),
|
|
8302
|
+
color: "blue",
|
|
8303
|
+
user: {
|
|
8304
|
+
id: users[0]?.id || "",
|
|
8305
|
+
name: users[0]?.name || "Unknown"
|
|
8306
|
+
}
|
|
8307
|
+
});
|
|
8308
|
+
onClose();
|
|
8309
|
+
};
|
|
8310
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-2 p-3", children: [
|
|
8311
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: format(date, "EEE, MMM d, h:mm a") }),
|
|
8312
|
+
/* @__PURE__ */ jsx(
|
|
8313
|
+
Input,
|
|
8314
|
+
{
|
|
8315
|
+
value: title,
|
|
8316
|
+
onChange: (e) => setTitle(e.target.value),
|
|
8317
|
+
placeholder: "Add title",
|
|
8318
|
+
className: "h-8",
|
|
8319
|
+
autoFocus: true
|
|
8320
|
+
}
|
|
8321
|
+
),
|
|
8322
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8323
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", disabled: !title.trim(), children: "Add" }),
|
|
8324
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onOpenDialog, children: "More options" })
|
|
8325
|
+
] })
|
|
8326
|
+
] });
|
|
8327
|
+
}
|
|
8328
|
+
function ChangeBadgeVariantInput() {
|
|
8329
|
+
const { badgeVariant, setBadgeVariant } = useEventCalendar();
|
|
8330
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
8331
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Change badge variant" }),
|
|
8332
|
+
/* @__PURE__ */ jsxs(
|
|
8333
|
+
Select,
|
|
8334
|
+
{
|
|
8335
|
+
value: badgeVariant,
|
|
8336
|
+
onValueChange: (value) => setBadgeVariant(value),
|
|
8337
|
+
children: [
|
|
8338
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8339
|
+
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
8340
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "dot", children: "Dot" }),
|
|
8341
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "colored", children: "Colored" }),
|
|
8342
|
+
/* @__PURE__ */ jsx(SelectItem, { value: "mixed", children: "Mixed" })
|
|
8343
|
+
] })
|
|
8344
|
+
]
|
|
8345
|
+
}
|
|
8346
|
+
)
|
|
8347
|
+
] });
|
|
8348
|
+
}
|
|
8349
|
+
var HOUR_OPTIONS = Array.from({ length: 25 }, (_, i) => {
|
|
8350
|
+
if (i === 0) return { value: "0", label: "12 AM" };
|
|
8351
|
+
if (i === 12) return { value: "12", label: "12 PM" };
|
|
8352
|
+
if (i === 24) return { value: "24", label: "12 AM (next)" };
|
|
8353
|
+
if (i < 12) return { value: String(i), label: `${i} AM` };
|
|
8354
|
+
return { value: String(i), label: `${i - 12} PM` };
|
|
8355
|
+
});
|
|
8356
|
+
function ChangeVisibleHoursInput() {
|
|
8357
|
+
const { visibleHours, setVisibleHours } = useEventCalendar();
|
|
8358
|
+
const [from, setFrom] = React14.useState(visibleHours.from);
|
|
8359
|
+
const [to, setTo] = React14.useState(visibleHours.to);
|
|
8360
|
+
const handleApply = () => {
|
|
8361
|
+
const toHour = to === 0 ? 24 : to;
|
|
8362
|
+
setVisibleHours({ from, to: toHour });
|
|
8363
|
+
};
|
|
8364
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8365
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8366
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Change visible hours" }),
|
|
8367
|
+
/* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 100, children: /* @__PURE__ */ jsxs(Tooltip2, { children: [
|
|
8368
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(Info, { className: "size-3" }) }),
|
|
8369
|
+
/* @__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." }) })
|
|
8370
|
+
] }) })
|
|
8371
|
+
] }),
|
|
8372
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
8373
|
+
/* @__PURE__ */ jsx("p", { children: "From" }),
|
|
8374
|
+
/* @__PURE__ */ jsxs(Select, { value: String(from), onValueChange: (v) => setFrom(Number(v)), children: [
|
|
8375
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-28", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8376
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS.slice(0, 24).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8377
|
+
] }),
|
|
8378
|
+
/* @__PURE__ */ jsx("p", { children: "To" }),
|
|
8379
|
+
/* @__PURE__ */ jsxs(Select, { value: String(to), onValueChange: (v) => setTo(Number(v)), children: [
|
|
8380
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-28", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8381
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS.slice(1).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8382
|
+
] })
|
|
8383
|
+
] }),
|
|
8384
|
+
/* @__PURE__ */ jsx(Button, { className: "mt-4 w-fit", onClick: handleApply, children: "Apply" })
|
|
8385
|
+
] });
|
|
8386
|
+
}
|
|
8387
|
+
var DAYS_OF_WEEK = [
|
|
8388
|
+
{ index: 0, name: "Sunday" },
|
|
8389
|
+
{ index: 1, name: "Monday" },
|
|
8390
|
+
{ index: 2, name: "Tuesday" },
|
|
8391
|
+
{ index: 3, name: "Wednesday" },
|
|
8392
|
+
{ index: 4, name: "Thursday" },
|
|
8393
|
+
{ index: 5, name: "Friday" },
|
|
8394
|
+
{ index: 6, name: "Saturday" }
|
|
8395
|
+
];
|
|
8396
|
+
var HOUR_OPTIONS2 = Array.from({ length: 25 }, (_, i) => {
|
|
8397
|
+
if (i === 0) return { value: "0", label: "12 AM" };
|
|
8398
|
+
if (i === 12) return { value: "12", label: "12 PM" };
|
|
8399
|
+
if (i === 24) return { value: "24", label: "12 AM (next)" };
|
|
8400
|
+
if (i < 12) return { value: String(i), label: `${i} AM` };
|
|
8401
|
+
return { value: String(i), label: `${i - 12} PM` };
|
|
8402
|
+
});
|
|
8403
|
+
function ChangeWorkingHoursInput() {
|
|
8404
|
+
const { workingHours, setWorkingHours } = useEventCalendar();
|
|
8405
|
+
const [localWorkingHours, setLocalWorkingHours] = React14.useState({
|
|
8406
|
+
...workingHours
|
|
8407
|
+
});
|
|
8408
|
+
const handleToggleDay = (dayId) => {
|
|
8409
|
+
setLocalWorkingHours((prev) => ({
|
|
8410
|
+
...prev,
|
|
8411
|
+
[dayId]: prev[dayId].from > 0 || prev[dayId].to > 0 ? { from: 0, to: 0 } : { from: 9, to: 17 }
|
|
8412
|
+
}));
|
|
8413
|
+
};
|
|
8414
|
+
const handleTimeChange = (dayId, timeType, value) => {
|
|
8415
|
+
const hour = Number(value);
|
|
8416
|
+
setLocalWorkingHours((prev) => {
|
|
8417
|
+
const updatedDay = { ...prev[dayId], [timeType]: hour };
|
|
8418
|
+
if (timeType === "to" && hour === 0 && updatedDay.from === 0) {
|
|
8419
|
+
updatedDay.to = 24;
|
|
8420
|
+
}
|
|
8421
|
+
return { ...prev, [dayId]: updatedDay };
|
|
8422
|
+
});
|
|
8423
|
+
};
|
|
8424
|
+
const handleSave = () => {
|
|
8425
|
+
const updatedWorkingHours = { ...localWorkingHours };
|
|
8426
|
+
for (const dayId in updatedWorkingHours) {
|
|
8427
|
+
const day = updatedWorkingHours[parseInt(dayId)];
|
|
8428
|
+
const isDayActive = localWorkingHours[parseInt(dayId)].from > 0 || localWorkingHours[parseInt(dayId)].to > 0;
|
|
8429
|
+
if (isDayActive) {
|
|
8430
|
+
if (day.from === 0 && day.to === 0) {
|
|
8431
|
+
updatedWorkingHours[dayId] = { from: 0, to: 24 };
|
|
8432
|
+
} else if (day.to === 0 && day.from > 0) {
|
|
8433
|
+
updatedWorkingHours[dayId] = { ...day, to: 24 };
|
|
8434
|
+
}
|
|
8435
|
+
} else {
|
|
8436
|
+
updatedWorkingHours[dayId] = { from: 0, to: 0 };
|
|
8437
|
+
}
|
|
8438
|
+
}
|
|
8439
|
+
setWorkingHours(updatedWorkingHours);
|
|
8440
|
+
};
|
|
8441
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
8442
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8443
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "Change working hours" }),
|
|
8444
|
+
/* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 100, children: /* @__PURE__ */ jsxs(Tooltip2, { children: [
|
|
8445
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(Info, { className: "size-3" }) }),
|
|
8446
|
+
/* @__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." }) })
|
|
8447
|
+
] }) })
|
|
8448
|
+
] }),
|
|
8449
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: DAYS_OF_WEEK.map((day) => {
|
|
8450
|
+
const isDayActive = localWorkingHours[day.index].from > 0 || localWorkingHours[day.index].to > 0;
|
|
8451
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 sm:gap-4", children: [
|
|
8452
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-32 items-center gap-2 sm:w-36", children: [
|
|
8453
|
+
/* @__PURE__ */ jsx(
|
|
8454
|
+
Switch,
|
|
8455
|
+
{
|
|
8456
|
+
checked: isDayActive,
|
|
8457
|
+
onCheckedChange: () => handleToggleDay(day.index)
|
|
8458
|
+
}
|
|
8459
|
+
),
|
|
8460
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: day.name.slice(0, 3) })
|
|
8461
|
+
] }),
|
|
8462
|
+
isDayActive ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
8463
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8464
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "From" }),
|
|
8465
|
+
/* @__PURE__ */ jsxs(
|
|
8466
|
+
Select,
|
|
8467
|
+
{
|
|
8468
|
+
value: String(localWorkingHours[day.index].from),
|
|
8469
|
+
onValueChange: (v) => handleTimeChange(day.index, "from", v),
|
|
8470
|
+
children: [
|
|
8471
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-24", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8472
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS2.slice(0, 24).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8473
|
+
]
|
|
8474
|
+
}
|
|
8475
|
+
)
|
|
8476
|
+
] }),
|
|
8477
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8478
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "To" }),
|
|
8479
|
+
/* @__PURE__ */ jsxs(
|
|
8480
|
+
Select,
|
|
8481
|
+
{
|
|
8482
|
+
value: String(localWorkingHours[day.index].to),
|
|
8483
|
+
onValueChange: (v) => handleTimeChange(day.index, "to", v),
|
|
8484
|
+
children: [
|
|
8485
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-24", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
8486
|
+
/* @__PURE__ */ jsx(SelectContent, { children: HOUR_OPTIONS2.slice(1).map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
8487
|
+
]
|
|
8488
|
+
}
|
|
8489
|
+
)
|
|
8490
|
+
] })
|
|
8491
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
|
|
8492
|
+
/* @__PURE__ */ jsx(Moon, { className: "size-4" }),
|
|
8493
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: "Closed" })
|
|
8494
|
+
] })
|
|
8495
|
+
] }, day.index);
|
|
8496
|
+
}) }),
|
|
8497
|
+
/* @__PURE__ */ jsx(Button, { className: "mt-4 w-fit", onClick: handleSave, children: "Apply" })
|
|
8498
|
+
] });
|
|
8499
|
+
}
|
|
8500
|
+
function CalendarSettingsPanel({
|
|
8501
|
+
className,
|
|
8502
|
+
showBadgeVariant = true,
|
|
8503
|
+
showVisibleHours = true,
|
|
8504
|
+
showWorkingHours = true
|
|
8505
|
+
}) {
|
|
8506
|
+
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: [
|
|
8507
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "flex-none gap-2 py-0 hover:no-underline", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
8508
|
+
/* @__PURE__ */ jsx(Settings, { className: "size-4" }),
|
|
8509
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-semibold", children: "Calendar settings" })
|
|
8510
|
+
] }) }),
|
|
8511
|
+
/* @__PURE__ */ jsx(AccordionContent, { children: /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col gap-6", children: [
|
|
8512
|
+
showBadgeVariant && /* @__PURE__ */ jsx(ChangeBadgeVariantInput, {}),
|
|
8513
|
+
showVisibleHours && /* @__PURE__ */ jsx(ChangeVisibleHoursInput, {}),
|
|
8514
|
+
showWorkingHours && /* @__PURE__ */ jsx(ChangeWorkingHoursInput, {})
|
|
8515
|
+
] }) })
|
|
8516
|
+
] }) });
|
|
8517
|
+
}
|
|
8518
|
+
function useMediaQuery(query) {
|
|
8519
|
+
const [matches, setMatches] = React14.useState(false);
|
|
8520
|
+
React14.useEffect(() => {
|
|
8521
|
+
const media = window.matchMedia(query);
|
|
8522
|
+
setMatches(media.matches);
|
|
8523
|
+
const listener = (event) => {
|
|
8524
|
+
setMatches(event.matches);
|
|
8525
|
+
};
|
|
8526
|
+
media.addEventListener("change", listener);
|
|
8527
|
+
return () => media.removeEventListener("change", listener);
|
|
8528
|
+
}, [query]);
|
|
8529
|
+
return matches;
|
|
8530
|
+
}
|
|
8531
|
+
function BigCalendar({
|
|
8532
|
+
className,
|
|
8533
|
+
compact = "auto",
|
|
8534
|
+
bordered = true,
|
|
8535
|
+
showHeader = true,
|
|
8536
|
+
showAddButton = true,
|
|
8537
|
+
showSettings = true,
|
|
8538
|
+
enableDragDrop = true,
|
|
8539
|
+
weekStartsOn = 0,
|
|
8540
|
+
maxEventsPerDay = 3,
|
|
8541
|
+
config,
|
|
8542
|
+
...providerProps
|
|
8543
|
+
}) {
|
|
8544
|
+
return /* @__PURE__ */ jsx(EventCalendarProvider, { ...providerProps, children: /* @__PURE__ */ jsx(DragProvider, { children: /* @__PURE__ */ jsx(
|
|
8545
|
+
BigCalendarInner,
|
|
8546
|
+
{
|
|
8547
|
+
className,
|
|
8548
|
+
compact,
|
|
8549
|
+
bordered,
|
|
8550
|
+
showHeader,
|
|
8551
|
+
showAddButton,
|
|
8552
|
+
showSettings,
|
|
8553
|
+
enableDragDrop,
|
|
8554
|
+
weekStartsOn,
|
|
8555
|
+
maxEventsPerDay,
|
|
8556
|
+
config
|
|
8557
|
+
}
|
|
8558
|
+
) }) });
|
|
8559
|
+
}
|
|
8560
|
+
function BigCalendarInner({
|
|
8561
|
+
className,
|
|
8562
|
+
compact,
|
|
8563
|
+
bordered,
|
|
8564
|
+
showHeader,
|
|
8565
|
+
showAddButton,
|
|
8566
|
+
showSettings,
|
|
8567
|
+
enableDragDrop,
|
|
8568
|
+
weekStartsOn,
|
|
8569
|
+
maxEventsPerDay
|
|
8570
|
+
}) {
|
|
8571
|
+
const { view, setView } = useEventCalendar();
|
|
8572
|
+
const [dialogOpen, setDialogOpen] = React14.useState(false);
|
|
8573
|
+
const [selectedEvent, setSelectedEvent] = React14.useState(null);
|
|
8574
|
+
const [dialogMode, setDialogMode] = React14.useState("add");
|
|
8575
|
+
const [defaultDate, setDefaultDate] = React14.useState(/* @__PURE__ */ new Date());
|
|
8576
|
+
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
8577
|
+
const isCompact = compact === "auto" ? isMobile : compact;
|
|
8578
|
+
const handleAddClick = () => {
|
|
8579
|
+
setSelectedEvent(null);
|
|
8580
|
+
setDialogMode("add");
|
|
8581
|
+
setDefaultDate(/* @__PURE__ */ new Date());
|
|
8582
|
+
setDialogOpen(true);
|
|
8583
|
+
};
|
|
8584
|
+
const handleEventClick = (event) => {
|
|
8585
|
+
setSelectedEvent(event);
|
|
8586
|
+
setDialogMode("edit");
|
|
8587
|
+
setDialogOpen(true);
|
|
8588
|
+
};
|
|
8589
|
+
const handleDateClick = (date) => {
|
|
8590
|
+
setDefaultDate(date);
|
|
8591
|
+
};
|
|
8592
|
+
const handleMoreClick = (date, events) => {
|
|
8593
|
+
setDefaultDate(date);
|
|
8594
|
+
setView("day");
|
|
8595
|
+
};
|
|
8596
|
+
const handleTimeClick = (date, hour, minute) => {
|
|
8597
|
+
setSelectedEvent(null);
|
|
8598
|
+
setDialogMode("add");
|
|
8599
|
+
const clickedDate = new Date(date);
|
|
8600
|
+
clickedDate.setHours(hour, minute, 0, 0);
|
|
8601
|
+
setDefaultDate(clickedDate);
|
|
8602
|
+
setDialogOpen(true);
|
|
8603
|
+
};
|
|
8604
|
+
const Wrapper = bordered ? Card : "div";
|
|
8605
|
+
const Content14 = bordered ? CardContent : "div";
|
|
8606
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8607
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4 relative", className), children: [
|
|
8608
|
+
/* @__PURE__ */ jsxs(
|
|
8609
|
+
Wrapper,
|
|
8610
|
+
{
|
|
8611
|
+
className: cn(
|
|
8612
|
+
"flex min-h-[600px] flex-col overflow-hidden rounded-sm",
|
|
8613
|
+
!bordered && "border border-border bg-card"
|
|
8614
|
+
),
|
|
8615
|
+
children: [
|
|
8616
|
+
showHeader && (isCompact ? /* @__PURE__ */ jsx(
|
|
8617
|
+
CalendarHeaderCompact,
|
|
8618
|
+
{
|
|
8619
|
+
showAddButton,
|
|
8620
|
+
onAddClick: handleAddClick
|
|
8621
|
+
}
|
|
8622
|
+
) : /* @__PURE__ */ jsx(
|
|
8623
|
+
CalendarHeader,
|
|
8624
|
+
{
|
|
8625
|
+
showAddButton,
|
|
8626
|
+
onAddClick: handleAddClick
|
|
8627
|
+
}
|
|
8628
|
+
)),
|
|
8629
|
+
/* @__PURE__ */ jsx(Content14, { className: cn("flex-1 overflow-hidden", bordered ? "p-0" : ""), children: /* @__PURE__ */ jsx(
|
|
8630
|
+
CalendarView,
|
|
8631
|
+
{
|
|
8632
|
+
view,
|
|
8633
|
+
weekStartsOn,
|
|
8634
|
+
maxEventsPerDay,
|
|
8635
|
+
onEventClick: handleEventClick,
|
|
8636
|
+
onDateClick: handleDateClick,
|
|
8637
|
+
onMoreClick: handleMoreClick,
|
|
8638
|
+
onTimeClick: handleTimeClick
|
|
8639
|
+
}
|
|
8640
|
+
) })
|
|
8641
|
+
]
|
|
8642
|
+
}
|
|
8643
|
+
),
|
|
8644
|
+
showSettings && /* @__PURE__ */ jsx(CalendarSettingsPanel, {})
|
|
8645
|
+
] }),
|
|
8646
|
+
/* @__PURE__ */ jsx(
|
|
8647
|
+
EventDialog,
|
|
8648
|
+
{
|
|
8649
|
+
open: dialogOpen,
|
|
8650
|
+
onOpenChange: setDialogOpen,
|
|
8651
|
+
mode: dialogMode,
|
|
8652
|
+
event: selectedEvent,
|
|
8653
|
+
defaultDate
|
|
8654
|
+
}
|
|
8655
|
+
)
|
|
8656
|
+
] });
|
|
8657
|
+
}
|
|
8658
|
+
function CalendarView({
|
|
8659
|
+
view,
|
|
8660
|
+
weekStartsOn,
|
|
8661
|
+
maxEventsPerDay,
|
|
8662
|
+
onEventClick,
|
|
8663
|
+
onDateClick,
|
|
8664
|
+
onMoreClick,
|
|
8665
|
+
onTimeClick
|
|
8666
|
+
}) {
|
|
8667
|
+
switch (view) {
|
|
8668
|
+
case "month":
|
|
8669
|
+
return /* @__PURE__ */ jsx(
|
|
8670
|
+
MonthView,
|
|
8671
|
+
{
|
|
8672
|
+
className: "h-full",
|
|
8673
|
+
weekStartsOn,
|
|
8674
|
+
maxEventsPerDay,
|
|
8675
|
+
onEventClick,
|
|
8676
|
+
onDateClick,
|
|
8677
|
+
onMoreClick
|
|
8678
|
+
}
|
|
8679
|
+
);
|
|
8680
|
+
case "week":
|
|
8681
|
+
return /* @__PURE__ */ jsx(
|
|
8682
|
+
WeekView,
|
|
8683
|
+
{
|
|
8684
|
+
className: "h-full",
|
|
8685
|
+
weekStartsOn,
|
|
8686
|
+
onEventClick,
|
|
8687
|
+
onDateClick,
|
|
8688
|
+
onTimeClick
|
|
8689
|
+
}
|
|
8690
|
+
);
|
|
8691
|
+
case "day":
|
|
8692
|
+
return /* @__PURE__ */ jsx(
|
|
8693
|
+
DayView,
|
|
8694
|
+
{
|
|
8695
|
+
className: "h-full",
|
|
8696
|
+
onEventClick,
|
|
8697
|
+
onTimeClick
|
|
8698
|
+
}
|
|
8699
|
+
);
|
|
8700
|
+
case "year":
|
|
8701
|
+
return /* @__PURE__ */ jsx(
|
|
8702
|
+
YearView,
|
|
8703
|
+
{
|
|
8704
|
+
className: "h-full",
|
|
8705
|
+
weekStartsOn,
|
|
8706
|
+
onDateClick
|
|
8707
|
+
}
|
|
8708
|
+
);
|
|
8709
|
+
case "agenda":
|
|
8710
|
+
return /* @__PURE__ */ jsx(
|
|
8711
|
+
AgendaView,
|
|
8712
|
+
{
|
|
8713
|
+
className: "h-full",
|
|
8714
|
+
onEventClick,
|
|
8715
|
+
onDateClick
|
|
8716
|
+
}
|
|
8717
|
+
);
|
|
8718
|
+
default:
|
|
8719
|
+
return null;
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
5430
8722
|
|
|
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,
|
|
8723
|
+
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, 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
8724
|
//# sourceMappingURL=index.js.map
|
|
5433
8725
|
//# sourceMappingURL=index.js.map
|