@melony/react 0.1.53 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -34
- package/dist/index.cjs +22 -4074
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -428
- package/dist/index.d.ts +6 -428
- package/dist/index.js +20 -3993
- package/dist/index.js.map +1 -1
- package/package.json +2 -10
package/dist/index.js
CHANGED
|
@@ -1,4021 +1,48 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { filterEventsBySlots, convertEventsToMessages } from 'melony';
|
|
4
|
-
import { NuqsAdapter } from 'nuqs/adapters/react';
|
|
5
|
-
import { QueryClient, QueryClientProvider, useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
6
|
-
import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
|
|
7
|
-
import { clsx } from 'clsx';
|
|
8
|
-
import { twMerge } from 'tailwind-merge';
|
|
9
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
-
import * as ICONS from '@tabler/icons-react';
|
|
11
|
-
import { IconX, IconChevronLeft, IconChevronRight, IconLoader2, IconCheck, IconUpload, IconDotsVertical, IconUser, IconLogout, IconBrandGoogle, IconFileText, IconFile, IconPaperclip, IconChevronDown, IconArrowUp, IconHistory, IconPlus, IconArrowLeft, IconMessage, IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightExpand, IconLayoutSidebarRightCollapse, IconDeviceDesktop, IconMoon, IconSun, IconSelector, IconChevronUp } from '@tabler/icons-react';
|
|
12
|
-
export * from '@tabler/icons-react';
|
|
13
|
-
import { Separator as Separator$1 } from '@base-ui/react/separator';
|
|
14
|
-
import { mergeProps } from '@base-ui/react/merge-props';
|
|
15
|
-
import { useRender } from '@base-ui/react/use-render';
|
|
16
|
-
import { cva } from 'class-variance-authority';
|
|
17
|
-
import { Input as Input$1 } from '@base-ui/react/input';
|
|
18
|
-
import { Select as Select$1 } from '@base-ui/react/select';
|
|
19
|
-
import { createPortal } from 'react-dom';
|
|
20
|
-
import { Button as Button$1 } from '@base-ui/react/button';
|
|
21
|
-
import { Menu } from '@base-ui/react/menu';
|
|
22
|
-
import { useQueryState, parseAsString } from 'nuqs';
|
|
23
|
-
import { useHotkeys } from 'react-hotkeys-hook';
|
|
1
|
+
import { createContext, useState, useEffect, useMemo, useContext } from 'react';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
24
3
|
|
|
25
4
|
// src/providers/melony-provider.tsx
|
|
26
|
-
function cn(...inputs) {
|
|
27
|
-
return twMerge(clsx(inputs));
|
|
28
|
-
}
|
|
29
|
-
function Dialog({ ...props }) {
|
|
30
|
-
return /* @__PURE__ */ jsx(Dialog$1.Root, { "data-slot": "dialog", ...props });
|
|
31
|
-
}
|
|
32
|
-
function DialogTrigger({ ...props }) {
|
|
33
|
-
return /* @__PURE__ */ jsx(Dialog$1.Trigger, { "data-slot": "dialog-trigger", ...props });
|
|
34
|
-
}
|
|
35
|
-
function DialogPortal({ ...props }) {
|
|
36
|
-
return /* @__PURE__ */ jsx(Dialog$1.Portal, { "data-slot": "dialog-portal", ...props });
|
|
37
|
-
}
|
|
38
|
-
function DialogOverlay({
|
|
39
|
-
className,
|
|
40
|
-
...props
|
|
41
|
-
}) {
|
|
42
|
-
return /* @__PURE__ */ jsx(
|
|
43
|
-
Dialog$1.Backdrop,
|
|
44
|
-
{
|
|
45
|
-
"data-slot": "dialog-overlay",
|
|
46
|
-
className: cn(
|
|
47
|
-
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-200 supports-backdrop-filter:backdrop-blur-sm fixed inset-0 isolate z-50",
|
|
48
|
-
className
|
|
49
|
-
),
|
|
50
|
-
...props
|
|
51
|
-
}
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
function DialogContent({
|
|
55
|
-
className,
|
|
56
|
-
...props
|
|
57
|
-
}) {
|
|
58
|
-
return /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
59
|
-
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
60
|
-
/* @__PURE__ */ jsx(
|
|
61
|
-
Dialog$1.Popup,
|
|
62
|
-
{
|
|
63
|
-
"data-slot": "dialog-content",
|
|
64
|
-
className: cn(
|
|
65
|
-
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg outline-none",
|
|
66
|
-
className
|
|
67
|
-
),
|
|
68
|
-
...props
|
|
69
|
-
}
|
|
70
|
-
)
|
|
71
|
-
] });
|
|
72
|
-
}
|
|
73
|
-
function DialogClose({
|
|
74
|
-
className,
|
|
75
|
-
...props
|
|
76
|
-
}) {
|
|
77
|
-
return /* @__PURE__ */ jsx(
|
|
78
|
-
Dialog$1.Close,
|
|
79
|
-
{
|
|
80
|
-
"data-slot": "dialog-close",
|
|
81
|
-
className: cn(
|
|
82
|
-
"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
|
|
83
|
-
className
|
|
84
|
-
),
|
|
85
|
-
...props
|
|
86
|
-
}
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
function DialogHeader({
|
|
90
|
-
className,
|
|
91
|
-
...props
|
|
92
|
-
}) {
|
|
93
|
-
return /* @__PURE__ */ jsx(
|
|
94
|
-
"div",
|
|
95
|
-
{
|
|
96
|
-
"data-slot": "dialog-header",
|
|
97
|
-
className: cn(
|
|
98
|
-
"flex flex-col space-y-1.5 text-center sm:text-left",
|
|
99
|
-
className
|
|
100
|
-
),
|
|
101
|
-
...props
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
function DialogTitle({
|
|
106
|
-
className,
|
|
107
|
-
...props
|
|
108
|
-
}) {
|
|
109
|
-
return /* @__PURE__ */ jsx(
|
|
110
|
-
Dialog$1.Title,
|
|
111
|
-
{
|
|
112
|
-
"data-slot": "dialog-title",
|
|
113
|
-
className: cn(
|
|
114
|
-
"text-lg font-semibold leading-none tracking-tight",
|
|
115
|
-
className
|
|
116
|
-
),
|
|
117
|
-
...props
|
|
118
|
-
}
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
function DialogDescription({
|
|
122
|
-
className,
|
|
123
|
-
...props
|
|
124
|
-
}) {
|
|
125
|
-
return /* @__PURE__ */ jsx(
|
|
126
|
-
Dialog$1.Description,
|
|
127
|
-
{
|
|
128
|
-
"data-slot": "dialog-description",
|
|
129
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
130
|
-
...props
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
function Card({
|
|
135
|
-
className,
|
|
136
|
-
size = "default",
|
|
137
|
-
...props
|
|
138
|
-
}) {
|
|
139
|
-
return /* @__PURE__ */ jsx(
|
|
140
|
-
"div",
|
|
141
|
-
{
|
|
142
|
-
"data-slot": "card",
|
|
143
|
-
"data-size": size,
|
|
144
|
-
className: cn("ring-foreground/10 bg-card text-card-foreground gap-6 overflow-hidden rounded-2xl py-6 text-sm ring-1 has-[>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className),
|
|
145
|
-
...props
|
|
146
|
-
}
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
function CardHeader({ className, ...props }) {
|
|
150
|
-
return /* @__PURE__ */ jsx(
|
|
151
|
-
"div",
|
|
152
|
-
{
|
|
153
|
-
"data-slot": "card-header",
|
|
154
|
-
className: cn(
|
|
155
|
-
"gap-2 rounded-t-xl px-6 group-data-[size=sm]/card:px-4 [.border-b]:pb-6 group-data-[size=sm]/card:[.border-b]:pb-4 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
|
|
156
|
-
className
|
|
157
|
-
),
|
|
158
|
-
...props
|
|
159
|
-
}
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
function CardTitle({ className, ...props }) {
|
|
163
|
-
return /* @__PURE__ */ jsx(
|
|
164
|
-
"div",
|
|
165
|
-
{
|
|
166
|
-
"data-slot": "card-title",
|
|
167
|
-
className: cn("text-base font-medium", className),
|
|
168
|
-
...props
|
|
169
|
-
}
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
function CardDescription({ className, ...props }) {
|
|
173
|
-
return /* @__PURE__ */ jsx(
|
|
174
|
-
"div",
|
|
175
|
-
{
|
|
176
|
-
"data-slot": "card-description",
|
|
177
|
-
className: cn("text-muted-foreground text-sm", className),
|
|
178
|
-
...props
|
|
179
|
-
}
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
function CardContent({ className, ...props }) {
|
|
183
|
-
return /* @__PURE__ */ jsx(
|
|
184
|
-
"div",
|
|
185
|
-
{
|
|
186
|
-
"data-slot": "card-content",
|
|
187
|
-
className: cn("px-6 group-data-[size=sm]/card:px-4", className),
|
|
188
|
-
...props
|
|
189
|
-
}
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// src/lib/theme-utils.ts
|
|
194
|
-
var paddingMap = {
|
|
195
|
-
none: "p-0",
|
|
196
|
-
xs: "p-1",
|
|
197
|
-
sm: "p-2",
|
|
198
|
-
md: "p-4",
|
|
199
|
-
lg: "p-6",
|
|
200
|
-
xl: "p-8",
|
|
201
|
-
xxl: "p-12"
|
|
202
|
-
};
|
|
203
|
-
var marginMap = {
|
|
204
|
-
none: "m-0",
|
|
205
|
-
xs: "m-1",
|
|
206
|
-
sm: "m-2",
|
|
207
|
-
md: "m-4",
|
|
208
|
-
lg: "m-6",
|
|
209
|
-
xl: "m-8",
|
|
210
|
-
xxl: "m-12"
|
|
211
|
-
};
|
|
212
|
-
var gapMap = {
|
|
213
|
-
none: "gap-0",
|
|
214
|
-
xs: "gap-1",
|
|
215
|
-
sm: "gap-2",
|
|
216
|
-
md: "gap-4",
|
|
217
|
-
lg: "gap-6",
|
|
218
|
-
xl: "gap-8",
|
|
219
|
-
xxl: "gap-12"
|
|
220
|
-
};
|
|
221
|
-
var colorBgMap = {
|
|
222
|
-
primary: "bg-primary text-primary-foreground",
|
|
223
|
-
secondary: "bg-secondary text-secondary-foreground",
|
|
224
|
-
success: "bg-green-500 text-white",
|
|
225
|
-
danger: "bg-destructive text-destructive-foreground",
|
|
226
|
-
warning: "bg-yellow-500 text-white",
|
|
227
|
-
info: "bg-blue-500 text-white",
|
|
228
|
-
background: "bg-background text-foreground",
|
|
229
|
-
foreground: "bg-foreground text-background",
|
|
230
|
-
muted: "bg-muted text-muted-foreground",
|
|
231
|
-
mutedForeground: "bg-muted-foreground text-muted",
|
|
232
|
-
border: "bg-border",
|
|
233
|
-
transparent: "bg-transparent"
|
|
234
|
-
};
|
|
235
|
-
var colorTextMap = {
|
|
236
|
-
primary: "text-primary",
|
|
237
|
-
secondary: "text-secondary",
|
|
238
|
-
success: "text-green-600",
|
|
239
|
-
danger: "text-destructive",
|
|
240
|
-
warning: "text-yellow-600",
|
|
241
|
-
info: "text-blue-600",
|
|
242
|
-
background: "text-background",
|
|
243
|
-
foreground: "text-foreground",
|
|
244
|
-
muted: "text-muted-foreground",
|
|
245
|
-
mutedForeground: "text-muted-foreground",
|
|
246
|
-
border: "text-border",
|
|
247
|
-
transparent: "text-transparent"
|
|
248
|
-
};
|
|
249
|
-
var colorBorderMap = {
|
|
250
|
-
primary: "border-primary",
|
|
251
|
-
secondary: "border-secondary",
|
|
252
|
-
success: "border-green-500",
|
|
253
|
-
danger: "border-destructive",
|
|
254
|
-
warning: "border-yellow-500",
|
|
255
|
-
info: "border-blue-500",
|
|
256
|
-
background: "border-background",
|
|
257
|
-
foreground: "border-foreground",
|
|
258
|
-
muted: "border-muted",
|
|
259
|
-
mutedForeground: "border-muted-foreground",
|
|
260
|
-
border: "border-border",
|
|
261
|
-
transparent: "border-transparent"
|
|
262
|
-
};
|
|
263
|
-
var widthMap = {
|
|
264
|
-
auto: "w-auto",
|
|
265
|
-
full: "w-full",
|
|
266
|
-
min: "w-min",
|
|
267
|
-
max: "w-max",
|
|
268
|
-
"1/2": "w-1/2",
|
|
269
|
-
"1/3": "w-1/3",
|
|
270
|
-
"2/3": "w-2/3",
|
|
271
|
-
"1/4": "w-1/4",
|
|
272
|
-
"3/4": "w-3/4"
|
|
273
|
-
};
|
|
274
|
-
var shadowMap = {
|
|
275
|
-
none: "shadow-none",
|
|
276
|
-
sm: "shadow-sm",
|
|
277
|
-
md: "shadow-md",
|
|
278
|
-
lg: "shadow-lg",
|
|
279
|
-
xl: "shadow-xl"
|
|
280
|
-
};
|
|
281
|
-
var radiusMap = {
|
|
282
|
-
none: "rounded-none",
|
|
283
|
-
sm: "rounded-sm",
|
|
284
|
-
md: "rounded-md",
|
|
285
|
-
lg: "rounded-lg",
|
|
286
|
-
full: "rounded-full"
|
|
287
|
-
};
|
|
288
|
-
var alignMap = {
|
|
289
|
-
start: "items-start",
|
|
290
|
-
center: "items-center",
|
|
291
|
-
end: "items-end",
|
|
292
|
-
stretch: "items-stretch"
|
|
293
|
-
};
|
|
294
|
-
var justifyMap = {
|
|
295
|
-
start: "justify-start",
|
|
296
|
-
center: "justify-center",
|
|
297
|
-
end: "justify-end",
|
|
298
|
-
between: "justify-between",
|
|
299
|
-
around: "justify-around"
|
|
300
|
-
};
|
|
301
|
-
var wrapMap = {
|
|
302
|
-
nowrap: "flex-nowrap",
|
|
303
|
-
wrap: "flex-wrap",
|
|
304
|
-
"wrap-reverse": "flex-wrap-reverse"
|
|
305
|
-
};
|
|
306
|
-
var textSizeMap = {
|
|
307
|
-
none: "text-[0]",
|
|
308
|
-
xs: "text-xs",
|
|
309
|
-
sm: "text-sm",
|
|
310
|
-
md: "text-base",
|
|
311
|
-
lg: "text-lg",
|
|
312
|
-
xl: "text-xl",
|
|
313
|
-
xxl: "text-2xl"
|
|
314
|
-
};
|
|
315
|
-
var textAlignMap = {
|
|
316
|
-
start: "text-left",
|
|
317
|
-
center: "text-center",
|
|
318
|
-
end: "text-right",
|
|
319
|
-
stretch: "text-justify"
|
|
320
|
-
};
|
|
321
|
-
var fontWeightMap = {
|
|
322
|
-
normal: "font-normal",
|
|
323
|
-
medium: "font-medium",
|
|
324
|
-
semibold: "font-semibold",
|
|
325
|
-
bold: "font-bold"
|
|
326
|
-
};
|
|
327
|
-
var Card2 = ({
|
|
328
|
-
children,
|
|
329
|
-
title,
|
|
330
|
-
subtitle,
|
|
331
|
-
background,
|
|
332
|
-
padding = "md",
|
|
333
|
-
radius = "md",
|
|
334
|
-
shadow = "md"
|
|
335
|
-
}) => {
|
|
336
|
-
return /* @__PURE__ */ jsxs(
|
|
337
|
-
Card,
|
|
338
|
-
{
|
|
339
|
-
className: cn(
|
|
340
|
-
"min-w-96 relative",
|
|
341
|
-
background && colorBgMap[background],
|
|
342
|
-
radius && radiusMap[radius],
|
|
343
|
-
shadow && shadowMap[shadow]
|
|
344
|
-
),
|
|
345
|
-
children: [
|
|
346
|
-
(title || subtitle) && /* @__PURE__ */ jsxs(CardHeader, { className: "pb-3", children: [
|
|
347
|
-
title && /* @__PURE__ */ jsx(CardTitle, { className: "text-lg", children: title }),
|
|
348
|
-
subtitle && /* @__PURE__ */ jsx(CardDescription, { children: subtitle })
|
|
349
|
-
] }),
|
|
350
|
-
/* @__PURE__ */ jsx(CardContent, { className: cn("flex flex-col gap-4", paddingMap[padding]), children })
|
|
351
|
-
]
|
|
352
|
-
}
|
|
353
|
-
);
|
|
354
|
-
};
|
|
355
|
-
var Row = ({
|
|
356
|
-
children,
|
|
357
|
-
align = "start",
|
|
358
|
-
justify = "start",
|
|
359
|
-
wrap = "nowrap",
|
|
360
|
-
gap = "none",
|
|
361
|
-
padding = "none",
|
|
362
|
-
width = "full"
|
|
363
|
-
}) => {
|
|
364
|
-
return /* @__PURE__ */ jsx(
|
|
365
|
-
"div",
|
|
366
|
-
{
|
|
367
|
-
className: cn(
|
|
368
|
-
"flex flex-row",
|
|
369
|
-
alignMap[align],
|
|
370
|
-
justifyMap[justify],
|
|
371
|
-
wrapMap[wrap],
|
|
372
|
-
gapMap[gap],
|
|
373
|
-
paddingMap[padding],
|
|
374
|
-
widthMap[width]
|
|
375
|
-
),
|
|
376
|
-
children
|
|
377
|
-
}
|
|
378
|
-
);
|
|
379
|
-
};
|
|
380
|
-
var Col = ({
|
|
381
|
-
children,
|
|
382
|
-
align = "start",
|
|
383
|
-
justify = "start",
|
|
384
|
-
gap = "none",
|
|
385
|
-
width = "auto",
|
|
386
|
-
height = "auto",
|
|
387
|
-
padding = "none",
|
|
388
|
-
background,
|
|
389
|
-
radius
|
|
390
|
-
}) => {
|
|
391
|
-
return /* @__PURE__ */ jsx(
|
|
392
|
-
"div",
|
|
393
|
-
{
|
|
394
|
-
className: cn(
|
|
395
|
-
"flex flex-col",
|
|
396
|
-
alignMap[align],
|
|
397
|
-
justifyMap[justify],
|
|
398
|
-
gapMap[gap],
|
|
399
|
-
paddingMap[padding],
|
|
400
|
-
widthMap[width],
|
|
401
|
-
height === "full" && "h-full",
|
|
402
|
-
background && colorBgMap[background],
|
|
403
|
-
radius && radiusMap[radius]
|
|
404
|
-
),
|
|
405
|
-
children
|
|
406
|
-
}
|
|
407
|
-
);
|
|
408
|
-
};
|
|
409
|
-
var Box = ({
|
|
410
|
-
children,
|
|
411
|
-
padding = "none",
|
|
412
|
-
margin = "none",
|
|
413
|
-
background,
|
|
414
|
-
border = false,
|
|
415
|
-
borderColor = "border",
|
|
416
|
-
radius = "none",
|
|
417
|
-
width = "auto",
|
|
418
|
-
height = "auto",
|
|
419
|
-
shadow = "none"
|
|
420
|
-
}) => {
|
|
421
|
-
return /* @__PURE__ */ jsx(
|
|
422
|
-
"div",
|
|
423
|
-
{
|
|
424
|
-
className: cn(
|
|
425
|
-
"relative",
|
|
426
|
-
paddingMap[padding],
|
|
427
|
-
marginMap[margin],
|
|
428
|
-
background && colorBgMap[background],
|
|
429
|
-
border && "border",
|
|
430
|
-
border && colorBorderMap[borderColor],
|
|
431
|
-
radiusMap[radius],
|
|
432
|
-
widthMap[width],
|
|
433
|
-
height === "full" && "h-full",
|
|
434
|
-
shadowMap[shadow]
|
|
435
|
-
),
|
|
436
|
-
children
|
|
437
|
-
}
|
|
438
|
-
);
|
|
439
|
-
};
|
|
440
|
-
var Float = ({
|
|
441
|
-
children,
|
|
442
|
-
position = "top-right",
|
|
443
|
-
offsetX = "none",
|
|
444
|
-
offsetY = "none",
|
|
445
|
-
showOnHover = false
|
|
446
|
-
}) => {
|
|
447
|
-
const positionClasses = {
|
|
448
|
-
"top-left": "top-0 left-0",
|
|
449
|
-
"top-right": "top-0 right-0",
|
|
450
|
-
"bottom-left": "bottom-0 left-0",
|
|
451
|
-
"bottom-right": "bottom-0 right-0",
|
|
452
|
-
"center": "top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
|
|
453
|
-
};
|
|
454
|
-
const marginXClass = position.endsWith("left") ? marginMap[offsetX].replace("m-", "ml-") : marginMap[offsetX].replace("m-", "mr-");
|
|
455
|
-
const marginYClass = position.startsWith("top") ? marginMap[offsetY].replace("m-", "mt-") : marginMap[offsetY].replace("m-", "mb-");
|
|
456
|
-
return /* @__PURE__ */ jsx(
|
|
457
|
-
"div",
|
|
458
|
-
{
|
|
459
|
-
className: cn(
|
|
460
|
-
"absolute z-10",
|
|
461
|
-
positionClasses[position],
|
|
462
|
-
marginXClass,
|
|
463
|
-
marginYClass,
|
|
464
|
-
showOnHover && "opacity-0 group-hover:opacity-100 transition-opacity"
|
|
465
|
-
),
|
|
466
|
-
children
|
|
467
|
-
}
|
|
468
|
-
);
|
|
469
|
-
};
|
|
470
|
-
var Spacer = ({
|
|
471
|
-
size = "md",
|
|
472
|
-
direction = "vertical"
|
|
473
|
-
}) => {
|
|
474
|
-
return /* @__PURE__ */ jsx(
|
|
475
|
-
"div",
|
|
476
|
-
{
|
|
477
|
-
className: cn(
|
|
478
|
-
direction === "vertical" ? "w-full" : "h-full",
|
|
479
|
-
paddingMap[size]
|
|
480
|
-
)
|
|
481
|
-
}
|
|
482
|
-
);
|
|
483
|
-
};
|
|
484
|
-
function Separator({
|
|
485
|
-
className,
|
|
486
|
-
orientation = "horizontal",
|
|
487
|
-
...props
|
|
488
|
-
}) {
|
|
489
|
-
return /* @__PURE__ */ jsx(
|
|
490
|
-
Separator$1,
|
|
491
|
-
{
|
|
492
|
-
"data-slot": "separator",
|
|
493
|
-
orientation,
|
|
494
|
-
className: cn(
|
|
495
|
-
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch",
|
|
496
|
-
className
|
|
497
|
-
),
|
|
498
|
-
...props
|
|
499
|
-
}
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
var Divider = ({
|
|
503
|
-
orientation = "horizontal",
|
|
504
|
-
color = "border",
|
|
505
|
-
margin = "md"
|
|
506
|
-
}) => {
|
|
507
|
-
return /* @__PURE__ */ jsx(
|
|
508
|
-
Separator,
|
|
509
|
-
{
|
|
510
|
-
orientation,
|
|
511
|
-
className: cn(
|
|
512
|
-
marginMap[margin],
|
|
513
|
-
colorBgMap[color]
|
|
514
|
-
)
|
|
515
|
-
}
|
|
516
|
-
);
|
|
517
|
-
};
|
|
518
|
-
var List = ({ children, padding = "none", gap = "none", flex, overflow }) => {
|
|
519
|
-
return /* @__PURE__ */ jsx(
|
|
520
|
-
"div",
|
|
521
|
-
{
|
|
522
|
-
className: cn(
|
|
523
|
-
"flex flex-col list-none m-0",
|
|
524
|
-
paddingMap[padding],
|
|
525
|
-
gapMap[gap]
|
|
526
|
-
),
|
|
527
|
-
style: { flex, overflow },
|
|
528
|
-
children
|
|
529
|
-
}
|
|
530
|
-
);
|
|
531
|
-
};
|
|
532
|
-
var useMelony = (options) => {
|
|
533
|
-
const context = useContext(MelonyContext);
|
|
534
|
-
if (context === void 0) {
|
|
535
|
-
throw new Error("useMelony must be used within a MelonyClientProvider");
|
|
536
|
-
}
|
|
537
|
-
const { client, reset } = context;
|
|
538
|
-
const { initialEvents } = options || {};
|
|
539
|
-
const prevInitialEventsRef = useRef(void 0);
|
|
540
|
-
useEffect(() => {
|
|
541
|
-
if (initialEvents && initialEvents === client.getState().events) {
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
const currentSerialized = initialEvents ? JSON.stringify(initialEvents) : void 0;
|
|
545
|
-
if (currentSerialized !== prevInitialEventsRef.current) {
|
|
546
|
-
if (initialEvents) {
|
|
547
|
-
reset(initialEvents);
|
|
548
|
-
} else {
|
|
549
|
-
reset([]);
|
|
550
|
-
}
|
|
551
|
-
prevInitialEventsRef.current = currentSerialized;
|
|
552
|
-
}
|
|
553
|
-
}, [client, initialEvents, reset]);
|
|
554
|
-
return context;
|
|
555
|
-
};
|
|
556
|
-
var ListItem = ({
|
|
557
|
-
children,
|
|
558
|
-
onClickAction,
|
|
559
|
-
gap = "sm",
|
|
560
|
-
padding = "sm",
|
|
561
|
-
background,
|
|
562
|
-
radius = "md",
|
|
563
|
-
align = "center"
|
|
564
|
-
}) => {
|
|
565
|
-
const { sendEvent } = useMelony();
|
|
566
|
-
const isInteractive = !!onClickAction;
|
|
567
|
-
const handleClick = () => {
|
|
568
|
-
if (onClickAction) {
|
|
569
|
-
sendEvent(onClickAction);
|
|
570
|
-
}
|
|
571
|
-
};
|
|
572
|
-
return /* @__PURE__ */ jsx(
|
|
573
|
-
"div",
|
|
574
|
-
{
|
|
575
|
-
onClick: isInteractive ? handleClick : void 0,
|
|
576
|
-
className: cn(
|
|
577
|
-
"flex flex-row transition-colors text-sm",
|
|
578
|
-
paddingMap[padding],
|
|
579
|
-
background ? colorBgMap[background] : isInteractive && "hover:bg-muted",
|
|
580
|
-
radiusMap[radius],
|
|
581
|
-
isInteractive ? "cursor-pointer" : "cursor-default"
|
|
582
|
-
),
|
|
583
|
-
children: /* @__PURE__ */ jsx(Row, { align, gap, children })
|
|
584
|
-
}
|
|
585
|
-
);
|
|
586
|
-
};
|
|
587
|
-
var Image = ({
|
|
588
|
-
src,
|
|
589
|
-
alt,
|
|
590
|
-
width = "auto",
|
|
591
|
-
height,
|
|
592
|
-
radius = "md",
|
|
593
|
-
objectFit = "cover"
|
|
594
|
-
}) => {
|
|
595
|
-
const [hasError, setHasError] = useState(false);
|
|
596
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
597
|
-
const [open, setOpen] = useState(false);
|
|
598
|
-
const [currentIndex, setCurrentIndex] = useState(0);
|
|
599
|
-
const [gallery, setGallery] = useState([]);
|
|
600
|
-
const triggerRef = useRef(null);
|
|
601
|
-
useEffect(() => {
|
|
602
|
-
if (open && triggerRef.current) {
|
|
603
|
-
let parent = triggerRef.current.parentElement;
|
|
604
|
-
while (parent && parent.parentElement && parent.parentElement.children.length === 1) {
|
|
605
|
-
parent = parent.parentElement;
|
|
606
|
-
}
|
|
607
|
-
const container = parent?.parentElement;
|
|
608
|
-
if (container) {
|
|
609
|
-
const foundImgs = Array.from(container.querySelectorAll("img")).map((img) => ({
|
|
610
|
-
src: img.getAttribute("src") || "",
|
|
611
|
-
alt: img.getAttribute("alt") || ""
|
|
612
|
-
})).filter((v, i, a) => a.findIndex((t) => t.src === v.src) === i);
|
|
613
|
-
setGallery(foundImgs);
|
|
614
|
-
const idx = foundImgs.findIndex((img) => img.src === src);
|
|
615
|
-
setCurrentIndex(idx >= 0 ? idx : 0);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
}, [open, src]);
|
|
619
|
-
const navigate = (dir) => {
|
|
620
|
-
setCurrentIndex((prev) => (prev + dir + gallery.length) % gallery.length);
|
|
621
|
-
};
|
|
622
|
-
const currentImage = gallery[currentIndex] || { src, alt };
|
|
623
|
-
const hasMultiple = gallery.length > 1;
|
|
624
|
-
const handleError = () => {
|
|
625
|
-
setHasError(true);
|
|
626
|
-
setIsLoading(false);
|
|
627
|
-
};
|
|
628
|
-
const handleLoad = () => {
|
|
629
|
-
setIsLoading(false);
|
|
630
|
-
};
|
|
631
|
-
if (hasError) {
|
|
632
|
-
return /* @__PURE__ */ jsx(
|
|
633
|
-
"div",
|
|
634
|
-
{
|
|
635
|
-
className: cn(
|
|
636
|
-
"flex items-center justify-center bg-muted text-muted-foreground",
|
|
637
|
-
widthMap[width],
|
|
638
|
-
radiusMap[radius]
|
|
639
|
-
),
|
|
640
|
-
style: { height: height || "100px" },
|
|
641
|
-
children: /* @__PURE__ */ jsx("span", { className: "text-[10px]", children: "Error" })
|
|
642
|
-
}
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
646
|
-
/* @__PURE__ */ jsx(DialogTrigger, { children: /* @__PURE__ */ jsxs(
|
|
647
|
-
"div",
|
|
648
|
-
{
|
|
649
|
-
ref: triggerRef,
|
|
650
|
-
className: cn(
|
|
651
|
-
"relative overflow-hidden cursor-pointer",
|
|
652
|
-
widthMap[width],
|
|
653
|
-
radiusMap[radius]
|
|
654
|
-
),
|
|
655
|
-
style: { height },
|
|
656
|
-
children: [
|
|
657
|
-
/* @__PURE__ */ jsx(
|
|
658
|
-
"img",
|
|
659
|
-
{
|
|
660
|
-
src,
|
|
661
|
-
alt,
|
|
662
|
-
onError: handleError,
|
|
663
|
-
onLoad: handleLoad,
|
|
664
|
-
className: cn(
|
|
665
|
-
"block w-full transition-opacity duration-200 hover:opacity-90",
|
|
666
|
-
isLoading ? "opacity-0" : "opacity-100",
|
|
667
|
-
objectFit === "cover" ? "object-cover" : objectFit === "contain" ? "object-contain" : "object-fill",
|
|
668
|
-
height ? "h-full" : "h-auto"
|
|
669
|
-
)
|
|
670
|
-
}
|
|
671
|
-
),
|
|
672
|
-
isLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-muted animate-pulse" })
|
|
673
|
-
]
|
|
674
|
-
}
|
|
675
|
-
) }),
|
|
676
|
-
/* @__PURE__ */ jsx(
|
|
677
|
-
DialogContent,
|
|
678
|
-
{
|
|
679
|
-
className: "max-w-[90vw] max-h-[90vh] p-0 bg-transparent border-none shadow-none outline-none",
|
|
680
|
-
onClick: (e) => e.stopPropagation(),
|
|
681
|
-
children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center group/lightbox", children: [
|
|
682
|
-
/* @__PURE__ */ jsx(DialogClose, { className: "absolute -top-12 right-0 text-white hover:text-gray-300 transition-colors z-50 bg-black/50 rounded-full p-2", children: /* @__PURE__ */ jsx(IconX, { size: 20 }) }),
|
|
683
|
-
hasMultiple && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
684
|
-
/* @__PURE__ */ jsx(
|
|
685
|
-
"button",
|
|
686
|
-
{
|
|
687
|
-
onClick: (e) => {
|
|
688
|
-
e.stopPropagation();
|
|
689
|
-
navigate(-1);
|
|
690
|
-
},
|
|
691
|
-
className: "absolute left-4 z-50 p-3 bg-black/40 hover:bg-black/60 text-white rounded-full transition-all opacity-0 group-hover/lightbox:opacity-100",
|
|
692
|
-
children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 28 })
|
|
693
|
-
}
|
|
694
|
-
),
|
|
695
|
-
/* @__PURE__ */ jsx(
|
|
696
|
-
"button",
|
|
697
|
-
{
|
|
698
|
-
onClick: (e) => {
|
|
699
|
-
e.stopPropagation();
|
|
700
|
-
navigate(1);
|
|
701
|
-
},
|
|
702
|
-
className: "absolute right-4 z-50 p-3 bg-black/40 hover:bg-black/60 text-white rounded-full transition-all opacity-0 group-hover/lightbox:opacity-100",
|
|
703
|
-
children: /* @__PURE__ */ jsx(IconChevronRight, { size: 28 })
|
|
704
|
-
}
|
|
705
|
-
)
|
|
706
|
-
] }),
|
|
707
|
-
/* @__PURE__ */ jsx(
|
|
708
|
-
"img",
|
|
709
|
-
{
|
|
710
|
-
src: currentImage.src,
|
|
711
|
-
alt: currentImage.alt || alt || "Enlarged image",
|
|
712
|
-
className: "max-w-full max-h-[85vh] object-contain rounded-lg shadow-2xl"
|
|
713
|
-
}
|
|
714
|
-
),
|
|
715
|
-
hasMultiple && /* @__PURE__ */ jsxs("div", { className: "absolute -bottom-10 left-1/2 -translate-x-1/2 text-white bg-black/50 px-3 py-1 rounded-full text-sm font-medium", children: [
|
|
716
|
-
currentIndex + 1,
|
|
717
|
-
" / ",
|
|
718
|
-
gallery.length
|
|
719
|
-
] })
|
|
720
|
-
] })
|
|
721
|
-
}
|
|
722
|
-
)
|
|
723
|
-
] });
|
|
724
|
-
};
|
|
725
|
-
var Video = ({
|
|
726
|
-
src,
|
|
727
|
-
poster,
|
|
728
|
-
autoPlay = false,
|
|
729
|
-
controls = true,
|
|
730
|
-
loop = false,
|
|
731
|
-
muted = false,
|
|
732
|
-
aspectRatio = "16/9",
|
|
733
|
-
width = "full",
|
|
734
|
-
radius = "lg"
|
|
735
|
-
}) => {
|
|
736
|
-
const aspectRatios = {
|
|
737
|
-
"16/9": "aspect-video",
|
|
738
|
-
"4/3": "aspect-[4/3]",
|
|
739
|
-
"1/1": "aspect-square",
|
|
740
|
-
"9/16": "aspect-[9/16]"
|
|
741
|
-
};
|
|
742
|
-
return /* @__PURE__ */ jsx(
|
|
743
|
-
"div",
|
|
744
|
-
{
|
|
745
|
-
className: cn(
|
|
746
|
-
"relative overflow-hidden bg-black shadow-sm",
|
|
747
|
-
aspectRatios[aspectRatio] || "aspect-video",
|
|
748
|
-
widthMap[width],
|
|
749
|
-
radiusMap[radius]
|
|
750
|
-
),
|
|
751
|
-
children: /* @__PURE__ */ jsx(
|
|
752
|
-
"video",
|
|
753
|
-
{
|
|
754
|
-
src,
|
|
755
|
-
poster,
|
|
756
|
-
autoPlay,
|
|
757
|
-
controls,
|
|
758
|
-
loop,
|
|
759
|
-
muted,
|
|
760
|
-
playsInline: true,
|
|
761
|
-
className: "h-full w-full object-cover"
|
|
762
|
-
}
|
|
763
|
-
)
|
|
764
|
-
}
|
|
765
|
-
);
|
|
766
|
-
};
|
|
767
|
-
var Icon = ({
|
|
768
|
-
name,
|
|
769
|
-
size = "md",
|
|
770
|
-
color = "foreground"
|
|
771
|
-
}) => {
|
|
772
|
-
const IconComponent = ICONS[name];
|
|
773
|
-
if (!IconComponent) return null;
|
|
774
|
-
const sizeMap = {
|
|
775
|
-
sm: 16,
|
|
776
|
-
md: 20,
|
|
777
|
-
lg: 24
|
|
778
|
-
};
|
|
779
|
-
const resolvedSize = typeof size === "number" ? size : sizeMap[size] || 20;
|
|
780
|
-
return /* @__PURE__ */ jsx("div", { className: cn("inline-flex items-center justify-center", colorTextMap[color]), children: /* @__PURE__ */ jsx(
|
|
781
|
-
IconComponent,
|
|
782
|
-
{
|
|
783
|
-
size: resolvedSize,
|
|
784
|
-
strokeWidth: 1.5
|
|
785
|
-
}
|
|
786
|
-
) });
|
|
787
|
-
};
|
|
788
|
-
var badgeVariants = cva(
|
|
789
|
-
"h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
|
|
790
|
-
{
|
|
791
|
-
variants: {
|
|
792
|
-
variant: {
|
|
793
|
-
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
794
|
-
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
795
|
-
destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
|
|
796
|
-
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
|
|
797
|
-
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
798
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
799
|
-
}
|
|
800
|
-
},
|
|
801
|
-
defaultVariants: {
|
|
802
|
-
variant: "default"
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
);
|
|
806
|
-
function Badge({
|
|
807
|
-
className,
|
|
808
|
-
variant = "default",
|
|
809
|
-
render,
|
|
810
|
-
...props
|
|
811
|
-
}) {
|
|
812
|
-
return useRender({
|
|
813
|
-
defaultTagName: "span",
|
|
814
|
-
props: mergeProps(
|
|
815
|
-
{
|
|
816
|
-
className: cn(badgeVariants({ className, variant }))
|
|
817
|
-
},
|
|
818
|
-
props
|
|
819
|
-
),
|
|
820
|
-
render,
|
|
821
|
-
state: {
|
|
822
|
-
slot: "badge",
|
|
823
|
-
variant
|
|
824
|
-
}
|
|
825
|
-
});
|
|
826
|
-
}
|
|
827
|
-
var Badge2 = ({
|
|
828
|
-
label,
|
|
829
|
-
variant = "primary",
|
|
830
|
-
size = "md"
|
|
831
|
-
}) => {
|
|
832
|
-
const variantMap = {
|
|
833
|
-
primary: "default",
|
|
834
|
-
secondary: "secondary",
|
|
835
|
-
danger: "destructive",
|
|
836
|
-
success: "default",
|
|
837
|
-
warning: "secondary",
|
|
838
|
-
outline: "outline"
|
|
839
|
-
};
|
|
840
|
-
const sizeClasses = {
|
|
841
|
-
sm: "text-[10px] px-1.5 py-0",
|
|
842
|
-
md: "text-xs px-2.5 py-0.5",
|
|
843
|
-
lg: "text-sm px-3 py-1"
|
|
844
|
-
};
|
|
845
|
-
return /* @__PURE__ */ jsx(
|
|
846
|
-
Badge,
|
|
847
|
-
{
|
|
848
|
-
variant: variantMap[variant] || "default",
|
|
849
|
-
className: sizeClasses[size],
|
|
850
|
-
children: label
|
|
851
|
-
}
|
|
852
|
-
);
|
|
853
|
-
};
|
|
854
|
-
var Chart = ({
|
|
855
|
-
data,
|
|
856
|
-
chartType = "bar",
|
|
857
|
-
title,
|
|
858
|
-
height = 250,
|
|
859
|
-
showValues = false,
|
|
860
|
-
showGrid = false,
|
|
861
|
-
showTooltips = true
|
|
862
|
-
}) => {
|
|
863
|
-
const [tooltip, setTooltip] = useState(null);
|
|
864
|
-
if (!Array.isArray(data)) {
|
|
865
|
-
return /* @__PURE__ */ jsx("div", { className: "p-4 text-destructive border border-destructive/20 rounded-md bg-destructive/5 text-sm", children: "Error: Chart data must be an array" });
|
|
866
|
-
}
|
|
867
|
-
const maxValue = Math.max(...data.map((d) => d.value), 1);
|
|
868
|
-
const padding = { top: 40, right: 20, bottom: 40, left: 20 };
|
|
869
|
-
const chartHeight = height;
|
|
870
|
-
const chartWidth = 600;
|
|
871
|
-
const defaultColors = [
|
|
872
|
-
"hsl(var(--primary))",
|
|
873
|
-
"hsl(var(--chart-1, 217 91% 60%))",
|
|
874
|
-
"hsl(var(--chart-2, 142 71% 45%))",
|
|
875
|
-
"hsl(var(--chart-3, 31 92% 55%))",
|
|
876
|
-
"hsl(var(--chart-4, 346 84% 61%))",
|
|
877
|
-
"hsl(var(--chart-5, 271 81% 56%))"
|
|
878
|
-
];
|
|
879
|
-
const getColor = (index, color) => {
|
|
880
|
-
if (color) return color;
|
|
881
|
-
return defaultColors[index % defaultColors.length];
|
|
882
|
-
};
|
|
883
|
-
const renderGrid = () => {
|
|
884
|
-
if (!showGrid) return null;
|
|
885
|
-
return [0, 0.25, 0.5, 0.75, 1].map((fraction, i) => /* @__PURE__ */ jsx(
|
|
886
|
-
"line",
|
|
887
|
-
{
|
|
888
|
-
x1: padding.left,
|
|
889
|
-
y1: padding.top + chartHeight * (1 - fraction),
|
|
890
|
-
x2: chartWidth - padding.right,
|
|
891
|
-
y2: padding.top + chartHeight * (1 - fraction),
|
|
892
|
-
stroke: "currentColor",
|
|
893
|
-
className: "text-border",
|
|
894
|
-
strokeDasharray: "4,4",
|
|
895
|
-
strokeOpacity: 0.5
|
|
896
|
-
},
|
|
897
|
-
i
|
|
898
|
-
));
|
|
899
|
-
};
|
|
900
|
-
const renderTooltip = () => {
|
|
901
|
-
if (!tooltip || !tooltip.visible) return null;
|
|
902
|
-
return /* @__PURE__ */ jsxs("g", { className: "pointer-events-none", children: [
|
|
903
|
-
/* @__PURE__ */ jsx(
|
|
904
|
-
"rect",
|
|
905
|
-
{
|
|
906
|
-
x: tooltip.x - 40,
|
|
907
|
-
y: tooltip.y - 45,
|
|
908
|
-
width: 80,
|
|
909
|
-
height: 40,
|
|
910
|
-
fill: "hsl(var(--popover))",
|
|
911
|
-
stroke: "hsl(var(--border))",
|
|
912
|
-
strokeWidth: 1,
|
|
913
|
-
rx: 6,
|
|
914
|
-
className: "shadow-md"
|
|
915
|
-
}
|
|
916
|
-
),
|
|
917
|
-
/* @__PURE__ */ jsx(
|
|
918
|
-
"text",
|
|
919
|
-
{
|
|
920
|
-
x: tooltip.x,
|
|
921
|
-
y: tooltip.y - 28,
|
|
922
|
-
textAnchor: "middle",
|
|
923
|
-
className: "fill-popover-foreground text-[10px] font-semibold",
|
|
924
|
-
children: tooltip.value
|
|
925
|
-
}
|
|
926
|
-
),
|
|
927
|
-
/* @__PURE__ */ jsx(
|
|
928
|
-
"text",
|
|
929
|
-
{
|
|
930
|
-
x: tooltip.x,
|
|
931
|
-
y: tooltip.y - 14,
|
|
932
|
-
textAnchor: "middle",
|
|
933
|
-
className: "fill-muted-foreground text-[9px]",
|
|
934
|
-
children: tooltip.label
|
|
935
|
-
}
|
|
936
|
-
)
|
|
937
|
-
] });
|
|
938
|
-
};
|
|
939
|
-
const renderBarChart = () => {
|
|
940
|
-
const totalBarSpace = chartWidth - padding.left - padding.right;
|
|
941
|
-
const barSpacing = data.length > 1 ? totalBarSpace * 0.1 / data.length : 0;
|
|
942
|
-
const actualBarWidth = (totalBarSpace - barSpacing * (data.length + 1)) / data.length;
|
|
943
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${chartWidth} ${chartHeight + padding.bottom}`, className: "w-full h-auto overflow-visible", children: [
|
|
944
|
-
renderGrid(),
|
|
945
|
-
data.map((item, index) => {
|
|
946
|
-
const barHeight = item.value / maxValue * chartHeight;
|
|
947
|
-
const x = padding.left + barSpacing + index * (actualBarWidth + barSpacing);
|
|
948
|
-
const y = padding.top + chartHeight - barHeight;
|
|
949
|
-
return /* @__PURE__ */ jsxs("g", { children: [
|
|
950
|
-
/* @__PURE__ */ jsx(
|
|
951
|
-
"rect",
|
|
952
|
-
{
|
|
953
|
-
x,
|
|
954
|
-
y,
|
|
955
|
-
width: actualBarWidth,
|
|
956
|
-
height: barHeight,
|
|
957
|
-
fill: getColor(index, item.color),
|
|
958
|
-
rx: 4,
|
|
959
|
-
onMouseEnter: () => showTooltips && setTooltip({ visible: true, x: x + actualBarWidth / 2, y: y - 5, label: item.label, value: item.value }),
|
|
960
|
-
onMouseLeave: () => setTooltip({ visible: false, x: 0, y: 0, label: "", value: 0 }),
|
|
961
|
-
className: "transition-all hover:opacity-80 cursor-pointer"
|
|
962
|
-
}
|
|
963
|
-
),
|
|
964
|
-
/* @__PURE__ */ jsx(
|
|
965
|
-
"text",
|
|
966
|
-
{
|
|
967
|
-
x: x + actualBarWidth / 2,
|
|
968
|
-
y: padding.top + chartHeight + 20,
|
|
969
|
-
textAnchor: "middle",
|
|
970
|
-
className: "fill-muted-foreground text-[10px]",
|
|
971
|
-
children: item.label
|
|
972
|
-
}
|
|
973
|
-
)
|
|
974
|
-
] }, index);
|
|
975
|
-
}),
|
|
976
|
-
showTooltips && renderTooltip()
|
|
977
|
-
] });
|
|
978
|
-
};
|
|
979
|
-
const renderLineChart = () => {
|
|
980
|
-
const points = data.map((item, index) => ({
|
|
981
|
-
x: padding.left + index / Math.max(data.length - 1, 1) * (chartWidth - padding.left - padding.right),
|
|
982
|
-
y: padding.top + chartHeight - item.value / maxValue * chartHeight,
|
|
983
|
-
...item
|
|
984
|
-
}));
|
|
985
|
-
const pathData = points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
|
|
986
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${chartWidth} ${chartHeight + padding.bottom}`, className: "w-full h-auto overflow-visible", children: [
|
|
987
|
-
renderGrid(),
|
|
988
|
-
/* @__PURE__ */ jsx("path", { d: pathData, fill: "none", stroke: getColor(0), strokeWidth: 3, className: "transition-all" }),
|
|
989
|
-
points.map((point, index) => /* @__PURE__ */ jsxs("g", { children: [
|
|
990
|
-
/* @__PURE__ */ jsx(
|
|
991
|
-
"circle",
|
|
992
|
-
{
|
|
993
|
-
cx: point.x,
|
|
994
|
-
cy: point.y,
|
|
995
|
-
r: 5,
|
|
996
|
-
fill: getColor(index, point.color),
|
|
997
|
-
stroke: "hsl(var(--background))",
|
|
998
|
-
strokeWidth: 2,
|
|
999
|
-
onMouseEnter: () => showTooltips && setTooltip({ visible: true, x: point.x, y: point.y - 5, label: point.label, value: point.value }),
|
|
1000
|
-
onMouseLeave: () => setTooltip({ visible: false, x: 0, y: 0, label: "", value: 0 }),
|
|
1001
|
-
className: "hover:r-6 transition-all cursor-pointer"
|
|
1002
|
-
}
|
|
1003
|
-
),
|
|
1004
|
-
/* @__PURE__ */ jsx(
|
|
1005
|
-
"text",
|
|
1006
|
-
{
|
|
1007
|
-
x: point.x,
|
|
1008
|
-
y: padding.top + chartHeight + 20,
|
|
1009
|
-
textAnchor: "middle",
|
|
1010
|
-
className: "fill-muted-foreground text-[10px]",
|
|
1011
|
-
children: point.label
|
|
1012
|
-
}
|
|
1013
|
-
)
|
|
1014
|
-
] }, index)),
|
|
1015
|
-
showTooltips && renderTooltip()
|
|
1016
|
-
] });
|
|
1017
|
-
};
|
|
1018
|
-
const renderChart = () => {
|
|
1019
|
-
switch (chartType) {
|
|
1020
|
-
case "line":
|
|
1021
|
-
return renderLineChart();
|
|
1022
|
-
case "bar":
|
|
1023
|
-
default:
|
|
1024
|
-
return renderBarChart();
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
return /* @__PURE__ */ jsxs("div", { className: "py-4 w-full", children: [
|
|
1028
|
-
title && /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold mb-4 text-center", children: title }),
|
|
1029
|
-
renderChart()
|
|
1030
|
-
] });
|
|
1031
|
-
};
|
|
1032
|
-
var Text = ({
|
|
1033
|
-
value,
|
|
1034
|
-
size = "md",
|
|
1035
|
-
weight = "normal",
|
|
1036
|
-
align = "start",
|
|
1037
|
-
color = "foreground"
|
|
1038
|
-
}) => {
|
|
1039
|
-
return /* @__PURE__ */ jsx(
|
|
1040
|
-
"span",
|
|
1041
|
-
{
|
|
1042
|
-
className: cn(
|
|
1043
|
-
textSizeMap[size],
|
|
1044
|
-
fontWeightMap[weight],
|
|
1045
|
-
textAlignMap[align],
|
|
1046
|
-
colorTextMap[color]
|
|
1047
|
-
),
|
|
1048
|
-
children: value
|
|
1049
|
-
}
|
|
1050
|
-
);
|
|
1051
|
-
};
|
|
1052
|
-
var Heading = ({
|
|
1053
|
-
value,
|
|
1054
|
-
level = 2,
|
|
1055
|
-
color = "foreground",
|
|
1056
|
-
align = "start"
|
|
1057
|
-
}) => {
|
|
1058
|
-
const Tag = `h${level}`;
|
|
1059
|
-
const levelClasses = {
|
|
1060
|
-
h1: "text-3xl font-bold tracking-tight",
|
|
1061
|
-
h2: "text-2xl font-semibold tracking-tight",
|
|
1062
|
-
h3: "text-xl font-semibold tracking-tight",
|
|
1063
|
-
h4: "text-lg font-semibold tracking-tight",
|
|
1064
|
-
h5: "text-base font-semibold",
|
|
1065
|
-
h6: "text-sm font-semibold"
|
|
1066
|
-
};
|
|
1067
|
-
return /* @__PURE__ */ jsx(
|
|
1068
|
-
Tag,
|
|
1069
|
-
{
|
|
1070
|
-
className: cn(
|
|
1071
|
-
levelClasses[Tag] || levelClasses.h2,
|
|
1072
|
-
colorTextMap[color],
|
|
1073
|
-
textAlignMap[align]
|
|
1074
|
-
),
|
|
1075
|
-
children: value
|
|
1076
|
-
}
|
|
1077
|
-
);
|
|
1078
|
-
};
|
|
1079
|
-
function Input({ className, type, ...props }) {
|
|
1080
|
-
return /* @__PURE__ */ jsx(
|
|
1081
|
-
Input$1,
|
|
1082
|
-
{
|
|
1083
|
-
type,
|
|
1084
|
-
"data-slot": "input",
|
|
1085
|
-
className: cn(
|
|
1086
|
-
"bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 h-9 rounded-4xl border px-3 py-1 text-base transition-colors file:h-7 file:text-sm file:font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
1087
|
-
className
|
|
1088
|
-
),
|
|
1089
|
-
...props
|
|
1090
|
-
}
|
|
1091
|
-
);
|
|
1092
|
-
}
|
|
1093
|
-
function Label({ className, ...props }) {
|
|
1094
|
-
return /* @__PURE__ */ jsx(
|
|
1095
|
-
"label",
|
|
1096
|
-
{
|
|
1097
|
-
"data-slot": "label",
|
|
1098
|
-
className: cn(
|
|
1099
|
-
"gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed",
|
|
1100
|
-
className
|
|
1101
|
-
),
|
|
1102
|
-
...props
|
|
1103
|
-
}
|
|
1104
|
-
);
|
|
1105
|
-
}
|
|
1106
|
-
var fieldVariants = cva("data-[invalid=true]:text-destructive gap-3 group/field flex w-full", {
|
|
1107
|
-
variants: {
|
|
1108
|
-
orientation: {
|
|
1109
|
-
vertical: "flex-col [&>*]:w-full [&>.sr-only]:w-auto",
|
|
1110
|
-
horizontal: "flex-row items-center [&>[data-slot=field-label]]:flex-auto has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
1111
|
-
responsive: "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto @md/field-group:[&>[data-slot=field-label]]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px"
|
|
1112
|
-
}
|
|
1113
|
-
},
|
|
1114
|
-
defaultVariants: {
|
|
1115
|
-
orientation: "vertical"
|
|
1116
|
-
}
|
|
1117
|
-
});
|
|
1118
|
-
function Field({
|
|
1119
|
-
className,
|
|
1120
|
-
orientation = "vertical",
|
|
1121
|
-
...props
|
|
1122
|
-
}) {
|
|
1123
|
-
return /* @__PURE__ */ jsx(
|
|
1124
|
-
"div",
|
|
1125
|
-
{
|
|
1126
|
-
role: "group",
|
|
1127
|
-
"data-slot": "field",
|
|
1128
|
-
"data-orientation": orientation,
|
|
1129
|
-
className: cn(fieldVariants({ orientation }), className),
|
|
1130
|
-
...props
|
|
1131
|
-
}
|
|
1132
|
-
);
|
|
1133
|
-
}
|
|
1134
|
-
function FieldTitle({ className, ...props }) {
|
|
1135
|
-
return /* @__PURE__ */ jsx(
|
|
1136
|
-
"div",
|
|
1137
|
-
{
|
|
1138
|
-
"data-slot": "field-label",
|
|
1139
|
-
className: cn(
|
|
1140
|
-
"gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug",
|
|
1141
|
-
className
|
|
1142
|
-
),
|
|
1143
|
-
...props
|
|
1144
|
-
}
|
|
1145
|
-
);
|
|
1146
|
-
}
|
|
1147
|
-
var Input2 = ({
|
|
1148
|
-
inputType = "text",
|
|
1149
|
-
placeholder,
|
|
1150
|
-
defaultValue,
|
|
1151
|
-
label,
|
|
1152
|
-
name,
|
|
1153
|
-
disabled,
|
|
1154
|
-
required,
|
|
1155
|
-
width = "full",
|
|
1156
|
-
onChangeAction
|
|
1157
|
-
}) => {
|
|
1158
|
-
const { sendEvent } = useMelony();
|
|
1159
|
-
const handleChange = (e) => {
|
|
1160
|
-
if (onChangeAction) {
|
|
1161
|
-
sendEvent({
|
|
1162
|
-
...onChangeAction,
|
|
1163
|
-
data: {
|
|
1164
|
-
name: name || "",
|
|
1165
|
-
value: e.target.value
|
|
1166
|
-
}
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
};
|
|
1170
|
-
return /* @__PURE__ */ jsxs(Field, { className: cn(widthMap[width]), children: [
|
|
1171
|
-
label && /* @__PURE__ */ jsxs(FieldTitle, { children: [
|
|
1172
|
-
label,
|
|
1173
|
-
required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
|
|
1174
|
-
] }),
|
|
1175
|
-
/* @__PURE__ */ jsx(
|
|
1176
|
-
Input,
|
|
1177
|
-
{
|
|
1178
|
-
type: inputType,
|
|
1179
|
-
name,
|
|
1180
|
-
id: name,
|
|
1181
|
-
placeholder,
|
|
1182
|
-
defaultValue,
|
|
1183
|
-
disabled,
|
|
1184
|
-
onChange: handleChange,
|
|
1185
|
-
required
|
|
1186
|
-
}
|
|
1187
|
-
)
|
|
1188
|
-
] });
|
|
1189
|
-
};
|
|
1190
|
-
function Textarea({ className, ...props }) {
|
|
1191
|
-
return /* @__PURE__ */ jsx(
|
|
1192
|
-
"textarea",
|
|
1193
|
-
{
|
|
1194
|
-
"data-slot": "textarea",
|
|
1195
|
-
className: cn(
|
|
1196
|
-
"border-input bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none rounded-xl border px-3 py-3 text-base transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
1197
|
-
className
|
|
1198
|
-
),
|
|
1199
|
-
...props
|
|
1200
|
-
}
|
|
1201
|
-
);
|
|
1202
|
-
}
|
|
1203
|
-
var Textarea2 = ({
|
|
1204
|
-
placeholder,
|
|
1205
|
-
defaultValue,
|
|
1206
|
-
label,
|
|
1207
|
-
name,
|
|
1208
|
-
disabled,
|
|
1209
|
-
rows,
|
|
1210
|
-
required,
|
|
1211
|
-
width = "full",
|
|
1212
|
-
onChangeAction
|
|
1213
|
-
}) => {
|
|
1214
|
-
const { sendEvent } = useMelony();
|
|
1215
|
-
const handleChange = (e) => {
|
|
1216
|
-
if (onChangeAction) {
|
|
1217
|
-
sendEvent({
|
|
1218
|
-
...onChangeAction,
|
|
1219
|
-
data: {
|
|
1220
|
-
name: name || "",
|
|
1221
|
-
value: e.target.value
|
|
1222
|
-
}
|
|
1223
|
-
});
|
|
1224
|
-
}
|
|
1225
|
-
};
|
|
1226
|
-
return /* @__PURE__ */ jsxs(Field, { className: cn(widthMap[width]), children: [
|
|
1227
|
-
label && /* @__PURE__ */ jsxs(FieldTitle, { children: [
|
|
1228
|
-
label,
|
|
1229
|
-
required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
|
|
1230
|
-
] }),
|
|
1231
|
-
/* @__PURE__ */ jsx(
|
|
1232
|
-
Textarea,
|
|
1233
|
-
{
|
|
1234
|
-
name,
|
|
1235
|
-
id: name,
|
|
1236
|
-
placeholder,
|
|
1237
|
-
defaultValue,
|
|
1238
|
-
disabled,
|
|
1239
|
-
rows,
|
|
1240
|
-
onChange: handleChange,
|
|
1241
|
-
required
|
|
1242
|
-
}
|
|
1243
|
-
)
|
|
1244
|
-
] });
|
|
1245
|
-
};
|
|
1246
|
-
var Select = Select$1.Root;
|
|
1247
|
-
function SelectValue({ className, ...props }) {
|
|
1248
|
-
return /* @__PURE__ */ jsx(
|
|
1249
|
-
Select$1.Value,
|
|
1250
|
-
{
|
|
1251
|
-
"data-slot": "select-value",
|
|
1252
|
-
className: cn("flex flex-1 text-left", className),
|
|
1253
|
-
...props
|
|
1254
|
-
}
|
|
1255
|
-
);
|
|
1256
|
-
}
|
|
1257
|
-
function SelectTrigger({
|
|
1258
|
-
className,
|
|
1259
|
-
size = "default",
|
|
1260
|
-
children,
|
|
1261
|
-
...props
|
|
1262
|
-
}) {
|
|
1263
|
-
return /* @__PURE__ */ jsxs(
|
|
1264
|
-
Select$1.Trigger,
|
|
1265
|
-
{
|
|
1266
|
-
"data-slot": "select-trigger",
|
|
1267
|
-
"data-size": size,
|
|
1268
|
-
className: cn(
|
|
1269
|
-
"border-input data-[placeholder]:text-muted-foreground bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-4xl border px-3 py-2 text-sm transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:flex *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
1270
|
-
className
|
|
1271
|
-
),
|
|
1272
|
-
...props,
|
|
1273
|
-
children: [
|
|
1274
|
-
children,
|
|
1275
|
-
/* @__PURE__ */ jsx(
|
|
1276
|
-
Select$1.Icon,
|
|
1277
|
-
{
|
|
1278
|
-
render: /* @__PURE__ */ jsx(IconSelector, { className: "text-muted-foreground size-4 pointer-events-none" })
|
|
1279
|
-
}
|
|
1280
|
-
)
|
|
1281
|
-
]
|
|
1282
|
-
}
|
|
1283
|
-
);
|
|
1284
|
-
}
|
|
1285
|
-
function SelectContent({
|
|
1286
|
-
className,
|
|
1287
|
-
children,
|
|
1288
|
-
side = "bottom",
|
|
1289
|
-
sideOffset = 4,
|
|
1290
|
-
align = "center",
|
|
1291
|
-
alignOffset = 0,
|
|
1292
|
-
alignItemWithTrigger = true,
|
|
1293
|
-
...props
|
|
1294
|
-
}) {
|
|
1295
|
-
return /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(
|
|
1296
|
-
Select$1.Positioner,
|
|
1297
|
-
{
|
|
1298
|
-
side,
|
|
1299
|
-
sideOffset,
|
|
1300
|
-
align,
|
|
1301
|
-
alignOffset,
|
|
1302
|
-
alignItemWithTrigger,
|
|
1303
|
-
className: "isolate z-50",
|
|
1304
|
-
children: /* @__PURE__ */ jsxs(
|
|
1305
|
-
Select$1.Popup,
|
|
1306
|
-
{
|
|
1307
|
-
"data-slot": "select-content",
|
|
1308
|
-
className: cn("bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/5 min-w-36 rounded-2xl shadow-2xl ring-1 duration-100 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto", className),
|
|
1309
|
-
...props,
|
|
1310
|
-
children: [
|
|
1311
|
-
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
1312
|
-
/* @__PURE__ */ jsx(Select$1.List, { children }),
|
|
1313
|
-
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
1314
|
-
]
|
|
1315
|
-
}
|
|
1316
|
-
)
|
|
1317
|
-
}
|
|
1318
|
-
) });
|
|
1319
|
-
}
|
|
1320
|
-
function SelectItem({
|
|
1321
|
-
className,
|
|
1322
|
-
children,
|
|
1323
|
-
...props
|
|
1324
|
-
}) {
|
|
1325
|
-
return /* @__PURE__ */ jsxs(
|
|
1326
|
-
Select$1.Item,
|
|
1327
|
-
{
|
|
1328
|
-
"data-slot": "select-item",
|
|
1329
|
-
className: cn(
|
|
1330
|
-
"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2.5 rounded-xl py-2 pr-8 pl-3 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
1331
|
-
className
|
|
1332
|
-
),
|
|
1333
|
-
...props,
|
|
1334
|
-
children: [
|
|
1335
|
-
/* @__PURE__ */ jsx(Select$1.ItemText, { className: "flex flex-1 gap-2 shrink-0 whitespace-nowrap", children }),
|
|
1336
|
-
/* @__PURE__ */ jsx(
|
|
1337
|
-
Select$1.ItemIndicator,
|
|
1338
|
-
{
|
|
1339
|
-
render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
|
|
1340
|
-
children: /* @__PURE__ */ jsx(IconCheck, { className: "pointer-events-none" })
|
|
1341
|
-
}
|
|
1342
|
-
)
|
|
1343
|
-
]
|
|
1344
|
-
}
|
|
1345
|
-
);
|
|
1346
|
-
}
|
|
1347
|
-
function SelectScrollUpButton({
|
|
1348
|
-
className,
|
|
1349
|
-
...props
|
|
1350
|
-
}) {
|
|
1351
|
-
return /* @__PURE__ */ jsx(
|
|
1352
|
-
Select$1.ScrollUpArrow,
|
|
1353
|
-
{
|
|
1354
|
-
"data-slot": "select-scroll-up-button",
|
|
1355
|
-
className: cn("bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4 top-0 w-full", className),
|
|
1356
|
-
...props,
|
|
1357
|
-
children: /* @__PURE__ */ jsx(
|
|
1358
|
-
IconChevronUp,
|
|
1359
|
-
{}
|
|
1360
|
-
)
|
|
1361
|
-
}
|
|
1362
|
-
);
|
|
1363
|
-
}
|
|
1364
|
-
function SelectScrollDownButton({
|
|
1365
|
-
className,
|
|
1366
|
-
...props
|
|
1367
|
-
}) {
|
|
1368
|
-
return /* @__PURE__ */ jsx(
|
|
1369
|
-
Select$1.ScrollDownArrow,
|
|
1370
|
-
{
|
|
1371
|
-
"data-slot": "select-scroll-down-button",
|
|
1372
|
-
className: cn("bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4 bottom-0 w-full", className),
|
|
1373
|
-
...props,
|
|
1374
|
-
children: /* @__PURE__ */ jsx(
|
|
1375
|
-
IconChevronDown,
|
|
1376
|
-
{}
|
|
1377
|
-
)
|
|
1378
|
-
}
|
|
1379
|
-
);
|
|
1380
|
-
}
|
|
1381
|
-
var Select2 = ({
|
|
1382
|
-
options,
|
|
1383
|
-
defaultValue,
|
|
1384
|
-
label,
|
|
1385
|
-
name,
|
|
1386
|
-
disabled,
|
|
1387
|
-
required,
|
|
1388
|
-
width = "full",
|
|
1389
|
-
placeholder,
|
|
1390
|
-
onChangeAction
|
|
1391
|
-
}) => {
|
|
1392
|
-
const { sendEvent } = useMelony();
|
|
1393
|
-
const handleValueChange = (val) => {
|
|
1394
|
-
if (onChangeAction) {
|
|
1395
|
-
sendEvent({
|
|
1396
|
-
...onChangeAction,
|
|
1397
|
-
data: {
|
|
1398
|
-
name: name || "",
|
|
1399
|
-
value: val
|
|
1400
|
-
}
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1403
|
-
};
|
|
1404
|
-
return /* @__PURE__ */ jsxs(Field, { className: cn(widthMap[width]), children: [
|
|
1405
|
-
label && /* @__PURE__ */ jsxs(FieldTitle, { children: [
|
|
1406
|
-
label,
|
|
1407
|
-
required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
|
|
1408
|
-
] }),
|
|
1409
|
-
/* @__PURE__ */ jsxs(
|
|
1410
|
-
Select,
|
|
1411
|
-
{
|
|
1412
|
-
defaultValue,
|
|
1413
|
-
disabled,
|
|
1414
|
-
onValueChange: (value) => handleValueChange(value || ""),
|
|
1415
|
-
required,
|
|
1416
|
-
children: [
|
|
1417
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
1418
|
-
/* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1419
|
-
]
|
|
1420
|
-
}
|
|
1421
|
-
)
|
|
1422
|
-
] });
|
|
1423
|
-
};
|
|
1424
|
-
var Label2 = ({
|
|
1425
|
-
value,
|
|
1426
|
-
htmlFor,
|
|
1427
|
-
required,
|
|
1428
|
-
size = "md",
|
|
1429
|
-
color = "foreground"
|
|
1430
|
-
}) => {
|
|
1431
|
-
return /* @__PURE__ */ jsxs(
|
|
1432
|
-
Label,
|
|
1433
|
-
{
|
|
1434
|
-
htmlFor,
|
|
1435
|
-
className: cn(
|
|
1436
|
-
"flex items-center gap-1",
|
|
1437
|
-
textSizeMap[size],
|
|
1438
|
-
colorTextMap[color]
|
|
1439
|
-
),
|
|
1440
|
-
children: [
|
|
1441
|
-
value,
|
|
1442
|
-
required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
|
|
1443
|
-
]
|
|
1444
|
-
}
|
|
1445
|
-
);
|
|
1446
|
-
};
|
|
1447
|
-
var Checkbox = ({
|
|
1448
|
-
label,
|
|
1449
|
-
name,
|
|
1450
|
-
checked,
|
|
1451
|
-
disabled,
|
|
1452
|
-
onChangeAction
|
|
1453
|
-
}) => {
|
|
1454
|
-
const { sendEvent } = useMelony();
|
|
1455
|
-
const handleChange = (e) => {
|
|
1456
|
-
if (onChangeAction) {
|
|
1457
|
-
sendEvent({
|
|
1458
|
-
...onChangeAction,
|
|
1459
|
-
data: {
|
|
1460
|
-
name: name || "",
|
|
1461
|
-
checked: e.target.checked
|
|
1462
|
-
}
|
|
1463
|
-
});
|
|
1464
|
-
}
|
|
1465
|
-
};
|
|
1466
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1467
|
-
/* @__PURE__ */ jsx(
|
|
1468
|
-
"input",
|
|
1469
|
-
{
|
|
1470
|
-
type: "checkbox",
|
|
1471
|
-
name,
|
|
1472
|
-
id: name,
|
|
1473
|
-
checked,
|
|
1474
|
-
disabled,
|
|
1475
|
-
onChange: handleChange,
|
|
1476
|
-
className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
|
|
1477
|
-
}
|
|
1478
|
-
),
|
|
1479
|
-
label && /* @__PURE__ */ jsx(
|
|
1480
|
-
Label2,
|
|
1481
|
-
{
|
|
1482
|
-
htmlFor: name,
|
|
1483
|
-
value: label,
|
|
1484
|
-
color: disabled ? "muted" : "foreground",
|
|
1485
|
-
size: "sm"
|
|
1486
|
-
}
|
|
1487
|
-
)
|
|
1488
|
-
] });
|
|
1489
|
-
};
|
|
1490
|
-
var Hidden = ({ name, value }) => {
|
|
1491
|
-
return /* @__PURE__ */ jsx("input", { type: "hidden", name, value });
|
|
1492
|
-
};
|
|
1493
|
-
var PopoverContext = React3.createContext(
|
|
1494
|
-
void 0
|
|
1495
|
-
);
|
|
1496
|
-
function usePopoverContext() {
|
|
1497
|
-
const context = React3.useContext(PopoverContext);
|
|
1498
|
-
if (!context) {
|
|
1499
|
-
throw new Error("Popover components must be used within a Popover");
|
|
1500
|
-
}
|
|
1501
|
-
return context;
|
|
1502
|
-
}
|
|
1503
|
-
function Popover({
|
|
1504
|
-
children,
|
|
1505
|
-
defaultOpen = false,
|
|
1506
|
-
open: controlledOpen,
|
|
1507
|
-
onOpenChange
|
|
1508
|
-
}) {
|
|
1509
|
-
const [internalOpen, setInternalOpen] = React3.useState(defaultOpen);
|
|
1510
|
-
const triggerRef = React3.useRef(null);
|
|
1511
|
-
const open = controlledOpen ?? internalOpen;
|
|
1512
|
-
const setOpen = React3.useCallback(
|
|
1513
|
-
(newOpen) => {
|
|
1514
|
-
if (controlledOpen === void 0) {
|
|
1515
|
-
setInternalOpen(newOpen);
|
|
1516
|
-
}
|
|
1517
|
-
onOpenChange?.(newOpen);
|
|
1518
|
-
},
|
|
1519
|
-
[controlledOpen, onOpenChange]
|
|
1520
|
-
);
|
|
1521
|
-
const value = React3.useMemo(
|
|
1522
|
-
() => ({
|
|
1523
|
-
open,
|
|
1524
|
-
setOpen,
|
|
1525
|
-
triggerRef
|
|
1526
|
-
}),
|
|
1527
|
-
[open, setOpen]
|
|
1528
|
-
);
|
|
1529
|
-
return /* @__PURE__ */ jsx(PopoverContext.Provider, { value, children });
|
|
1530
|
-
}
|
|
1531
|
-
var PopoverTrigger = React3.forwardRef(
|
|
1532
|
-
({ asChild, className, children, ...props }, ref) => {
|
|
1533
|
-
const { setOpen, triggerRef } = usePopoverContext();
|
|
1534
|
-
const handleClick = (e) => {
|
|
1535
|
-
setOpen(true);
|
|
1536
|
-
props.onClick?.(e);
|
|
1537
|
-
};
|
|
1538
|
-
if (asChild && React3.isValidElement(children)) {
|
|
1539
|
-
return React3.cloneElement(children, {
|
|
1540
|
-
ref: (node) => {
|
|
1541
|
-
triggerRef.current = node;
|
|
1542
|
-
if (typeof children.ref === "function") {
|
|
1543
|
-
children.ref(node);
|
|
1544
|
-
} else if (children.ref) {
|
|
1545
|
-
children.ref.current = node;
|
|
1546
|
-
}
|
|
1547
|
-
},
|
|
1548
|
-
onClick: handleClick
|
|
1549
|
-
});
|
|
1550
|
-
}
|
|
1551
|
-
return /* @__PURE__ */ jsx(
|
|
1552
|
-
"button",
|
|
1553
|
-
{
|
|
1554
|
-
ref: (node) => {
|
|
1555
|
-
triggerRef.current = node;
|
|
1556
|
-
if (typeof ref === "function") {
|
|
1557
|
-
ref(node);
|
|
1558
|
-
} else if (ref) {
|
|
1559
|
-
ref.current = node;
|
|
1560
|
-
}
|
|
1561
|
-
},
|
|
1562
|
-
className,
|
|
1563
|
-
onClick: handleClick,
|
|
1564
|
-
...props,
|
|
1565
|
-
children
|
|
1566
|
-
}
|
|
1567
|
-
);
|
|
1568
|
-
}
|
|
1569
|
-
);
|
|
1570
|
-
PopoverTrigger.displayName = "PopoverTrigger";
|
|
1571
|
-
var PopoverContent = React3.forwardRef(
|
|
1572
|
-
({
|
|
1573
|
-
className,
|
|
1574
|
-
side = "bottom",
|
|
1575
|
-
align = "start",
|
|
1576
|
-
sideOffset = 4,
|
|
1577
|
-
alignOffset = 0,
|
|
1578
|
-
children,
|
|
1579
|
-
...props
|
|
1580
|
-
}, ref) => {
|
|
1581
|
-
const { open, setOpen, triggerRef } = usePopoverContext();
|
|
1582
|
-
const [position, setPosition] = React3.useState({ top: 0, left: 0 });
|
|
1583
|
-
const contentRef = React3.useRef(null);
|
|
1584
|
-
React3.useEffect(() => {
|
|
1585
|
-
if (!open || !triggerRef.current) return;
|
|
1586
|
-
const updatePosition = () => {
|
|
1587
|
-
if (!triggerRef.current || !contentRef.current) return;
|
|
1588
|
-
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
1589
|
-
const contentRect = contentRef.current.getBoundingClientRect();
|
|
1590
|
-
const scrollX = window.scrollX;
|
|
1591
|
-
const scrollY = window.scrollY;
|
|
1592
|
-
let top = 0;
|
|
1593
|
-
let left = 0;
|
|
1594
|
-
switch (side) {
|
|
1595
|
-
case "bottom":
|
|
1596
|
-
top = triggerRect.bottom + sideOffset + scrollY;
|
|
1597
|
-
break;
|
|
1598
|
-
case "top":
|
|
1599
|
-
top = triggerRect.top - contentRect.height - sideOffset + scrollY;
|
|
1600
|
-
break;
|
|
1601
|
-
case "right":
|
|
1602
|
-
top = triggerRect.top + scrollY;
|
|
1603
|
-
left = triggerRect.right + sideOffset + scrollX;
|
|
1604
|
-
break;
|
|
1605
|
-
case "left":
|
|
1606
|
-
top = triggerRect.top + scrollY;
|
|
1607
|
-
left = triggerRect.left - contentRect.width - sideOffset + scrollX;
|
|
1608
|
-
break;
|
|
1609
|
-
}
|
|
1610
|
-
switch (align) {
|
|
1611
|
-
case "start":
|
|
1612
|
-
if (side === "top" || side === "bottom") {
|
|
1613
|
-
left = triggerRect.left + scrollX + alignOffset;
|
|
1614
|
-
} else {
|
|
1615
|
-
top += alignOffset;
|
|
1616
|
-
}
|
|
1617
|
-
break;
|
|
1618
|
-
case "center":
|
|
1619
|
-
if (side === "top" || side === "bottom") {
|
|
1620
|
-
left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2 + scrollX + alignOffset;
|
|
1621
|
-
} else {
|
|
1622
|
-
top += triggerRect.height / 2 - contentRect.height / 2 + alignOffset;
|
|
1623
|
-
}
|
|
1624
|
-
break;
|
|
1625
|
-
case "end":
|
|
1626
|
-
if (side === "top" || side === "bottom") {
|
|
1627
|
-
left = triggerRect.left + triggerRect.width - contentRect.width + scrollX + alignOffset;
|
|
1628
|
-
} else {
|
|
1629
|
-
top += triggerRect.height - contentRect.height + alignOffset;
|
|
1630
|
-
}
|
|
1631
|
-
break;
|
|
1632
|
-
}
|
|
1633
|
-
setPosition({ top, left });
|
|
1634
|
-
};
|
|
1635
|
-
requestAnimationFrame(() => {
|
|
1636
|
-
updatePosition();
|
|
1637
|
-
});
|
|
1638
|
-
window.addEventListener("resize", updatePosition);
|
|
1639
|
-
window.addEventListener("scroll", updatePosition, true);
|
|
1640
|
-
return () => {
|
|
1641
|
-
window.removeEventListener("resize", updatePosition);
|
|
1642
|
-
window.removeEventListener("scroll", updatePosition, true);
|
|
1643
|
-
};
|
|
1644
|
-
}, [open, side, align, sideOffset, alignOffset, triggerRef]);
|
|
1645
|
-
React3.useEffect(() => {
|
|
1646
|
-
if (!open) return;
|
|
1647
|
-
const handleClickOutside = (event) => {
|
|
1648
|
-
if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
|
|
1649
|
-
setOpen(false);
|
|
1650
|
-
}
|
|
1651
|
-
};
|
|
1652
|
-
const handleEscape = (event) => {
|
|
1653
|
-
if (event.key === "Escape") {
|
|
1654
|
-
setOpen(false);
|
|
1655
|
-
}
|
|
1656
|
-
};
|
|
1657
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
1658
|
-
document.addEventListener("keydown", handleEscape);
|
|
1659
|
-
return () => {
|
|
1660
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
1661
|
-
document.removeEventListener("keydown", handleEscape);
|
|
1662
|
-
};
|
|
1663
|
-
}, [open, setOpen, triggerRef]);
|
|
1664
|
-
if (!open) return null;
|
|
1665
|
-
const content = /* @__PURE__ */ jsx(
|
|
1666
|
-
"div",
|
|
1667
|
-
{
|
|
1668
|
-
ref: (node) => {
|
|
1669
|
-
contentRef.current = node;
|
|
1670
|
-
if (typeof ref === "function") {
|
|
1671
|
-
ref(node);
|
|
1672
|
-
} else if (ref) {
|
|
1673
|
-
ref.current = node;
|
|
1674
|
-
}
|
|
1675
|
-
},
|
|
1676
|
-
className: cn(
|
|
1677
|
-
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/5 rounded-2xl shadow-2xl ring-1 z-50 min-w-48 max-h-96 overflow-hidden",
|
|
1678
|
-
className
|
|
1679
|
-
),
|
|
1680
|
-
style: {
|
|
1681
|
-
position: "absolute",
|
|
1682
|
-
top: `${position.top}px`,
|
|
1683
|
-
left: `${position.left}px`
|
|
1684
|
-
},
|
|
1685
|
-
...props,
|
|
1686
|
-
children
|
|
1687
|
-
}
|
|
1688
|
-
);
|
|
1689
|
-
return createPortal(content, document.body);
|
|
1690
|
-
}
|
|
1691
|
-
);
|
|
1692
|
-
PopoverContent.displayName = "PopoverContent";
|
|
1693
|
-
var PRESET_COLORS = [
|
|
1694
|
-
"#000000",
|
|
1695
|
-
"#ffffff",
|
|
1696
|
-
"#f44336",
|
|
1697
|
-
"#e91e63",
|
|
1698
|
-
"#9c27b0",
|
|
1699
|
-
"#673ab7",
|
|
1700
|
-
"#3f51b5",
|
|
1701
|
-
"#2196f3",
|
|
1702
|
-
"#03a9f4",
|
|
1703
|
-
"#00bcd4",
|
|
1704
|
-
"#009688",
|
|
1705
|
-
"#4caf50",
|
|
1706
|
-
"#8bc34a",
|
|
1707
|
-
"#cddc39",
|
|
1708
|
-
"#ffeb3b",
|
|
1709
|
-
"#ffc107",
|
|
1710
|
-
"#ff9800",
|
|
1711
|
-
"#ff5722",
|
|
1712
|
-
"#795548",
|
|
1713
|
-
"#9e9e9e",
|
|
1714
|
-
"#607d8b"
|
|
1715
|
-
];
|
|
1716
|
-
var ColorPicker = ({
|
|
1717
|
-
name,
|
|
1718
|
-
label,
|
|
1719
|
-
defaultValue = "#000000",
|
|
1720
|
-
onChangeAction,
|
|
1721
|
-
disabled
|
|
1722
|
-
}) => {
|
|
1723
|
-
const { sendEvent } = useMelony();
|
|
1724
|
-
const [color, setColor] = useState(defaultValue);
|
|
1725
|
-
const handleColorChange = (newColor) => {
|
|
1726
|
-
setColor(newColor);
|
|
1727
|
-
if (onChangeAction) {
|
|
1728
|
-
sendEvent({
|
|
1729
|
-
...onChangeAction,
|
|
1730
|
-
data: {
|
|
1731
|
-
name: name || "",
|
|
1732
|
-
value: newColor
|
|
1733
|
-
}
|
|
1734
|
-
});
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
return /* @__PURE__ */ jsxs(Field, { className: "w-full", children: [
|
|
1738
|
-
label && /* @__PURE__ */ jsx(FieldTitle, { children: label }),
|
|
1739
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1740
|
-
/* @__PURE__ */ jsxs(Popover, { children: [
|
|
1741
|
-
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
1742
|
-
"button",
|
|
1743
|
-
{
|
|
1744
|
-
type: "button",
|
|
1745
|
-
disabled,
|
|
1746
|
-
className: cn(
|
|
1747
|
-
"w-10 h-10 rounded-lg border border-border shadow-sm transition-transform hover:scale-105 active:scale-95 disabled:opacity-50 disabled:hover:scale-100",
|
|
1748
|
-
"flex items-center justify-center p-1"
|
|
1749
|
-
),
|
|
1750
|
-
children: /* @__PURE__ */ jsx(
|
|
1751
|
-
"div",
|
|
1752
|
-
{
|
|
1753
|
-
className: "w-full h-full rounded-md",
|
|
1754
|
-
style: { backgroundColor: color }
|
|
1755
|
-
}
|
|
1756
|
-
)
|
|
1757
|
-
}
|
|
1758
|
-
) }),
|
|
1759
|
-
/* @__PURE__ */ jsx(PopoverContent, { className: "p-3 w-64", side: "bottom", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
1760
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: PRESET_COLORS.map((preset) => /* @__PURE__ */ jsx(
|
|
1761
|
-
"button",
|
|
1762
|
-
{
|
|
1763
|
-
type: "button",
|
|
1764
|
-
className: cn(
|
|
1765
|
-
"w-6 h-6 rounded-md border border-border transition-transform hover:scale-110 active:scale-90",
|
|
1766
|
-
color === preset && "ring-2 ring-primary ring-offset-1"
|
|
1767
|
-
),
|
|
1768
|
-
style: { backgroundColor: preset },
|
|
1769
|
-
onClick: () => handleColorChange(preset)
|
|
1770
|
-
},
|
|
1771
|
-
preset
|
|
1772
|
-
)) }),
|
|
1773
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1774
|
-
/* @__PURE__ */ jsx(
|
|
1775
|
-
"input",
|
|
1776
|
-
{
|
|
1777
|
-
type: "color",
|
|
1778
|
-
value: color,
|
|
1779
|
-
onChange: (e) => handleColorChange(e.target.value),
|
|
1780
|
-
className: "w-8 h-8 rounded border-none p-0 cursor-pointer"
|
|
1781
|
-
}
|
|
1782
|
-
),
|
|
1783
|
-
/* @__PURE__ */ jsx(
|
|
1784
|
-
"input",
|
|
1785
|
-
{
|
|
1786
|
-
type: "text",
|
|
1787
|
-
value: color,
|
|
1788
|
-
onChange: (e) => handleColorChange(e.target.value),
|
|
1789
|
-
className: "flex-1 h-8 px-2 text-xs font-mono border border-border rounded uppercase focus:outline-none focus:ring-1 focus:ring-primary"
|
|
1790
|
-
}
|
|
1791
|
-
)
|
|
1792
|
-
] })
|
|
1793
|
-
] }) })
|
|
1794
|
-
] }),
|
|
1795
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-mono uppercase text-muted-foreground", children: color })
|
|
1796
|
-
] }),
|
|
1797
|
-
/* @__PURE__ */ jsx("input", { type: "hidden", name, value: color })
|
|
1798
|
-
] });
|
|
1799
|
-
};
|
|
1800
|
-
var RadioGroup = ({
|
|
1801
|
-
name,
|
|
1802
|
-
options,
|
|
1803
|
-
defaultValue,
|
|
1804
|
-
label,
|
|
1805
|
-
disabled,
|
|
1806
|
-
orientation = "vertical",
|
|
1807
|
-
onChangeAction
|
|
1808
|
-
}) => {
|
|
1809
|
-
const { sendEvent } = useMelony();
|
|
1810
|
-
const handleChange = (e) => {
|
|
1811
|
-
if (onChangeAction) {
|
|
1812
|
-
sendEvent({
|
|
1813
|
-
...onChangeAction,
|
|
1814
|
-
data: {
|
|
1815
|
-
name,
|
|
1816
|
-
value: e.target.value
|
|
1817
|
-
}
|
|
1818
|
-
});
|
|
1819
|
-
}
|
|
1820
|
-
};
|
|
1821
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
1822
|
-
label && /* @__PURE__ */ jsx(Label2, { value: label }),
|
|
1823
|
-
/* @__PURE__ */ jsx(
|
|
1824
|
-
"div",
|
|
1825
|
-
{
|
|
1826
|
-
className: cn(
|
|
1827
|
-
"flex",
|
|
1828
|
-
orientation === "horizontal" ? "flex-row gap-4" : "flex-col gap-2"
|
|
1829
|
-
),
|
|
1830
|
-
children: options.map((option, index) => {
|
|
1831
|
-
const radioId = `${name}-${index}`;
|
|
1832
|
-
const isDisabled = disabled || option.disabled;
|
|
1833
|
-
return /* @__PURE__ */ jsxs(
|
|
1834
|
-
"div",
|
|
1835
|
-
{
|
|
1836
|
-
className: "flex items-center gap-2",
|
|
1837
|
-
children: [
|
|
1838
|
-
/* @__PURE__ */ jsx(
|
|
1839
|
-
"input",
|
|
1840
|
-
{
|
|
1841
|
-
type: "radio",
|
|
1842
|
-
name,
|
|
1843
|
-
id: radioId,
|
|
1844
|
-
value: option.value,
|
|
1845
|
-
defaultChecked: defaultValue === option.value,
|
|
1846
|
-
disabled: isDisabled,
|
|
1847
|
-
onChange: handleChange,
|
|
1848
|
-
className: "h-4 w-4 border-gray-300 text-primary focus:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
|
|
1849
|
-
}
|
|
1850
|
-
),
|
|
1851
|
-
/* @__PURE__ */ jsx(
|
|
1852
|
-
Label2,
|
|
1853
|
-
{
|
|
1854
|
-
htmlFor: radioId,
|
|
1855
|
-
value: option.label,
|
|
1856
|
-
size: "sm",
|
|
1857
|
-
color: isDisabled ? "muted" : "foreground"
|
|
1858
|
-
}
|
|
1859
|
-
)
|
|
1860
|
-
]
|
|
1861
|
-
},
|
|
1862
|
-
index
|
|
1863
|
-
);
|
|
1864
|
-
})
|
|
1865
|
-
}
|
|
1866
|
-
)
|
|
1867
|
-
] });
|
|
1868
|
-
};
|
|
1869
|
-
var buttonVariants = cva(
|
|
1870
|
-
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-4xl border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-[3px] aria-invalid:ring-[3px] [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
|
|
1871
|
-
{
|
|
1872
|
-
variants: {
|
|
1873
|
-
variant: {
|
|
1874
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
1875
|
-
outline: "border-border bg-input/30 hover:bg-input/50 hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
1876
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
1877
|
-
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
|
1878
|
-
destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
|
1879
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
1880
|
-
},
|
|
1881
|
-
size: {
|
|
1882
|
-
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
1883
|
-
xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
|
|
1884
|
-
sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
1885
|
-
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
1886
|
-
icon: "size-9",
|
|
1887
|
-
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
1888
|
-
"icon-sm": "size-8",
|
|
1889
|
-
"icon-lg": "size-10"
|
|
1890
|
-
}
|
|
1891
|
-
},
|
|
1892
|
-
defaultVariants: {
|
|
1893
|
-
variant: "default",
|
|
1894
|
-
size: "default"
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
);
|
|
1898
|
-
function Button({
|
|
1899
|
-
className,
|
|
1900
|
-
variant = "default",
|
|
1901
|
-
size = "default",
|
|
1902
|
-
...props
|
|
1903
|
-
}) {
|
|
1904
|
-
return /* @__PURE__ */ jsx(
|
|
1905
|
-
Button$1,
|
|
1906
|
-
{
|
|
1907
|
-
"data-slot": "button",
|
|
1908
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
1909
|
-
...props
|
|
1910
|
-
}
|
|
1911
|
-
);
|
|
1912
|
-
}
|
|
1913
|
-
var Button2 = ({
|
|
1914
|
-
type = "button",
|
|
1915
|
-
label,
|
|
1916
|
-
variant = "primary",
|
|
1917
|
-
size = "md",
|
|
1918
|
-
disabled = false,
|
|
1919
|
-
width,
|
|
1920
|
-
onClickAction,
|
|
1921
|
-
justify = "center"
|
|
1922
|
-
}) => {
|
|
1923
|
-
const { sendEvent } = useMelony();
|
|
1924
|
-
const variantMap = {
|
|
1925
|
-
primary: "default",
|
|
1926
|
-
secondary: "secondary",
|
|
1927
|
-
danger: "destructive",
|
|
1928
|
-
success: "default",
|
|
1929
|
-
// We might want a custom success style later
|
|
1930
|
-
outline: "outline",
|
|
1931
|
-
ghost: "ghost",
|
|
1932
|
-
link: "link"
|
|
1933
|
-
};
|
|
1934
|
-
const widthMap2 = {
|
|
1935
|
-
full: "w-full",
|
|
1936
|
-
auto: "w-auto",
|
|
1937
|
-
"1/2": "w-1/2",
|
|
1938
|
-
"1/3": "w-1/3",
|
|
1939
|
-
"2/3": "w-2/3",
|
|
1940
|
-
"1/4": "w-1/4",
|
|
1941
|
-
"3/4": "w-3/4"
|
|
1942
|
-
};
|
|
1943
|
-
return /* @__PURE__ */ jsx(
|
|
1944
|
-
Button,
|
|
1945
|
-
{
|
|
1946
|
-
type,
|
|
1947
|
-
variant: variantMap[variant] || "default",
|
|
1948
|
-
size: size === "md" ? "default" : size,
|
|
1949
|
-
disabled,
|
|
1950
|
-
className: cn(width && widthMap2[width], justifyMap[justify]),
|
|
1951
|
-
onClick: () => {
|
|
1952
|
-
if (onClickAction) {
|
|
1953
|
-
sendEvent(onClickAction);
|
|
1954
|
-
}
|
|
1955
|
-
},
|
|
1956
|
-
children: label
|
|
1957
|
-
}
|
|
1958
|
-
);
|
|
1959
|
-
};
|
|
1960
|
-
var Upload = ({
|
|
1961
|
-
label = "Upload",
|
|
1962
|
-
multiple = false,
|
|
1963
|
-
accept,
|
|
1964
|
-
onUploadAction,
|
|
1965
|
-
initialFiles,
|
|
1966
|
-
mode = "append",
|
|
1967
|
-
disabled
|
|
1968
|
-
}) => {
|
|
1969
|
-
const { sendEvent, events } = useMelony();
|
|
1970
|
-
const fileInputRef = useRef(null);
|
|
1971
|
-
const [isUploading, setIsUploading] = useState(false);
|
|
1972
|
-
const [status, setStatus] = useState("idle");
|
|
1973
|
-
const uploadedFilesEvents = events.filter(
|
|
1974
|
-
(event) => event.type === "uploaded-files"
|
|
1975
|
-
);
|
|
1976
|
-
const displayEvents = mode === "replace" && uploadedFilesEvents.length > 0 ? [uploadedFilesEvents[uploadedFilesEvents.length - 1]] : uploadedFilesEvents;
|
|
1977
|
-
const showInitialFiles = mode === "replace" ? displayEvents.length === 0 : true;
|
|
1978
|
-
const handleFileChange = async (e) => {
|
|
1979
|
-
const files = Array.from(e.target.files || []);
|
|
1980
|
-
if (files.length === 0) return;
|
|
1981
|
-
setIsUploading(true);
|
|
1982
|
-
setStatus("idle");
|
|
1983
|
-
try {
|
|
1984
|
-
const filePromises = files.map((file) => {
|
|
1985
|
-
return new Promise((resolve, reject) => {
|
|
1986
|
-
const reader = new FileReader();
|
|
1987
|
-
reader.onload = () => {
|
|
1988
|
-
try {
|
|
1989
|
-
const base64 = reader.result;
|
|
1990
|
-
if (!base64) {
|
|
1991
|
-
reject(new Error("FileReader returned empty result"));
|
|
1992
|
-
return;
|
|
1993
|
-
}
|
|
1994
|
-
resolve({
|
|
1995
|
-
name: file.name,
|
|
1996
|
-
type: file.type,
|
|
1997
|
-
size: file.size,
|
|
1998
|
-
data: base64
|
|
1999
|
-
});
|
|
2000
|
-
} catch (error) {
|
|
2001
|
-
reject(error);
|
|
2002
|
-
}
|
|
2003
|
-
};
|
|
2004
|
-
reader.onerror = (error) => {
|
|
2005
|
-
reject(new Error(`Failed to read file ${file.name}: ${error}`));
|
|
2006
|
-
};
|
|
2007
|
-
reader.readAsDataURL(file);
|
|
2008
|
-
});
|
|
2009
|
-
});
|
|
2010
|
-
const convertedFiles = await Promise.all(filePromises);
|
|
2011
|
-
if (onUploadAction) {
|
|
2012
|
-
if (typeof onUploadAction === "function") {
|
|
2013
|
-
await sendEvent(onUploadAction({ files: convertedFiles }));
|
|
2014
|
-
} else {
|
|
2015
|
-
await sendEvent({
|
|
2016
|
-
...onUploadAction,
|
|
2017
|
-
data: {
|
|
2018
|
-
...onUploadAction.data,
|
|
2019
|
-
files: convertedFiles
|
|
2020
|
-
}
|
|
2021
|
-
});
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
setStatus("success");
|
|
2025
|
-
setTimeout(() => setStatus("idle"), 3e3);
|
|
2026
|
-
} catch (error) {
|
|
2027
|
-
console.error("Upload failed:", error);
|
|
2028
|
-
setStatus("error");
|
|
2029
|
-
setTimeout(() => setStatus("idle"), 3e3);
|
|
2030
|
-
} finally {
|
|
2031
|
-
setIsUploading(false);
|
|
2032
|
-
if (fileInputRef.current) {
|
|
2033
|
-
fileInputRef.current.value = "";
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
};
|
|
2037
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative inline-block", children: [
|
|
2038
|
-
/* @__PURE__ */ jsx(
|
|
2039
|
-
"input",
|
|
2040
|
-
{
|
|
2041
|
-
type: "file",
|
|
2042
|
-
ref: fileInputRef,
|
|
2043
|
-
onChange: handleFileChange,
|
|
2044
|
-
multiple,
|
|
2045
|
-
accept,
|
|
2046
|
-
className: "hidden",
|
|
2047
|
-
disabled: isUploading || disabled
|
|
2048
|
-
}
|
|
2049
|
-
),
|
|
2050
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 mb-2 items-center", children: [
|
|
2051
|
-
showInitialFiles && initialFiles?.map((file, index) => /* @__PURE__ */ jsx(Image, { src: file.url, alt: file.name, width: "min", radius: "md" }, index)),
|
|
2052
|
-
displayEvents.map(
|
|
2053
|
-
(event, index) => event.ui ? /* @__PURE__ */ jsx(UIRenderer, { node: event.ui }, index) : null
|
|
2054
|
-
),
|
|
2055
|
-
/* @__PURE__ */ jsxs(
|
|
2056
|
-
Button,
|
|
2057
|
-
{
|
|
2058
|
-
type: "button",
|
|
2059
|
-
disabled: isUploading || disabled,
|
|
2060
|
-
onClick: () => fileInputRef.current?.click(),
|
|
2061
|
-
variant: "default",
|
|
2062
|
-
children: [
|
|
2063
|
-
isUploading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-4 w-4 animate-spin mr-2" }) : status === "success" ? /* @__PURE__ */ jsx(IconCheck, { className: "h-4 w-4 text-green-500 mr-2" }) : status === "error" ? /* @__PURE__ */ jsx(IconX, { className: "h-4 w-4 mr-2" }) : /* @__PURE__ */ jsx(IconUpload, { className: "h-4 w-4 mr-2" }),
|
|
2064
|
-
status === "success" ? "Uploaded" : status === "error" ? "Failed" : label
|
|
2065
|
-
]
|
|
2066
|
-
}
|
|
2067
|
-
)
|
|
2068
|
-
] })
|
|
2069
|
-
] });
|
|
2070
|
-
};
|
|
2071
|
-
var Form = ({
|
|
2072
|
-
children,
|
|
2073
|
-
onSubmitAction,
|
|
2074
|
-
gap = "md"
|
|
2075
|
-
}) => {
|
|
2076
|
-
const { sendEvent } = useMelony();
|
|
2077
|
-
const [isSubmitted, setIsSubmitted] = useState(false);
|
|
2078
|
-
const handleSubmit = (e) => {
|
|
2079
|
-
e.preventDefault();
|
|
2080
|
-
if (isSubmitted) return;
|
|
2081
|
-
const formData = new FormData(e.currentTarget);
|
|
2082
|
-
const data = {};
|
|
2083
|
-
formData.forEach((value, key) => {
|
|
2084
|
-
data[key] = value;
|
|
2085
|
-
});
|
|
2086
|
-
if (onSubmitAction) {
|
|
2087
|
-
setIsSubmitted(true);
|
|
2088
|
-
if (typeof onSubmitAction === "object" && "type" in onSubmitAction) {
|
|
2089
|
-
sendEvent({
|
|
2090
|
-
...onSubmitAction,
|
|
2091
|
-
data: {
|
|
2092
|
-
...onSubmitAction?.data || {},
|
|
2093
|
-
...data
|
|
2094
|
-
}
|
|
2095
|
-
});
|
|
2096
|
-
} else if (typeof onSubmitAction === "function") {
|
|
2097
|
-
sendEvent(onSubmitAction(data));
|
|
2098
|
-
}
|
|
2099
|
-
}
|
|
2100
|
-
};
|
|
2101
|
-
return /* @__PURE__ */ jsx(
|
|
2102
|
-
"form",
|
|
2103
|
-
{
|
|
2104
|
-
onSubmit: handleSubmit,
|
|
2105
|
-
className: "w-full",
|
|
2106
|
-
children: /* @__PURE__ */ jsx("fieldset", { disabled: isSubmitted, className: "m-0 border-0 p-0", children: /* @__PURE__ */ jsx(
|
|
2107
|
-
"div",
|
|
2108
|
-
{
|
|
2109
|
-
className: cn(
|
|
2110
|
-
"flex flex-col transition-opacity",
|
|
2111
|
-
gapMap[gap],
|
|
2112
|
-
isSubmitted && "opacity-60 pointer-events-none"
|
|
2113
|
-
),
|
|
2114
|
-
children
|
|
2115
|
-
}
|
|
2116
|
-
) })
|
|
2117
|
-
}
|
|
2118
|
-
);
|
|
2119
|
-
};
|
|
2120
|
-
function DropdownMenu({ ...props }) {
|
|
2121
|
-
return /* @__PURE__ */ jsx(Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
2122
|
-
}
|
|
2123
|
-
function DropdownMenuTrigger({ ...props }) {
|
|
2124
|
-
return /* @__PURE__ */ jsx(Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
2125
|
-
}
|
|
2126
|
-
function DropdownMenuContent({
|
|
2127
|
-
align = "start",
|
|
2128
|
-
alignOffset = 0,
|
|
2129
|
-
side = "bottom",
|
|
2130
|
-
sideOffset = 4,
|
|
2131
|
-
className,
|
|
2132
|
-
...props
|
|
2133
|
-
}) {
|
|
2134
|
-
return /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(
|
|
2135
|
-
Menu.Positioner,
|
|
2136
|
-
{
|
|
2137
|
-
className: "isolate z-50 outline-none",
|
|
2138
|
-
align,
|
|
2139
|
-
alignOffset,
|
|
2140
|
-
side,
|
|
2141
|
-
sideOffset,
|
|
2142
|
-
children: /* @__PURE__ */ jsx(
|
|
2143
|
-
Menu.Popup,
|
|
2144
|
-
{
|
|
2145
|
-
"data-slot": "dropdown-menu-content",
|
|
2146
|
-
className: cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/5 bg-popover text-popover-foreground min-w-48 rounded-2xl p-1 shadow-2xl ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden", className),
|
|
2147
|
-
...props
|
|
2148
|
-
}
|
|
2149
|
-
)
|
|
2150
|
-
}
|
|
2151
|
-
) });
|
|
2152
|
-
}
|
|
2153
|
-
function DropdownMenuGroup({ ...props }) {
|
|
2154
|
-
return /* @__PURE__ */ jsx(Menu.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
2155
|
-
}
|
|
2156
|
-
function DropdownMenuLabel({
|
|
2157
|
-
className,
|
|
2158
|
-
inset,
|
|
2159
|
-
...props
|
|
2160
|
-
}) {
|
|
2161
|
-
return /* @__PURE__ */ jsx(
|
|
2162
|
-
Menu.GroupLabel,
|
|
2163
|
-
{
|
|
2164
|
-
"data-slot": "dropdown-menu-label",
|
|
2165
|
-
"data-inset": inset,
|
|
2166
|
-
className: cn("text-muted-foreground px-3 py-2.5 text-xs data-[inset]:pl-8", className),
|
|
2167
|
-
...props
|
|
2168
|
-
}
|
|
2169
|
-
);
|
|
2170
|
-
}
|
|
2171
|
-
function DropdownMenuItem({
|
|
2172
|
-
className,
|
|
2173
|
-
inset,
|
|
2174
|
-
variant = "default",
|
|
2175
|
-
...props
|
|
2176
|
-
}) {
|
|
2177
|
-
return /* @__PURE__ */ jsx(
|
|
2178
|
-
Menu.Item,
|
|
2179
|
-
{
|
|
2180
|
-
"data-slot": "dropdown-menu-item",
|
|
2181
|
-
"data-inset": inset,
|
|
2182
|
-
"data-variant": variant,
|
|
2183
|
-
className: cn(
|
|
2184
|
-
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2.5 rounded-xl px-3 py-2 text-sm [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
2185
|
-
className
|
|
2186
|
-
),
|
|
2187
|
-
...props
|
|
2188
|
-
}
|
|
2189
|
-
);
|
|
2190
|
-
}
|
|
2191
|
-
function DropdownMenuCheckboxItem({
|
|
2192
|
-
className,
|
|
2193
|
-
children,
|
|
2194
|
-
checked,
|
|
2195
|
-
...props
|
|
2196
|
-
}) {
|
|
2197
|
-
return /* @__PURE__ */ jsxs(
|
|
2198
|
-
Menu.CheckboxItem,
|
|
2199
|
-
{
|
|
2200
|
-
"data-slot": "dropdown-menu-checkbox-item",
|
|
2201
|
-
className: cn(
|
|
2202
|
-
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2.5 rounded-xl py-2 pr-8 pl-3 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
2203
|
-
className
|
|
2204
|
-
),
|
|
2205
|
-
checked,
|
|
2206
|
-
...props,
|
|
2207
|
-
children: [
|
|
2208
|
-
/* @__PURE__ */ jsx(
|
|
2209
|
-
"span",
|
|
2210
|
-
{
|
|
2211
|
-
className: "pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none",
|
|
2212
|
-
"data-slot": "dropdown-menu-checkbox-item-indicator",
|
|
2213
|
-
children: /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx(
|
|
2214
|
-
IconCheck,
|
|
2215
|
-
{}
|
|
2216
|
-
) })
|
|
2217
|
-
}
|
|
2218
|
-
),
|
|
2219
|
-
children
|
|
2220
|
-
]
|
|
2221
|
-
}
|
|
2222
|
-
);
|
|
2223
|
-
}
|
|
2224
|
-
function DropdownMenuSeparator({
|
|
2225
|
-
className,
|
|
2226
|
-
...props
|
|
2227
|
-
}) {
|
|
2228
|
-
return /* @__PURE__ */ jsx(
|
|
2229
|
-
Menu.Separator,
|
|
2230
|
-
{
|
|
2231
|
-
"data-slot": "dropdown-menu-separator",
|
|
2232
|
-
className: cn("bg-border/50 -mx-1 my-1 h-px", className),
|
|
2233
|
-
...props
|
|
2234
|
-
}
|
|
2235
|
-
);
|
|
2236
|
-
}
|
|
2237
|
-
var Dropdown = ({
|
|
2238
|
-
items = [],
|
|
2239
|
-
children
|
|
2240
|
-
}) => {
|
|
2241
|
-
const { sendEvent } = useMelony();
|
|
2242
|
-
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2243
|
-
/* @__PURE__ */ jsx(
|
|
2244
|
-
DropdownMenuTrigger,
|
|
2245
|
-
{
|
|
2246
|
-
render: (props) => /* @__PURE__ */ jsx(
|
|
2247
|
-
Button,
|
|
2248
|
-
{
|
|
2249
|
-
variant: "ghost",
|
|
2250
|
-
size: "icon-xs",
|
|
2251
|
-
...props,
|
|
2252
|
-
onClick: (e) => {
|
|
2253
|
-
e.stopPropagation();
|
|
2254
|
-
props.onClick?.(e);
|
|
2255
|
-
},
|
|
2256
|
-
children: children || /* @__PURE__ */ jsx(IconDotsVertical, { className: "size-3.5" })
|
|
2257
|
-
}
|
|
2258
|
-
)
|
|
2259
|
-
}
|
|
2260
|
-
),
|
|
2261
|
-
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: cn("w-32"), children: items.map((item, i) => /* @__PURE__ */ jsxs(
|
|
2262
|
-
DropdownMenuItem,
|
|
2263
|
-
{
|
|
2264
|
-
onClick: (e) => {
|
|
2265
|
-
e.stopPropagation();
|
|
2266
|
-
if (item.onClickAction) {
|
|
2267
|
-
sendEvent(item.onClickAction);
|
|
2268
|
-
}
|
|
2269
|
-
},
|
|
2270
|
-
children: [
|
|
2271
|
-
item.icon && /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }),
|
|
2272
|
-
/* @__PURE__ */ jsx("span", { className: item.icon ? "ml-2" : "", children: item.label })
|
|
2273
|
-
]
|
|
2274
|
-
},
|
|
2275
|
-
`${item.label}-${i}`
|
|
2276
|
-
)) })
|
|
2277
|
-
] });
|
|
2278
|
-
};
|
|
2279
|
-
function UIRenderer({ node }) {
|
|
2280
|
-
const { type, props, children } = node;
|
|
2281
|
-
const typeMap = {
|
|
2282
|
-
card: Card2,
|
|
2283
|
-
button: Button2,
|
|
2284
|
-
row: Row,
|
|
2285
|
-
col: Col,
|
|
2286
|
-
text: Text,
|
|
2287
|
-
heading: Heading,
|
|
2288
|
-
badge: Badge2,
|
|
2289
|
-
input: Input2,
|
|
2290
|
-
hidden: Hidden,
|
|
2291
|
-
textarea: Textarea2,
|
|
2292
|
-
select: Select2,
|
|
2293
|
-
checkbox: Checkbox,
|
|
2294
|
-
radioGroup: RadioGroup,
|
|
2295
|
-
colorPicker: ColorPicker,
|
|
2296
|
-
spacer: Spacer,
|
|
2297
|
-
divider: Divider,
|
|
2298
|
-
box: Box,
|
|
2299
|
-
float: Float,
|
|
2300
|
-
image: Image,
|
|
2301
|
-
video: Video,
|
|
2302
|
-
icon: Icon,
|
|
2303
|
-
list: List,
|
|
2304
|
-
listItem: ListItem,
|
|
2305
|
-
form: Form,
|
|
2306
|
-
chart: Chart,
|
|
2307
|
-
label: Label2,
|
|
2308
|
-
upload: Upload,
|
|
2309
|
-
dropdown: Dropdown
|
|
2310
|
-
};
|
|
2311
|
-
const Component = typeMap[type];
|
|
2312
|
-
if (!Component) {
|
|
2313
|
-
return /* @__PURE__ */ jsxs("div", { className: "text-destructive italic text-sm p-2 border border-dashed rounded border-destructive/50 bg-destructive/5", children: [
|
|
2314
|
-
"[Unknown component: ",
|
|
2315
|
-
type,
|
|
2316
|
-
"]"
|
|
2317
|
-
] });
|
|
2318
|
-
}
|
|
2319
|
-
const renderedChildren = children?.map((child, i) => /* @__PURE__ */ jsx(UIRenderer, { node: child }, i));
|
|
2320
|
-
return /* @__PURE__ */ jsx(Component, { ...props, children: renderedChildren });
|
|
2321
|
-
}
|
|
2322
5
|
var MelonyContext = createContext(
|
|
2323
6
|
void 0
|
|
2324
7
|
);
|
|
2325
|
-
var
|
|
2326
|
-
defaultOptions: {
|
|
2327
|
-
queries: {
|
|
2328
|
-
retry: false,
|
|
2329
|
-
refetchOnWindowFocus: false
|
|
2330
|
-
}
|
|
2331
|
-
}
|
|
2332
|
-
});
|
|
2333
|
-
var MelonyContextProviderInner = ({
|
|
8
|
+
var MelonyProvider = ({
|
|
2334
9
|
children,
|
|
2335
10
|
client,
|
|
2336
|
-
initialEvents
|
|
2337
|
-
setContextValue
|
|
11
|
+
initialEvents
|
|
2338
12
|
}) => {
|
|
2339
13
|
const [state, setState] = useState(client.getState());
|
|
2340
|
-
const queryClient = useQueryClient();
|
|
2341
|
-
const [dialog, setDialog] = useState();
|
|
2342
|
-
const { data: config } = useQuery({
|
|
2343
|
-
queryKey: ["melony-config", client.url],
|
|
2344
|
-
queryFn: () => client.getConfig(),
|
|
2345
|
-
staleTime: Infinity
|
|
2346
|
-
});
|
|
2347
14
|
useEffect(() => {
|
|
2348
|
-
if (initialEvents
|
|
15
|
+
if (initialEvents?.length && client.getState().events.length === 0) {
|
|
2349
16
|
client.reset(initialEvents);
|
|
2350
17
|
}
|
|
2351
|
-
}, [
|
|
18
|
+
}, []);
|
|
2352
19
|
useEffect(() => {
|
|
2353
|
-
setState(client.getState());
|
|
2354
20
|
const unsubscribe = client.subscribe(setState);
|
|
2355
|
-
return
|
|
2356
|
-
unsubscribe();
|
|
2357
|
-
};
|
|
21
|
+
return unsubscribe;
|
|
2358
22
|
}, [client]);
|
|
2359
|
-
const
|
|
2360
|
-
(events) => client.reset(events),
|
|
2361
|
-
[client]
|
|
2362
|
-
);
|
|
2363
|
-
const dispatchClientAction = useCallback(
|
|
2364
|
-
async (event) => {
|
|
2365
|
-
if (!event.type.startsWith("client:")) return false;
|
|
2366
|
-
switch (event.type) {
|
|
2367
|
-
case "client:navigate": {
|
|
2368
|
-
const url = event.data?.url;
|
|
2369
|
-
if (url) {
|
|
2370
|
-
const isStreaming = client.getState().isLoading;
|
|
2371
|
-
if (isStreaming) {
|
|
2372
|
-
window.history.replaceState(null, "", url);
|
|
2373
|
-
} else {
|
|
2374
|
-
window.history.pushState(null, "", url);
|
|
2375
|
-
}
|
|
2376
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
2377
|
-
}
|
|
2378
|
-
return true;
|
|
2379
|
-
}
|
|
2380
|
-
case "client:open-url": {
|
|
2381
|
-
const { url, target = "_blank" } = event.data || {};
|
|
2382
|
-
if (url) {
|
|
2383
|
-
window.open(url, target);
|
|
2384
|
-
}
|
|
2385
|
-
return true;
|
|
2386
|
-
}
|
|
2387
|
-
case "client:copy": {
|
|
2388
|
-
const { text } = event.data || {};
|
|
2389
|
-
if (text) {
|
|
2390
|
-
await navigator.clipboard.writeText(text);
|
|
2391
|
-
}
|
|
2392
|
-
return true;
|
|
2393
|
-
}
|
|
2394
|
-
case "client:reset": {
|
|
2395
|
-
reset([]);
|
|
2396
|
-
return true;
|
|
2397
|
-
}
|
|
2398
|
-
case "client:invalidate-query": {
|
|
2399
|
-
const { queryKey } = event.data || {};
|
|
2400
|
-
if (queryKey) {
|
|
2401
|
-
await queryClient.invalidateQueries({ queryKey });
|
|
2402
|
-
}
|
|
2403
|
-
return true;
|
|
2404
|
-
}
|
|
2405
|
-
case "client:open-dialog": {
|
|
2406
|
-
setDialog(event.data);
|
|
2407
|
-
return true;
|
|
2408
|
-
}
|
|
2409
|
-
case "client:close-dialog": {
|
|
2410
|
-
setDialog(null);
|
|
2411
|
-
return true;
|
|
2412
|
-
}
|
|
2413
|
-
default:
|
|
2414
|
-
return false;
|
|
2415
|
-
}
|
|
2416
|
-
},
|
|
2417
|
-
[client, reset, queryClient]
|
|
2418
|
-
);
|
|
2419
|
-
const sendEvent = useCallback(
|
|
2420
|
-
async (event) => {
|
|
2421
|
-
const handled = await dispatchClientAction(event);
|
|
2422
|
-
if (handled) return;
|
|
2423
|
-
const generator = client.sendEvent(event);
|
|
2424
|
-
for await (const incomingEvent of generator) {
|
|
2425
|
-
await dispatchClientAction(incomingEvent);
|
|
2426
|
-
}
|
|
2427
|
-
},
|
|
2428
|
-
[client, dispatchClientAction]
|
|
2429
|
-
);
|
|
2430
|
-
const value = useMemo(
|
|
23
|
+
const contextValue = useMemo(
|
|
2431
24
|
() => ({
|
|
2432
25
|
...state,
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
config
|
|
2438
|
-
}),
|
|
2439
|
-
[state, sendEvent, reset, client, config]
|
|
2440
|
-
);
|
|
2441
|
-
useEffect(() => {
|
|
2442
|
-
setContextValue(value);
|
|
2443
|
-
}, [value, setContextValue]);
|
|
2444
|
-
return /* @__PURE__ */ jsxs(NuqsAdapter, { children: [
|
|
2445
|
-
children,
|
|
2446
|
-
/* @__PURE__ */ jsx(
|
|
2447
|
-
Dialog,
|
|
2448
|
-
{
|
|
2449
|
-
open: !!dialog,
|
|
2450
|
-
onOpenChange: (open) => {
|
|
2451
|
-
!open && setDialog(null);
|
|
2452
|
-
},
|
|
2453
|
-
children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md max-h-[90vh] overflow-y-auto", children: [
|
|
2454
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2455
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: dialog?.title }),
|
|
2456
|
-
dialog?.description && /* @__PURE__ */ jsx(DialogDescription, { children: dialog?.description })
|
|
2457
|
-
] }),
|
|
2458
|
-
/* @__PURE__ */ jsxs(DialogClose, { children: [
|
|
2459
|
-
/* @__PURE__ */ jsx(IconX, { className: "size-4" }),
|
|
2460
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
2461
|
-
] }),
|
|
2462
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: dialog?.ui && /* @__PURE__ */ jsx(UIRenderer, { node: dialog.ui }) })
|
|
2463
|
-
] })
|
|
2464
|
-
}
|
|
2465
|
-
)
|
|
2466
|
-
] });
|
|
2467
|
-
};
|
|
2468
|
-
var MelonyProvider = ({
|
|
2469
|
-
children,
|
|
2470
|
-
client,
|
|
2471
|
-
initialEvents,
|
|
2472
|
-
queryClient = defaultQueryClient
|
|
2473
|
-
}) => {
|
|
2474
|
-
const [contextValue, setContextValue] = useState(void 0);
|
|
2475
|
-
return /* @__PURE__ */ jsx(MelonyContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(
|
|
2476
|
-
MelonyContextProviderInner,
|
|
2477
|
-
{
|
|
2478
|
-
client,
|
|
2479
|
-
initialEvents,
|
|
2480
|
-
setContextValue,
|
|
2481
|
-
children
|
|
2482
|
-
}
|
|
2483
|
-
) }) });
|
|
2484
|
-
};
|
|
2485
|
-
var useAuth = () => {
|
|
2486
|
-
const context = useContext(AuthContext);
|
|
2487
|
-
if (context === void 0) {
|
|
2488
|
-
throw new Error("useAuth must be used within an AuthProvider");
|
|
2489
|
-
}
|
|
2490
|
-
return context;
|
|
2491
|
-
};
|
|
2492
|
-
var AccountButton = ({
|
|
2493
|
-
className,
|
|
2494
|
-
variant = "outline",
|
|
2495
|
-
size
|
|
2496
|
-
}) => {
|
|
2497
|
-
const { isLoading, isAuthenticated, user, login, logout } = useAuth();
|
|
2498
|
-
const [open, setOpen] = React3.useState(false);
|
|
2499
|
-
const [accountInfoOpen, setAccountInfoOpen] = React3.useState(false);
|
|
2500
|
-
const [error, setError] = React3.useState(null);
|
|
2501
|
-
const initials = React3.useMemo(() => {
|
|
2502
|
-
const name = user?.displayName || user?.name;
|
|
2503
|
-
if (!name) return "";
|
|
2504
|
-
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
2505
|
-
}, [user?.displayName, user?.name]);
|
|
2506
|
-
const handleGoogleSignIn = async () => {
|
|
2507
|
-
login();
|
|
2508
|
-
};
|
|
2509
|
-
if (isAuthenticated) {
|
|
2510
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2511
|
-
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2512
|
-
/* @__PURE__ */ jsx(
|
|
2513
|
-
DropdownMenuTrigger,
|
|
2514
|
-
{
|
|
2515
|
-
render: (props) => /* @__PURE__ */ jsx(
|
|
2516
|
-
Button,
|
|
2517
|
-
{
|
|
2518
|
-
variant,
|
|
2519
|
-
size: "icon",
|
|
2520
|
-
...props,
|
|
2521
|
-
className: cn("rounded-full", className),
|
|
2522
|
-
children: user?.picture ? /* @__PURE__ */ jsx(
|
|
2523
|
-
"img",
|
|
2524
|
-
{
|
|
2525
|
-
src: user.picture,
|
|
2526
|
-
alt: user.displayName || user.name,
|
|
2527
|
-
className: "size-7 rounded-full object-cover"
|
|
2528
|
-
}
|
|
2529
|
-
) : /* @__PURE__ */ jsx("div", { className: "flex size-7 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsx(IconUser, { className: "size-4" }) })
|
|
2530
|
-
}
|
|
2531
|
-
)
|
|
2532
|
-
}
|
|
2533
|
-
),
|
|
2534
|
-
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
|
|
2535
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-2", children: [
|
|
2536
|
-
user?.picture ? /* @__PURE__ */ jsx(
|
|
2537
|
-
"img",
|
|
2538
|
-
{
|
|
2539
|
-
src: user.picture,
|
|
2540
|
-
alt: user.displayName || user.name,
|
|
2541
|
-
className: "size-8 rounded-full object-cover"
|
|
2542
|
-
}
|
|
2543
|
-
) : /* @__PURE__ */ jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-muted text-xs font-bold", children: initials || /* @__PURE__ */ jsx(IconUser, { className: "size-4" }) }),
|
|
2544
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-0.5 overflow-hidden", children: [
|
|
2545
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: user?.displayName || user?.name }),
|
|
2546
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: user?.email })
|
|
2547
|
-
] })
|
|
2548
|
-
] }),
|
|
2549
|
-
/* @__PURE__ */ jsx(Separator, { className: "my-1" }),
|
|
2550
|
-
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: () => setAccountInfoOpen(true), children: [
|
|
2551
|
-
/* @__PURE__ */ jsx(IconUser, { className: "mr-2 size-4" }),
|
|
2552
|
-
"Account Settings"
|
|
2553
|
-
] }),
|
|
2554
|
-
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: logout, className: "text-destructive", children: [
|
|
2555
|
-
/* @__PURE__ */ jsx(IconLogout, { className: "mr-2 size-4" }),
|
|
2556
|
-
"Logout"
|
|
2557
|
-
] })
|
|
2558
|
-
] })
|
|
2559
|
-
] }),
|
|
2560
|
-
/* @__PURE__ */ jsx(Dialog, { open: accountInfoOpen, onOpenChange: setAccountInfoOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
|
|
2561
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2562
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: "Account Information" }),
|
|
2563
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: "Your account details and settings." })
|
|
2564
|
-
] }),
|
|
2565
|
-
/* @__PURE__ */ jsxs(DialogClose, { children: [
|
|
2566
|
-
/* @__PURE__ */ jsx(IconX, { className: "size-4" }),
|
|
2567
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
2568
|
-
] }),
|
|
2569
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 py-4", children: [
|
|
2570
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
2571
|
-
user?.picture ? /* @__PURE__ */ jsx(
|
|
2572
|
-
"img",
|
|
2573
|
-
{
|
|
2574
|
-
src: user.picture,
|
|
2575
|
-
alt: user.displayName || user.name,
|
|
2576
|
-
className: "size-16 rounded-full object-cover"
|
|
2577
|
-
}
|
|
2578
|
-
) : /* @__PURE__ */ jsx("div", { className: "flex size-16 items-center justify-center rounded-full bg-muted text-xl font-bold", children: initials || /* @__PURE__ */ jsx(IconUser, { className: "size-8 text-muted-foreground" }) }),
|
|
2579
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
2580
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: user?.displayName || user?.name }),
|
|
2581
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: user?.email })
|
|
2582
|
-
] })
|
|
2583
|
-
] }),
|
|
2584
|
-
/* @__PURE__ */ jsx(Separator, {}),
|
|
2585
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
2586
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2587
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "User ID" }),
|
|
2588
|
-
/* @__PURE__ */ jsx("p", { className: "font-mono text-xs truncate", children: user?.uid || user?.id })
|
|
2589
|
-
] }),
|
|
2590
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2591
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-muted-foreground", children: "Created At" }),
|
|
2592
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs", children: user?.createdAt || "N/A" })
|
|
2593
|
-
] })
|
|
2594
|
-
] })
|
|
2595
|
-
] })
|
|
2596
|
-
] }) })
|
|
2597
|
-
] });
|
|
2598
|
-
}
|
|
2599
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2600
|
-
/* @__PURE__ */ jsx(
|
|
2601
|
-
Button,
|
|
2602
|
-
{
|
|
2603
|
-
variant,
|
|
2604
|
-
size,
|
|
2605
|
-
onClick: () => setOpen(true),
|
|
2606
|
-
className,
|
|
2607
|
-
children: "Sign in"
|
|
2608
|
-
}
|
|
2609
|
-
),
|
|
2610
|
-
/* @__PURE__ */ jsx(Dialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", children: [
|
|
2611
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2612
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: "Sign in to continue" }),
|
|
2613
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: "Choose your preferred sign-in method to access your account." })
|
|
2614
|
-
] }),
|
|
2615
|
-
/* @__PURE__ */ jsxs(DialogClose, { children: [
|
|
2616
|
-
/* @__PURE__ */ jsx(IconX, { className: "size-4" }),
|
|
2617
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
2618
|
-
] }),
|
|
2619
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
2620
|
-
error && /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
2621
|
-
/* @__PURE__ */ jsxs(
|
|
2622
|
-
Button,
|
|
2623
|
-
{
|
|
2624
|
-
onClick: handleGoogleSignIn,
|
|
2625
|
-
disabled: isLoading,
|
|
2626
|
-
variant: "outline",
|
|
2627
|
-
className: "w-full",
|
|
2628
|
-
size: "lg",
|
|
2629
|
-
children: [
|
|
2630
|
-
/* @__PURE__ */ jsx(IconBrandGoogle, { className: "mr-2 size-5" }),
|
|
2631
|
-
isLoading ? "Signing in..." : "Continue with Google"
|
|
2632
|
-
]
|
|
2633
|
-
}
|
|
2634
|
-
)
|
|
2635
|
-
] })
|
|
2636
|
-
] }) })
|
|
2637
|
-
] });
|
|
2638
|
-
};
|
|
2639
|
-
function WelcomeScreen({
|
|
2640
|
-
title = "Welcome to Melony",
|
|
2641
|
-
description = "The most powerful AI agent framework for building modern applications. Connect your tools, build your brain, and ship faster.",
|
|
2642
|
-
features = [
|
|
2643
|
-
{
|
|
2644
|
-
title: "Context Aware",
|
|
2645
|
-
description: "Built-in state management for complex LLM flows."
|
|
2646
|
-
},
|
|
2647
|
-
{
|
|
2648
|
-
title: "Extensible",
|
|
2649
|
-
description: "Plugin architecture for easy integrations."
|
|
2650
|
-
},
|
|
2651
|
-
{
|
|
2652
|
-
title: "Real-time",
|
|
2653
|
-
description: "Streaming responses and live state updates."
|
|
2654
|
-
},
|
|
2655
|
-
{
|
|
2656
|
-
title: "Tool-ready",
|
|
2657
|
-
description: "Ready-to-use actions for common tasks."
|
|
2658
|
-
}
|
|
2659
|
-
],
|
|
2660
|
-
className,
|
|
2661
|
-
onLoginClick,
|
|
2662
|
-
termsUrl = "#",
|
|
2663
|
-
privacyUrl = "#",
|
|
2664
|
-
imageUrl,
|
|
2665
|
-
imageAlt = "Product screenshot"
|
|
2666
|
-
}) {
|
|
2667
|
-
const { login, isLoading } = useAuth();
|
|
2668
|
-
return /* @__PURE__ */ jsxs(
|
|
2669
|
-
"div",
|
|
2670
|
-
{
|
|
2671
|
-
className: cn(
|
|
2672
|
-
"flex min-h-[600px] h-full w-full flex-col md:flex-row bg-background overflow-hidden",
|
|
2673
|
-
className
|
|
2674
|
-
),
|
|
2675
|
-
children: [
|
|
2676
|
-
/* @__PURE__ */ jsxs("div", { className: "flex w-8/12 flex-col bg-sidebar text-foreground relative overflow-hidden", children: [
|
|
2677
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -top-24 -left-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
|
|
2678
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -bottom-24 -right-24 size-96 bg-primary/5 rounded-full blur-3xl" }),
|
|
2679
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto overflow-x-hidden relative z-10 flex flex-col p-8 md:p-12 lg:p-20", children: /* @__PURE__ */ jsxs("div", { className: "max-w-xl mx-auto w-full my-auto", children: [
|
|
2680
|
-
/* @__PURE__ */ jsx("h1", { className: "mb-6 text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl text-foreground", children: title }),
|
|
2681
|
-
/* @__PURE__ */ jsx("p", { className: "mb-12 text-lg text-muted-foreground md:text-xl leading-relaxed", children: description }),
|
|
2682
|
-
imageUrl && /* @__PURE__ */ jsxs("div", { className: "mb-12 relative group", children: [
|
|
2683
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -inset-1 bg-gradient-to-r from-primary/20 to-primary/10 rounded-xl blur opacity-25 group-hover:opacity-50 transition duration-1000 group-hover:duration-200" }),
|
|
2684
|
-
/* @__PURE__ */ jsx(
|
|
2685
|
-
"img",
|
|
2686
|
-
{
|
|
2687
|
-
src: imageUrl,
|
|
2688
|
-
alt: imageAlt,
|
|
2689
|
-
className: "relative rounded-xl border border-border/50 shadow-2xl transition-transform duration-500 hover:scale-[1.02] w-full"
|
|
2690
|
-
}
|
|
2691
|
-
)
|
|
2692
|
-
] }),
|
|
2693
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-x-8 gap-y-10 sm:grid-cols-2", children: features.map((feature, i) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2694
|
-
/* @__PURE__ */ jsx("h3", { className: "font-bold text-lg text-foreground", children: feature.title }),
|
|
2695
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: feature.description })
|
|
2696
|
-
] }, i)) })
|
|
2697
|
-
] }) })
|
|
2698
|
-
] }),
|
|
2699
|
-
/* @__PURE__ */ jsx("div", { className: "flex w-4/12 flex-col overflow-y-auto p-8 md:p-12 lg:p-20 bg-background transition-colors duration-300", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm space-y-8 my-auto mx-auto", children: [
|
|
2700
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-3 text-center md:text-left", children: [
|
|
2701
|
-
/* @__PURE__ */ jsx("h2", { className: "text-3xl font-bold tracking-tight text-foreground", children: "Get Started" }),
|
|
2702
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-lg", children: "Sign in to your account to continue" })
|
|
2703
|
-
] }),
|
|
2704
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsx(AccountButton, {}) }),
|
|
2705
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground leading-relaxed text-center md:text-left", children: [
|
|
2706
|
-
"By continuing, you agree to our ",
|
|
2707
|
-
/* @__PURE__ */ jsx("br", { className: "hidden md:block" }),
|
|
2708
|
-
/* @__PURE__ */ jsx(
|
|
2709
|
-
"a",
|
|
2710
|
-
{
|
|
2711
|
-
href: termsUrl,
|
|
2712
|
-
target: "_blank",
|
|
2713
|
-
rel: "noopener noreferrer",
|
|
2714
|
-
className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
|
|
2715
|
-
children: "Terms of Service"
|
|
2716
|
-
}
|
|
2717
|
-
),
|
|
2718
|
-
" ",
|
|
2719
|
-
"and",
|
|
2720
|
-
" ",
|
|
2721
|
-
/* @__PURE__ */ jsx(
|
|
2722
|
-
"a",
|
|
2723
|
-
{
|
|
2724
|
-
href: privacyUrl,
|
|
2725
|
-
target: "_blank",
|
|
2726
|
-
rel: "noopener noreferrer",
|
|
2727
|
-
className: "underline underline-offset-4 hover:text-primary transition-colors font-medium",
|
|
2728
|
-
children: "Privacy Policy"
|
|
2729
|
-
}
|
|
2730
|
-
),
|
|
2731
|
-
"."
|
|
2732
|
-
] })
|
|
2733
|
-
] }) })
|
|
2734
|
-
]
|
|
2735
|
-
}
|
|
2736
|
-
);
|
|
2737
|
-
}
|
|
2738
|
-
var AuthContext = createContext(
|
|
2739
|
-
void 0
|
|
2740
|
-
);
|
|
2741
|
-
var AuthProvider = ({
|
|
2742
|
-
children,
|
|
2743
|
-
service,
|
|
2744
|
-
welcomeScreenProps
|
|
2745
|
-
}) => {
|
|
2746
|
-
const queryClient = useQueryClient();
|
|
2747
|
-
const { data: user, isLoading } = useQuery({
|
|
2748
|
-
queryKey: ["auth-user", service],
|
|
2749
|
-
queryFn: () => service.getMe(),
|
|
2750
|
-
retry: false
|
|
2751
|
-
});
|
|
2752
|
-
const logoutMutation = useMutation({
|
|
2753
|
-
mutationFn: () => service.logout(),
|
|
2754
|
-
onSuccess: () => {
|
|
2755
|
-
queryClient.setQueryData(["auth-user", service], null);
|
|
2756
|
-
}
|
|
2757
|
-
});
|
|
2758
|
-
const login = useCallback(() => {
|
|
2759
|
-
service.login();
|
|
2760
|
-
}, [service]);
|
|
2761
|
-
const logout = useCallback(async () => {
|
|
2762
|
-
try {
|
|
2763
|
-
await logoutMutation.mutateAsync();
|
|
2764
|
-
} catch (error) {
|
|
2765
|
-
console.error("Failed to logout:", error);
|
|
2766
|
-
}
|
|
2767
|
-
}, [logoutMutation]);
|
|
2768
|
-
if (isLoading) {
|
|
2769
|
-
return /* @__PURE__ */ jsx(
|
|
2770
|
-
"div",
|
|
2771
|
-
{
|
|
2772
|
-
style: {
|
|
2773
|
-
height: "100vh",
|
|
2774
|
-
width: "100vw",
|
|
2775
|
-
display: "flex",
|
|
2776
|
-
justifyContent: "center",
|
|
2777
|
-
alignItems: "center",
|
|
2778
|
-
fontSize: "0.875rem",
|
|
2779
|
-
letterSpacing: "0.01em"
|
|
2780
|
-
},
|
|
2781
|
-
className: "text-muted-foreground animate-pulse",
|
|
2782
|
-
children: "Loading..."
|
|
2783
|
-
}
|
|
2784
|
-
);
|
|
2785
|
-
}
|
|
2786
|
-
const value = {
|
|
2787
|
-
user: user || null,
|
|
2788
|
-
isAuthenticated: !!user,
|
|
2789
|
-
isLoading,
|
|
2790
|
-
login,
|
|
2791
|
-
logout,
|
|
2792
|
-
getToken: service.getToken
|
|
2793
|
-
};
|
|
2794
|
-
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children: !value.isAuthenticated && welcomeScreenProps ? /* @__PURE__ */ jsx(WelcomeScreen, { ...welcomeScreenProps }) : children });
|
|
2795
|
-
};
|
|
2796
|
-
var ThreadContext = createContext(
|
|
2797
|
-
void 0
|
|
2798
|
-
);
|
|
2799
|
-
var ThreadProvider = ({
|
|
2800
|
-
children,
|
|
2801
|
-
service,
|
|
2802
|
-
initialThreadId: providedInitialThreadId
|
|
2803
|
-
}) => {
|
|
2804
|
-
const queryClient = useQueryClient();
|
|
2805
|
-
const melonyContext = useContext(MelonyContext);
|
|
2806
|
-
const [activeThreadId, setActiveThreadId] = useQueryState(
|
|
2807
|
-
"threadId",
|
|
2808
|
-
parseAsString
|
|
2809
|
-
);
|
|
2810
|
-
const prevActiveThreadIdRef = useRef(activeThreadId);
|
|
2811
|
-
useEffect(() => {
|
|
2812
|
-
prevActiveThreadIdRef.current = activeThreadId;
|
|
2813
|
-
}, [activeThreadId]);
|
|
2814
|
-
useEffect(() => {
|
|
2815
|
-
if (!activeThreadId && providedInitialThreadId) {
|
|
2816
|
-
setActiveThreadId(providedInitialThreadId);
|
|
2817
|
-
}
|
|
2818
|
-
}, [activeThreadId, providedInitialThreadId, setActiveThreadId]);
|
|
2819
|
-
const {
|
|
2820
|
-
data: threads = [],
|
|
2821
|
-
isLoading,
|
|
2822
|
-
isFetched: isFetchedThreads,
|
|
2823
|
-
error: threadsError,
|
|
2824
|
-
refetch: refreshThreads
|
|
2825
|
-
} = useQuery({
|
|
2826
|
-
queryKey: ["threads"],
|
|
2827
|
-
queryFn: () => service.getThreads(),
|
|
2828
|
-
staleTime: prevActiveThreadIdRef.current === null && activeThreadId !== null ? Infinity : 0
|
|
2829
|
-
});
|
|
2830
|
-
const isNewThread = useMemo(() => {
|
|
2831
|
-
if (!activeThreadId || !isFetchedThreads) return false;
|
|
2832
|
-
return !threads.some((t) => t.id === activeThreadId);
|
|
2833
|
-
}, [activeThreadId, threads, isFetchedThreads]);
|
|
2834
|
-
const { data: threadEvents = [], isLoading: isLoadingEvents } = useQuery({
|
|
2835
|
-
queryKey: ["threads", activeThreadId, "events"],
|
|
2836
|
-
queryFn: () => service.getEvents(activeThreadId),
|
|
2837
|
-
enabled: !!activeThreadId,
|
|
2838
|
-
initialData: isNewThread ? melonyContext?.events : void 0,
|
|
2839
|
-
staleTime: isNewThread ? Infinity : 0
|
|
2840
|
-
});
|
|
2841
|
-
const createMutation = useMutation({
|
|
2842
|
-
mutationFn: async () => {
|
|
2843
|
-
return null;
|
|
2844
|
-
},
|
|
2845
|
-
onSuccess: async () => {
|
|
2846
|
-
await setActiveThreadId(null);
|
|
2847
|
-
}
|
|
2848
|
-
});
|
|
2849
|
-
const deleteMutation = useMutation({
|
|
2850
|
-
mutationFn: (threadId) => service.deleteThread(threadId),
|
|
2851
|
-
onSuccess: async (_, threadId) => {
|
|
2852
|
-
await queryClient.invalidateQueries({ queryKey: ["threads"] });
|
|
2853
|
-
if (activeThreadId === threadId) {
|
|
2854
|
-
const remainingThreads = threads.filter((t) => t.id !== threadId);
|
|
2855
|
-
const nextId = remainingThreads.length > 0 ? remainingThreads[0].id : null;
|
|
2856
|
-
await setActiveThreadId(nextId);
|
|
2857
|
-
}
|
|
2858
|
-
}
|
|
2859
|
-
});
|
|
2860
|
-
const selectThread = useCallback(
|
|
2861
|
-
(threadId) => {
|
|
2862
|
-
setActiveThreadId(threadId);
|
|
2863
|
-
},
|
|
2864
|
-
[setActiveThreadId]
|
|
2865
|
-
);
|
|
2866
|
-
const createThread = useCallback(async () => {
|
|
2867
|
-
return createMutation.mutateAsync();
|
|
2868
|
-
}, [createMutation]);
|
|
2869
|
-
const deleteThread = useCallback(
|
|
2870
|
-
async (threadId) => {
|
|
2871
|
-
return deleteMutation.mutateAsync(threadId);
|
|
2872
|
-
},
|
|
2873
|
-
[deleteMutation]
|
|
2874
|
-
);
|
|
2875
|
-
const value = useMemo(
|
|
2876
|
-
() => ({
|
|
2877
|
-
threads,
|
|
2878
|
-
activeThreadId,
|
|
2879
|
-
isLoading,
|
|
2880
|
-
error: threadsError || null,
|
|
2881
|
-
selectThread,
|
|
2882
|
-
createThread,
|
|
2883
|
-
deleteThread,
|
|
2884
|
-
refreshThreads: async () => {
|
|
2885
|
-
await refreshThreads();
|
|
26
|
+
sendEvent: async (event) => {
|
|
27
|
+
const generator = client.sendEvent(event);
|
|
28
|
+
for await (const _ of generator) {
|
|
29
|
+
}
|
|
2886
30
|
},
|
|
2887
|
-
|
|
2888
|
-
|
|
31
|
+
reset: client.reset.bind(client),
|
|
32
|
+
client
|
|
2889
33
|
}),
|
|
2890
|
-
[
|
|
2891
|
-
threads,
|
|
2892
|
-
activeThreadId,
|
|
2893
|
-
isLoading,
|
|
2894
|
-
threadsError,
|
|
2895
|
-
selectThread,
|
|
2896
|
-
createThread,
|
|
2897
|
-
deleteThread,
|
|
2898
|
-
refreshThreads,
|
|
2899
|
-
threadEvents,
|
|
2900
|
-
isLoadingEvents
|
|
2901
|
-
]
|
|
34
|
+
[state, client]
|
|
2902
35
|
);
|
|
2903
|
-
return /* @__PURE__ */ jsx(
|
|
36
|
+
return /* @__PURE__ */ jsx(MelonyContext.Provider, { value: contextValue, children });
|
|
2904
37
|
};
|
|
2905
|
-
|
|
2906
|
-
const
|
|
2907
|
-
if (typeof window === "undefined") {
|
|
2908
|
-
return {
|
|
2909
|
-
width: 1024,
|
|
2910
|
-
height: 768,
|
|
2911
|
-
isMobile: false,
|
|
2912
|
-
isTablet: false,
|
|
2913
|
-
isDesktop: true
|
|
2914
|
-
};
|
|
2915
|
-
}
|
|
2916
|
-
const width = window.innerWidth;
|
|
2917
|
-
return {
|
|
2918
|
-
width,
|
|
2919
|
-
height: window.innerHeight,
|
|
2920
|
-
isMobile: width < mobileBreakpoint,
|
|
2921
|
-
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
2922
|
-
isDesktop: width >= tabletBreakpoint
|
|
2923
|
-
};
|
|
2924
|
-
});
|
|
2925
|
-
useEffect(() => {
|
|
2926
|
-
if (typeof window === "undefined") return;
|
|
2927
|
-
const updateScreenSize = () => {
|
|
2928
|
-
const width = window.innerWidth;
|
|
2929
|
-
const height = window.innerHeight;
|
|
2930
|
-
setScreenSize({
|
|
2931
|
-
width,
|
|
2932
|
-
height,
|
|
2933
|
-
isMobile: width < mobileBreakpoint,
|
|
2934
|
-
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
2935
|
-
isDesktop: width >= tabletBreakpoint
|
|
2936
|
-
});
|
|
2937
|
-
};
|
|
2938
|
-
updateScreenSize();
|
|
2939
|
-
window.addEventListener("resize", updateScreenSize);
|
|
2940
|
-
return () => {
|
|
2941
|
-
window.removeEventListener("resize", updateScreenSize);
|
|
2942
|
-
};
|
|
2943
|
-
}, [mobileBreakpoint, tabletBreakpoint]);
|
|
2944
|
-
return screenSize;
|
|
2945
|
-
}
|
|
2946
|
-
var SidebarContext = createContext(
|
|
2947
|
-
void 0
|
|
2948
|
-
);
|
|
2949
|
-
function useSidebar() {
|
|
2950
|
-
const context = useContext(SidebarContext);
|
|
2951
|
-
if (context === void 0) {
|
|
2952
|
-
throw new Error("useSidebar must be used within a SidebarProvider");
|
|
2953
|
-
}
|
|
2954
|
-
return context;
|
|
2955
|
-
}
|
|
2956
|
-
function SidebarProvider({
|
|
2957
|
-
children,
|
|
2958
|
-
defaultLeftCollapsed,
|
|
2959
|
-
defaultRightCollapsed
|
|
2960
|
-
}) {
|
|
2961
|
-
const { isMobile, isTablet } = useScreenSize();
|
|
2962
|
-
const isSmallScreen = isMobile || isTablet;
|
|
2963
|
-
const [leftCollapsed, setLeftCollapsed] = useState(() => {
|
|
2964
|
-
if (defaultLeftCollapsed !== void 0) return defaultLeftCollapsed;
|
|
2965
|
-
if (typeof window !== "undefined") {
|
|
2966
|
-
return window.innerWidth < 1024;
|
|
2967
|
-
}
|
|
2968
|
-
return false;
|
|
2969
|
-
});
|
|
2970
|
-
const [rightCollapsed, setRightCollapsed] = useState(() => {
|
|
2971
|
-
if (defaultRightCollapsed !== void 0) return defaultRightCollapsed;
|
|
2972
|
-
if (typeof window !== "undefined") {
|
|
2973
|
-
return window.innerWidth < 1024;
|
|
2974
|
-
}
|
|
2975
|
-
return false;
|
|
2976
|
-
});
|
|
2977
|
-
useEffect(() => {
|
|
2978
|
-
if (isSmallScreen) {
|
|
2979
|
-
setLeftCollapsed(true);
|
|
2980
|
-
setRightCollapsed(true);
|
|
2981
|
-
}
|
|
2982
|
-
}, [isSmallScreen]);
|
|
2983
|
-
const handleLeftToggle = useCallback((collapsed) => {
|
|
2984
|
-
setLeftCollapsed(collapsed);
|
|
2985
|
-
}, []);
|
|
2986
|
-
const handleRightToggle = useCallback((collapsed) => {
|
|
2987
|
-
setRightCollapsed(collapsed);
|
|
2988
|
-
}, []);
|
|
2989
|
-
const contextValue = useMemo(
|
|
2990
|
-
() => ({
|
|
2991
|
-
leftCollapsed,
|
|
2992
|
-
rightCollapsed,
|
|
2993
|
-
setLeftCollapsed: handleLeftToggle,
|
|
2994
|
-
setRightCollapsed: handleRightToggle,
|
|
2995
|
-
leftCollapsible: true,
|
|
2996
|
-
rightCollapsible: true
|
|
2997
|
-
}),
|
|
2998
|
-
[leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
|
|
2999
|
-
);
|
|
3000
|
-
return /* @__PURE__ */ jsx(SidebarContext.Provider, { value: contextValue, children });
|
|
3001
|
-
}
|
|
3002
|
-
var ThemeContext = createContext(void 0);
|
|
3003
|
-
function ThemeProvider({ children }) {
|
|
3004
|
-
const [theme, setThemeState] = useState("system");
|
|
3005
|
-
const [resolvedTheme, setResolvedTheme] = useState("light");
|
|
3006
|
-
useEffect(() => {
|
|
3007
|
-
if (typeof window !== "undefined") {
|
|
3008
|
-
const stored = localStorage.getItem("theme");
|
|
3009
|
-
if (stored) {
|
|
3010
|
-
setThemeState(stored);
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
}, []);
|
|
3014
|
-
useEffect(() => {
|
|
3015
|
-
if (typeof window !== "undefined") {
|
|
3016
|
-
if (theme === "system") {
|
|
3017
|
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
3018
|
-
const updateResolvedTheme = () => {
|
|
3019
|
-
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
3020
|
-
};
|
|
3021
|
-
updateResolvedTheme();
|
|
3022
|
-
mediaQuery.addEventListener("change", updateResolvedTheme);
|
|
3023
|
-
return () => mediaQuery.removeEventListener("change", updateResolvedTheme);
|
|
3024
|
-
} else {
|
|
3025
|
-
setResolvedTheme(theme);
|
|
3026
|
-
}
|
|
3027
|
-
}
|
|
3028
|
-
}, [theme]);
|
|
3029
|
-
useEffect(() => {
|
|
3030
|
-
if (typeof window !== "undefined") {
|
|
3031
|
-
const root = document.documentElement;
|
|
3032
|
-
if (resolvedTheme === "dark") {
|
|
3033
|
-
root.classList.add("dark");
|
|
3034
|
-
} else {
|
|
3035
|
-
root.classList.remove("dark");
|
|
3036
|
-
}
|
|
3037
|
-
}
|
|
3038
|
-
}, [resolvedTheme]);
|
|
3039
|
-
const setTheme = (newTheme) => {
|
|
3040
|
-
setThemeState(newTheme);
|
|
3041
|
-
if (typeof window !== "undefined") {
|
|
3042
|
-
localStorage.setItem("theme", newTheme);
|
|
3043
|
-
}
|
|
3044
|
-
};
|
|
3045
|
-
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme, resolvedTheme }, children });
|
|
3046
|
-
}
|
|
3047
|
-
function useTheme() {
|
|
3048
|
-
const context = useContext(ThemeContext);
|
|
3049
|
-
if (context === void 0) {
|
|
3050
|
-
throw new Error("useTheme must be used within a ThemeProvider");
|
|
3051
|
-
}
|
|
3052
|
-
return context;
|
|
3053
|
-
}
|
|
3054
|
-
var useThreads = () => {
|
|
3055
|
-
const context = useContext(ThreadContext);
|
|
38
|
+
var useMelony = () => {
|
|
39
|
+
const context = useContext(MelonyContext);
|
|
3056
40
|
if (context === void 0) {
|
|
3057
|
-
throw new Error("
|
|
41
|
+
throw new Error("useMelony must be used within a MelonyProvider");
|
|
3058
42
|
}
|
|
3059
43
|
return context;
|
|
3060
44
|
};
|
|
3061
|
-
var useSurface = (options) => {
|
|
3062
|
-
const { events } = useMelony();
|
|
3063
|
-
const surfaceEvents = useMemo(() => {
|
|
3064
|
-
const filtered = events.filter((event) => event.surface === options.name);
|
|
3065
|
-
return filterEventsBySlots(filtered);
|
|
3066
|
-
}, [events, options.name]);
|
|
3067
|
-
return {
|
|
3068
|
-
events: surfaceEvents
|
|
3069
|
-
};
|
|
3070
|
-
};
|
|
3071
|
-
function Composer({
|
|
3072
|
-
value,
|
|
3073
|
-
onChange,
|
|
3074
|
-
onSubmit,
|
|
3075
|
-
placeholder = "Type a message...",
|
|
3076
|
-
isLoading,
|
|
3077
|
-
className,
|
|
3078
|
-
options = [],
|
|
3079
|
-
autoFocus = false,
|
|
3080
|
-
defaultSelectedIds = [],
|
|
3081
|
-
fileAttachments
|
|
3082
|
-
}) {
|
|
3083
|
-
const enabled = fileAttachments?.enabled || false;
|
|
3084
|
-
const accept = fileAttachments?.accept;
|
|
3085
|
-
const maxFiles = fileAttachments?.maxFiles ?? 10;
|
|
3086
|
-
const maxFileSize = fileAttachments?.maxFileSize ?? 10 * 1024 * 1024;
|
|
3087
|
-
const [selectedOptions, setSelectedOptions] = React3__default.useState(
|
|
3088
|
-
() => new Set(defaultSelectedIds)
|
|
3089
|
-
);
|
|
3090
|
-
const [attachedFiles, setAttachedFiles] = React3__default.useState([]);
|
|
3091
|
-
const [previews, setPreviews] = React3__default.useState([]);
|
|
3092
|
-
const fileInputRef = React3__default.useRef(null);
|
|
3093
|
-
React3__default.useEffect(() => {
|
|
3094
|
-
const newPreviews = attachedFiles.map((file) => ({
|
|
3095
|
-
name: file.name,
|
|
3096
|
-
type: file.type,
|
|
3097
|
-
size: file.size,
|
|
3098
|
-
url: file.type.startsWith("image/") ? URL.createObjectURL(file) : ""
|
|
3099
|
-
}));
|
|
3100
|
-
setPreviews(newPreviews);
|
|
3101
|
-
return () => {
|
|
3102
|
-
newPreviews.forEach((p) => {
|
|
3103
|
-
if (p.url) URL.revokeObjectURL(p.url);
|
|
3104
|
-
});
|
|
3105
|
-
};
|
|
3106
|
-
}, [attachedFiles]);
|
|
3107
|
-
const toggleOption = (id, groupOptions, type = "multiple") => {
|
|
3108
|
-
const next = new Set(selectedOptions);
|
|
3109
|
-
if (type === "single") {
|
|
3110
|
-
const isAlreadySelected = next.has(id);
|
|
3111
|
-
if (groupOptions) {
|
|
3112
|
-
groupOptions.forEach((o) => next.delete(o.id));
|
|
3113
|
-
}
|
|
3114
|
-
if (!isAlreadySelected) {
|
|
3115
|
-
next.add(id);
|
|
3116
|
-
}
|
|
3117
|
-
} else {
|
|
3118
|
-
if (next.has(id)) {
|
|
3119
|
-
next.delete(id);
|
|
3120
|
-
} else {
|
|
3121
|
-
next.add(id);
|
|
3122
|
-
}
|
|
3123
|
-
}
|
|
3124
|
-
setSelectedOptions(next);
|
|
3125
|
-
};
|
|
3126
|
-
const handleFileSelect = (e) => {
|
|
3127
|
-
const files = Array.from(e.target.files || []);
|
|
3128
|
-
const validFiles = files.filter((file) => {
|
|
3129
|
-
if (file.size > maxFileSize) {
|
|
3130
|
-
console.warn(
|
|
3131
|
-
`File ${file.name} exceeds maximum size of ${maxFileSize} bytes`
|
|
3132
|
-
);
|
|
3133
|
-
return false;
|
|
3134
|
-
}
|
|
3135
|
-
return true;
|
|
3136
|
-
});
|
|
3137
|
-
const remainingSlots = maxFiles - attachedFiles.length;
|
|
3138
|
-
const filesToAdd = validFiles.slice(0, remainingSlots);
|
|
3139
|
-
if (filesToAdd.length < validFiles.length) {
|
|
3140
|
-
console.warn(
|
|
3141
|
-
`Only ${filesToAdd.length} files can be added (max: ${maxFiles})`
|
|
3142
|
-
);
|
|
3143
|
-
}
|
|
3144
|
-
setAttachedFiles((prev) => [...prev, ...filesToAdd]);
|
|
3145
|
-
if (fileInputRef.current) {
|
|
3146
|
-
fileInputRef.current.value = "";
|
|
3147
|
-
}
|
|
3148
|
-
};
|
|
3149
|
-
const handleRemoveFile = (index) => {
|
|
3150
|
-
setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
3151
|
-
};
|
|
3152
|
-
const handleInternalSubmit = async () => {
|
|
3153
|
-
const state = {};
|
|
3154
|
-
options.forEach((group) => {
|
|
3155
|
-
const selectedInGroup = group.options.filter(
|
|
3156
|
-
(o) => selectedOptions.has(o.id)
|
|
3157
|
-
);
|
|
3158
|
-
if (selectedInGroup.length > 0) {
|
|
3159
|
-
if (group.type === "single") {
|
|
3160
|
-
state[group.id] = selectedInGroup[0].value;
|
|
3161
|
-
} else {
|
|
3162
|
-
state[group.id] = selectedInGroup.map((o) => ({
|
|
3163
|
-
id: o.id,
|
|
3164
|
-
value: o.value
|
|
3165
|
-
}));
|
|
3166
|
-
}
|
|
3167
|
-
}
|
|
3168
|
-
});
|
|
3169
|
-
if (attachedFiles.length > 0) {
|
|
3170
|
-
const filePromises = attachedFiles.map((file) => {
|
|
3171
|
-
return new Promise((resolve, reject) => {
|
|
3172
|
-
const reader = new FileReader();
|
|
3173
|
-
reader.onload = () => {
|
|
3174
|
-
try {
|
|
3175
|
-
const base64 = reader.result;
|
|
3176
|
-
if (!base64) {
|
|
3177
|
-
reject(new Error("FileReader returned empty result"));
|
|
3178
|
-
return;
|
|
3179
|
-
}
|
|
3180
|
-
resolve({
|
|
3181
|
-
name: file.name,
|
|
3182
|
-
type: file.type,
|
|
3183
|
-
size: file.size,
|
|
3184
|
-
data: base64
|
|
3185
|
-
});
|
|
3186
|
-
} catch (error) {
|
|
3187
|
-
reject(error);
|
|
3188
|
-
}
|
|
3189
|
-
};
|
|
3190
|
-
reader.onerror = (error) => {
|
|
3191
|
-
reject(new Error(`Failed to read file ${file.name}: ${error}`));
|
|
3192
|
-
};
|
|
3193
|
-
reader.onabort = () => {
|
|
3194
|
-
reject(new Error(`File read aborted for ${file.name}`));
|
|
3195
|
-
};
|
|
3196
|
-
reader.readAsDataURL(file);
|
|
3197
|
-
});
|
|
3198
|
-
});
|
|
3199
|
-
try {
|
|
3200
|
-
const convertedFiles = await Promise.all(filePromises);
|
|
3201
|
-
if (convertedFiles.length > 0) {
|
|
3202
|
-
state.files = convertedFiles;
|
|
3203
|
-
}
|
|
3204
|
-
} catch (error) {
|
|
3205
|
-
console.error("Failed to convert files to base64:", error);
|
|
3206
|
-
}
|
|
3207
|
-
}
|
|
3208
|
-
onSubmit(state);
|
|
3209
|
-
setAttachedFiles([]);
|
|
3210
|
-
};
|
|
3211
|
-
const handleKeyDown = (e) => {
|
|
3212
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
3213
|
-
e.preventDefault();
|
|
3214
|
-
handleInternalSubmit().catch(console.error);
|
|
3215
|
-
}
|
|
3216
|
-
};
|
|
3217
|
-
const handlePaste = (e) => {
|
|
3218
|
-
if (!enabled) return;
|
|
3219
|
-
const items = Array.from(e.clipboardData.items);
|
|
3220
|
-
const files = items.map((item) => item.getAsFile()).filter((file) => file !== null);
|
|
3221
|
-
if (files.length > 0) {
|
|
3222
|
-
const remainingSlots = maxFiles - attachedFiles.length;
|
|
3223
|
-
const validFiles = files.filter((f) => f.size <= maxFileSize);
|
|
3224
|
-
const filesToAdd = validFiles.slice(0, remainingSlots);
|
|
3225
|
-
if (filesToAdd.length > 0) {
|
|
3226
|
-
setAttachedFiles((prev) => [...prev, ...filesToAdd]);
|
|
3227
|
-
}
|
|
3228
|
-
}
|
|
3229
|
-
};
|
|
3230
|
-
return /* @__PURE__ */ jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col w-full border-input border-[1.5px] rounded-3xl bg-background shadow-sm focus-within:border-ring transition-all p-2", children: [
|
|
3231
|
-
previews.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3 p-2 px-3 pb-3", children: previews.map((preview, index) => /* @__PURE__ */ jsxs(
|
|
3232
|
-
"div",
|
|
3233
|
-
{
|
|
3234
|
-
className: "group relative flex flex-col items-center justify-center w-20 h-20 rounded-xl border bg-muted/30 overflow-hidden shadow-sm",
|
|
3235
|
-
children: [
|
|
3236
|
-
preview.type.startsWith("image/") ? /* @__PURE__ */ jsx(
|
|
3237
|
-
"img",
|
|
3238
|
-
{
|
|
3239
|
-
src: preview.url,
|
|
3240
|
-
alt: preview.name,
|
|
3241
|
-
className: "w-full h-full object-cover"
|
|
3242
|
-
}
|
|
3243
|
-
) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center p-2 text-center", children: [
|
|
3244
|
-
preview.type.includes("text") || preview.type.includes("pdf") ? /* @__PURE__ */ jsx(IconFileText, { className: "h-8 w-8 text-muted-foreground" }) : /* @__PURE__ */ jsx(IconFile, { className: "h-8 w-8 text-muted-foreground" }),
|
|
3245
|
-
/* @__PURE__ */ jsx("span", { className: "text-[9px] truncate w-full px-1 mt-1 text-muted-foreground", children: preview.name })
|
|
3246
|
-
] }),
|
|
3247
|
-
/* @__PURE__ */ jsx(
|
|
3248
|
-
"button",
|
|
3249
|
-
{
|
|
3250
|
-
type: "button",
|
|
3251
|
-
onClick: () => handleRemoveFile(index),
|
|
3252
|
-
className: "absolute top-1 right-1 p-1 rounded-full bg-foreground/10 hover:bg-foreground/20 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity",
|
|
3253
|
-
children: /* @__PURE__ */ jsx(IconX, { className: "h-3 w-3" })
|
|
3254
|
-
}
|
|
3255
|
-
)
|
|
3256
|
-
]
|
|
3257
|
-
},
|
|
3258
|
-
index
|
|
3259
|
-
)) }),
|
|
3260
|
-
/* @__PURE__ */ jsx(
|
|
3261
|
-
Textarea,
|
|
3262
|
-
{
|
|
3263
|
-
value,
|
|
3264
|
-
onChange: (e) => onChange(e.target.value),
|
|
3265
|
-
onKeyDown: handleKeyDown,
|
|
3266
|
-
onPaste: handlePaste,
|
|
3267
|
-
placeholder,
|
|
3268
|
-
className: "min-h-[44px] max-h-[200px] border-none bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 py-2 text-[15px] resize-none",
|
|
3269
|
-
autoFocus
|
|
3270
|
-
}
|
|
3271
|
-
),
|
|
3272
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
|
|
3273
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
3274
|
-
enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3275
|
-
/* @__PURE__ */ jsx(
|
|
3276
|
-
"input",
|
|
3277
|
-
{
|
|
3278
|
-
ref: fileInputRef,
|
|
3279
|
-
type: "file",
|
|
3280
|
-
multiple: true,
|
|
3281
|
-
accept,
|
|
3282
|
-
onChange: handleFileSelect,
|
|
3283
|
-
className: "hidden",
|
|
3284
|
-
disabled: isLoading || attachedFiles.length >= maxFiles
|
|
3285
|
-
}
|
|
3286
|
-
),
|
|
3287
|
-
/* @__PURE__ */ jsxs(
|
|
3288
|
-
Button,
|
|
3289
|
-
{
|
|
3290
|
-
type: "button",
|
|
3291
|
-
variant: "ghost",
|
|
3292
|
-
size: "sm",
|
|
3293
|
-
onClick: () => fileInputRef.current?.click(),
|
|
3294
|
-
disabled: isLoading || attachedFiles.length >= maxFiles,
|
|
3295
|
-
className: "text-muted-foreground",
|
|
3296
|
-
title: "Attach file",
|
|
3297
|
-
children: [
|
|
3298
|
-
/* @__PURE__ */ jsx(IconPaperclip, { className: "h-4 w-4" }),
|
|
3299
|
-
attachedFiles.length > 0 && /* @__PURE__ */ jsx(Badge, { className: "ml-1 h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
|
|
3300
|
-
]
|
|
3301
|
-
}
|
|
3302
|
-
)
|
|
3303
|
-
] }),
|
|
3304
|
-
options.map((group) => {
|
|
3305
|
-
const selectedInGroup = group.options.filter(
|
|
3306
|
-
(o) => selectedOptions.has(o.id)
|
|
3307
|
-
);
|
|
3308
|
-
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : group.label;
|
|
3309
|
-
const isSingle = group.type === "single";
|
|
3310
|
-
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
3311
|
-
/* @__PURE__ */ jsx(
|
|
3312
|
-
DropdownMenuTrigger,
|
|
3313
|
-
{
|
|
3314
|
-
render: (props) => /* @__PURE__ */ jsxs(
|
|
3315
|
-
Button,
|
|
3316
|
-
{
|
|
3317
|
-
variant: "ghost",
|
|
3318
|
-
size: "sm",
|
|
3319
|
-
...props,
|
|
3320
|
-
className: cn(
|
|
3321
|
-
"gap-2",
|
|
3322
|
-
selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
|
|
3323
|
-
),
|
|
3324
|
-
children: [
|
|
3325
|
-
label,
|
|
3326
|
-
selectedInGroup.length > 1 && /* @__PURE__ */ jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: selectedInGroup.length }),
|
|
3327
|
-
/* @__PURE__ */ jsx(IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
3328
|
-
]
|
|
3329
|
-
}
|
|
3330
|
-
)
|
|
3331
|
-
}
|
|
3332
|
-
),
|
|
3333
|
-
/* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "w-56", children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
3334
|
-
/* @__PURE__ */ jsx(DropdownMenuLabel, { children: group.label }),
|
|
3335
|
-
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
3336
|
-
group.options.map((option) => /* @__PURE__ */ jsx(
|
|
3337
|
-
DropdownMenuCheckboxItem,
|
|
3338
|
-
{
|
|
3339
|
-
checked: selectedOptions.has(option.id),
|
|
3340
|
-
onCheckedChange: () => toggleOption(
|
|
3341
|
-
option.id,
|
|
3342
|
-
group.options,
|
|
3343
|
-
isSingle ? "single" : "multiple"
|
|
3344
|
-
),
|
|
3345
|
-
onSelect: (e) => e.preventDefault(),
|
|
3346
|
-
children: option.label
|
|
3347
|
-
},
|
|
3348
|
-
option.id
|
|
3349
|
-
))
|
|
3350
|
-
] }) })
|
|
3351
|
-
] }, group.id);
|
|
3352
|
-
})
|
|
3353
|
-
] }),
|
|
3354
|
-
/* @__PURE__ */ jsx(
|
|
3355
|
-
Button,
|
|
3356
|
-
{
|
|
3357
|
-
type: "submit",
|
|
3358
|
-
disabled: !value.trim() && attachedFiles.length === 0 && selectedOptions.size === 0 && !isLoading || isLoading,
|
|
3359
|
-
size: "icon-lg",
|
|
3360
|
-
onClick: () => handleInternalSubmit().catch(console.error),
|
|
3361
|
-
children: isLoading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsx(IconArrowUp, { className: "h-5 w-5" })
|
|
3362
|
-
}
|
|
3363
|
-
)
|
|
3364
|
-
] })
|
|
3365
|
-
] }) });
|
|
3366
|
-
}
|
|
3367
|
-
function StarterPrompts({
|
|
3368
|
-
prompts
|
|
3369
|
-
}) {
|
|
3370
|
-
if (!prompts || prompts.length === 0) {
|
|
3371
|
-
return null;
|
|
3372
|
-
}
|
|
3373
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-4 animate-in fade-in slide-in-from-bottom-4 duration-500 mt-auto max-w-2xl", children: [
|
|
3374
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold tracking-tight", children: "What can I help with today?" }) }),
|
|
3375
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1 w-full", children: prompts.map((item, index) => /* @__PURE__ */ jsx(
|
|
3376
|
-
Button2,
|
|
3377
|
-
{
|
|
3378
|
-
label: item.label,
|
|
3379
|
-
variant: "ghost",
|
|
3380
|
-
size: "lg",
|
|
3381
|
-
onClickAction: {
|
|
3382
|
-
type: "text",
|
|
3383
|
-
role: "user",
|
|
3384
|
-
data: { content: item.prompt }
|
|
3385
|
-
},
|
|
3386
|
-
justify: "start"
|
|
3387
|
-
},
|
|
3388
|
-
index
|
|
3389
|
-
)) })
|
|
3390
|
-
] });
|
|
3391
|
-
}
|
|
3392
|
-
function MessageContent({ events }) {
|
|
3393
|
-
const displayEvents = useMemo(() => filterEventsBySlots(events), [events]);
|
|
3394
|
-
return /* @__PURE__ */ jsx(Fragment, { children: displayEvents.map((displayEvent, index) => {
|
|
3395
|
-
if (displayEvent.type === "text-delta") {
|
|
3396
|
-
return /* @__PURE__ */ jsx("span", { children: displayEvent.data?.delta }, index);
|
|
3397
|
-
}
|
|
3398
|
-
if (displayEvent.type === "text") {
|
|
3399
|
-
return /* @__PURE__ */ jsx("p", { children: displayEvent.data?.content || displayEvent.data?.text }, index);
|
|
3400
|
-
}
|
|
3401
|
-
if (displayEvent.ui) {
|
|
3402
|
-
return /* @__PURE__ */ jsx(UIRenderer, { node: displayEvent.ui }, index);
|
|
3403
|
-
}
|
|
3404
|
-
return null;
|
|
3405
|
-
}) });
|
|
3406
|
-
}
|
|
3407
|
-
function MessageBubble({ message }) {
|
|
3408
|
-
const isUser = message.role === "user";
|
|
3409
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", isUser ? "items-end" : "items-start"), children: /* @__PURE__ */ jsx(
|
|
3410
|
-
"div",
|
|
3411
|
-
{
|
|
3412
|
-
className: cn(
|
|
3413
|
-
"flex flex-col items-start max-w-[85%] rounded-2xl px-4 py-2 space-y-4 whitespace-pre-wrap",
|
|
3414
|
-
isUser ? "bg-primary text-primary-foreground" : "px-0 py-0 text-foreground"
|
|
3415
|
-
),
|
|
3416
|
-
children: /* @__PURE__ */ jsx(MessageContent, { events: message.content })
|
|
3417
|
-
}
|
|
3418
|
-
) });
|
|
3419
|
-
}
|
|
3420
|
-
function LoadingIndicator({ status }) {
|
|
3421
|
-
const [isExpanded, setIsExpanded] = useState(false);
|
|
3422
|
-
const message = status?.message || "Processing...";
|
|
3423
|
-
const details = status?.details;
|
|
3424
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3425
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground group", children: [
|
|
3426
|
-
/* @__PURE__ */ jsx(IconLoader2, { className: "size-3.5 animate-spin" }),
|
|
3427
|
-
/* @__PURE__ */ jsx("div", { className: "animate-pulse", children: message }),
|
|
3428
|
-
details && /* @__PURE__ */ jsx(
|
|
3429
|
-
"button",
|
|
3430
|
-
{
|
|
3431
|
-
onClick: () => setIsExpanded(!isExpanded),
|
|
3432
|
-
className: "p-0.5 hover:bg-muted rounded-sm transition-colors flex items-center justify-center",
|
|
3433
|
-
title: isExpanded ? "Hide details" : "Show details",
|
|
3434
|
-
children: isExpanded ? /* @__PURE__ */ jsx(IconChevronUp, { className: "size-3.5 opacity-50 group-hover:opacity-100" }) : /* @__PURE__ */ jsx(IconChevronDown, { className: "size-3.5 opacity-50 group-hover:opacity-100" })
|
|
3435
|
-
}
|
|
3436
|
-
)
|
|
3437
|
-
] }),
|
|
3438
|
-
isExpanded && details && /* @__PURE__ */ jsx("div", { className: "text-[10px] leading-relaxed font-mono bg-muted/30 p-2.5 rounded border border-border/50 max-h-64 overflow-y-auto whitespace-pre-wrap text-muted-foreground shadow-sm", children: details })
|
|
3439
|
-
] });
|
|
3440
|
-
}
|
|
3441
|
-
function ErrorDisplay({ error }) {
|
|
3442
|
-
return /* @__PURE__ */ jsx("div", { className: "text-destructive p-2 border border-destructive rounded-md bg-destructive/10", children: error.message });
|
|
3443
|
-
}
|
|
3444
|
-
function MessageList({
|
|
3445
|
-
messages,
|
|
3446
|
-
isLoading,
|
|
3447
|
-
error,
|
|
3448
|
-
loadingStatus
|
|
3449
|
-
}) {
|
|
3450
|
-
if (messages.length === 0) {
|
|
3451
|
-
return null;
|
|
3452
|
-
}
|
|
3453
|
-
const isTextStreaming = useMemo(() => {
|
|
3454
|
-
if (messages.length === 0 || !isLoading) return false;
|
|
3455
|
-
const lastMessage = messages[messages.length - 1];
|
|
3456
|
-
return lastMessage.content.some((event) => event.type === "text-delta");
|
|
3457
|
-
}, [messages, isLoading]);
|
|
3458
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
3459
|
-
messages.map((message, index) => /* @__PURE__ */ jsx(MessageBubble, { message }, index)),
|
|
3460
|
-
isLoading && !isTextStreaming && /* @__PURE__ */ jsx(LoadingIndicator, { status: loadingStatus }),
|
|
3461
|
-
error && /* @__PURE__ */ jsx(ErrorDisplay, { error })
|
|
3462
|
-
] });
|
|
3463
|
-
}
|
|
3464
|
-
function Thread({
|
|
3465
|
-
placeholder = "Type a message...",
|
|
3466
|
-
starterPrompts: localStarterPrompts,
|
|
3467
|
-
options: localOptions,
|
|
3468
|
-
autoFocus = false,
|
|
3469
|
-
defaultSelectedIds
|
|
3470
|
-
}) {
|
|
3471
|
-
const { activeThreadId, threadEvents, isLoadingEvents } = useThreads();
|
|
3472
|
-
const {
|
|
3473
|
-
messages: initialMessages,
|
|
3474
|
-
isLoading,
|
|
3475
|
-
error,
|
|
3476
|
-
sendEvent,
|
|
3477
|
-
loadingStatus,
|
|
3478
|
-
config
|
|
3479
|
-
} = useMelony({
|
|
3480
|
-
initialEvents: threadEvents
|
|
3481
|
-
});
|
|
3482
|
-
const messages = useMemo(() => {
|
|
3483
|
-
return initialMessages.map((msg) => ({
|
|
3484
|
-
...msg,
|
|
3485
|
-
content: msg.content.filter((event) => !event.surface)
|
|
3486
|
-
})).filter(
|
|
3487
|
-
(msg) => ["user", "assistant"].includes(msg.role) && msg.content.length > 0
|
|
3488
|
-
);
|
|
3489
|
-
}, [initialMessages]);
|
|
3490
|
-
const starterPrompts = localStarterPrompts ?? config?.starterPrompts;
|
|
3491
|
-
const options = localOptions ?? config?.options;
|
|
3492
|
-
const fileAttachments = config?.fileAttachments;
|
|
3493
|
-
const allDefaultSelectedIds = useMemo(() => {
|
|
3494
|
-
const defaultSelectedIdsFromOptions = options?.flatMap((group) => group.defaultSelectedIds ?? []) ?? [];
|
|
3495
|
-
return [
|
|
3496
|
-
.../* @__PURE__ */ new Set([
|
|
3497
|
-
...defaultSelectedIdsFromOptions,
|
|
3498
|
-
...defaultSelectedIds ?? []
|
|
3499
|
-
])
|
|
3500
|
-
];
|
|
3501
|
-
}, [options, defaultSelectedIds]);
|
|
3502
|
-
const [input, setInput] = useState("");
|
|
3503
|
-
const messagesEndRef = useRef(null);
|
|
3504
|
-
useEffect(() => {
|
|
3505
|
-
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3506
|
-
}, [messages]);
|
|
3507
|
-
const handleSubmit = async (state, overrideInput) => {
|
|
3508
|
-
const text = (overrideInput ?? input).trim();
|
|
3509
|
-
const hasFiles = state?.files && Array.isArray(state.files) && state.files.length > 0;
|
|
3510
|
-
if (!text && !hasFiles || isLoading) return;
|
|
3511
|
-
if (!overrideInput) setInput("");
|
|
3512
|
-
await sendEvent({
|
|
3513
|
-
type: "text",
|
|
3514
|
-
role: "user",
|
|
3515
|
-
data: { content: text || "" },
|
|
3516
|
-
state: {
|
|
3517
|
-
...state,
|
|
3518
|
-
threadId: activeThreadId ?? void 0
|
|
3519
|
-
}
|
|
3520
|
-
});
|
|
3521
|
-
};
|
|
3522
|
-
const showStarterPrompts = messages.length === 0 && starterPrompts && starterPrompts.length > 0 && !isLoadingEvents;
|
|
3523
|
-
return /* @__PURE__ */ jsxs(
|
|
3524
|
-
"div",
|
|
3525
|
-
{
|
|
3526
|
-
className: "relative flex flex-col h-full bg-background flex-1 overflow-hidden",
|
|
3527
|
-
children: [
|
|
3528
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-4 pb-36", children: [
|
|
3529
|
-
/* @__PURE__ */ jsx(
|
|
3530
|
-
"div",
|
|
3531
|
-
{
|
|
3532
|
-
className: cn(
|
|
3533
|
-
"max-w-[48rem] mx-auto w-full p-4",
|
|
3534
|
-
showStarterPrompts && "min-h-full flex flex-col"
|
|
3535
|
-
),
|
|
3536
|
-
children: isLoadingEvents && messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx(LoadingIndicator, { status: { message: "Loading messages..." } }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3537
|
-
showStarterPrompts && /* @__PURE__ */ jsx(
|
|
3538
|
-
StarterPrompts,
|
|
3539
|
-
{
|
|
3540
|
-
prompts: starterPrompts
|
|
3541
|
-
}
|
|
3542
|
-
),
|
|
3543
|
-
/* @__PURE__ */ jsx(
|
|
3544
|
-
MessageList,
|
|
3545
|
-
{
|
|
3546
|
-
messages,
|
|
3547
|
-
isLoading,
|
|
3548
|
-
error,
|
|
3549
|
-
loadingStatus
|
|
3550
|
-
}
|
|
3551
|
-
)
|
|
3552
|
-
] })
|
|
3553
|
-
}
|
|
3554
|
-
),
|
|
3555
|
-
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
3556
|
-
] }),
|
|
3557
|
-
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 p-4 w-full", children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto", children: /* @__PURE__ */ jsx(
|
|
3558
|
-
Composer,
|
|
3559
|
-
{
|
|
3560
|
-
value: input,
|
|
3561
|
-
onChange: setInput,
|
|
3562
|
-
onSubmit: handleSubmit,
|
|
3563
|
-
placeholder,
|
|
3564
|
-
isLoading,
|
|
3565
|
-
options,
|
|
3566
|
-
autoFocus,
|
|
3567
|
-
defaultSelectedIds: allDefaultSelectedIds,
|
|
3568
|
-
fileAttachments
|
|
3569
|
-
}
|
|
3570
|
-
) }) })
|
|
3571
|
-
]
|
|
3572
|
-
}
|
|
3573
|
-
);
|
|
3574
|
-
}
|
|
3575
|
-
function ChatHeader({
|
|
3576
|
-
leftContent,
|
|
3577
|
-
rightContent,
|
|
3578
|
-
className,
|
|
3579
|
-
children
|
|
3580
|
-
}) {
|
|
3581
|
-
if (children) {
|
|
3582
|
-
return /* @__PURE__ */ jsx(
|
|
3583
|
-
"div",
|
|
3584
|
-
{
|
|
3585
|
-
className: cn(
|
|
3586
|
-
"px-2 border-b border-border h-14 flex items-center shrink-0",
|
|
3587
|
-
className
|
|
3588
|
-
),
|
|
3589
|
-
children
|
|
3590
|
-
}
|
|
3591
|
-
);
|
|
3592
|
-
}
|
|
3593
|
-
return /* @__PURE__ */ jsxs(
|
|
3594
|
-
"div",
|
|
3595
|
-
{
|
|
3596
|
-
className: cn(
|
|
3597
|
-
"px-2 border-b border-border h-14 flex items-center justify-between shrink-0",
|
|
3598
|
-
className
|
|
3599
|
-
),
|
|
3600
|
-
children: [
|
|
3601
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: leftContent }),
|
|
3602
|
-
rightContent && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 shrink-0 ml-2", children: rightContent })
|
|
3603
|
-
]
|
|
3604
|
-
}
|
|
3605
|
-
);
|
|
3606
|
-
}
|
|
3607
|
-
var ThreadList = ({ padding, background, gap, radius = "md" }) => {
|
|
3608
|
-
const { threads, activeThreadId } = useThreads();
|
|
3609
|
-
const sortedThreads = React3.useMemo(() => {
|
|
3610
|
-
return [...threads].sort((a, b) => {
|
|
3611
|
-
const dateA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
|
|
3612
|
-
const dateB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
|
|
3613
|
-
return dateB - dateA;
|
|
3614
|
-
});
|
|
3615
|
-
}, [threads]);
|
|
3616
|
-
return /* @__PURE__ */ jsx(List, { padding, gap, flex: "1", overflow: "scroll", children: sortedThreads.map((thread) => {
|
|
3617
|
-
thread.id === activeThreadId;
|
|
3618
|
-
return /* @__PURE__ */ jsxs(
|
|
3619
|
-
ListItem,
|
|
3620
|
-
{
|
|
3621
|
-
onClickAction: {
|
|
3622
|
-
type: "client:navigate",
|
|
3623
|
-
data: {
|
|
3624
|
-
url: `?threadId=${thread.id}`
|
|
3625
|
-
}
|
|
3626
|
-
},
|
|
3627
|
-
background,
|
|
3628
|
-
radius,
|
|
3629
|
-
padding,
|
|
3630
|
-
gap,
|
|
3631
|
-
children: [
|
|
3632
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate", children: thread.title || `Thread ${thread.id.slice(0, 8)}` }) }),
|
|
3633
|
-
/* @__PURE__ */ jsx("div", { className: "shrink-0 flex items-center opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx(
|
|
3634
|
-
Dropdown,
|
|
3635
|
-
{
|
|
3636
|
-
items: [
|
|
3637
|
-
{
|
|
3638
|
-
label: "Delete",
|
|
3639
|
-
icon: "trash",
|
|
3640
|
-
onClickAction: {
|
|
3641
|
-
role: "system",
|
|
3642
|
-
type: "delete-thread",
|
|
3643
|
-
data: {
|
|
3644
|
-
threadId: thread.id
|
|
3645
|
-
}
|
|
3646
|
-
}
|
|
3647
|
-
}
|
|
3648
|
-
]
|
|
3649
|
-
}
|
|
3650
|
-
) })
|
|
3651
|
-
]
|
|
3652
|
-
},
|
|
3653
|
-
thread.id
|
|
3654
|
-
);
|
|
3655
|
-
}) });
|
|
3656
|
-
};
|
|
3657
|
-
function PopupChat({
|
|
3658
|
-
title = "Chat",
|
|
3659
|
-
placeholder = "Message the AI",
|
|
3660
|
-
starterPrompts,
|
|
3661
|
-
options,
|
|
3662
|
-
defaultOpen = false,
|
|
3663
|
-
headerProps,
|
|
3664
|
-
defaultSelectedIds
|
|
3665
|
-
}) {
|
|
3666
|
-
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
3667
|
-
const [view, setView] = useState("chat");
|
|
3668
|
-
const { createThread } = useThreads();
|
|
3669
|
-
const handleNewChat = async () => {
|
|
3670
|
-
try {
|
|
3671
|
-
await createThread();
|
|
3672
|
-
setView("chat");
|
|
3673
|
-
} catch (error) {
|
|
3674
|
-
console.error("Failed to create new chat:", error);
|
|
3675
|
-
}
|
|
3676
|
-
};
|
|
3677
|
-
return /* @__PURE__ */ jsxs("div", { className: "fixed bottom-6 right-6 z-50 flex flex-col items-end gap-4 font-sans", children: [
|
|
3678
|
-
isOpen && /* @__PURE__ */ jsxs(Card, { className: "py-0 w-[440px] h-[640px] gap-0 flex flex-col overflow-hidden border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60 shadow-2xl animate-in fade-in zoom-in-95 duration-200 origin-bottom-right", children: [
|
|
3679
|
-
/* @__PURE__ */ jsx(
|
|
3680
|
-
ChatHeader,
|
|
3681
|
-
{
|
|
3682
|
-
title: view === "history" ? "History" : title,
|
|
3683
|
-
leftContent: view === "history" ? /* @__PURE__ */ jsx(
|
|
3684
|
-
Button,
|
|
3685
|
-
{
|
|
3686
|
-
variant: "ghost",
|
|
3687
|
-
size: "icon-xs",
|
|
3688
|
-
onClick: () => setView("chat"),
|
|
3689
|
-
className: "text-muted-foreground hover:text-foreground",
|
|
3690
|
-
children: /* @__PURE__ */ jsx(IconArrowLeft, { className: "size-4" })
|
|
3691
|
-
}
|
|
3692
|
-
) : void 0,
|
|
3693
|
-
rightContent: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3694
|
-
view === "chat" && /* @__PURE__ */ jsx(
|
|
3695
|
-
Button,
|
|
3696
|
-
{
|
|
3697
|
-
variant: "ghost",
|
|
3698
|
-
size: "icon-xs",
|
|
3699
|
-
onClick: () => setView("history"),
|
|
3700
|
-
className: "text-muted-foreground hover:text-foreground",
|
|
3701
|
-
title: "History",
|
|
3702
|
-
children: /* @__PURE__ */ jsx(IconHistory, { className: "size-4" })
|
|
3703
|
-
}
|
|
3704
|
-
),
|
|
3705
|
-
/* @__PURE__ */ jsx(
|
|
3706
|
-
Button,
|
|
3707
|
-
{
|
|
3708
|
-
variant: "ghost",
|
|
3709
|
-
size: "icon-xs",
|
|
3710
|
-
onClick: handleNewChat,
|
|
3711
|
-
className: "text-muted-foreground hover:text-foreground",
|
|
3712
|
-
title: "New Chat",
|
|
3713
|
-
children: /* @__PURE__ */ jsx(IconPlus, { className: "size-4" })
|
|
3714
|
-
}
|
|
3715
|
-
),
|
|
3716
|
-
/* @__PURE__ */ jsx(
|
|
3717
|
-
Button,
|
|
3718
|
-
{
|
|
3719
|
-
variant: "ghost",
|
|
3720
|
-
size: "icon-xs",
|
|
3721
|
-
onClick: () => setIsOpen(false),
|
|
3722
|
-
className: "text-muted-foreground hover:text-foreground",
|
|
3723
|
-
children: /* @__PURE__ */ jsx(IconX, { className: "size-4" })
|
|
3724
|
-
}
|
|
3725
|
-
)
|
|
3726
|
-
] }),
|
|
3727
|
-
...headerProps
|
|
3728
|
-
}
|
|
3729
|
-
),
|
|
3730
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: view === "chat" ? /* @__PURE__ */ jsx(
|
|
3731
|
-
Thread,
|
|
3732
|
-
{
|
|
3733
|
-
placeholder,
|
|
3734
|
-
starterPrompts,
|
|
3735
|
-
options,
|
|
3736
|
-
defaultSelectedIds
|
|
3737
|
-
}
|
|
3738
|
-
) : /* @__PURE__ */ jsx(
|
|
3739
|
-
ThreadList,
|
|
3740
|
-
{
|
|
3741
|
-
padding: "md",
|
|
3742
|
-
gap: "md",
|
|
3743
|
-
background: "muted",
|
|
3744
|
-
radius: "md"
|
|
3745
|
-
}
|
|
3746
|
-
) })
|
|
3747
|
-
] }),
|
|
3748
|
-
/* @__PURE__ */ jsx(
|
|
3749
|
-
Button,
|
|
3750
|
-
{
|
|
3751
|
-
size: "icon-lg",
|
|
3752
|
-
className: cn(
|
|
3753
|
-
"h-14 w-14 rounded-full shadow-2xl transition-all hover:scale-105 active:scale-95",
|
|
3754
|
-
isOpen ? "bg-muted text-muted-foreground hover:bg-muted/80" : "bg-primary text-primary-foreground"
|
|
3755
|
-
),
|
|
3756
|
-
onClick: () => setIsOpen(!isOpen),
|
|
3757
|
-
children: isOpen ? /* @__PURE__ */ jsx(IconX, { className: "size-6" }) : /* @__PURE__ */ jsx(IconMessage, { className: "size-6" })
|
|
3758
|
-
}
|
|
3759
|
-
)
|
|
3760
|
-
] });
|
|
3761
|
-
}
|
|
3762
|
-
function Sidebar({ side, children, width = "1/4" }) {
|
|
3763
|
-
const { leftCollapsed, rightCollapsed } = useSidebar();
|
|
3764
|
-
const collapsed = side === "left" ? leftCollapsed : rightCollapsed;
|
|
3765
|
-
const widthClass = widthMap[width];
|
|
3766
|
-
return /* @__PURE__ */ jsx(
|
|
3767
|
-
"div",
|
|
3768
|
-
{
|
|
3769
|
-
className: cn(
|
|
3770
|
-
"flex-shrink-0 border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3771
|
-
side === "left" ? "border-r" : "border-l",
|
|
3772
|
-
collapsed ? "w-0 border-r-0 border-l-0 min-w-0" : "",
|
|
3773
|
-
!collapsed && widthClass
|
|
3774
|
-
),
|
|
3775
|
-
style: !collapsed && !widthClass ? { width } : void 0,
|
|
3776
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-h-0 flex flex-col", children })
|
|
3777
|
-
}
|
|
3778
|
-
);
|
|
3779
|
-
}
|
|
3780
|
-
function FullChat({
|
|
3781
|
-
title = "Chat",
|
|
3782
|
-
placeholder,
|
|
3783
|
-
starterPrompts,
|
|
3784
|
-
options,
|
|
3785
|
-
className,
|
|
3786
|
-
headerProps,
|
|
3787
|
-
autoFocus = false,
|
|
3788
|
-
defaultSelectedIds
|
|
3789
|
-
}) {
|
|
3790
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full w-full bg-background", className), children: [
|
|
3791
|
-
title && /* @__PURE__ */ jsx(ChatHeader, { title, ...headerProps }),
|
|
3792
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden flex relative", children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsx(
|
|
3793
|
-
Thread,
|
|
3794
|
-
{
|
|
3795
|
-
placeholder,
|
|
3796
|
-
starterPrompts,
|
|
3797
|
-
options,
|
|
3798
|
-
autoFocus,
|
|
3799
|
-
defaultSelectedIds
|
|
3800
|
-
}
|
|
3801
|
-
) }) })
|
|
3802
|
-
] });
|
|
3803
|
-
}
|
|
3804
|
-
function Surface({ name, children }) {
|
|
3805
|
-
const { events } = useSurface({ name });
|
|
3806
|
-
return /* @__PURE__ */ jsx(Fragment, { children: children(events) });
|
|
3807
|
-
}
|
|
3808
|
-
function SidebarToggle({ side, className }) {
|
|
3809
|
-
const {
|
|
3810
|
-
leftCollapsed,
|
|
3811
|
-
rightCollapsed,
|
|
3812
|
-
setLeftCollapsed,
|
|
3813
|
-
setRightCollapsed,
|
|
3814
|
-
leftCollapsible,
|
|
3815
|
-
rightCollapsible
|
|
3816
|
-
} = useSidebar();
|
|
3817
|
-
if (side === "left") {
|
|
3818
|
-
if (!leftCollapsible) return null;
|
|
3819
|
-
return /* @__PURE__ */ jsx(
|
|
3820
|
-
Button,
|
|
3821
|
-
{
|
|
3822
|
-
variant: "ghost",
|
|
3823
|
-
size: "icon",
|
|
3824
|
-
onClick: () => setLeftCollapsed(!leftCollapsed),
|
|
3825
|
-
"aria-label": leftCollapsed ? "Expand left sidebar" : "Collapse left sidebar",
|
|
3826
|
-
className: cn("", className),
|
|
3827
|
-
children: leftCollapsed ? /* @__PURE__ */ jsx(IconLayoutSidebarLeftExpand, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconLayoutSidebarLeftCollapse, { className: "h-4 w-4" })
|
|
3828
|
-
}
|
|
3829
|
-
);
|
|
3830
|
-
}
|
|
3831
|
-
if (side === "right") {
|
|
3832
|
-
if (!rightCollapsible) return null;
|
|
3833
|
-
return /* @__PURE__ */ jsx(
|
|
3834
|
-
Button,
|
|
3835
|
-
{
|
|
3836
|
-
variant: "ghost",
|
|
3837
|
-
size: "icon",
|
|
3838
|
-
onClick: () => setRightCollapsed(!rightCollapsed),
|
|
3839
|
-
"aria-label": rightCollapsed ? "Expand right sidebar" : "Collapse right sidebar",
|
|
3840
|
-
className: cn("", className),
|
|
3841
|
-
children: rightCollapsed ? /* @__PURE__ */ jsx(IconLayoutSidebarRightExpand, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconLayoutSidebarRightCollapse, { className: "h-4 w-4" })
|
|
3842
|
-
}
|
|
3843
|
-
);
|
|
3844
|
-
}
|
|
3845
|
-
return null;
|
|
3846
|
-
}
|
|
3847
|
-
var ThreadPopover = ({}) => {
|
|
3848
|
-
const [isOpen, setIsOpen] = React3.useState(false);
|
|
3849
|
-
useHotkeys(
|
|
3850
|
-
"h",
|
|
3851
|
-
(e) => {
|
|
3852
|
-
e.preventDefault();
|
|
3853
|
-
setIsOpen((prev) => !prev);
|
|
3854
|
-
},
|
|
3855
|
-
{
|
|
3856
|
-
enableOnFormTags: false,
|
|
3857
|
-
// Don't trigger when typing in form inputs
|
|
3858
|
-
enableOnContentEditable: false
|
|
3859
|
-
// Don't trigger in contenteditable elements
|
|
3860
|
-
}
|
|
3861
|
-
);
|
|
3862
|
-
return /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
3863
|
-
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3864
|
-
Button,
|
|
3865
|
-
{
|
|
3866
|
-
variant: "ghost",
|
|
3867
|
-
size: "icon",
|
|
3868
|
-
children: /* @__PURE__ */ jsx(IconHistory, { className: "size-4" })
|
|
3869
|
-
}
|
|
3870
|
-
) }),
|
|
3871
|
-
/* @__PURE__ */ jsx(
|
|
3872
|
-
PopoverContent,
|
|
3873
|
-
{
|
|
3874
|
-
className: "w-80 p-0",
|
|
3875
|
-
side: "bottom",
|
|
3876
|
-
align: "start",
|
|
3877
|
-
sideOffset: 8,
|
|
3878
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex flex-col h-[400px]", children: /* @__PURE__ */ jsx(ThreadList, {}) })
|
|
3879
|
-
}
|
|
3880
|
-
)
|
|
3881
|
-
] });
|
|
3882
|
-
};
|
|
3883
|
-
var CreateThreadButton = ({
|
|
3884
|
-
className,
|
|
3885
|
-
variant = "ghost",
|
|
3886
|
-
size = "default",
|
|
3887
|
-
onThreadCreated
|
|
3888
|
-
}) => {
|
|
3889
|
-
const { createThread } = useThreads();
|
|
3890
|
-
const [isCreating, setIsCreating] = React3.useState(false);
|
|
3891
|
-
const handleCreateThread = async () => {
|
|
3892
|
-
if (isCreating) return;
|
|
3893
|
-
try {
|
|
3894
|
-
setIsCreating(true);
|
|
3895
|
-
const threadId = await createThread();
|
|
3896
|
-
if (threadId) {
|
|
3897
|
-
onThreadCreated?.(threadId);
|
|
3898
|
-
}
|
|
3899
|
-
} catch (error) {
|
|
3900
|
-
console.error("Failed to create thread:", error);
|
|
3901
|
-
} finally {
|
|
3902
|
-
setIsCreating(false);
|
|
3903
|
-
}
|
|
3904
|
-
};
|
|
3905
|
-
useHotkeys(
|
|
3906
|
-
"n",
|
|
3907
|
-
(e) => {
|
|
3908
|
-
e.preventDefault();
|
|
3909
|
-
handleCreateThread();
|
|
3910
|
-
},
|
|
3911
|
-
{
|
|
3912
|
-
enableOnFormTags: false,
|
|
3913
|
-
// Don't trigger when typing in form inputs
|
|
3914
|
-
enableOnContentEditable: false
|
|
3915
|
-
// Don't trigger in contenteditable elements
|
|
3916
|
-
}
|
|
3917
|
-
);
|
|
3918
|
-
return /* @__PURE__ */ jsxs(
|
|
3919
|
-
Button,
|
|
3920
|
-
{
|
|
3921
|
-
variant,
|
|
3922
|
-
size,
|
|
3923
|
-
onClick: handleCreateThread,
|
|
3924
|
-
disabled: isCreating,
|
|
3925
|
-
className: cn(className),
|
|
3926
|
-
children: [
|
|
3927
|
-
/* @__PURE__ */ jsx(IconPlus, { className: "size-4" }),
|
|
3928
|
-
"New chat"
|
|
3929
|
-
]
|
|
3930
|
-
}
|
|
3931
|
-
);
|
|
3932
|
-
};
|
|
3933
|
-
function ThemeToggle() {
|
|
3934
|
-
const { theme, setTheme, resolvedTheme } = useTheme();
|
|
3935
|
-
const cycleTheme = () => {
|
|
3936
|
-
if (theme === "light") {
|
|
3937
|
-
setTheme("dark");
|
|
3938
|
-
} else if (theme === "dark") {
|
|
3939
|
-
setTheme("system");
|
|
3940
|
-
} else {
|
|
3941
|
-
setTheme("light");
|
|
3942
|
-
}
|
|
3943
|
-
};
|
|
3944
|
-
const getIcon = () => {
|
|
3945
|
-
if (theme === "system") {
|
|
3946
|
-
return /* @__PURE__ */ jsx(IconDeviceDesktop, { className: "h-4 w-4" });
|
|
3947
|
-
}
|
|
3948
|
-
return resolvedTheme === "dark" ? /* @__PURE__ */ jsx(IconMoon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconSun, { className: "h-4 w-4" });
|
|
3949
|
-
};
|
|
3950
|
-
const getLabel = () => {
|
|
3951
|
-
if (theme === "system") {
|
|
3952
|
-
return "System";
|
|
3953
|
-
}
|
|
3954
|
-
return resolvedTheme === "dark" ? "Dark" : "Light";
|
|
3955
|
-
};
|
|
3956
|
-
return /* @__PURE__ */ jsx(
|
|
3957
|
-
Button,
|
|
3958
|
-
{
|
|
3959
|
-
variant: "ghost",
|
|
3960
|
-
size: "icon",
|
|
3961
|
-
onClick: cycleTheme,
|
|
3962
|
-
"aria-label": `Toggle theme (current: ${getLabel()})`,
|
|
3963
|
-
title: `Current: ${getLabel()}. Click to cycle: Light \u2192 Dark \u2192 System`,
|
|
3964
|
-
children: getIcon()
|
|
3965
|
-
}
|
|
3966
|
-
);
|
|
3967
|
-
}
|
|
3968
|
-
var CreateThreadListItem = ({
|
|
3969
|
-
padding = "sm",
|
|
3970
|
-
background,
|
|
3971
|
-
radius = "md"
|
|
3972
|
-
}) => {
|
|
3973
|
-
const { createThread } = useThreads();
|
|
3974
|
-
const [isCreating, setIsCreating] = React3.useState(false);
|
|
3975
|
-
const handleCreateThread = async () => {
|
|
3976
|
-
if (isCreating) return;
|
|
3977
|
-
try {
|
|
3978
|
-
setIsCreating(true);
|
|
3979
|
-
const threadId = await createThread();
|
|
3980
|
-
} catch (error) {
|
|
3981
|
-
console.error("Failed to create thread:", error);
|
|
3982
|
-
} finally {
|
|
3983
|
-
setIsCreating(false);
|
|
3984
|
-
}
|
|
3985
|
-
};
|
|
3986
|
-
useHotkeys(
|
|
3987
|
-
"n",
|
|
3988
|
-
(e) => {
|
|
3989
|
-
e.preventDefault();
|
|
3990
|
-
handleCreateThread();
|
|
3991
|
-
},
|
|
3992
|
-
{
|
|
3993
|
-
enableOnFormTags: false,
|
|
3994
|
-
// Don't trigger when typing in form inputs
|
|
3995
|
-
enableOnContentEditable: false
|
|
3996
|
-
// Don't trigger in contenteditable elements
|
|
3997
|
-
}
|
|
3998
|
-
);
|
|
3999
|
-
return /* @__PURE__ */ jsxs(
|
|
4000
|
-
ListItem,
|
|
4001
|
-
{
|
|
4002
|
-
onClickAction: {
|
|
4003
|
-
type: "client:navigate",
|
|
4004
|
-
data: {
|
|
4005
|
-
url: "?"
|
|
4006
|
-
}
|
|
4007
|
-
},
|
|
4008
|
-
padding,
|
|
4009
|
-
background,
|
|
4010
|
-
radius,
|
|
4011
|
-
children: [
|
|
4012
|
-
/* @__PURE__ */ jsx(IconPlus, { className: "size-4" }),
|
|
4013
|
-
"New chat"
|
|
4014
|
-
]
|
|
4015
|
-
}
|
|
4016
|
-
);
|
|
4017
|
-
};
|
|
4018
45
|
|
|
4019
|
-
export {
|
|
46
|
+
export { MelonyContext, MelonyProvider, useMelony };
|
|
4020
47
|
//# sourceMappingURL=index.js.map
|
|
4021
48
|
//# sourceMappingURL=index.js.map
|