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