@yca-software/yca-react-core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/admin/index.d.ts +10 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin-BVYdWtEy.d.ts +3 -0
- package/dist/api/index.d.ts +68 -0
- package/dist/api/index.js +3 -0
- package/dist/api/index.js.map +1 -0
- package/dist/auth/index.d.ts +49 -0
- package/dist/auth/index.js +3 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/chunk-2HJO2ICF.js +339 -0
- package/dist/chunk-2HJO2ICF.js.map +1 -0
- package/dist/chunk-3AYG73DK.js +174 -0
- package/dist/chunk-3AYG73DK.js.map +1 -0
- package/dist/chunk-3SCZ4Z6P.js +26 -0
- package/dist/chunk-3SCZ4Z6P.js.map +1 -0
- package/dist/chunk-3ZLODBRJ.js +21 -0
- package/dist/chunk-3ZLODBRJ.js.map +1 -0
- package/dist/chunk-6LO5O4G6.js +224 -0
- package/dist/chunk-6LO5O4G6.js.map +1 -0
- package/dist/chunk-APZVW5SW.js +75 -0
- package/dist/chunk-APZVW5SW.js.map +1 -0
- package/dist/chunk-EVZBADFR.js +583 -0
- package/dist/chunk-EVZBADFR.js.map +1 -0
- package/dist/chunk-GXWVFQCK.js +52 -0
- package/dist/chunk-GXWVFQCK.js.map +1 -0
- package/dist/chunk-KG4JVAKS.js +13 -0
- package/dist/chunk-KG4JVAKS.js.map +1 -0
- package/dist/chunk-KZH56VPP.js +183 -0
- package/dist/chunk-KZH56VPP.js.map +1 -0
- package/dist/chunk-LP7Q75C6.js +96 -0
- package/dist/chunk-LP7Q75C6.js.map +1 -0
- package/dist/chunk-NL4NAHXG.js +3 -0
- package/dist/chunk-NL4NAHXG.js.map +1 -0
- package/dist/chunk-PLSNCPEC.js +2507 -0
- package/dist/chunk-PLSNCPEC.js.map +1 -0
- package/dist/chunk-QFKVPVFC.js +1391 -0
- package/dist/chunk-QFKVPVFC.js.map +1 -0
- package/dist/chunk-TSXUUD64.js +64 -0
- package/dist/chunk-TSXUUD64.js.map +1 -0
- package/dist/chunk-UCJ76BEC.js +32 -0
- package/dist/chunk-UCJ76BEC.js.map +1 -0
- package/dist/chunk-WFTIYYII.js +3 -0
- package/dist/chunk-WFTIYYII.js.map +1 -0
- package/dist/components/forms/index.d.ts +101 -0
- package/dist/components/forms/index.js +7 -0
- package/dist/components/forms/index.js.map +1 -0
- package/dist/components/marketing/index.d.ts +473 -0
- package/dist/components/marketing/index.js +5 -0
- package/dist/components/marketing/index.js.map +1 -0
- package/dist/components/spa/index.d.ts +275 -0
- package/dist/components/spa/index.js +8 -0
- package/dist/components/spa/index.js.map +1 -0
- package/dist/components/ui/index.d.ts +420 -0
- package/dist/components/ui/index.js +6 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/constants/index.d.ts +2 -0
- package/dist/constants/index.js +4 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/cookies-ZS_QYOR7.d.ts +8 -0
- package/dist/dateRangePickerTranslations-B99F2WQA.d.ts +9 -0
- package/dist/errors/index.d.ts +48 -0
- package/dist/errors/index.js +3 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/forms-VpLvEFob.d.ts +18 -0
- package/dist/hooks/index.d.ts +18 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/index.d.ts +49 -0
- package/dist/lib/index.js +7 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/pagination-CFqoqiAG.d.ts +10 -0
- package/dist/radix-overlays-BlCr-uem.d.ts +10 -0
- package/dist/styles.css +9 -0
- package/dist/theme/marketing.css +750 -0
- package/dist/theme/tokens.css +115 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types-BuNHOJ1h.d.ts +58 -0
- package/dist/types-CN73TWSY.d.ts +51 -0
- package/dist/useAdminListPage-C4ZTTllP.d.ts +26 -0
- package/package.json +152 -0
|
@@ -0,0 +1,2507 @@
|
|
|
1
|
+
import { buttonVariants, Input, Button } from './chunk-3AYG73DK.js';
|
|
2
|
+
import { normalizeDate, DISPLAY_FORMAT, preventDismissOnPortaledOverlay, INPUT_FORMAT, INPUT_FORMAT_ALT } from './chunk-TSXUUD64.js';
|
|
3
|
+
import { cn, surfaceOverlay, controlFocus, controlInvalid, controlBase, surfaceCard } from './chunk-GXWVFQCK.js';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
7
|
+
import * as React6 from 'react';
|
|
8
|
+
import { useRef, useId, useState, useEffect } from 'react';
|
|
9
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
10
|
+
import { Check, ChevronLeft, ChevronRight, Loader2, Calendar as Calendar$1, XIcon, ChevronUp, ChevronDown, X, CheckSquare, FileText, ImagePlus, UploadCloud } from 'lucide-react';
|
|
11
|
+
import { DayPicker } from 'react-day-picker';
|
|
12
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
13
|
+
import { format, parse } from 'date-fns';
|
|
14
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
15
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
16
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
17
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
18
|
+
import { FormProvider, Controller, useFormContext, useFormState } from 'react-hook-form';
|
|
19
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
20
|
+
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
21
|
+
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
22
|
+
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
23
|
+
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
24
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
25
|
+
|
|
26
|
+
var alertVariants = cva(
|
|
27
|
+
"relative w-full rounded-xl border border-border/45 px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start shadow-[var(--shadow-surface)] [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
|
28
|
+
{
|
|
29
|
+
variants: {
|
|
30
|
+
variant: {
|
|
31
|
+
default: "bg-card text-card-foreground *:data-[slot=alert-description]:text-muted-foreground",
|
|
32
|
+
destructive: "bg-destructive/90 dark:bg-destructive text-destructive-foreground border-destructive/50 dark:border-destructive/70 [&>svg]:text-destructive-foreground *:data-[slot=alert-description]:text-destructive-foreground"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
defaultVariants: {
|
|
36
|
+
variant: "default"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
function Alert({
|
|
41
|
+
className,
|
|
42
|
+
variant,
|
|
43
|
+
...props
|
|
44
|
+
}) {
|
|
45
|
+
return /* @__PURE__ */ jsx(
|
|
46
|
+
"div",
|
|
47
|
+
{
|
|
48
|
+
"data-slot": "alert",
|
|
49
|
+
role: "alert",
|
|
50
|
+
className: cn(alertVariants({ variant }), className),
|
|
51
|
+
...props
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
function AlertDescription({ className, ...props }) {
|
|
56
|
+
return /* @__PURE__ */ jsx(
|
|
57
|
+
"div",
|
|
58
|
+
{
|
|
59
|
+
"data-slot": "alert-description",
|
|
60
|
+
className: cn(
|
|
61
|
+
"col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
|
|
62
|
+
className
|
|
63
|
+
),
|
|
64
|
+
...props
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
var AlertDialog = AlertDialogPrimitive.Root;
|
|
69
|
+
var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
70
|
+
var AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
71
|
+
var AlertDialogOverlay = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
72
|
+
AlertDialogPrimitive.Overlay,
|
|
73
|
+
{
|
|
74
|
+
className: cn(
|
|
75
|
+
"fixed inset-0 z-110 bg-foreground/20 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
76
|
+
className
|
|
77
|
+
),
|
|
78
|
+
...props,
|
|
79
|
+
ref
|
|
80
|
+
}
|
|
81
|
+
));
|
|
82
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
83
|
+
var AlertDialogContent = React6.forwardRef(({ className, onOverlayClick, overlayClassName, ...props }, ref) => /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [
|
|
84
|
+
/* @__PURE__ */ jsx(AlertDialogOverlay, { onClick: onOverlayClick, className: overlayClassName }),
|
|
85
|
+
/* @__PURE__ */ jsx(
|
|
86
|
+
AlertDialogPrimitive.Content,
|
|
87
|
+
{
|
|
88
|
+
ref,
|
|
89
|
+
className: cn(
|
|
90
|
+
surfaceOverlay,
|
|
91
|
+
"bg-background fixed left-[50%] top-[50%] z-110 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 p-6 duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
92
|
+
className
|
|
93
|
+
),
|
|
94
|
+
...props
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
] }));
|
|
98
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
99
|
+
var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
|
|
100
|
+
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
101
|
+
var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
102
|
+
"div",
|
|
103
|
+
{
|
|
104
|
+
className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
|
|
105
|
+
...props
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
109
|
+
var AlertDialogTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
110
|
+
AlertDialogPrimitive.Title,
|
|
111
|
+
{
|
|
112
|
+
ref,
|
|
113
|
+
className: cn("text-lg font-semibold", className),
|
|
114
|
+
...props
|
|
115
|
+
}
|
|
116
|
+
));
|
|
117
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
118
|
+
var AlertDialogDescription = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
119
|
+
AlertDialogPrimitive.Description,
|
|
120
|
+
{
|
|
121
|
+
ref,
|
|
122
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
123
|
+
...props
|
|
124
|
+
}
|
|
125
|
+
));
|
|
126
|
+
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
127
|
+
var AlertDialogAction = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
128
|
+
AlertDialogPrimitive.Action,
|
|
129
|
+
{
|
|
130
|
+
ref,
|
|
131
|
+
"data-slot": "alert-dialog-action",
|
|
132
|
+
className: cn(buttonVariants(), className),
|
|
133
|
+
...props
|
|
134
|
+
}
|
|
135
|
+
));
|
|
136
|
+
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
|
|
137
|
+
var AlertDialogCancel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
138
|
+
AlertDialogPrimitive.Cancel,
|
|
139
|
+
{
|
|
140
|
+
ref,
|
|
141
|
+
"data-slot": "alert-dialog-cancel",
|
|
142
|
+
className: cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className),
|
|
143
|
+
...props
|
|
144
|
+
}
|
|
145
|
+
));
|
|
146
|
+
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
|
|
147
|
+
var Avatar = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
148
|
+
AvatarPrimitive.Root,
|
|
149
|
+
{
|
|
150
|
+
ref,
|
|
151
|
+
className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
|
|
152
|
+
...props
|
|
153
|
+
}
|
|
154
|
+
));
|
|
155
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
156
|
+
var AvatarImage = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
157
|
+
AvatarPrimitive.Image,
|
|
158
|
+
{
|
|
159
|
+
ref,
|
|
160
|
+
className: cn("aspect-square h-full w-full", className),
|
|
161
|
+
...props
|
|
162
|
+
}
|
|
163
|
+
));
|
|
164
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
165
|
+
var AvatarFallback = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
166
|
+
AvatarPrimitive.Fallback,
|
|
167
|
+
{
|
|
168
|
+
ref,
|
|
169
|
+
className: cn(
|
|
170
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
171
|
+
className
|
|
172
|
+
),
|
|
173
|
+
...props
|
|
174
|
+
}
|
|
175
|
+
));
|
|
176
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
177
|
+
var badgeVariants = cva(
|
|
178
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold whitespace-nowrap transition-colors",
|
|
179
|
+
{
|
|
180
|
+
variants: {
|
|
181
|
+
variant: {
|
|
182
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
183
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
184
|
+
destructive: "border-transparent bg-destructive text-white hover:bg-destructive/80",
|
|
185
|
+
outline: "border-border/50 text-foreground bg-background/80"
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
defaultVariants: {
|
|
189
|
+
variant: "default"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
function Badge({
|
|
194
|
+
className,
|
|
195
|
+
variant,
|
|
196
|
+
...props
|
|
197
|
+
}) {
|
|
198
|
+
return /* @__PURE__ */ jsx("span", { "data-slot": "badge", className: cn(badgeVariants({ variant }), className), ...props });
|
|
199
|
+
}
|
|
200
|
+
function Calendar({
|
|
201
|
+
className,
|
|
202
|
+
classNames,
|
|
203
|
+
showOutsideDays = true,
|
|
204
|
+
weekStartsOn,
|
|
205
|
+
...props
|
|
206
|
+
}) {
|
|
207
|
+
return /* @__PURE__ */ jsx(
|
|
208
|
+
DayPicker,
|
|
209
|
+
{
|
|
210
|
+
"data-slot": "calendar",
|
|
211
|
+
showOutsideDays,
|
|
212
|
+
weekStartsOn: weekStartsOn ?? 1,
|
|
213
|
+
navLayout: "around",
|
|
214
|
+
className: cn("p-3", className),
|
|
215
|
+
classNames: {
|
|
216
|
+
months: "flex flex-col items-stretch justify-center gap-4 sm:flex-row sm:items-start sm:gap-6",
|
|
217
|
+
month: "relative min-w-0 space-y-3",
|
|
218
|
+
month_caption: "flex items-center justify-center w-full h-9 pt-1 px-10",
|
|
219
|
+
caption_label: "text-sm font-medium text-center pointer-events-none",
|
|
220
|
+
nav: "contents",
|
|
221
|
+
button_previous: cn(
|
|
222
|
+
buttonVariants({ variant: "outline", size: "icon-sm" }),
|
|
223
|
+
"absolute left-0 top-1 z-10 h-8 w-8 bg-transparent p-0 opacity-70 hover:opacity-100"
|
|
224
|
+
),
|
|
225
|
+
button_next: cn(
|
|
226
|
+
buttonVariants({ variant: "outline", size: "icon-sm" }),
|
|
227
|
+
"absolute right-0 top-1 z-10 h-8 w-8 bg-transparent p-0 opacity-70 hover:opacity-100"
|
|
228
|
+
),
|
|
229
|
+
month_grid: "w-full border-collapse",
|
|
230
|
+
weekdays: "",
|
|
231
|
+
weekday: "text-muted-foreground w-10 rounded-md font-normal text-[0.75rem] text-center p-1",
|
|
232
|
+
weeks: "mt-1",
|
|
233
|
+
week: "",
|
|
234
|
+
day: "relative h-10 w-10 text-center text-sm p-0 align-top focus-within:relative focus-within:z-20",
|
|
235
|
+
day_button: cn(
|
|
236
|
+
"day-button inline-flex size-10 items-center justify-center rounded-md text-sm font-normal transition-colors cursor-pointer",
|
|
237
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
238
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
239
|
+
"aria-disabled:text-muted-foreground/60 aria-disabled:opacity-50 aria-disabled:cursor-not-allowed"
|
|
240
|
+
),
|
|
241
|
+
selected: "bg-primary/10 text-primary [&_.day-button]:bg-primary [&_.day-button]:text-primary-foreground",
|
|
242
|
+
today: "text-primary [&_.day-button]:border [&_.day-button]:border-primary [&_.day-button]:rounded-md [&.selected]:bg-primary [&.selected]:text-primary-foreground",
|
|
243
|
+
outside: "text-muted-foreground/60 [&.selected]:bg-accent/40 [&.selected]:text-accent-foreground",
|
|
244
|
+
range_middle: "bg-primary/15 text-foreground [&_.day-button]:bg-primary/15 [&_.day-button]:text-foreground [&_.day-button]:rounded-none",
|
|
245
|
+
range_end: "rounded-r-md text-primary-foreground [&_.day-button]:bg-primary [&_.day-button]:text-primary-foreground [&_.day-button]:rounded-r-md [&_.day-button]:rounded-l-none [&.range_start_.day-button]:!rounded-md",
|
|
246
|
+
range_start: "rounded-l-md text-primary-foreground [&_.day-button]:bg-primary [&_.day-button]:text-primary-foreground [&_.day-button]:rounded-l-md [&_.day-button]:rounded-r-none [&.range_end_.day-button]:!rounded-md",
|
|
247
|
+
disabled: "text-muted-foreground/60 opacity-50 [&_.day-button]:cursor-not-allowed",
|
|
248
|
+
...classNames
|
|
249
|
+
},
|
|
250
|
+
components: {
|
|
251
|
+
Chevron: ({ orientation }) => orientation === "left" ? /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4", "aria-hidden": true }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-4", "aria-hidden": true })
|
|
252
|
+
},
|
|
253
|
+
...props
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
var Checkbox = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
258
|
+
CheckboxPrimitive.Root,
|
|
259
|
+
{
|
|
260
|
+
ref,
|
|
261
|
+
"data-slot": "checkbox",
|
|
262
|
+
className: cn(
|
|
263
|
+
"peer size-4 shrink-0 rounded-[5px] border border-border/55 bg-muted/30 shadow-[var(--shadow-surface)] transition-colors",
|
|
264
|
+
controlFocus,
|
|
265
|
+
controlInvalid,
|
|
266
|
+
"cursor-pointer disabled:cursor-not-allowed disabled:opacity-50",
|
|
267
|
+
"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground",
|
|
268
|
+
"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground",
|
|
269
|
+
className
|
|
270
|
+
),
|
|
271
|
+
...props,
|
|
272
|
+
children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: /* @__PURE__ */ jsx(Check, { className: "size-2.5", strokeWidth: 3 }) })
|
|
273
|
+
}
|
|
274
|
+
));
|
|
275
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
276
|
+
function ConfirmDialog({
|
|
277
|
+
open,
|
|
278
|
+
onOpenChange,
|
|
279
|
+
title,
|
|
280
|
+
description,
|
|
281
|
+
descriptionNote,
|
|
282
|
+
cancelLabel = "Cancel",
|
|
283
|
+
confirmLabel,
|
|
284
|
+
variant = "default",
|
|
285
|
+
onConfirm,
|
|
286
|
+
isPending = false,
|
|
287
|
+
confirmAriaLabel,
|
|
288
|
+
className,
|
|
289
|
+
closeOnOutsideClick = false
|
|
290
|
+
}) {
|
|
291
|
+
const confirmRef = useRef(null);
|
|
292
|
+
const isDestructive = variant === "destructive";
|
|
293
|
+
const confirmClassName = isDestructive ? "bg-destructive text-destructive-foreground hover:bg-destructive/90 focus-visible:ring-destructive/20" : void 0;
|
|
294
|
+
const handleConfirm = () => {
|
|
295
|
+
if (isPending) return;
|
|
296
|
+
onConfirm();
|
|
297
|
+
};
|
|
298
|
+
return /* @__PURE__ */ jsx(AlertDialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
299
|
+
AlertDialogContent,
|
|
300
|
+
{
|
|
301
|
+
"data-slot": "confirm-dialog-content",
|
|
302
|
+
className: cn("gap-4 sm:gap-6", className),
|
|
303
|
+
onOpenAutoFocus: (event) => {
|
|
304
|
+
event.preventDefault();
|
|
305
|
+
confirmRef.current?.focus();
|
|
306
|
+
},
|
|
307
|
+
onKeyDown: (event) => {
|
|
308
|
+
if (event.key !== "Enter" || isPending) return;
|
|
309
|
+
const target = event.target;
|
|
310
|
+
if (target.closest('[data-slot="alert-dialog-cancel"]')) return;
|
|
311
|
+
if (target.closest('[data-slot="alert-dialog-action"]')) return;
|
|
312
|
+
event.preventDefault();
|
|
313
|
+
handleConfirm();
|
|
314
|
+
},
|
|
315
|
+
...closeOnOutsideClick && {
|
|
316
|
+
onOverlayClick: () => onOpenChange(false)
|
|
317
|
+
},
|
|
318
|
+
children: [
|
|
319
|
+
/* @__PURE__ */ jsxs(AlertDialogHeader, { className: "gap-2", children: [
|
|
320
|
+
/* @__PURE__ */ jsx(AlertDialogTitle, { className: "text-base sm:text-lg", children: title }),
|
|
321
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
322
|
+
/* @__PURE__ */ jsx(AlertDialogDescription, { className: "text-sm", children: description }),
|
|
323
|
+
descriptionNote && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: descriptionNote })
|
|
324
|
+
] })
|
|
325
|
+
] }),
|
|
326
|
+
/* @__PURE__ */ jsxs(AlertDialogFooter, { className: "flex flex-col-reverse gap-2 pt-2 sm:flex-row sm:justify-end sm:gap-2 sm:pt-0", children: [
|
|
327
|
+
/* @__PURE__ */ jsx(
|
|
328
|
+
AlertDialogCancel,
|
|
329
|
+
{
|
|
330
|
+
onClick: () => onOpenChange(false),
|
|
331
|
+
disabled: isPending,
|
|
332
|
+
className: "m-0 w-full sm:w-auto",
|
|
333
|
+
children: cancelLabel
|
|
334
|
+
}
|
|
335
|
+
),
|
|
336
|
+
/* @__PURE__ */ jsxs(
|
|
337
|
+
AlertDialogAction,
|
|
338
|
+
{
|
|
339
|
+
ref: confirmRef,
|
|
340
|
+
onClick: handleConfirm,
|
|
341
|
+
disabled: isPending,
|
|
342
|
+
"aria-label": confirmAriaLabel ?? confirmLabel,
|
|
343
|
+
className: cn("m-0 w-full sm:w-auto", confirmClassName),
|
|
344
|
+
children: [
|
|
345
|
+
isPending && /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin", "aria-hidden": true }),
|
|
346
|
+
confirmLabel
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
)
|
|
350
|
+
] })
|
|
351
|
+
]
|
|
352
|
+
}
|
|
353
|
+
) });
|
|
354
|
+
}
|
|
355
|
+
function Popover({ ...props }) {
|
|
356
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
|
|
357
|
+
}
|
|
358
|
+
function PopoverTrigger({ ...props }) {
|
|
359
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
360
|
+
}
|
|
361
|
+
function PopoverContent({
|
|
362
|
+
className,
|
|
363
|
+
align = "start",
|
|
364
|
+
sideOffset = 4,
|
|
365
|
+
...props
|
|
366
|
+
}) {
|
|
367
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
368
|
+
PopoverPrimitive.Content,
|
|
369
|
+
{
|
|
370
|
+
"data-slot": "popover-content",
|
|
371
|
+
align,
|
|
372
|
+
sideOffset,
|
|
373
|
+
className: cn(
|
|
374
|
+
surfaceOverlay,
|
|
375
|
+
"z-110 w-auto min-w-48 p-3 outline-none",
|
|
376
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
377
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
378
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
379
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
380
|
+
"data-[side=top]:slide-in-from-bottom-2",
|
|
381
|
+
"data-[side=left]:slide-in-from-right-2",
|
|
382
|
+
"data-[side=right]:slide-in-from-left-2",
|
|
383
|
+
className
|
|
384
|
+
),
|
|
385
|
+
...props
|
|
386
|
+
}
|
|
387
|
+
) });
|
|
388
|
+
}
|
|
389
|
+
function DatePicker({
|
|
390
|
+
value,
|
|
391
|
+
onChange,
|
|
392
|
+
minDate,
|
|
393
|
+
maxDate,
|
|
394
|
+
placeholder = "Pick a date",
|
|
395
|
+
disabled = false,
|
|
396
|
+
locale,
|
|
397
|
+
className,
|
|
398
|
+
"aria-label": ariaLabel
|
|
399
|
+
}) {
|
|
400
|
+
const [open, setOpen] = React6.useState(false);
|
|
401
|
+
const normalizedMin = normalizeDate(minDate);
|
|
402
|
+
const normalizedMax = normalizeDate(maxDate);
|
|
403
|
+
const formatOpts = React6.useMemo(() => locale ? { locale } : void 0, [locale]);
|
|
404
|
+
const disabledMatchers = React6.useMemo(() => {
|
|
405
|
+
const toStartOfDay = (d) => {
|
|
406
|
+
const copy = new Date(d);
|
|
407
|
+
copy.setHours(0, 0, 0, 0);
|
|
408
|
+
return copy.getTime();
|
|
409
|
+
};
|
|
410
|
+
const matchers = [];
|
|
411
|
+
if (normalizedMin) {
|
|
412
|
+
matchers.push((date) => toStartOfDay(date) < toStartOfDay(normalizedMin));
|
|
413
|
+
}
|
|
414
|
+
if (normalizedMax) {
|
|
415
|
+
matchers.push((date) => toStartOfDay(date) > toStartOfDay(normalizedMax));
|
|
416
|
+
}
|
|
417
|
+
return matchers;
|
|
418
|
+
}, [normalizedMin, normalizedMax]);
|
|
419
|
+
const handleSelect = (date) => {
|
|
420
|
+
const day = date ? normalizeDate(date) : void 0;
|
|
421
|
+
onChange(day ?? void 0);
|
|
422
|
+
setOpen(false);
|
|
423
|
+
};
|
|
424
|
+
return /* @__PURE__ */ jsxs(Popover, { modal: false, open, onOpenChange: setOpen, children: [
|
|
425
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
426
|
+
"div",
|
|
427
|
+
{
|
|
428
|
+
role: "button",
|
|
429
|
+
tabIndex: disabled ? -1 : 0,
|
|
430
|
+
onKeyDown: (e) => {
|
|
431
|
+
if (!disabled && (e.key === "Enter" || e.key === " ")) {
|
|
432
|
+
e.preventDefault();
|
|
433
|
+
setOpen((o) => !o);
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
className: cn(
|
|
437
|
+
controlBase,
|
|
438
|
+
controlFocus,
|
|
439
|
+
"flex w-full cursor-pointer items-center overflow-hidden",
|
|
440
|
+
disabled && "pointer-events-none opacity-50",
|
|
441
|
+
className
|
|
442
|
+
),
|
|
443
|
+
children: [
|
|
444
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-9 w-9 shrink-0 items-center justify-center border-r border-border/40 bg-muted/25 text-muted-foreground", children: /* @__PURE__ */ jsx(Calendar$1, { className: "size-4", "aria-hidden": true }) }),
|
|
445
|
+
/* @__PURE__ */ jsx(
|
|
446
|
+
Input,
|
|
447
|
+
{
|
|
448
|
+
type: "text",
|
|
449
|
+
readOnly: true,
|
|
450
|
+
value: value ? format(value, DISPLAY_FORMAT, formatOpts) : "",
|
|
451
|
+
placeholder,
|
|
452
|
+
onClick: () => !disabled && setOpen(true),
|
|
453
|
+
className: cn(
|
|
454
|
+
"h-9 min-w-0 flex-1 cursor-pointer rounded-l-none border-0 bg-transparent py-2 pl-3 pr-3 text-base shadow-none focus-visible:ring-0 md:text-sm capitalize",
|
|
455
|
+
!value && "text-muted-foreground"
|
|
456
|
+
),
|
|
457
|
+
"aria-label": ariaLabel
|
|
458
|
+
}
|
|
459
|
+
)
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
) }),
|
|
463
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0 z-[120]", align: "start", children: /* @__PURE__ */ jsx(
|
|
464
|
+
Calendar,
|
|
465
|
+
{
|
|
466
|
+
mode: "single",
|
|
467
|
+
selected: value,
|
|
468
|
+
onSelect: handleSelect,
|
|
469
|
+
disabled: (date) => disabledMatchers.some((m) => m(date)),
|
|
470
|
+
locale
|
|
471
|
+
}
|
|
472
|
+
) })
|
|
473
|
+
] });
|
|
474
|
+
}
|
|
475
|
+
function Dialog({ ...props }) {
|
|
476
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
477
|
+
}
|
|
478
|
+
function DialogTrigger({ ...props }) {
|
|
479
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
|
|
480
|
+
}
|
|
481
|
+
function DialogPortal({ ...props }) {
|
|
482
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
|
|
483
|
+
}
|
|
484
|
+
function DialogClose({ ...props }) {
|
|
485
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
|
|
486
|
+
}
|
|
487
|
+
function DialogOverlay({
|
|
488
|
+
className,
|
|
489
|
+
...props
|
|
490
|
+
}) {
|
|
491
|
+
return /* @__PURE__ */ jsx(
|
|
492
|
+
DialogPrimitive.Overlay,
|
|
493
|
+
{
|
|
494
|
+
"data-slot": "dialog-overlay",
|
|
495
|
+
className: cn(
|
|
496
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-110 bg-foreground/20 backdrop-blur-[2px]",
|
|
497
|
+
className
|
|
498
|
+
),
|
|
499
|
+
...props
|
|
500
|
+
}
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
function DialogContent({
|
|
504
|
+
className,
|
|
505
|
+
children,
|
|
506
|
+
showCloseButton = true,
|
|
507
|
+
overlayClassName,
|
|
508
|
+
onPointerDownOutside,
|
|
509
|
+
onInteractOutside,
|
|
510
|
+
onFocusOutside,
|
|
511
|
+
...props
|
|
512
|
+
}) {
|
|
513
|
+
return /* @__PURE__ */ jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
|
|
514
|
+
/* @__PURE__ */ jsx(DialogOverlay, { className: overlayClassName }),
|
|
515
|
+
/* @__PURE__ */ jsxs(
|
|
516
|
+
DialogPrimitive.Content,
|
|
517
|
+
{
|
|
518
|
+
"data-slot": "dialog-content",
|
|
519
|
+
onPointerDownOutside: (event) => {
|
|
520
|
+
preventDismissOnPortaledOverlay(event);
|
|
521
|
+
if (!event.defaultPrevented) {
|
|
522
|
+
onPointerDownOutside?.(event);
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
onInteractOutside: (event) => {
|
|
526
|
+
preventDismissOnPortaledOverlay(event);
|
|
527
|
+
if (!event.defaultPrevented) {
|
|
528
|
+
onInteractOutside?.(event);
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
onFocusOutside: (event) => {
|
|
532
|
+
preventDismissOnPortaledOverlay(event);
|
|
533
|
+
if (!event.defaultPrevented) {
|
|
534
|
+
onFocusOutside?.(event);
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
className: cn(
|
|
538
|
+
surfaceOverlay,
|
|
539
|
+
"bg-background 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 fixed top-[50%] left-[50%] z-110 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 p-6 duration-200 outline-none sm:max-w-lg",
|
|
540
|
+
className
|
|
541
|
+
),
|
|
542
|
+
...props,
|
|
543
|
+
children: [
|
|
544
|
+
children,
|
|
545
|
+
showCloseButton && /* @__PURE__ */ jsxs(
|
|
546
|
+
DialogPrimitive.Close,
|
|
547
|
+
{
|
|
548
|
+
"data-slot": "dialog-close",
|
|
549
|
+
className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none cursor-pointer [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
550
|
+
children: [
|
|
551
|
+
/* @__PURE__ */ jsx(XIcon, {}),
|
|
552
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
553
|
+
]
|
|
554
|
+
}
|
|
555
|
+
)
|
|
556
|
+
]
|
|
557
|
+
}
|
|
558
|
+
)
|
|
559
|
+
] });
|
|
560
|
+
}
|
|
561
|
+
function DialogHeader({ className, ...props }) {
|
|
562
|
+
return /* @__PURE__ */ jsx(
|
|
563
|
+
"div",
|
|
564
|
+
{
|
|
565
|
+
"data-slot": "dialog-header",
|
|
566
|
+
className: cn("flex w-full flex-col items-center gap-2 text-center", className),
|
|
567
|
+
...props
|
|
568
|
+
}
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
function DialogFooter({ className, ...props }) {
|
|
572
|
+
return /* @__PURE__ */ jsx(
|
|
573
|
+
"div",
|
|
574
|
+
{
|
|
575
|
+
"data-slot": "dialog-footer",
|
|
576
|
+
className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className),
|
|
577
|
+
...props
|
|
578
|
+
}
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
function DialogTitle({ className, ...props }) {
|
|
582
|
+
return /* @__PURE__ */ jsx(
|
|
583
|
+
DialogPrimitive.Title,
|
|
584
|
+
{
|
|
585
|
+
"data-slot": "dialog-title",
|
|
586
|
+
className: cn("w-full text-lg leading-none font-semibold text-center", className),
|
|
587
|
+
...props
|
|
588
|
+
}
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
function DialogDescription({
|
|
592
|
+
className,
|
|
593
|
+
...props
|
|
594
|
+
}) {
|
|
595
|
+
return /* @__PURE__ */ jsx(
|
|
596
|
+
DialogPrimitive.Description,
|
|
597
|
+
{
|
|
598
|
+
"data-slot": "dialog-description",
|
|
599
|
+
className: cn("w-full text-muted-foreground text-sm text-center", className),
|
|
600
|
+
...props
|
|
601
|
+
}
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// src/components/ui/date-range-picker/constants.ts
|
|
606
|
+
var DATE_RANGE_MOBILE_MAX_PX = 640;
|
|
607
|
+
var DATE_RANGE_MOBILE_MQ = `(max-width: ${DATE_RANGE_MOBILE_MAX_PX - 1}px)`;
|
|
608
|
+
var DATE_RANGE_WIDE_MIN_PX = 768;
|
|
609
|
+
var DATE_RANGE_WIDE_MQ = `(min-width: ${DATE_RANGE_WIDE_MIN_PX}px)`;
|
|
610
|
+
var DEFAULT_PRESET_IDS = [
|
|
611
|
+
{ id: "today" },
|
|
612
|
+
{ id: "yesterday" },
|
|
613
|
+
{ id: "last7" },
|
|
614
|
+
{ id: "last14" },
|
|
615
|
+
{ id: "last30" },
|
|
616
|
+
{ id: "thisWeek" },
|
|
617
|
+
{ id: "lastWeek" },
|
|
618
|
+
{ id: "thisMonth" },
|
|
619
|
+
{ id: "lastMonth" }
|
|
620
|
+
];
|
|
621
|
+
var DEFAULT_PRESET_LABELS = {
|
|
622
|
+
today: "Today",
|
|
623
|
+
yesterday: "Yesterday",
|
|
624
|
+
last7: "Last 7 days",
|
|
625
|
+
last14: "Last 14 days",
|
|
626
|
+
last30: "Last 30 days",
|
|
627
|
+
thisWeek: "This week",
|
|
628
|
+
lastWeek: "Last week",
|
|
629
|
+
thisMonth: "This month",
|
|
630
|
+
lastMonth: "Last month"
|
|
631
|
+
};
|
|
632
|
+
var DEFAULT_TRANSLATIONS = {
|
|
633
|
+
applyButton: "Apply",
|
|
634
|
+
cancelButton: "Cancel",
|
|
635
|
+
startLabel: "Start",
|
|
636
|
+
endLabel: "End",
|
|
637
|
+
placeholder: "YYYY/MM/DD",
|
|
638
|
+
ariaLabel: "Date range",
|
|
639
|
+
presetLabels: DEFAULT_PRESET_LABELS,
|
|
640
|
+
presetsHeading: "Quick ranges"
|
|
641
|
+
};
|
|
642
|
+
function DateRangePickerActionFooter({
|
|
643
|
+
visible,
|
|
644
|
+
isMobileLayout,
|
|
645
|
+
cancelLabel,
|
|
646
|
+
applyLabel,
|
|
647
|
+
onCancel,
|
|
648
|
+
onApply,
|
|
649
|
+
className
|
|
650
|
+
}) {
|
|
651
|
+
if (!visible) return null;
|
|
652
|
+
return /* @__PURE__ */ jsxs(
|
|
653
|
+
"div",
|
|
654
|
+
{
|
|
655
|
+
className: cn(
|
|
656
|
+
"flex w-full items-center justify-end gap-2 border-t border-border/50 bg-muted/15 px-4 py-3",
|
|
657
|
+
isMobileLayout && "mt-auto shrink-0 bg-background pb-[max(1rem,env(safe-area-inset-bottom))] pt-4",
|
|
658
|
+
className
|
|
659
|
+
),
|
|
660
|
+
children: [
|
|
661
|
+
/* @__PURE__ */ jsx(
|
|
662
|
+
Button,
|
|
663
|
+
{
|
|
664
|
+
type: "button",
|
|
665
|
+
variant: "ghost",
|
|
666
|
+
size: "sm",
|
|
667
|
+
className: cn(isMobileLayout && "min-h-10 flex-1 sm:min-h-9 sm:flex-initial"),
|
|
668
|
+
onClick: onCancel,
|
|
669
|
+
children: cancelLabel
|
|
670
|
+
}
|
|
671
|
+
),
|
|
672
|
+
/* @__PURE__ */ jsx(
|
|
673
|
+
Button,
|
|
674
|
+
{
|
|
675
|
+
type: "button",
|
|
676
|
+
size: "sm",
|
|
677
|
+
className: cn(isMobileLayout && "min-h-10 flex-1 sm:min-h-9 sm:flex-initial"),
|
|
678
|
+
onClick: onApply,
|
|
679
|
+
children: applyLabel
|
|
680
|
+
}
|
|
681
|
+
)
|
|
682
|
+
]
|
|
683
|
+
}
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
function DateRangePickerFieldsCalendar({
|
|
687
|
+
calendarMonths,
|
|
688
|
+
draft,
|
|
689
|
+
displayedMonth,
|
|
690
|
+
onMonthChange,
|
|
691
|
+
onSelect,
|
|
692
|
+
disabledMatchers,
|
|
693
|
+
locale,
|
|
694
|
+
startInputId,
|
|
695
|
+
endInputId,
|
|
696
|
+
startLabel,
|
|
697
|
+
endLabel,
|
|
698
|
+
startInputText,
|
|
699
|
+
endInputText,
|
|
700
|
+
effectivePlaceholder,
|
|
701
|
+
onStartInputChange,
|
|
702
|
+
onEndInputChange,
|
|
703
|
+
onCommitStart,
|
|
704
|
+
onCommitEnd
|
|
705
|
+
}) {
|
|
706
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-4", children: [
|
|
707
|
+
/* @__PURE__ */ jsxs(
|
|
708
|
+
"div",
|
|
709
|
+
{
|
|
710
|
+
className: cn(
|
|
711
|
+
"grid w-full grid-cols-1 gap-3 rounded-xl border border-border/45 bg-muted/20 p-3 sm:grid-cols-2",
|
|
712
|
+
calendarMonths === 2 ? "max-w-none" : "max-w-md"
|
|
713
|
+
),
|
|
714
|
+
children: [
|
|
715
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
716
|
+
/* @__PURE__ */ jsx("label", { htmlFor: startInputId, className: "text-xs font-medium text-muted-foreground", children: startLabel }),
|
|
717
|
+
/* @__PURE__ */ jsx(
|
|
718
|
+
Input,
|
|
719
|
+
{
|
|
720
|
+
id: startInputId,
|
|
721
|
+
type: "text",
|
|
722
|
+
value: startInputText,
|
|
723
|
+
onChange: (e) => onStartInputChange(e.target.value),
|
|
724
|
+
onBlur: onCommitStart,
|
|
725
|
+
onKeyDown: (e) => {
|
|
726
|
+
if (e.key === "Enter") {
|
|
727
|
+
e.preventDefault();
|
|
728
|
+
onCommitStart();
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
placeholder: effectivePlaceholder,
|
|
732
|
+
className: "h-9 font-mono text-sm tabular-nums"
|
|
733
|
+
}
|
|
734
|
+
)
|
|
735
|
+
] }),
|
|
736
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
737
|
+
/* @__PURE__ */ jsx("label", { htmlFor: endInputId, className: "text-xs font-medium text-muted-foreground", children: endLabel }),
|
|
738
|
+
/* @__PURE__ */ jsx(
|
|
739
|
+
Input,
|
|
740
|
+
{
|
|
741
|
+
id: endInputId,
|
|
742
|
+
type: "text",
|
|
743
|
+
value: endInputText,
|
|
744
|
+
onChange: (e) => onEndInputChange(e.target.value),
|
|
745
|
+
onBlur: onCommitEnd,
|
|
746
|
+
onKeyDown: (e) => {
|
|
747
|
+
if (e.key === "Enter") {
|
|
748
|
+
e.preventDefault();
|
|
749
|
+
onCommitEnd();
|
|
750
|
+
}
|
|
751
|
+
},
|
|
752
|
+
placeholder: effectivePlaceholder,
|
|
753
|
+
className: "h-9 font-mono text-sm tabular-nums"
|
|
754
|
+
}
|
|
755
|
+
)
|
|
756
|
+
] })
|
|
757
|
+
]
|
|
758
|
+
}
|
|
759
|
+
),
|
|
760
|
+
/* @__PURE__ */ jsx("div", { className: cn(surfaceCard, "flex w-full justify-center p-1"), children: /* @__PURE__ */ jsx(
|
|
761
|
+
Calendar,
|
|
762
|
+
{
|
|
763
|
+
mode: "range",
|
|
764
|
+
numberOfMonths: calendarMonths,
|
|
765
|
+
month: displayedMonth,
|
|
766
|
+
onMonthChange,
|
|
767
|
+
selected: draft,
|
|
768
|
+
onSelect,
|
|
769
|
+
disabled: disabledMatchers,
|
|
770
|
+
locale,
|
|
771
|
+
className: cn(calendarMonths === 2 && "p-2")
|
|
772
|
+
}
|
|
773
|
+
) })
|
|
774
|
+
] });
|
|
775
|
+
}
|
|
776
|
+
function rangesMatch(a, b) {
|
|
777
|
+
const af = normalizeDate(a?.from)?.getTime();
|
|
778
|
+
const at = normalizeDate(a?.to)?.getTime();
|
|
779
|
+
const bf = normalizeDate(b.from)?.getTime();
|
|
780
|
+
const bt = normalizeDate(b.to)?.getTime();
|
|
781
|
+
return af === bf && at === bt;
|
|
782
|
+
}
|
|
783
|
+
function parseDate(part) {
|
|
784
|
+
const p = part.trim();
|
|
785
|
+
if (!p) return null;
|
|
786
|
+
const ref = /* @__PURE__ */ new Date();
|
|
787
|
+
for (const fmt of [INPUT_FORMAT, INPUT_FORMAT_ALT, DISPLAY_FORMAT]) {
|
|
788
|
+
try {
|
|
789
|
+
const d = parse(p, fmt, ref);
|
|
790
|
+
if (!Number.isNaN(d.getTime())) return d;
|
|
791
|
+
} catch {
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return null;
|
|
795
|
+
}
|
|
796
|
+
function parseInputToRange(text) {
|
|
797
|
+
const trimmed = text.trim();
|
|
798
|
+
if (!trimmed) return { from: void 0, to: void 0 };
|
|
799
|
+
const parts = trimmed.split(/\s*[–-]\s*/).map((p) => p.trim());
|
|
800
|
+
try {
|
|
801
|
+
if (parts.length >= 2) {
|
|
802
|
+
const from = parseDate(parts[0]);
|
|
803
|
+
const to = parseDate(parts[1]);
|
|
804
|
+
if (from && to) return { from, to };
|
|
805
|
+
if (from) return { from, to: void 0 };
|
|
806
|
+
} else if (parts.length === 1 && parts[0]) {
|
|
807
|
+
const from = parseDate(parts[0]);
|
|
808
|
+
if (from) return { from, to: void 0 };
|
|
809
|
+
}
|
|
810
|
+
} catch {
|
|
811
|
+
}
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
function formatRangeLabel(value, placeholder, formatOpts) {
|
|
815
|
+
const from = value?.from;
|
|
816
|
+
const to = value?.to;
|
|
817
|
+
if (from && to) {
|
|
818
|
+
return `${format(from, DISPLAY_FORMAT, formatOpts)} \u2013 ${format(to, DISPLAY_FORMAT, formatOpts)}`;
|
|
819
|
+
}
|
|
820
|
+
if (from) {
|
|
821
|
+
return format(from, DISPLAY_FORMAT, formatOpts);
|
|
822
|
+
}
|
|
823
|
+
return placeholder;
|
|
824
|
+
}
|
|
825
|
+
function DateRangePickerPresetList({
|
|
826
|
+
presets,
|
|
827
|
+
draft,
|
|
828
|
+
layout,
|
|
829
|
+
presetsHeading,
|
|
830
|
+
onPreset
|
|
831
|
+
}) {
|
|
832
|
+
if (presets.length === 0) return null;
|
|
833
|
+
if (layout === "mobile-row") {
|
|
834
|
+
return /* @__PURE__ */ jsx("div", { className: "shrink-0 border-b border-border/50 bg-muted/20 px-2 py-2", children: /* @__PURE__ */ jsx("div", { className: "flex gap-1 overflow-x-auto overscroll-x-contain px-1 py-1 [scrollbar-width:thin] [-webkit-overflow-scrolling:touch]", children: presets.map((preset) => {
|
|
835
|
+
const active = rangesMatch(draft, preset.getRange());
|
|
836
|
+
return /* @__PURE__ */ jsx(
|
|
837
|
+
Button,
|
|
838
|
+
{
|
|
839
|
+
type: "button",
|
|
840
|
+
variant: "ghost",
|
|
841
|
+
size: "sm",
|
|
842
|
+
className: cn(
|
|
843
|
+
"h-9 shrink-0 whitespace-nowrap rounded-lg px-2.5 text-sm font-normal",
|
|
844
|
+
active && "bg-accent font-medium text-accent-foreground"
|
|
845
|
+
),
|
|
846
|
+
onClick: () => onPreset(preset.getRange),
|
|
847
|
+
children: preset.label
|
|
848
|
+
},
|
|
849
|
+
preset.id
|
|
850
|
+
);
|
|
851
|
+
}) }) });
|
|
852
|
+
}
|
|
853
|
+
return /* @__PURE__ */ jsx("div", { className: "w-[11.5rem] shrink-0 border-r border-border/50 bg-muted/20", children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[min(420px,70vh)] flex-col gap-0.5 overflow-y-auto p-2 [scrollbar-width:thin]", children: [
|
|
854
|
+
presetsHeading ? /* @__PURE__ */ jsx("p", { className: "px-2 pb-1 pt-0.5 text-[0.65rem] font-semibold uppercase tracking-wider text-muted-foreground", children: presetsHeading }) : null,
|
|
855
|
+
presets.map((preset) => {
|
|
856
|
+
const active = rangesMatch(draft, preset.getRange());
|
|
857
|
+
return /* @__PURE__ */ jsx(
|
|
858
|
+
Button,
|
|
859
|
+
{
|
|
860
|
+
type: "button",
|
|
861
|
+
variant: "ghost",
|
|
862
|
+
size: "sm",
|
|
863
|
+
className: cn(
|
|
864
|
+
"h-9 w-full shrink-0 justify-start rounded-lg px-2.5 text-left text-sm font-normal",
|
|
865
|
+
active && "bg-accent font-medium text-accent-foreground"
|
|
866
|
+
),
|
|
867
|
+
onClick: () => onPreset(preset.getRange),
|
|
868
|
+
children: preset.label
|
|
869
|
+
},
|
|
870
|
+
preset.id
|
|
871
|
+
);
|
|
872
|
+
})
|
|
873
|
+
] }) });
|
|
874
|
+
}
|
|
875
|
+
function DateRangePickerTrigger({
|
|
876
|
+
className,
|
|
877
|
+
inputText,
|
|
878
|
+
effectivePlaceholder,
|
|
879
|
+
isEmpty,
|
|
880
|
+
ariaLabel,
|
|
881
|
+
onOpen,
|
|
882
|
+
onInputChange,
|
|
883
|
+
onInputFocus,
|
|
884
|
+
onInputBlur
|
|
885
|
+
}) {
|
|
886
|
+
return /* @__PURE__ */ jsxs(
|
|
887
|
+
"div",
|
|
888
|
+
{
|
|
889
|
+
role: "button",
|
|
890
|
+
tabIndex: 0,
|
|
891
|
+
onClick: onOpen,
|
|
892
|
+
onKeyDown: (e) => {
|
|
893
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
894
|
+
e.preventDefault();
|
|
895
|
+
onOpen();
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
className: cn(
|
|
899
|
+
controlBase,
|
|
900
|
+
"flex w-full min-w-[17rem] max-w-full cursor-pointer items-center overflow-hidden focus-within:ring-[3px] focus-within:ring-ring/40",
|
|
901
|
+
className
|
|
902
|
+
),
|
|
903
|
+
children: [
|
|
904
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center border-r border-border/40 bg-muted/25 text-muted-foreground", children: /* @__PURE__ */ jsx(Calendar$1, { className: "size-4", "aria-hidden": "true" }) }),
|
|
905
|
+
/* @__PURE__ */ jsx(
|
|
906
|
+
Input,
|
|
907
|
+
{
|
|
908
|
+
type: "text",
|
|
909
|
+
value: inputText,
|
|
910
|
+
onChange: (e) => onInputChange(e.target.value),
|
|
911
|
+
onFocus: onInputFocus,
|
|
912
|
+
onBlur: onInputBlur,
|
|
913
|
+
onClick: onOpen,
|
|
914
|
+
onKeyDown: (e) => {
|
|
915
|
+
if (e.key === "Enter") {
|
|
916
|
+
e.target.blur();
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
placeholder: effectivePlaceholder,
|
|
920
|
+
"data-empty": isEmpty || void 0,
|
|
921
|
+
className: cn(
|
|
922
|
+
"h-10 min-w-0 flex-1 cursor-pointer rounded-none border-0 bg-transparent py-2 pl-3 pr-3 text-sm shadow-none focus-visible:ring-0 whitespace-nowrap",
|
|
923
|
+
isEmpty && "text-muted-foreground"
|
|
924
|
+
),
|
|
925
|
+
title: !isEmpty ? inputText : void 0,
|
|
926
|
+
"aria-label": ariaLabel
|
|
927
|
+
}
|
|
928
|
+
)
|
|
929
|
+
]
|
|
930
|
+
}
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// src/components/ui/date-range-picker/useDateRangePresets.ts
|
|
935
|
+
function getPresetRange(presetId) {
|
|
936
|
+
const today = /* @__PURE__ */ new Date();
|
|
937
|
+
today.setHours(23, 59, 59, 999);
|
|
938
|
+
const from = new Date(today);
|
|
939
|
+
from.setHours(0, 0, 0, 0);
|
|
940
|
+
const to = new Date(today);
|
|
941
|
+
switch (presetId) {
|
|
942
|
+
case "today":
|
|
943
|
+
return { from, to };
|
|
944
|
+
case "yesterday":
|
|
945
|
+
from.setDate(from.getDate() - 1);
|
|
946
|
+
to.setDate(to.getDate() - 1);
|
|
947
|
+
return { from, to };
|
|
948
|
+
case "last7":
|
|
949
|
+
from.setDate(from.getDate() - 6);
|
|
950
|
+
return { from, to };
|
|
951
|
+
case "last14":
|
|
952
|
+
from.setDate(from.getDate() - 13);
|
|
953
|
+
return { from, to };
|
|
954
|
+
case "last30":
|
|
955
|
+
from.setDate(from.getDate() - 29);
|
|
956
|
+
return { from, to };
|
|
957
|
+
case "thisWeek": {
|
|
958
|
+
const day = from.getDay();
|
|
959
|
+
const mondayOffset = day === 0 ? -6 : 1 - day;
|
|
960
|
+
from.setDate(from.getDate() + mondayOffset);
|
|
961
|
+
return { from, to };
|
|
962
|
+
}
|
|
963
|
+
case "lastWeek": {
|
|
964
|
+
const day = from.getDay();
|
|
965
|
+
const mondayOffset = day === 0 ? -6 : 1 - day;
|
|
966
|
+
const thisMonday = from.getDate() + mondayOffset;
|
|
967
|
+
from.setDate(thisMonday - 7);
|
|
968
|
+
to.setDate(thisMonday - 1);
|
|
969
|
+
to.setHours(23, 59, 59, 999);
|
|
970
|
+
return { from, to };
|
|
971
|
+
}
|
|
972
|
+
case "thisMonth":
|
|
973
|
+
from.setDate(1);
|
|
974
|
+
return { from, to };
|
|
975
|
+
case "lastMonth":
|
|
976
|
+
from.setMonth(from.getMonth() - 1);
|
|
977
|
+
from.setDate(1);
|
|
978
|
+
to.setDate(0);
|
|
979
|
+
to.setHours(23, 59, 59, 999);
|
|
980
|
+
return { from, to };
|
|
981
|
+
default:
|
|
982
|
+
return { from, to };
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
function useMediaQuery(query, fallback = false) {
|
|
986
|
+
const subscribe = React6.useCallback(
|
|
987
|
+
(onChange) => {
|
|
988
|
+
const mql = window.matchMedia(query);
|
|
989
|
+
mql.addEventListener("change", onChange);
|
|
990
|
+
return () => mql.removeEventListener("change", onChange);
|
|
991
|
+
},
|
|
992
|
+
[query]
|
|
993
|
+
);
|
|
994
|
+
return React6.useSyncExternalStore(
|
|
995
|
+
subscribe,
|
|
996
|
+
() => window.matchMedia(query).matches,
|
|
997
|
+
() => fallback
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
function useIsDatePickerMobileLayout() {
|
|
1001
|
+
return useMediaQuery(DATE_RANGE_MOBILE_MQ, false);
|
|
1002
|
+
}
|
|
1003
|
+
function useIsWideDatePickerLayout() {
|
|
1004
|
+
return useMediaQuery(DATE_RANGE_WIDE_MQ, false);
|
|
1005
|
+
}
|
|
1006
|
+
function DateRangePicker({
|
|
1007
|
+
value,
|
|
1008
|
+
onChange,
|
|
1009
|
+
minDate,
|
|
1010
|
+
maxDate,
|
|
1011
|
+
placeholder,
|
|
1012
|
+
showPresets = true,
|
|
1013
|
+
presets: customPresets,
|
|
1014
|
+
translations,
|
|
1015
|
+
locale,
|
|
1016
|
+
onApply,
|
|
1017
|
+
isDateDisabled,
|
|
1018
|
+
className
|
|
1019
|
+
}) {
|
|
1020
|
+
const t = { ...DEFAULT_TRANSLATIONS, ...translations };
|
|
1021
|
+
const effectivePlaceholder = placeholder ?? t.placeholder;
|
|
1022
|
+
const presetList = React6.useMemo(() => {
|
|
1023
|
+
if (customPresets?.length) return customPresets;
|
|
1024
|
+
if (!showPresets) return [];
|
|
1025
|
+
return DEFAULT_PRESET_IDS.map(({ id }) => ({
|
|
1026
|
+
id,
|
|
1027
|
+
label: translations?.presetLabels?.[id] ?? DEFAULT_PRESET_LABELS[id],
|
|
1028
|
+
getRange: () => getPresetRange(id)
|
|
1029
|
+
}));
|
|
1030
|
+
}, [customPresets, showPresets, translations?.presetLabels]);
|
|
1031
|
+
const normalizedMin = normalizeDate(minDate);
|
|
1032
|
+
const normalizedMax = normalizeDate(maxDate);
|
|
1033
|
+
const isMobileLayout = useIsDatePickerMobileLayout();
|
|
1034
|
+
const isWideLayout = useIsWideDatePickerLayout();
|
|
1035
|
+
const calendarMonths = isMobileLayout ? 1 : isWideLayout ? 2 : 1;
|
|
1036
|
+
const [open, setOpen] = React6.useState(false);
|
|
1037
|
+
const [draft, setDraft] = React6.useState(value);
|
|
1038
|
+
const [displayedMonth, setDisplayedMonth] = React6.useState(() => value?.from ?? /* @__PURE__ */ new Date());
|
|
1039
|
+
const appliedRef = React6.useRef(value);
|
|
1040
|
+
const wasOpenRef = React6.useRef(false);
|
|
1041
|
+
const useApplyFlow = !!onApply;
|
|
1042
|
+
const idScope = React6.useId();
|
|
1043
|
+
const startInputId = `date-range-start-${idScope}`;
|
|
1044
|
+
const endInputId = `date-range-end-${idScope}`;
|
|
1045
|
+
React6.useEffect(() => {
|
|
1046
|
+
const wasOpen = wasOpenRef.current;
|
|
1047
|
+
wasOpenRef.current = open;
|
|
1048
|
+
if (open && !wasOpen) {
|
|
1049
|
+
appliedRef.current = value;
|
|
1050
|
+
setDraft(value);
|
|
1051
|
+
setDisplayedMonth(value?.from ?? /* @__PURE__ */ new Date());
|
|
1052
|
+
} else if (open && wasOpen) {
|
|
1053
|
+
setDraft(value);
|
|
1054
|
+
}
|
|
1055
|
+
}, [open, value]);
|
|
1056
|
+
const handleOpenChange = React6.useCallback(
|
|
1057
|
+
(next) => {
|
|
1058
|
+
if (!next && open && !useApplyFlow) {
|
|
1059
|
+
onChange(appliedRef.current);
|
|
1060
|
+
setDraft(appliedRef.current);
|
|
1061
|
+
}
|
|
1062
|
+
setOpen(next);
|
|
1063
|
+
},
|
|
1064
|
+
[open, useApplyFlow, onChange]
|
|
1065
|
+
);
|
|
1066
|
+
const formatOpts = React6.useMemo(() => locale ? { locale } : void 0, [locale]);
|
|
1067
|
+
const label = React6.useMemo(
|
|
1068
|
+
() => formatRangeLabel(value, effectivePlaceholder, formatOpts),
|
|
1069
|
+
[effectivePlaceholder, value, formatOpts]
|
|
1070
|
+
);
|
|
1071
|
+
const [inputText, setInputText] = React6.useState(label);
|
|
1072
|
+
const inputFocusedRef = React6.useRef(false);
|
|
1073
|
+
React6.useEffect(() => {
|
|
1074
|
+
if (!inputFocusedRef.current) setInputText(label);
|
|
1075
|
+
}, [label]);
|
|
1076
|
+
const handleInputBlur = () => {
|
|
1077
|
+
inputFocusedRef.current = false;
|
|
1078
|
+
const next = parseInputToRange(inputText);
|
|
1079
|
+
if (next) {
|
|
1080
|
+
const formatted = next.from && next.to ? `${format(next.from, DISPLAY_FORMAT, formatOpts)} \u2013 ${format(next.to, DISPLAY_FORMAT, formatOpts)}` : next.from ? format(next.from, DISPLAY_FORMAT, formatOpts) : effectivePlaceholder;
|
|
1081
|
+
if (useApplyFlow) {
|
|
1082
|
+
setDraft(next);
|
|
1083
|
+
setInputText(formatted);
|
|
1084
|
+
} else {
|
|
1085
|
+
onChange(next);
|
|
1086
|
+
setInputText(formatted);
|
|
1087
|
+
}
|
|
1088
|
+
} else {
|
|
1089
|
+
setInputText(label);
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
const disabledMatchers = React6.useMemo(() => {
|
|
1093
|
+
const toStartOfDay = (d) => {
|
|
1094
|
+
const copy = new Date(d);
|
|
1095
|
+
copy.setHours(0, 0, 0, 0);
|
|
1096
|
+
return copy.getTime();
|
|
1097
|
+
};
|
|
1098
|
+
const matchers = [];
|
|
1099
|
+
if (normalizedMin) {
|
|
1100
|
+
matchers.push((date) => toStartOfDay(date) < toStartOfDay(normalizedMin));
|
|
1101
|
+
}
|
|
1102
|
+
if (normalizedMax) {
|
|
1103
|
+
matchers.push((date) => toStartOfDay(date) > toStartOfDay(normalizedMax));
|
|
1104
|
+
}
|
|
1105
|
+
if (isDateDisabled) matchers.push((date) => isDateDisabled(date));
|
|
1106
|
+
return matchers;
|
|
1107
|
+
}, [normalizedMin, normalizedMax, isDateDisabled]);
|
|
1108
|
+
const handlePreset = (getRange) => {
|
|
1109
|
+
const range = getRange();
|
|
1110
|
+
setDraft(range);
|
|
1111
|
+
if (!useApplyFlow) onChange(range);
|
|
1112
|
+
};
|
|
1113
|
+
const handleApply = () => {
|
|
1114
|
+
if (useApplyFlow) {
|
|
1115
|
+
onChange(draft);
|
|
1116
|
+
onApply?.(draft);
|
|
1117
|
+
}
|
|
1118
|
+
setOpen(false);
|
|
1119
|
+
};
|
|
1120
|
+
const handleCancel = () => {
|
|
1121
|
+
if (useApplyFlow) {
|
|
1122
|
+
setDraft(appliedRef.current);
|
|
1123
|
+
} else {
|
|
1124
|
+
onChange(appliedRef.current);
|
|
1125
|
+
setDraft(appliedRef.current);
|
|
1126
|
+
}
|
|
1127
|
+
setOpen(false);
|
|
1128
|
+
};
|
|
1129
|
+
const handleSelect = (_next, triggerDate) => {
|
|
1130
|
+
const day = normalizeDate(triggerDate);
|
|
1131
|
+
if (!day) return;
|
|
1132
|
+
setDraft((prev) => {
|
|
1133
|
+
if (!prev?.from || prev.from && prev.to) {
|
|
1134
|
+
const nextRange2 = { from: day, to: void 0 };
|
|
1135
|
+
if (!useApplyFlow) onChange(nextRange2);
|
|
1136
|
+
return nextRange2;
|
|
1137
|
+
}
|
|
1138
|
+
if (day < prev.from) {
|
|
1139
|
+
const nextRange2 = { from: day, to: void 0 };
|
|
1140
|
+
if (!useApplyFlow) onChange(nextRange2);
|
|
1141
|
+
return nextRange2;
|
|
1142
|
+
}
|
|
1143
|
+
const nextRange = { from: prev.from, to: day };
|
|
1144
|
+
if (!useApplyFlow) onChange(nextRange);
|
|
1145
|
+
return nextRange;
|
|
1146
|
+
});
|
|
1147
|
+
};
|
|
1148
|
+
const [startInputText, setStartInputText] = React6.useState("");
|
|
1149
|
+
const [endInputText, setEndInputText] = React6.useState("");
|
|
1150
|
+
React6.useEffect(() => {
|
|
1151
|
+
if (open) {
|
|
1152
|
+
setStartInputText(draft?.from ? format(draft.from, INPUT_FORMAT) : "");
|
|
1153
|
+
setEndInputText(draft?.to ? format(draft.to, INPUT_FORMAT) : "");
|
|
1154
|
+
}
|
|
1155
|
+
}, [open, draft?.from, draft?.to]);
|
|
1156
|
+
const commitStartInput = () => {
|
|
1157
|
+
const d = parseDate(startInputText);
|
|
1158
|
+
if (d) {
|
|
1159
|
+
setDraft((prev) => ({ from: d, to: prev?.to && prev.to >= d ? prev.to : void 0 }));
|
|
1160
|
+
} else {
|
|
1161
|
+
setStartInputText(draft?.from ? format(draft.from, INPUT_FORMAT) : "");
|
|
1162
|
+
}
|
|
1163
|
+
};
|
|
1164
|
+
const commitEndInput = () => {
|
|
1165
|
+
const d = parseDate(endInputText);
|
|
1166
|
+
if (d) {
|
|
1167
|
+
setDraft((prev) => ({ from: prev?.from && prev.from <= d ? prev.from : d, to: d }));
|
|
1168
|
+
} else {
|
|
1169
|
+
setEndInputText(draft?.to ? format(draft.to, INPUT_FORMAT) : "");
|
|
1170
|
+
}
|
|
1171
|
+
};
|
|
1172
|
+
const fieldsCalendar = /* @__PURE__ */ jsx(
|
|
1173
|
+
DateRangePickerFieldsCalendar,
|
|
1174
|
+
{
|
|
1175
|
+
calendarMonths,
|
|
1176
|
+
draft,
|
|
1177
|
+
displayedMonth,
|
|
1178
|
+
onMonthChange: setDisplayedMonth,
|
|
1179
|
+
onSelect: handleSelect,
|
|
1180
|
+
disabledMatchers,
|
|
1181
|
+
locale,
|
|
1182
|
+
startInputId,
|
|
1183
|
+
endInputId,
|
|
1184
|
+
startLabel: t.startLabel,
|
|
1185
|
+
endLabel: t.endLabel,
|
|
1186
|
+
startInputText,
|
|
1187
|
+
endInputText,
|
|
1188
|
+
effectivePlaceholder,
|
|
1189
|
+
onStartInputChange: setStartInputText,
|
|
1190
|
+
onEndInputChange: setEndInputText,
|
|
1191
|
+
onCommitStart: commitStartInput,
|
|
1192
|
+
onCommitEnd: commitEndInput
|
|
1193
|
+
}
|
|
1194
|
+
);
|
|
1195
|
+
const footer = /* @__PURE__ */ jsx(
|
|
1196
|
+
DateRangePickerActionFooter,
|
|
1197
|
+
{
|
|
1198
|
+
visible: useApplyFlow || isMobileLayout,
|
|
1199
|
+
isMobileLayout,
|
|
1200
|
+
cancelLabel: t.cancelButton,
|
|
1201
|
+
applyLabel: t.applyButton,
|
|
1202
|
+
onCancel: handleCancel,
|
|
1203
|
+
onApply: handleApply
|
|
1204
|
+
}
|
|
1205
|
+
);
|
|
1206
|
+
const trigger = /* @__PURE__ */ jsx(
|
|
1207
|
+
DateRangePickerTrigger,
|
|
1208
|
+
{
|
|
1209
|
+
className,
|
|
1210
|
+
inputText,
|
|
1211
|
+
effectivePlaceholder,
|
|
1212
|
+
isEmpty: !value?.from,
|
|
1213
|
+
ariaLabel: t.ariaLabel,
|
|
1214
|
+
onOpen: () => setOpen(true),
|
|
1215
|
+
onInputChange: setInputText,
|
|
1216
|
+
onInputFocus: () => {
|
|
1217
|
+
inputFocusedRef.current = true;
|
|
1218
|
+
},
|
|
1219
|
+
onInputBlur: handleInputBlur
|
|
1220
|
+
}
|
|
1221
|
+
);
|
|
1222
|
+
if (isMobileLayout) {
|
|
1223
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1224
|
+
trigger,
|
|
1225
|
+
/* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(
|
|
1226
|
+
DialogContent,
|
|
1227
|
+
{
|
|
1228
|
+
showCloseButton: true,
|
|
1229
|
+
className: cn(
|
|
1230
|
+
"h-dvh max-h-dvh w-full max-w-full gap-0 rounded-none border-0 p-0 shadow-[var(--shadow-elevated)]",
|
|
1231
|
+
"top-0 left-0 flex translate-x-0 translate-y-0 flex-col"
|
|
1232
|
+
),
|
|
1233
|
+
overlayClassName: "z-110",
|
|
1234
|
+
children: [
|
|
1235
|
+
/* @__PURE__ */ jsx(DialogHeader, { className: "shrink-0 items-start border-b border-border/50 px-4 py-4 text-left", children: /* @__PURE__ */ jsx(DialogTitle, { className: "pr-10 text-left text-base", children: t.ariaLabel }) }),
|
|
1236
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: [
|
|
1237
|
+
/* @__PURE__ */ jsx(
|
|
1238
|
+
DateRangePickerPresetList,
|
|
1239
|
+
{
|
|
1240
|
+
presets: presetList,
|
|
1241
|
+
draft,
|
|
1242
|
+
layout: "mobile-row",
|
|
1243
|
+
onPreset: handlePreset
|
|
1244
|
+
}
|
|
1245
|
+
),
|
|
1246
|
+
/* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-y-auto px-4 py-4", children: /* @__PURE__ */ jsx("div", { className: "mx-auto flex w-full max-w-md flex-col items-center", children: fieldsCalendar }) }),
|
|
1247
|
+
footer
|
|
1248
|
+
] })
|
|
1249
|
+
]
|
|
1250
|
+
}
|
|
1251
|
+
) })
|
|
1252
|
+
] });
|
|
1253
|
+
}
|
|
1254
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
|
|
1255
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
|
|
1256
|
+
/* @__PURE__ */ jsx(
|
|
1257
|
+
PopoverContent,
|
|
1258
|
+
{
|
|
1259
|
+
className: cn(
|
|
1260
|
+
surfaceOverlay,
|
|
1261
|
+
"w-auto max-w-[min(calc(100vw-1.5rem),52rem)] overflow-hidden p-0",
|
|
1262
|
+
calendarMonths === 2 && "min-w-[36rem]"
|
|
1263
|
+
),
|
|
1264
|
+
align: "start",
|
|
1265
|
+
sideOffset: 8,
|
|
1266
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row", children: [
|
|
1267
|
+
/* @__PURE__ */ jsx(
|
|
1268
|
+
DateRangePickerPresetList,
|
|
1269
|
+
{
|
|
1270
|
+
presets: presetList,
|
|
1271
|
+
draft,
|
|
1272
|
+
layout: "sidebar",
|
|
1273
|
+
presetsHeading: t.presetsHeading,
|
|
1274
|
+
onPreset: handlePreset
|
|
1275
|
+
}
|
|
1276
|
+
),
|
|
1277
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col bg-background", children: [
|
|
1278
|
+
/* @__PURE__ */ jsx("div", { className: "flex w-full flex-col items-stretch p-4", children: fieldsCalendar }),
|
|
1279
|
+
footer
|
|
1280
|
+
] })
|
|
1281
|
+
] })
|
|
1282
|
+
}
|
|
1283
|
+
)
|
|
1284
|
+
] });
|
|
1285
|
+
}
|
|
1286
|
+
var dropdownMenuSelectOptionsMaxHeightClassName = "max-h-[min(var(--radix-dropdown-menu-content-available-height),13rem)]";
|
|
1287
|
+
function DropdownMenu({ ...props }) {
|
|
1288
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1289
|
+
}
|
|
1290
|
+
function DropdownMenuTrigger({
|
|
1291
|
+
...props
|
|
1292
|
+
}) {
|
|
1293
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1294
|
+
}
|
|
1295
|
+
function DropdownMenuContent({
|
|
1296
|
+
className,
|
|
1297
|
+
sideOffset = 4,
|
|
1298
|
+
portalled = true,
|
|
1299
|
+
...props
|
|
1300
|
+
}) {
|
|
1301
|
+
const content = /* @__PURE__ */ jsx(
|
|
1302
|
+
DropdownMenuPrimitive.Content,
|
|
1303
|
+
{
|
|
1304
|
+
"data-slot": "dropdown-menu-content",
|
|
1305
|
+
sideOffset,
|
|
1306
|
+
className: cn(
|
|
1307
|
+
surfaceOverlay,
|
|
1308
|
+
"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 p-1",
|
|
1309
|
+
className
|
|
1310
|
+
),
|
|
1311
|
+
...props
|
|
1312
|
+
}
|
|
1313
|
+
);
|
|
1314
|
+
if (!portalled) {
|
|
1315
|
+
return content;
|
|
1316
|
+
}
|
|
1317
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: content });
|
|
1318
|
+
}
|
|
1319
|
+
function DropdownMenuItem({
|
|
1320
|
+
className,
|
|
1321
|
+
...props
|
|
1322
|
+
}) {
|
|
1323
|
+
return /* @__PURE__ */ jsx(
|
|
1324
|
+
DropdownMenuPrimitive.Item,
|
|
1325
|
+
{
|
|
1326
|
+
"data-slot": "dropdown-menu-item",
|
|
1327
|
+
className: cn(
|
|
1328
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-pointer 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 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1329
|
+
className
|
|
1330
|
+
),
|
|
1331
|
+
...props
|
|
1332
|
+
}
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
function DropdownScrollableList({
|
|
1336
|
+
children,
|
|
1337
|
+
scrollKey,
|
|
1338
|
+
className,
|
|
1339
|
+
scrollAreaClassName,
|
|
1340
|
+
grow = true
|
|
1341
|
+
}) {
|
|
1342
|
+
const scrollRef = React6.useRef(null);
|
|
1343
|
+
const [showTop, setShowTop] = React6.useState(false);
|
|
1344
|
+
const [showBottom, setShowBottom] = React6.useState(false);
|
|
1345
|
+
const update = React6.useCallback(() => {
|
|
1346
|
+
const el = scrollRef.current;
|
|
1347
|
+
if (!el) {
|
|
1348
|
+
setShowTop(false);
|
|
1349
|
+
setShowBottom(false);
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
const { scrollTop, scrollHeight, clientHeight } = el;
|
|
1353
|
+
const overflow = scrollHeight - clientHeight > 2;
|
|
1354
|
+
if (!overflow) {
|
|
1355
|
+
setShowTop(false);
|
|
1356
|
+
setShowBottom(false);
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
setShowTop(scrollTop > 2);
|
|
1360
|
+
setShowBottom(scrollTop + clientHeight < scrollHeight - 2);
|
|
1361
|
+
}, []);
|
|
1362
|
+
React6.useLayoutEffect(() => {
|
|
1363
|
+
update();
|
|
1364
|
+
const id = requestAnimationFrame(() => {
|
|
1365
|
+
requestAnimationFrame(update);
|
|
1366
|
+
});
|
|
1367
|
+
return () => cancelAnimationFrame(id);
|
|
1368
|
+
}, [update, scrollKey]);
|
|
1369
|
+
React6.useEffect(() => {
|
|
1370
|
+
const el = scrollRef.current;
|
|
1371
|
+
if (!el) return;
|
|
1372
|
+
if (typeof ResizeObserver === "undefined") {
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
const ro = new ResizeObserver(() => {
|
|
1376
|
+
window.requestAnimationFrame(update);
|
|
1377
|
+
});
|
|
1378
|
+
ro.observe(el);
|
|
1379
|
+
return () => ro.disconnect();
|
|
1380
|
+
}, [update]);
|
|
1381
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex min-h-0 flex-col", grow && "flex-1", className), children: [
|
|
1382
|
+
/* @__PURE__ */ jsx(
|
|
1383
|
+
"div",
|
|
1384
|
+
{
|
|
1385
|
+
ref: scrollRef,
|
|
1386
|
+
className: cn(
|
|
1387
|
+
grow ? cn("min-h-0 flex-1 overflow-y-auto overscroll-y-contain p-1", scrollAreaClassName) : scrollAreaClassName
|
|
1388
|
+
),
|
|
1389
|
+
onScroll: update,
|
|
1390
|
+
children
|
|
1391
|
+
}
|
|
1392
|
+
),
|
|
1393
|
+
showTop ? /* @__PURE__ */ jsxs(
|
|
1394
|
+
"div",
|
|
1395
|
+
{
|
|
1396
|
+
className: "pointer-events-none absolute inset-x-0 top-0 z-[1] flex h-6 flex-col items-center justify-start pt-px",
|
|
1397
|
+
"aria-hidden": true,
|
|
1398
|
+
children: [
|
|
1399
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-b from-popover via-popover/35 to-transparent backdrop-blur-[0.5px]" }),
|
|
1400
|
+
/* @__PURE__ */ jsx(
|
|
1401
|
+
ChevronUp,
|
|
1402
|
+
{
|
|
1403
|
+
className: "relative z-[2] h-3.5 w-3.5 shrink-0 text-muted-foreground opacity-90 drop-shadow-sm",
|
|
1404
|
+
strokeWidth: 2.5
|
|
1405
|
+
}
|
|
1406
|
+
)
|
|
1407
|
+
]
|
|
1408
|
+
}
|
|
1409
|
+
) : null,
|
|
1410
|
+
showBottom ? /* @__PURE__ */ jsxs(
|
|
1411
|
+
"div",
|
|
1412
|
+
{
|
|
1413
|
+
className: "pointer-events-none absolute inset-x-0 bottom-0 z-[1] flex h-6 flex-col items-center justify-end pb-px",
|
|
1414
|
+
"aria-hidden": true,
|
|
1415
|
+
children: [
|
|
1416
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-popover via-popover/35 to-transparent backdrop-blur-[0.5px]" }),
|
|
1417
|
+
/* @__PURE__ */ jsx(
|
|
1418
|
+
ChevronDown,
|
|
1419
|
+
{
|
|
1420
|
+
className: "relative z-[2] h-3.5 w-3.5 shrink-0 text-muted-foreground opacity-90 drop-shadow-sm",
|
|
1421
|
+
strokeWidth: 2.5
|
|
1422
|
+
}
|
|
1423
|
+
)
|
|
1424
|
+
]
|
|
1425
|
+
}
|
|
1426
|
+
) : null
|
|
1427
|
+
] });
|
|
1428
|
+
}
|
|
1429
|
+
function DropdownSelectSearchInput({
|
|
1430
|
+
value,
|
|
1431
|
+
onChange,
|
|
1432
|
+
placeholder = "Search\u2026",
|
|
1433
|
+
className,
|
|
1434
|
+
autoFocus = false
|
|
1435
|
+
}) {
|
|
1436
|
+
return /* @__PURE__ */ jsx("div", { className: cn("shrink-0 px-1 pb-2 pt-1", className), children: /* @__PURE__ */ jsx(
|
|
1437
|
+
Input,
|
|
1438
|
+
{
|
|
1439
|
+
value,
|
|
1440
|
+
onChange: (event) => onChange(event.target.value),
|
|
1441
|
+
placeholder,
|
|
1442
|
+
"aria-label": placeholder,
|
|
1443
|
+
autoFocus,
|
|
1444
|
+
onKeyDown: (event) => event.stopPropagation()
|
|
1445
|
+
}
|
|
1446
|
+
) });
|
|
1447
|
+
}
|
|
1448
|
+
var labelVariants = cva(
|
|
1449
|
+
"text-sm font-medium leading-none tracking-tight text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
1450
|
+
);
|
|
1451
|
+
function Label({
|
|
1452
|
+
className,
|
|
1453
|
+
...props
|
|
1454
|
+
}) {
|
|
1455
|
+
return /* @__PURE__ */ jsx(LabelPrimitive.Root, { "data-slot": "label", className: cn(labelVariants(), className), ...props });
|
|
1456
|
+
}
|
|
1457
|
+
var Form = FormProvider;
|
|
1458
|
+
var FormFieldContext = React6.createContext(null);
|
|
1459
|
+
var FormField = ({
|
|
1460
|
+
...props
|
|
1461
|
+
}) => {
|
|
1462
|
+
return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
|
|
1463
|
+
};
|
|
1464
|
+
var useFormField = () => {
|
|
1465
|
+
const fieldContext = React6.useContext(FormFieldContext);
|
|
1466
|
+
const itemContext = React6.useContext(FormItemContext);
|
|
1467
|
+
if (fieldContext === null || fieldContext === void 0) {
|
|
1468
|
+
throw new Error("useFormField should be used within <FormField>");
|
|
1469
|
+
}
|
|
1470
|
+
const { getFieldState } = useFormContext();
|
|
1471
|
+
const formState = useFormState({ name: fieldContext.name });
|
|
1472
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
1473
|
+
const { id } = itemContext;
|
|
1474
|
+
return {
|
|
1475
|
+
id,
|
|
1476
|
+
name: fieldContext.name,
|
|
1477
|
+
formItemId: `${id}-form-item`,
|
|
1478
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
1479
|
+
formMessageId: `${id}-form-item-message`,
|
|
1480
|
+
...fieldState
|
|
1481
|
+
};
|
|
1482
|
+
};
|
|
1483
|
+
var FormItemContext = React6.createContext({});
|
|
1484
|
+
function FormItem({ className, ...props }) {
|
|
1485
|
+
const id = React6.useId();
|
|
1486
|
+
return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx("div", { "data-slot": "form-item", className: cn("grid gap-3", className), ...props }) });
|
|
1487
|
+
}
|
|
1488
|
+
function FormLabel({
|
|
1489
|
+
className,
|
|
1490
|
+
...props
|
|
1491
|
+
}) {
|
|
1492
|
+
const { error, formItemId } = useFormField();
|
|
1493
|
+
return /* @__PURE__ */ jsx(
|
|
1494
|
+
Label,
|
|
1495
|
+
{
|
|
1496
|
+
"data-slot": "form-label",
|
|
1497
|
+
"data-error": !!error,
|
|
1498
|
+
className: cn("data-[error=true]:text-destructive", className),
|
|
1499
|
+
htmlFor: formItemId,
|
|
1500
|
+
...props
|
|
1501
|
+
}
|
|
1502
|
+
);
|
|
1503
|
+
}
|
|
1504
|
+
function FormControl({ ...props }) {
|
|
1505
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
1506
|
+
return /* @__PURE__ */ jsx(
|
|
1507
|
+
Slot,
|
|
1508
|
+
{
|
|
1509
|
+
"data-slot": "form-control",
|
|
1510
|
+
id: formItemId,
|
|
1511
|
+
"aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
|
|
1512
|
+
"aria-invalid": !!error,
|
|
1513
|
+
...props
|
|
1514
|
+
}
|
|
1515
|
+
);
|
|
1516
|
+
}
|
|
1517
|
+
function FormDescription({ className, ...props }) {
|
|
1518
|
+
const { formDescriptionId } = useFormField();
|
|
1519
|
+
return /* @__PURE__ */ jsx(
|
|
1520
|
+
"p",
|
|
1521
|
+
{
|
|
1522
|
+
"data-slot": "form-description",
|
|
1523
|
+
id: formDescriptionId,
|
|
1524
|
+
className: cn("text-muted-foreground text-sm", className),
|
|
1525
|
+
...props
|
|
1526
|
+
}
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
function FormMessage({ className, ...props }) {
|
|
1530
|
+
const { error, formMessageId } = useFormField();
|
|
1531
|
+
const body = error ? String(error?.message ?? "") : props.children;
|
|
1532
|
+
if (!body) {
|
|
1533
|
+
return null;
|
|
1534
|
+
}
|
|
1535
|
+
return /* @__PURE__ */ jsx(
|
|
1536
|
+
"p",
|
|
1537
|
+
{
|
|
1538
|
+
"data-slot": "form-message",
|
|
1539
|
+
id: formMessageId,
|
|
1540
|
+
className: cn("text-destructive text-sm", className),
|
|
1541
|
+
...props,
|
|
1542
|
+
children: body
|
|
1543
|
+
}
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
var InsideModalScrollLockContext = React6.createContext(false);
|
|
1547
|
+
function InsideModalScrollLockProvider({
|
|
1548
|
+
children,
|
|
1549
|
+
active = true
|
|
1550
|
+
}) {
|
|
1551
|
+
return /* @__PURE__ */ jsx(InsideModalScrollLockContext.Provider, { value: active, children });
|
|
1552
|
+
}
|
|
1553
|
+
function useInsideModalScrollLock() {
|
|
1554
|
+
return React6.useContext(InsideModalScrollLockContext);
|
|
1555
|
+
}
|
|
1556
|
+
function Sheet({ ...props }) {
|
|
1557
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...props });
|
|
1558
|
+
}
|
|
1559
|
+
function SheetTrigger({ ...props }) {
|
|
1560
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { ...props });
|
|
1561
|
+
}
|
|
1562
|
+
function SheetClose({ ...props }) {
|
|
1563
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...props });
|
|
1564
|
+
}
|
|
1565
|
+
function SheetPortal({ ...props }) {
|
|
1566
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...props });
|
|
1567
|
+
}
|
|
1568
|
+
function SheetOverlay({
|
|
1569
|
+
className,
|
|
1570
|
+
...props
|
|
1571
|
+
}) {
|
|
1572
|
+
return /* @__PURE__ */ jsx(
|
|
1573
|
+
DialogPrimitive.Overlay,
|
|
1574
|
+
{
|
|
1575
|
+
className: cn(
|
|
1576
|
+
"fixed inset-0 z-[100] bg-foreground/20 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1577
|
+
className
|
|
1578
|
+
),
|
|
1579
|
+
...props
|
|
1580
|
+
}
|
|
1581
|
+
);
|
|
1582
|
+
}
|
|
1583
|
+
function SheetContent({
|
|
1584
|
+
className,
|
|
1585
|
+
children,
|
|
1586
|
+
side = "right",
|
|
1587
|
+
onPointerDownOutside,
|
|
1588
|
+
onInteractOutside,
|
|
1589
|
+
onFocusOutside,
|
|
1590
|
+
...props
|
|
1591
|
+
}) {
|
|
1592
|
+
return /* @__PURE__ */ jsxs(SheetPortal, { children: [
|
|
1593
|
+
/* @__PURE__ */ jsx(SheetOverlay, {}),
|
|
1594
|
+
/* @__PURE__ */ jsxs(
|
|
1595
|
+
DialogPrimitive.Content,
|
|
1596
|
+
{
|
|
1597
|
+
onPointerDownOutside: (event) => {
|
|
1598
|
+
preventDismissOnPortaledOverlay(event);
|
|
1599
|
+
if (!event.defaultPrevented) {
|
|
1600
|
+
onPointerDownOutside?.(event);
|
|
1601
|
+
}
|
|
1602
|
+
},
|
|
1603
|
+
onInteractOutside: (event) => {
|
|
1604
|
+
preventDismissOnPortaledOverlay(event);
|
|
1605
|
+
if (!event.defaultPrevented) {
|
|
1606
|
+
onInteractOutside?.(event);
|
|
1607
|
+
}
|
|
1608
|
+
},
|
|
1609
|
+
onFocusOutside: (event) => {
|
|
1610
|
+
preventDismissOnPortaledOverlay(event);
|
|
1611
|
+
if (!event.defaultPrevented) {
|
|
1612
|
+
onFocusOutside?.(event);
|
|
1613
|
+
}
|
|
1614
|
+
},
|
|
1615
|
+
className: cn(
|
|
1616
|
+
"bg-background border-border/50 data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-[100] flex flex-col gap-4 border p-6 shadow-[var(--shadow-elevated)] transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 overflow-y-auto overflow-x-hidden max-h-full",
|
|
1617
|
+
side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-11/12 border-l sm:max-w-sm",
|
|
1618
|
+
side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-11/12 border-r sm:max-w-sm",
|
|
1619
|
+
side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
|
|
1620
|
+
side === "bottom" && "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
|
|
1621
|
+
className
|
|
1622
|
+
),
|
|
1623
|
+
...props,
|
|
1624
|
+
children: [
|
|
1625
|
+
children,
|
|
1626
|
+
/* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-6 right-6 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none cursor-pointer", children: [
|
|
1627
|
+
/* @__PURE__ */ jsx(XIcon, { className: "h-4 w-4" }),
|
|
1628
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
1629
|
+
] })
|
|
1630
|
+
]
|
|
1631
|
+
}
|
|
1632
|
+
)
|
|
1633
|
+
] });
|
|
1634
|
+
}
|
|
1635
|
+
var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-2 text-left pb-4", className), ...props });
|
|
1636
|
+
SheetHeader.displayName = "SheetHeader";
|
|
1637
|
+
var SheetFooter = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
1638
|
+
"div",
|
|
1639
|
+
{
|
|
1640
|
+
className: cn(
|
|
1641
|
+
"flex flex-col-reverse gap-2 pt-4 border-t sm:flex-row sm:justify-end sm:space-x-2 sm:gap-0",
|
|
1642
|
+
className
|
|
1643
|
+
),
|
|
1644
|
+
...props
|
|
1645
|
+
}
|
|
1646
|
+
);
|
|
1647
|
+
SheetFooter.displayName = "SheetFooter";
|
|
1648
|
+
function SheetTitle({ className, ...props }) {
|
|
1649
|
+
return /* @__PURE__ */ jsx(
|
|
1650
|
+
DialogPrimitive.Title,
|
|
1651
|
+
{
|
|
1652
|
+
className: cn("text-lg font-semibold text-foreground", className),
|
|
1653
|
+
...props
|
|
1654
|
+
}
|
|
1655
|
+
);
|
|
1656
|
+
}
|
|
1657
|
+
function SheetDescription({
|
|
1658
|
+
className,
|
|
1659
|
+
...props
|
|
1660
|
+
}) {
|
|
1661
|
+
return /* @__PURE__ */ jsx(
|
|
1662
|
+
DialogPrimitive.Description,
|
|
1663
|
+
{
|
|
1664
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
1665
|
+
...props
|
|
1666
|
+
}
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
function FormDrawer({
|
|
1670
|
+
open,
|
|
1671
|
+
onOpenChange,
|
|
1672
|
+
title,
|
|
1673
|
+
description,
|
|
1674
|
+
children,
|
|
1675
|
+
className,
|
|
1676
|
+
contentClassName
|
|
1677
|
+
}) {
|
|
1678
|
+
return /* @__PURE__ */ jsx(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
1679
|
+
SheetContent,
|
|
1680
|
+
{
|
|
1681
|
+
"data-slot": "form-drawer-content",
|
|
1682
|
+
className: cn(
|
|
1683
|
+
"flex flex-col gap-4 w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] sm:max-w-lg overflow-hidden",
|
|
1684
|
+
contentClassName
|
|
1685
|
+
),
|
|
1686
|
+
children: [
|
|
1687
|
+
/* @__PURE__ */ jsxs(SheetHeader, { className: "flex-shrink-0 gap-2 pb-2", children: [
|
|
1688
|
+
/* @__PURE__ */ jsx(SheetTitle, { className: "text-base sm:text-lg", children: title }),
|
|
1689
|
+
description && /* @__PURE__ */ jsx(SheetDescription, { className: "text-sm", children: description })
|
|
1690
|
+
] }),
|
|
1691
|
+
/* @__PURE__ */ jsx(InsideModalScrollLockProvider, { children: /* @__PURE__ */ jsx(
|
|
1692
|
+
"div",
|
|
1693
|
+
{
|
|
1694
|
+
className: cn(
|
|
1695
|
+
// Inset so focus rings / box-shadow on full-width inputs are not clipped by overflow-y-auto
|
|
1696
|
+
"flex flex-col flex-1 min-h-0 gap-4 overflow-y-auto px-2 py-1",
|
|
1697
|
+
className
|
|
1698
|
+
),
|
|
1699
|
+
children
|
|
1700
|
+
}
|
|
1701
|
+
) })
|
|
1702
|
+
]
|
|
1703
|
+
}
|
|
1704
|
+
) });
|
|
1705
|
+
}
|
|
1706
|
+
var linkStyles = "cursor-pointer font-medium text-blue-600 underline-offset-4 hover:text-blue-700 hover:underline dark:text-blue-400 dark:hover:text-blue-300";
|
|
1707
|
+
var ALLOWED_SCHEMES = ["http:", "https:", "mailto:", "tel:", ""];
|
|
1708
|
+
function sanitizeHref(to) {
|
|
1709
|
+
const trimmed = to.trim();
|
|
1710
|
+
if (!trimmed) return "#";
|
|
1711
|
+
const hasScheme = /^[a-z][a-z0-9+.-]*:/i.test(trimmed);
|
|
1712
|
+
if (hasScheme) {
|
|
1713
|
+
const scheme = trimmed.split(":")[0];
|
|
1714
|
+
if (scheme && !ALLOWED_SCHEMES.includes(`${scheme.toLowerCase()}:`)) {
|
|
1715
|
+
return "#";
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
return trimmed;
|
|
1719
|
+
}
|
|
1720
|
+
function Link({ className, external, to, ...props }) {
|
|
1721
|
+
const href = sanitizeHref(to);
|
|
1722
|
+
if (external) {
|
|
1723
|
+
return /* @__PURE__ */ jsx(
|
|
1724
|
+
"a",
|
|
1725
|
+
{
|
|
1726
|
+
href,
|
|
1727
|
+
target: "_blank",
|
|
1728
|
+
rel: "noopener noreferrer",
|
|
1729
|
+
className: cn(linkStyles, className),
|
|
1730
|
+
...props
|
|
1731
|
+
}
|
|
1732
|
+
);
|
|
1733
|
+
}
|
|
1734
|
+
return /* @__PURE__ */ jsx("a", { href, className: cn(linkStyles, className), ...props });
|
|
1735
|
+
}
|
|
1736
|
+
var DEFAULT_TRANSLATIONS2 = {
|
|
1737
|
+
triggerLabel: "Select options",
|
|
1738
|
+
searchPlaceholder: "Search...",
|
|
1739
|
+
noOptionsText: "No options",
|
|
1740
|
+
removeOptionAriaLabel: "Remove"
|
|
1741
|
+
};
|
|
1742
|
+
function MultiSelect({
|
|
1743
|
+
value,
|
|
1744
|
+
onValueChange,
|
|
1745
|
+
options,
|
|
1746
|
+
disabled = false,
|
|
1747
|
+
className,
|
|
1748
|
+
"aria-label": ariaLabel,
|
|
1749
|
+
showSelectedTags = false,
|
|
1750
|
+
translations
|
|
1751
|
+
}) {
|
|
1752
|
+
const t = { ...DEFAULT_TRANSLATIONS2, ...translations };
|
|
1753
|
+
const insideModalScrollLock = useInsideModalScrollLock();
|
|
1754
|
+
const [search, setSearch] = React6.useState("");
|
|
1755
|
+
const selectedSet = React6.useMemo(() => new Set(value), [value]);
|
|
1756
|
+
const labelByValue = React6.useMemo(() => {
|
|
1757
|
+
const map = /* @__PURE__ */ new Map();
|
|
1758
|
+
for (const opt of options) map.set(opt.value, opt.label);
|
|
1759
|
+
return map;
|
|
1760
|
+
}, [options]);
|
|
1761
|
+
const filteredOptions = React6.useMemo(() => {
|
|
1762
|
+
const q = search.trim().toLowerCase();
|
|
1763
|
+
if (!q) return options;
|
|
1764
|
+
return options.filter((opt) => opt.label.toLowerCase().includes(q));
|
|
1765
|
+
}, [options, search]);
|
|
1766
|
+
const toggle = (optionValue, checked) => {
|
|
1767
|
+
if (checked) {
|
|
1768
|
+
onValueChange([...value, optionValue]);
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
onValueChange(value.filter((item) => item !== optionValue));
|
|
1772
|
+
};
|
|
1773
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
|
|
1774
|
+
showSelectedTags && value.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: value.map((optionValue) => {
|
|
1775
|
+
const label = labelByValue.get(optionValue) ?? optionValue;
|
|
1776
|
+
return /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "gap-1 pr-1 font-normal", children: [
|
|
1777
|
+
label,
|
|
1778
|
+
!disabled ? /* @__PURE__ */ jsx(
|
|
1779
|
+
"button",
|
|
1780
|
+
{
|
|
1781
|
+
type: "button",
|
|
1782
|
+
className: "rounded-full p-0.5 hover:bg-muted-foreground/20",
|
|
1783
|
+
"aria-label": `${t.removeOptionAriaLabel} ${label}`,
|
|
1784
|
+
onClick: () => toggle(optionValue, false),
|
|
1785
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
|
|
1786
|
+
}
|
|
1787
|
+
) : null
|
|
1788
|
+
] }, optionValue);
|
|
1789
|
+
}) }) : null,
|
|
1790
|
+
/* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
|
|
1791
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1792
|
+
Button,
|
|
1793
|
+
{
|
|
1794
|
+
type: "button",
|
|
1795
|
+
variant: "outline",
|
|
1796
|
+
className: "w-full justify-between",
|
|
1797
|
+
"aria-label": ariaLabel ?? t.triggerLabel,
|
|
1798
|
+
disabled,
|
|
1799
|
+
children: [
|
|
1800
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
1801
|
+
/* @__PURE__ */ jsx(CheckSquare, { className: "h-4 w-4" }),
|
|
1802
|
+
t.triggerLabel
|
|
1803
|
+
] }),
|
|
1804
|
+
!showSelectedTags && value.length > 0 ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: value.length }) : null
|
|
1805
|
+
]
|
|
1806
|
+
}
|
|
1807
|
+
) }),
|
|
1808
|
+
/* @__PURE__ */ jsxs(
|
|
1809
|
+
DropdownMenuContent,
|
|
1810
|
+
{
|
|
1811
|
+
align: "start",
|
|
1812
|
+
portalled: !insideModalScrollLock,
|
|
1813
|
+
className: "z-120 flex w-(--radix-dropdown-menu-trigger-width) min-w-[16rem] flex-col overflow-hidden p-0",
|
|
1814
|
+
children: [
|
|
1815
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 px-1 pb-2 pt-1", children: /* @__PURE__ */ jsx(
|
|
1816
|
+
Input,
|
|
1817
|
+
{
|
|
1818
|
+
value: search,
|
|
1819
|
+
onChange: (event) => setSearch(event.target.value),
|
|
1820
|
+
placeholder: t.searchPlaceholder,
|
|
1821
|
+
"aria-label": t.searchPlaceholder
|
|
1822
|
+
}
|
|
1823
|
+
) }),
|
|
1824
|
+
/* @__PURE__ */ jsx(
|
|
1825
|
+
DropdownScrollableList,
|
|
1826
|
+
{
|
|
1827
|
+
grow: false,
|
|
1828
|
+
scrollAreaClassName: "max-h-52 overflow-y-auto",
|
|
1829
|
+
scrollKey: `${filteredOptions.length}:${search}`,
|
|
1830
|
+
children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: t.noOptionsText }) : filteredOptions.map((option) => {
|
|
1831
|
+
const checked = selectedSet.has(option.value);
|
|
1832
|
+
return /* @__PURE__ */ jsxs(
|
|
1833
|
+
DropdownMenuItem,
|
|
1834
|
+
{
|
|
1835
|
+
onSelect: (event) => {
|
|
1836
|
+
event.preventDefault();
|
|
1837
|
+
toggle(option.value, !checked);
|
|
1838
|
+
},
|
|
1839
|
+
children: [
|
|
1840
|
+
/* @__PURE__ */ jsx(Checkbox, { checked }),
|
|
1841
|
+
option.label
|
|
1842
|
+
]
|
|
1843
|
+
},
|
|
1844
|
+
option.value
|
|
1845
|
+
);
|
|
1846
|
+
})
|
|
1847
|
+
}
|
|
1848
|
+
)
|
|
1849
|
+
]
|
|
1850
|
+
}
|
|
1851
|
+
)
|
|
1852
|
+
] })
|
|
1853
|
+
] });
|
|
1854
|
+
}
|
|
1855
|
+
var ScrollArea = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1856
|
+
ScrollAreaPrimitive.Root,
|
|
1857
|
+
{
|
|
1858
|
+
ref,
|
|
1859
|
+
className: cn("relative overflow-hidden", className),
|
|
1860
|
+
...props,
|
|
1861
|
+
children: [
|
|
1862
|
+
/* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
|
|
1863
|
+
/* @__PURE__ */ jsx(ScrollBar, {}),
|
|
1864
|
+
/* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
|
|
1865
|
+
]
|
|
1866
|
+
}
|
|
1867
|
+
));
|
|
1868
|
+
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
1869
|
+
var ScrollBar = React6.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1870
|
+
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
1871
|
+
{
|
|
1872
|
+
ref,
|
|
1873
|
+
orientation,
|
|
1874
|
+
className: cn(
|
|
1875
|
+
"flex touch-none select-none transition-colors",
|
|
1876
|
+
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
|
|
1877
|
+
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
|
1878
|
+
className
|
|
1879
|
+
),
|
|
1880
|
+
...props,
|
|
1881
|
+
children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
|
|
1882
|
+
}
|
|
1883
|
+
));
|
|
1884
|
+
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
1885
|
+
|
|
1886
|
+
// src/components/ui/select-search/index.ts
|
|
1887
|
+
var SEARCHABLE_SELECT_MIN_OPTIONS = 8;
|
|
1888
|
+
function filterSelectOptions(options, query) {
|
|
1889
|
+
const q = query.trim().toLowerCase();
|
|
1890
|
+
if (!q) return options;
|
|
1891
|
+
return options.filter((option) => option.label.toLowerCase().includes(q));
|
|
1892
|
+
}
|
|
1893
|
+
function isSelectSearchable(optionCount, searchable) {
|
|
1894
|
+
if (searchable === true) return true;
|
|
1895
|
+
if (searchable === false) return false;
|
|
1896
|
+
return optionCount >= SEARCHABLE_SELECT_MIN_OPTIONS;
|
|
1897
|
+
}
|
|
1898
|
+
var DEFAULT_TRANSLATIONS3 = {
|
|
1899
|
+
searchPlaceholder: "Search\u2026",
|
|
1900
|
+
noOptionsText: "No options"
|
|
1901
|
+
};
|
|
1902
|
+
function Select({
|
|
1903
|
+
value,
|
|
1904
|
+
onValueChange,
|
|
1905
|
+
options,
|
|
1906
|
+
placeholder = "",
|
|
1907
|
+
disabled = false,
|
|
1908
|
+
className,
|
|
1909
|
+
triggerClassName,
|
|
1910
|
+
searchable,
|
|
1911
|
+
translations,
|
|
1912
|
+
"aria-label": ariaLabel
|
|
1913
|
+
}) {
|
|
1914
|
+
const t = { ...DEFAULT_TRANSLATIONS3, ...translations };
|
|
1915
|
+
const insideModalScrollLock = useInsideModalScrollLock();
|
|
1916
|
+
const [open, setOpen] = React6.useState(false);
|
|
1917
|
+
const [search, setSearch] = React6.useState("");
|
|
1918
|
+
const showSearch = isSelectSearchable(options.length, searchable);
|
|
1919
|
+
const filteredOptions = React6.useMemo(
|
|
1920
|
+
() => showSearch ? filterSelectOptions(options, search) : options,
|
|
1921
|
+
[options, search, showSearch]
|
|
1922
|
+
);
|
|
1923
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
1924
|
+
const displayValue = selectedOption?.label ?? placeholder;
|
|
1925
|
+
const handleOpenChange = (nextOpen) => {
|
|
1926
|
+
setOpen(nextOpen);
|
|
1927
|
+
if (!nextOpen) setSearch("");
|
|
1928
|
+
};
|
|
1929
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { modal: false, open, onOpenChange: handleOpenChange, children: [
|
|
1930
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1931
|
+
"button",
|
|
1932
|
+
{
|
|
1933
|
+
type: "button",
|
|
1934
|
+
role: "combobox",
|
|
1935
|
+
"aria-expanded": open,
|
|
1936
|
+
"aria-label": ariaLabel,
|
|
1937
|
+
"aria-haspopup": "listbox",
|
|
1938
|
+
disabled,
|
|
1939
|
+
className: cn(
|
|
1940
|
+
controlBase,
|
|
1941
|
+
controlFocus,
|
|
1942
|
+
"flex h-9 w-full cursor-pointer items-center justify-between px-3 py-2 text-sm",
|
|
1943
|
+
"hover:bg-accent/40 disabled:pointer-events-none disabled:opacity-50",
|
|
1944
|
+
!value && "text-muted-foreground",
|
|
1945
|
+
triggerClassName,
|
|
1946
|
+
className
|
|
1947
|
+
),
|
|
1948
|
+
children: [
|
|
1949
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-left", children: displayValue }),
|
|
1950
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "ml-2 h-4 w-4 shrink-0 text-muted-foreground" })
|
|
1951
|
+
]
|
|
1952
|
+
}
|
|
1953
|
+
) }),
|
|
1954
|
+
/* @__PURE__ */ jsxs(
|
|
1955
|
+
DropdownMenuContent,
|
|
1956
|
+
{
|
|
1957
|
+
align: "start",
|
|
1958
|
+
sideOffset: 0,
|
|
1959
|
+
portalled: !insideModalScrollLock,
|
|
1960
|
+
className: "z-[120] flex min-w-(--radix-dropdown-menu-trigger-width) flex-col overflow-hidden p-0",
|
|
1961
|
+
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
1962
|
+
children: [
|
|
1963
|
+
showSearch ? /* @__PURE__ */ jsx(
|
|
1964
|
+
DropdownSelectSearchInput,
|
|
1965
|
+
{
|
|
1966
|
+
value: search,
|
|
1967
|
+
onChange: setSearch,
|
|
1968
|
+
placeholder: t.searchPlaceholder,
|
|
1969
|
+
autoFocus: open
|
|
1970
|
+
}
|
|
1971
|
+
) : null,
|
|
1972
|
+
/* @__PURE__ */ jsx(
|
|
1973
|
+
DropdownScrollableList,
|
|
1974
|
+
{
|
|
1975
|
+
grow: false,
|
|
1976
|
+
scrollAreaClassName: cn(
|
|
1977
|
+
"overflow-y-auto overscroll-y-contain p-1",
|
|
1978
|
+
dropdownMenuSelectOptionsMaxHeightClassName
|
|
1979
|
+
),
|
|
1980
|
+
scrollKey: `${filteredOptions.length}-${open ? 1 : 0}-${search}`,
|
|
1981
|
+
children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: t.noOptionsText }) : filteredOptions.map((opt) => /* @__PURE__ */ jsx(
|
|
1982
|
+
DropdownMenuItem,
|
|
1983
|
+
{
|
|
1984
|
+
onClick: () => {
|
|
1985
|
+
onValueChange(opt.value);
|
|
1986
|
+
setOpen(false);
|
|
1987
|
+
setSearch("");
|
|
1988
|
+
},
|
|
1989
|
+
children: opt.label
|
|
1990
|
+
},
|
|
1991
|
+
opt.value
|
|
1992
|
+
))
|
|
1993
|
+
}
|
|
1994
|
+
)
|
|
1995
|
+
]
|
|
1996
|
+
}
|
|
1997
|
+
)
|
|
1998
|
+
] });
|
|
1999
|
+
}
|
|
2000
|
+
function ChevronDownIcon({ className, ...props }) {
|
|
2001
|
+
return /* @__PURE__ */ jsxs(
|
|
2002
|
+
"svg",
|
|
2003
|
+
{
|
|
2004
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2005
|
+
width: "24",
|
|
2006
|
+
height: "24",
|
|
2007
|
+
viewBox: "0 0 24 24",
|
|
2008
|
+
fill: "none",
|
|
2009
|
+
stroke: "currentColor",
|
|
2010
|
+
strokeWidth: "2",
|
|
2011
|
+
strokeLinecap: "round",
|
|
2012
|
+
strokeLinejoin: "round",
|
|
2013
|
+
className,
|
|
2014
|
+
"aria-hidden": "true",
|
|
2015
|
+
...props,
|
|
2016
|
+
children: [
|
|
2017
|
+
/* @__PURE__ */ jsx("title", { children: "Chevron down" }),
|
|
2018
|
+
/* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
2019
|
+
]
|
|
2020
|
+
}
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
var Separator = React6.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2024
|
+
SeparatorPrimitive.Root,
|
|
2025
|
+
{
|
|
2026
|
+
ref,
|
|
2027
|
+
decorative,
|
|
2028
|
+
orientation,
|
|
2029
|
+
className: cn(
|
|
2030
|
+
"shrink-0 bg-border",
|
|
2031
|
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
2032
|
+
className
|
|
2033
|
+
),
|
|
2034
|
+
...props
|
|
2035
|
+
}
|
|
2036
|
+
));
|
|
2037
|
+
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
2038
|
+
var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2039
|
+
SwitchPrimitive.Root,
|
|
2040
|
+
{
|
|
2041
|
+
ref,
|
|
2042
|
+
"data-slot": "switch",
|
|
2043
|
+
className: cn(
|
|
2044
|
+
"peer inline-flex h-[22px] w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-[var(--shadow-surface)] transition-colors",
|
|
2045
|
+
controlFocus,
|
|
2046
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
2047
|
+
"data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
|
2048
|
+
className
|
|
2049
|
+
),
|
|
2050
|
+
...props,
|
|
2051
|
+
children: /* @__PURE__ */ jsx(
|
|
2052
|
+
SwitchPrimitive.Thumb,
|
|
2053
|
+
{
|
|
2054
|
+
"data-slot": "switch-thumb",
|
|
2055
|
+
className: cn(
|
|
2056
|
+
"pointer-events-none block size-[18px] rounded-full bg-background shadow-sm ring-0 transition-transform",
|
|
2057
|
+
"data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-0.5"
|
|
2058
|
+
)
|
|
2059
|
+
}
|
|
2060
|
+
)
|
|
2061
|
+
}
|
|
2062
|
+
));
|
|
2063
|
+
Switch.displayName = SwitchPrimitive.Root.displayName;
|
|
2064
|
+
var Table = React6.forwardRef(
|
|
2065
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props }) })
|
|
2066
|
+
);
|
|
2067
|
+
Table.displayName = "Table";
|
|
2068
|
+
var TableHeader = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2069
|
+
"thead",
|
|
2070
|
+
{
|
|
2071
|
+
ref,
|
|
2072
|
+
className: cn("[&_tr]:border-border/40 [&_tr]:border-b", className),
|
|
2073
|
+
...props
|
|
2074
|
+
}
|
|
2075
|
+
));
|
|
2076
|
+
TableHeader.displayName = "TableHeader";
|
|
2077
|
+
var TableBody = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
|
|
2078
|
+
TableBody.displayName = "TableBody";
|
|
2079
|
+
var TableFooter = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2080
|
+
"tfoot",
|
|
2081
|
+
{
|
|
2082
|
+
ref,
|
|
2083
|
+
className: cn(
|
|
2084
|
+
"border-border/40 border-t bg-muted/40 font-medium [&>tr]:last:border-b-0",
|
|
2085
|
+
className
|
|
2086
|
+
),
|
|
2087
|
+
...props
|
|
2088
|
+
}
|
|
2089
|
+
));
|
|
2090
|
+
TableFooter.displayName = "TableFooter";
|
|
2091
|
+
var TableRow = React6.forwardRef(
|
|
2092
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2093
|
+
"tr",
|
|
2094
|
+
{
|
|
2095
|
+
ref,
|
|
2096
|
+
className: cn(
|
|
2097
|
+
"border-border/40 border-b transition-colors hover:bg-muted/40 data-[state=selected]:bg-muted/60",
|
|
2098
|
+
className
|
|
2099
|
+
),
|
|
2100
|
+
...props
|
|
2101
|
+
}
|
|
2102
|
+
)
|
|
2103
|
+
);
|
|
2104
|
+
TableRow.displayName = "TableRow";
|
|
2105
|
+
var TableHead = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2106
|
+
"th",
|
|
2107
|
+
{
|
|
2108
|
+
ref,
|
|
2109
|
+
className: cn(
|
|
2110
|
+
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
2111
|
+
className
|
|
2112
|
+
),
|
|
2113
|
+
...props
|
|
2114
|
+
}
|
|
2115
|
+
));
|
|
2116
|
+
TableHead.displayName = "TableHead";
|
|
2117
|
+
var TableCell = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2118
|
+
"td",
|
|
2119
|
+
{
|
|
2120
|
+
ref,
|
|
2121
|
+
className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
|
|
2122
|
+
...props
|
|
2123
|
+
}
|
|
2124
|
+
));
|
|
2125
|
+
TableCell.displayName = "TableCell";
|
|
2126
|
+
var TableCaption = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
|
|
2127
|
+
TableCaption.displayName = "TableCaption";
|
|
2128
|
+
function Tabs({ className, ...props }) {
|
|
2129
|
+
return /* @__PURE__ */ jsx(
|
|
2130
|
+
TabsPrimitive.Root,
|
|
2131
|
+
{
|
|
2132
|
+
"data-slot": "tabs",
|
|
2133
|
+
className: cn("flex flex-col gap-2", className),
|
|
2134
|
+
...props
|
|
2135
|
+
}
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
function TabsList({ className, ...props }) {
|
|
2139
|
+
return /* @__PURE__ */ jsx(
|
|
2140
|
+
TabsPrimitive.List,
|
|
2141
|
+
{
|
|
2142
|
+
"data-slot": "tabs-list",
|
|
2143
|
+
className: cn(
|
|
2144
|
+
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
|
2145
|
+
className
|
|
2146
|
+
),
|
|
2147
|
+
...props
|
|
2148
|
+
}
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
function TabsTrigger({
|
|
2152
|
+
className,
|
|
2153
|
+
...props
|
|
2154
|
+
}) {
|
|
2155
|
+
return /* @__PURE__ */ jsx(
|
|
2156
|
+
TabsPrimitive.Trigger,
|
|
2157
|
+
{
|
|
2158
|
+
"data-slot": "tabs-trigger",
|
|
2159
|
+
className: cn(
|
|
2160
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all cursor-pointer",
|
|
2161
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
2162
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
2163
|
+
"data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
|
2164
|
+
className
|
|
2165
|
+
),
|
|
2166
|
+
...props
|
|
2167
|
+
}
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
function TabsContent({
|
|
2171
|
+
className,
|
|
2172
|
+
...props
|
|
2173
|
+
}) {
|
|
2174
|
+
return /* @__PURE__ */ jsx(
|
|
2175
|
+
TabsPrimitive.Content,
|
|
2176
|
+
{
|
|
2177
|
+
"data-slot": "tabs-content",
|
|
2178
|
+
className: cn(
|
|
2179
|
+
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
2180
|
+
className
|
|
2181
|
+
),
|
|
2182
|
+
...props
|
|
2183
|
+
}
|
|
2184
|
+
);
|
|
2185
|
+
}
|
|
2186
|
+
var Textarea = React6.forwardRef(
|
|
2187
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2188
|
+
"textarea",
|
|
2189
|
+
{
|
|
2190
|
+
ref,
|
|
2191
|
+
"data-slot": "textarea",
|
|
2192
|
+
className: cn(
|
|
2193
|
+
controlBase,
|
|
2194
|
+
controlFocus,
|
|
2195
|
+
controlInvalid,
|
|
2196
|
+
"placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground",
|
|
2197
|
+
"flex min-h-[96px] w-full min-w-0 px-3 py-2 text-base md:text-sm",
|
|
2198
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
2199
|
+
className
|
|
2200
|
+
),
|
|
2201
|
+
...props
|
|
2202
|
+
}
|
|
2203
|
+
)
|
|
2204
|
+
);
|
|
2205
|
+
Textarea.displayName = "Textarea";
|
|
2206
|
+
var TooltipProvider = TooltipPrimitive.Provider;
|
|
2207
|
+
function Tooltip({
|
|
2208
|
+
content,
|
|
2209
|
+
children,
|
|
2210
|
+
side = "top",
|
|
2211
|
+
align = "center",
|
|
2212
|
+
delayDuration = 400,
|
|
2213
|
+
closeDelay = 100
|
|
2214
|
+
}) {
|
|
2215
|
+
const [open, setOpen] = React6.useState(false);
|
|
2216
|
+
const openTimeoutRef = React6.useRef(null);
|
|
2217
|
+
const closeTimeoutRef = React6.useRef(null);
|
|
2218
|
+
const clearOpenTimeout = React6.useCallback(() => {
|
|
2219
|
+
if (openTimeoutRef.current !== null) {
|
|
2220
|
+
window.clearTimeout(openTimeoutRef.current);
|
|
2221
|
+
openTimeoutRef.current = null;
|
|
2222
|
+
}
|
|
2223
|
+
}, []);
|
|
2224
|
+
const clearCloseTimeout = React6.useCallback(() => {
|
|
2225
|
+
if (closeTimeoutRef.current !== null) {
|
|
2226
|
+
window.clearTimeout(closeTimeoutRef.current);
|
|
2227
|
+
closeTimeoutRef.current = null;
|
|
2228
|
+
}
|
|
2229
|
+
}, []);
|
|
2230
|
+
const handleOpenChange = React6.useCallback(
|
|
2231
|
+
(next) => {
|
|
2232
|
+
if (!next) {
|
|
2233
|
+
clearOpenTimeout();
|
|
2234
|
+
clearCloseTimeout();
|
|
2235
|
+
setOpen(false);
|
|
2236
|
+
}
|
|
2237
|
+
},
|
|
2238
|
+
[clearCloseTimeout, clearOpenTimeout]
|
|
2239
|
+
);
|
|
2240
|
+
const handlePointerEnter = React6.useCallback(() => {
|
|
2241
|
+
clearCloseTimeout();
|
|
2242
|
+
clearOpenTimeout();
|
|
2243
|
+
openTimeoutRef.current = window.setTimeout(() => {
|
|
2244
|
+
setOpen(true);
|
|
2245
|
+
}, delayDuration);
|
|
2246
|
+
}, [clearCloseTimeout, clearOpenTimeout, delayDuration]);
|
|
2247
|
+
const handlePointerLeave = React6.useCallback(() => {
|
|
2248
|
+
clearOpenTimeout();
|
|
2249
|
+
clearCloseTimeout();
|
|
2250
|
+
if (closeDelay === 0) {
|
|
2251
|
+
setOpen(false);
|
|
2252
|
+
return;
|
|
2253
|
+
}
|
|
2254
|
+
closeTimeoutRef.current = window.setTimeout(() => {
|
|
2255
|
+
setOpen(false);
|
|
2256
|
+
}, closeDelay);
|
|
2257
|
+
}, [clearCloseTimeout, clearOpenTimeout, closeDelay]);
|
|
2258
|
+
React6.useEffect(
|
|
2259
|
+
() => () => {
|
|
2260
|
+
clearOpenTimeout();
|
|
2261
|
+
clearCloseTimeout();
|
|
2262
|
+
},
|
|
2263
|
+
[clearCloseTimeout, clearOpenTimeout]
|
|
2264
|
+
);
|
|
2265
|
+
return /* @__PURE__ */ jsxs(TooltipPrimitive.Root, { open, onOpenChange: handleOpenChange, children: [
|
|
2266
|
+
/* @__PURE__ */ jsx(
|
|
2267
|
+
TooltipPrimitive.Trigger,
|
|
2268
|
+
{
|
|
2269
|
+
asChild: true,
|
|
2270
|
+
onPointerEnter: handlePointerEnter,
|
|
2271
|
+
onPointerLeave: handlePointerLeave,
|
|
2272
|
+
children
|
|
2273
|
+
}
|
|
2274
|
+
),
|
|
2275
|
+
/* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
2276
|
+
TooltipPrimitive.Content,
|
|
2277
|
+
{
|
|
2278
|
+
side,
|
|
2279
|
+
align,
|
|
2280
|
+
sideOffset: 6,
|
|
2281
|
+
onPointerEnter: handlePointerEnter,
|
|
2282
|
+
onPointerLeave: handlePointerLeave,
|
|
2283
|
+
className: cn(
|
|
2284
|
+
surfaceOverlay,
|
|
2285
|
+
"z-110 max-w-xs px-3 py-2 text-sm outline-none",
|
|
2286
|
+
"animate-in fade-in-0 zoom-in-95",
|
|
2287
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
|
|
2288
|
+
),
|
|
2289
|
+
children: content
|
|
2290
|
+
}
|
|
2291
|
+
) })
|
|
2292
|
+
] });
|
|
2293
|
+
}
|
|
2294
|
+
var headingVariants = cva("font-semibold tracking-tight text-foreground", {
|
|
2295
|
+
variants: {
|
|
2296
|
+
level: {
|
|
2297
|
+
h1: "text-3xl font-bold",
|
|
2298
|
+
h2: "text-2xl",
|
|
2299
|
+
h3: "text-xl",
|
|
2300
|
+
h4: "text-lg"
|
|
2301
|
+
}
|
|
2302
|
+
},
|
|
2303
|
+
defaultVariants: {
|
|
2304
|
+
level: "h1"
|
|
2305
|
+
}
|
|
2306
|
+
});
|
|
2307
|
+
var paragraphVariants = cva("text-muted-foreground leading-relaxed", {
|
|
2308
|
+
variants: {
|
|
2309
|
+
size: {
|
|
2310
|
+
default: "text-base",
|
|
2311
|
+
sm: "text-sm",
|
|
2312
|
+
lg: "text-lg"
|
|
2313
|
+
}
|
|
2314
|
+
},
|
|
2315
|
+
defaultVariants: {
|
|
2316
|
+
size: "default"
|
|
2317
|
+
}
|
|
2318
|
+
});
|
|
2319
|
+
var Heading = React6.forwardRef(
|
|
2320
|
+
({ className, level, as, ...props }, ref) => {
|
|
2321
|
+
const Component = as || (level === "h1" ? "h1" : level === "h2" ? "h2" : level === "h3" ? "h3" : "h4");
|
|
2322
|
+
return /* @__PURE__ */ jsx(
|
|
2323
|
+
Component,
|
|
2324
|
+
{
|
|
2325
|
+
ref,
|
|
2326
|
+
className: cn(headingVariants({ level: level || as }), className),
|
|
2327
|
+
...props
|
|
2328
|
+
}
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2331
|
+
);
|
|
2332
|
+
Heading.displayName = "Heading";
|
|
2333
|
+
var Paragraph = React6.forwardRef(
|
|
2334
|
+
({ className, size, ...props }, ref) => {
|
|
2335
|
+
return /* @__PURE__ */ jsx("p", { ref, className: cn(paragraphVariants({ size }), className), ...props });
|
|
2336
|
+
}
|
|
2337
|
+
);
|
|
2338
|
+
Paragraph.displayName = "Paragraph";
|
|
2339
|
+
var H3 = React6.forwardRef(
|
|
2340
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(Heading, { ref, level: "h3", as: "h3", className, ...props })
|
|
2341
|
+
);
|
|
2342
|
+
H3.displayName = "H3";
|
|
2343
|
+
var DEFAULT_TRANSLATIONS4 = {
|
|
2344
|
+
imageAlt: "Image",
|
|
2345
|
+
dropHintText: "Drag and drop an image here, or click to choose a file.",
|
|
2346
|
+
chooseImageText: "Choose image",
|
|
2347
|
+
chooseFileText: "Choose file",
|
|
2348
|
+
removeText: "Remove",
|
|
2349
|
+
removeExistingImageText: "Remove existing image"
|
|
2350
|
+
};
|
|
2351
|
+
function UploadDropzone(props) {
|
|
2352
|
+
const isFile = props.variant === "file";
|
|
2353
|
+
const inputId = useId();
|
|
2354
|
+
const removeExistingLabelId = useId();
|
|
2355
|
+
const pickerDisabled = isFile && props.disabled;
|
|
2356
|
+
const t = { ...DEFAULT_TRANSLATIONS4, ...props.translations };
|
|
2357
|
+
const inputRef = useRef(null);
|
|
2358
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
2359
|
+
const [previewUrl, setPreviewUrl] = useState(null);
|
|
2360
|
+
useEffect(() => {
|
|
2361
|
+
if (isFile) {
|
|
2362
|
+
if (!props.value || !props.value.type.startsWith("video/")) {
|
|
2363
|
+
setPreviewUrl(null);
|
|
2364
|
+
return;
|
|
2365
|
+
}
|
|
2366
|
+
const nextUrl2 = URL.createObjectURL(props.value);
|
|
2367
|
+
setPreviewUrl(nextUrl2);
|
|
2368
|
+
return () => URL.revokeObjectURL(nextUrl2);
|
|
2369
|
+
}
|
|
2370
|
+
if (!props.value) {
|
|
2371
|
+
setPreviewUrl(null);
|
|
2372
|
+
return;
|
|
2373
|
+
}
|
|
2374
|
+
const nextUrl = URL.createObjectURL(props.value);
|
|
2375
|
+
setPreviewUrl(nextUrl);
|
|
2376
|
+
return () => URL.revokeObjectURL(nextUrl);
|
|
2377
|
+
}, [isFile, props.value]);
|
|
2378
|
+
const handleFile = (file) => {
|
|
2379
|
+
if (!file) return;
|
|
2380
|
+
if (props.maxSizeBytes != null && file.size > props.maxSizeBytes) {
|
|
2381
|
+
props.onFileTooLarge?.();
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2384
|
+
if (isFile) {
|
|
2385
|
+
if (props.disabled) return;
|
|
2386
|
+
props.onChange(file);
|
|
2387
|
+
return;
|
|
2388
|
+
}
|
|
2389
|
+
if (!file.type.startsWith("image/")) return;
|
|
2390
|
+
props.onChange(file);
|
|
2391
|
+
props.onRemoveExistingImageChange?.(false);
|
|
2392
|
+
};
|
|
2393
|
+
const displayedImage = !isFile && (previewUrl ?? (!props.removeExistingImage ? props.existingImageUrl : void 0));
|
|
2394
|
+
const dashedClasses = cn(
|
|
2395
|
+
"block rounded-xl border-2 border-dashed border-border/55 p-4 transition-colors",
|
|
2396
|
+
pickerDisabled && "pointer-events-none opacity-50",
|
|
2397
|
+
!pickerDisabled && "cursor-pointer hover:border-primary/50 hover:bg-muted/15",
|
|
2398
|
+
isDragging ? "border-primary/70 bg-primary/5" : void 0
|
|
2399
|
+
);
|
|
2400
|
+
const chooseLabel = isFile ? t.chooseFileText : t.chooseImageText;
|
|
2401
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", isFile ? props.className : void 0), children: [
|
|
2402
|
+
/* @__PURE__ */ jsxs(
|
|
2403
|
+
"label",
|
|
2404
|
+
{
|
|
2405
|
+
htmlFor: pickerDisabled ? void 0 : inputId,
|
|
2406
|
+
className: dashedClasses,
|
|
2407
|
+
onDragOver: (event) => {
|
|
2408
|
+
event.preventDefault();
|
|
2409
|
+
if (pickerDisabled) return;
|
|
2410
|
+
setIsDragging(true);
|
|
2411
|
+
},
|
|
2412
|
+
onDragLeave: () => setIsDragging(false),
|
|
2413
|
+
onDrop: (event) => {
|
|
2414
|
+
event.preventDefault();
|
|
2415
|
+
setIsDragging(false);
|
|
2416
|
+
if (pickerDisabled) return;
|
|
2417
|
+
const file = event.dataTransfer.files?.[0] ?? null;
|
|
2418
|
+
handleFile(file);
|
|
2419
|
+
},
|
|
2420
|
+
children: [
|
|
2421
|
+
/* @__PURE__ */ jsx(
|
|
2422
|
+
"input",
|
|
2423
|
+
{
|
|
2424
|
+
id: inputId,
|
|
2425
|
+
ref: inputRef,
|
|
2426
|
+
type: "file",
|
|
2427
|
+
accept: isFile ? props.accept : "image/*",
|
|
2428
|
+
disabled: pickerDisabled || void 0,
|
|
2429
|
+
className: "sr-only",
|
|
2430
|
+
onChange: (event) => handleFile(event.target.files?.[0] ?? null)
|
|
2431
|
+
}
|
|
2432
|
+
),
|
|
2433
|
+
isFile ? /* @__PURE__ */ jsxs("div", { className: "mb-3 flex min-h-28 flex-col items-center justify-center gap-2 rounded-lg border border-border/45 bg-muted/20 px-3 py-4 text-center", children: [
|
|
2434
|
+
previewUrl ? /* @__PURE__ */ jsx(
|
|
2435
|
+
"video",
|
|
2436
|
+
{
|
|
2437
|
+
src: previewUrl,
|
|
2438
|
+
controls: true,
|
|
2439
|
+
className: "max-h-44 w-full rounded-lg border border-border/45 bg-foreground"
|
|
2440
|
+
}
|
|
2441
|
+
) : /* @__PURE__ */ jsx(FileText, { className: "h-8 w-8 shrink-0 text-muted-foreground", "aria-hidden": true }),
|
|
2442
|
+
props.value ? /* @__PURE__ */ jsx("p", { className: "line-clamp-2 w-full break-all text-sm font-medium", children: props.value.name }) : null
|
|
2443
|
+
] }) : displayedImage ? /* @__PURE__ */ jsx(
|
|
2444
|
+
"img",
|
|
2445
|
+
{
|
|
2446
|
+
src: displayedImage,
|
|
2447
|
+
alt: t.imageAlt,
|
|
2448
|
+
className: "mb-3 h-44 w-full rounded-lg border border-border/45 object-cover"
|
|
2449
|
+
}
|
|
2450
|
+
) : /* @__PURE__ */ jsx("div", { className: "mb-3 flex h-32 items-center justify-center rounded-lg border border-border/45 bg-muted/20", children: /* @__PURE__ */ jsx(ImagePlus, { className: "h-8 w-8 text-muted-foreground", "aria-hidden": true }) }),
|
|
2451
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
2452
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t.dropHintText }),
|
|
2453
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
2454
|
+
/* @__PURE__ */ jsxs(
|
|
2455
|
+
Button,
|
|
2456
|
+
{
|
|
2457
|
+
type: "button",
|
|
2458
|
+
size: "sm",
|
|
2459
|
+
variant: "outline",
|
|
2460
|
+
disabled: pickerDisabled || void 0,
|
|
2461
|
+
onClick: (event) => {
|
|
2462
|
+
event.preventDefault();
|
|
2463
|
+
inputRef.current?.click();
|
|
2464
|
+
},
|
|
2465
|
+
children: [
|
|
2466
|
+
/* @__PURE__ */ jsx(UploadCloud, { className: "mr-2 h-4 w-4", "aria-hidden": true }),
|
|
2467
|
+
chooseLabel
|
|
2468
|
+
]
|
|
2469
|
+
}
|
|
2470
|
+
),
|
|
2471
|
+
props.value ? /* @__PURE__ */ jsx(
|
|
2472
|
+
Button,
|
|
2473
|
+
{
|
|
2474
|
+
type: "button",
|
|
2475
|
+
size: "sm",
|
|
2476
|
+
variant: "outline",
|
|
2477
|
+
disabled: pickerDisabled || void 0,
|
|
2478
|
+
onClick: (event) => {
|
|
2479
|
+
event.preventDefault();
|
|
2480
|
+
event.stopPropagation();
|
|
2481
|
+
props.onChange(null);
|
|
2482
|
+
},
|
|
2483
|
+
children: t.removeText
|
|
2484
|
+
}
|
|
2485
|
+
) : null
|
|
2486
|
+
] })
|
|
2487
|
+
] })
|
|
2488
|
+
]
|
|
2489
|
+
}
|
|
2490
|
+
),
|
|
2491
|
+
!isFile && props.existingImageUrl && props.onRemoveExistingImageChange && t.removeExistingImageText ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-lg border border-border/45 bg-muted/15 px-3 py-2", children: [
|
|
2492
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", id: removeExistingLabelId, children: t.removeExistingImageText }),
|
|
2493
|
+
/* @__PURE__ */ jsx(
|
|
2494
|
+
Checkbox,
|
|
2495
|
+
{
|
|
2496
|
+
"aria-labelledby": removeExistingLabelId,
|
|
2497
|
+
checked: props.removeExistingImage,
|
|
2498
|
+
onCheckedChange: (checked) => props.onRemoveExistingImageChange?.(checked === true)
|
|
2499
|
+
}
|
|
2500
|
+
)
|
|
2501
|
+
] }) : null
|
|
2502
|
+
] });
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
export { Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarFallback, AvatarImage, Badge, Calendar, Checkbox, ConfirmDialog, DatePicker, DateRangePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, DropdownScrollableList, DropdownSelectSearchInput, Form, FormControl, FormDescription, FormDrawer, FormField, FormItem, FormLabel, FormMessage, H3, Heading, Label, Link, MultiSelect, Paragraph, Popover, PopoverContent, PopoverTrigger, SEARCHABLE_SELECT_MIN_OPTIONS, ScrollArea, ScrollBar, Select, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Tooltip, TooltipProvider, UploadDropzone, badgeVariants, dropdownMenuSelectOptionsMaxHeightClassName, filterSelectOptions, headingVariants, isSelectSearchable, linkStyles, paragraphVariants, useFormField };
|
|
2506
|
+
//# sourceMappingURL=chunk-PLSNCPEC.js.map
|
|
2507
|
+
//# sourceMappingURL=chunk-PLSNCPEC.js.map
|