@melony/ui-shadcn 0.1.3 → 0.1.5

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.js CHANGED
@@ -6,6 +6,7 @@ import { useMelony } from '@melony/react';
6
6
  import * as React3 from 'react';
7
7
  import { createContext, useState, useRef, useEffect, useMemo, useContext } from 'react';
8
8
  import { Dialog as Dialog$1 } from '@base-ui/react/dialog';
9
+ import * as LucideIcons from 'lucide-react';
9
10
  import { mergeProps } from '@base-ui/react/merge-props';
10
11
  import { useRender } from '@base-ui/react/use-render';
11
12
  import { cva } from 'class-variance-authority';
@@ -15,6 +16,9 @@ import { createPortal } from 'react-dom';
15
16
  import { Button as Button$1 } from '@base-ui/react/button';
16
17
  import { MelonyRenderer } from '@melony/ui-kit';
17
18
  import { Menu } from '@base-ui/react/menu';
19
+ import ReactMarkdown from 'react-markdown';
20
+ import remarkGfm from 'remark-gfm';
21
+ import remarkBreaks from 'remark-breaks';
18
22
 
19
23
  // src/lib/utils.ts
20
24
  function cn(...inputs) {
@@ -31,7 +35,7 @@ function Card({
31
35
  "data-slot": "card",
32
36
  "data-size": size,
33
37
  className: cn(
34
- "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",
38
+ "ring-foreground/10 bg-card text-card-foreground gap-2 overflow-hidden rounded-2xl py-2 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",
35
39
  className
36
40
  ),
37
41
  ...props
@@ -44,7 +48,7 @@ function CardHeader({ className, ...props }) {
44
48
  {
45
49
  "data-slot": "card-header",
46
50
  className: cn(
47
- "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]",
51
+ "gap-2 rounded-t-xl px-4 group-data-[size=sm]/card:px-4 [.border-b]:pb-2 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]",
48
52
  className
49
53
  ),
50
54
  ...props
@@ -261,6 +265,22 @@ var fontWeightMap = {
261
265
  semibold: "font-semibold",
262
266
  bold: "font-bold"
263
267
  };
268
+ var resolveUIStyle = (property, value) => {
269
+ if (!value) return {};
270
+ const [colorName, opacityStr] = value.split("/");
271
+ if (!opacityStr && (colorBgMap[value] || colorTextMap[value] || colorBorderMap[value])) {
272
+ return {};
273
+ }
274
+ const opacity = opacityStr ? parseInt(opacityStr, 10) / 100 : 1;
275
+ const kebabName = colorName.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
276
+ const variable = `var(--color-${kebabName}, var(--${kebabName}))`;
277
+ if (opacity === 1) {
278
+ return { [property]: variable };
279
+ }
280
+ return {
281
+ [property]: `color-mix(in oklch, ${variable}, transparent ${100 - opacity * 100}%)`
282
+ };
283
+ };
264
284
  var Card2 = ({
265
285
  children,
266
286
  title,
@@ -274,31 +294,35 @@ var Card2 = ({
274
294
  Card,
275
295
  {
276
296
  className: cn(
277
- "min-w-96 relative",
297
+ "w-full max-w-full relative overflow-hidden transition-all duration-200",
278
298
  background && colorBgMap[background],
279
299
  radius && radiusMap[radius],
280
- shadow && shadowMap[shadow]
300
+ shadow && shadowMap[shadow],
301
+ !shadow && "shadow-sm border border-border/40"
281
302
  ),
282
303
  children: [
283
- (title || subtitle) && /* @__PURE__ */ jsxs(CardHeader, { className: "pb-3", children: [
284
- title && /* @__PURE__ */ jsx(CardTitle, { className: "text-lg", children: title }),
285
- subtitle && /* @__PURE__ */ jsx(CardDescription, { children: subtitle })
304
+ (title || subtitle) && /* @__PURE__ */ jsxs(CardHeader, { className: "py-2.5 px-3 space-y-0.5 border-b border-border/40 bg-muted/5", children: [
305
+ title && /* @__PURE__ */ jsx(CardTitle, { className: "text-sm font-semibold tracking-tight leading-none", children: title }),
306
+ subtitle && /* @__PURE__ */ jsx(CardDescription, { className: "text-xs leading-tight text-muted-foreground/80", children: subtitle })
286
307
  ] }),
287
- /* @__PURE__ */ jsx(CardContent, { className: cn("flex flex-col gap-4", paddingMap[padding]), children })
308
+ /* @__PURE__ */ jsx(CardContent, { className: cn("flex flex-col gap-2", paddingMap[padding]), children })
288
309
  ]
289
310
  }
290
311
  );
291
312
  };
292
- var Row = ({
293
- children,
294
- align = "start",
295
- justify = "start",
296
- wrap = "nowrap",
297
- gap = "none",
298
- padding = "none",
299
- width = "full",
300
- height = "auto"
301
- }) => {
313
+ var Row = (props) => {
314
+ const {
315
+ children,
316
+ align = "start",
317
+ justify = "start",
318
+ wrap = "nowrap",
319
+ gap = "none",
320
+ padding = "none",
321
+ width = "full",
322
+ height = "auto",
323
+ flex = void 0,
324
+ overflow = "hidden"
325
+ } = props;
302
326
  return /* @__PURE__ */ jsx(
303
327
  "div",
304
328
  {
@@ -312,22 +336,25 @@ var Row = ({
312
336
  widthMap[width],
313
337
  height === "full" && "h-full"
314
338
  ),
315
- style: { width: width && typeof width === "number" ? `${width}px` : void 0 },
339
+ style: { flex, width: width && typeof width === "number" ? `${width}px` : void 0, overflow },
316
340
  children
317
341
  }
318
342
  );
319
343
  };
320
- var Col = ({
321
- children,
322
- align = "start",
323
- justify = "start",
324
- gap = "none",
325
- width = "auto",
326
- height = "auto",
327
- padding = "none",
328
- background,
329
- radius
330
- }) => {
344
+ var Col = (props) => {
345
+ const {
346
+ children,
347
+ align = "start",
348
+ justify = "start",
349
+ gap = "none",
350
+ width = "auto",
351
+ height = "auto",
352
+ padding = "none",
353
+ background,
354
+ radius,
355
+ flex = void 0,
356
+ overflow = "hidden"
357
+ } = props;
331
358
  return /* @__PURE__ */ jsx(
332
359
  "div",
333
360
  {
@@ -342,28 +369,37 @@ var Col = ({
342
369
  background && colorBgMap[background],
343
370
  radius && radiusMap[radius]
344
371
  ),
345
- style: { width: width && typeof width === "number" ? `${width}px` : void 0 },
372
+ style: { flex, width: width && typeof width === "number" ? `${width}px` : void 0, overflow },
346
373
  children
347
374
  }
348
375
  );
349
376
  };
350
- var Box = ({
351
- children,
352
- padding,
353
- paddingVertical,
354
- paddingHorizontal,
355
- margin,
356
- marginVertical,
357
- marginHorizontal,
358
- background,
359
- border = false,
360
- borderColor = "border",
361
- radius = "none",
362
- width = "auto",
363
- height = "auto",
364
- shadow = "none",
365
- group = false
366
- }) => {
377
+ var Box = (props) => {
378
+ const {
379
+ children,
380
+ padding,
381
+ paddingVertical,
382
+ paddingHorizontal,
383
+ margin,
384
+ marginVertical,
385
+ marginHorizontal,
386
+ background,
387
+ border = false,
388
+ borderColor = "border",
389
+ radius = "none",
390
+ width = "auto",
391
+ height = "auto",
392
+ shadow = "none",
393
+ group = false,
394
+ flex = void 0,
395
+ overflow = "hidden"
396
+ } = props;
397
+ const [baseBgColor] = (background || "").split("/");
398
+ const [baseBorderColor] = (borderColor || "").split("/");
399
+ const dynamicStyles = {
400
+ ...resolveUIStyle("backgroundColor", background),
401
+ ...resolveUIStyle("borderColor", borderColor)
402
+ };
367
403
  return /* @__PURE__ */ jsx(
368
404
  "div",
369
405
  {
@@ -375,16 +411,21 @@ var Box = ({
375
411
  marginVertical && marginVerticalMap[marginVertical],
376
412
  marginHorizontal && marginHorizontalMap[marginHorizontal],
377
413
  margin && marginMap[margin],
378
- background && colorBgMap[background],
414
+ baseBgColor && colorBgMap[baseBgColor],
379
415
  border && "border",
380
- border && colorBorderMap[borderColor],
416
+ baseBorderColor && colorBorderMap[baseBorderColor],
381
417
  radiusMap[radius],
382
418
  widthMap[width],
383
419
  height === "full" && "h-full",
384
420
  shadowMap[shadow],
385
421
  group && "group"
386
422
  ),
387
- style: { width: width && typeof width === "number" ? `${width}px` : void 0 },
423
+ style: {
424
+ ...dynamicStyles,
425
+ flex,
426
+ width: width && typeof width === "number" ? `${width}px` : void 0,
427
+ overflow
428
+ },
388
429
  children
389
430
  }
390
431
  );
@@ -468,16 +509,17 @@ var Divider = ({
468
509
  }
469
510
  );
470
511
  };
471
- var List = ({ children, padding = "none", gap = "none", flex, overflow }) => {
512
+ var List = ({ children, padding = "none", gap = "none", flex, overflow, width }) => {
472
513
  return /* @__PURE__ */ jsx(
473
514
  "div",
474
515
  {
475
516
  className: cn(
476
517
  "flex flex-col list-none m-0",
477
518
  paddingMap[padding],
478
- gapMap[gap]
519
+ gapMap[gap],
520
+ widthMap[width]
479
521
  ),
480
- style: { flex, overflow },
522
+ style: { flex, overflow, width: width && typeof width === "number" ? `${width}px` : void 0 },
481
523
  children
482
524
  }
483
525
  );
@@ -567,18 +609,20 @@ function DialogClose({ className, ...props }) {
567
609
  }
568
610
  );
569
611
  }
570
- var Icon = ({
571
- name,
572
- size = "md",
573
- color,
574
- className
575
- }) => {
612
+ var Icon = (props) => {
613
+ const {
614
+ name,
615
+ size = "md",
616
+ color,
617
+ className
618
+ } = props;
576
619
  const sizeMap = {
577
620
  sm: "14px",
578
621
  md: "18px",
579
622
  lg: "24px"
580
623
  };
581
624
  const resolvedSize = typeof size === "number" ? `${size}px` : sizeMap[size] || "18px";
625
+ const LucideIcon = LucideIcons[name];
582
626
  return /* @__PURE__ */ jsx(
583
627
  "div",
584
628
  {
@@ -595,7 +639,7 @@ var Icon = ({
595
639
  alignItems: "center",
596
640
  justifyContent: "center"
597
641
  },
598
- children: name
642
+ children: LucideIcon ? /* @__PURE__ */ jsx(LucideIcon, { size: resolvedSize }) : name
599
643
  }
600
644
  );
601
645
  };
@@ -1066,13 +1110,15 @@ var Chart = ({
1066
1110
  renderChart()
1067
1111
  ] });
1068
1112
  };
1069
- var Text = ({
1070
- value,
1071
- size = "md",
1072
- weight = "normal",
1073
- align = "start",
1074
- color = "foreground"
1075
- }) => {
1113
+ var Text = (props) => {
1114
+ const {
1115
+ value,
1116
+ size = "md",
1117
+ weight = "normal",
1118
+ align = "start",
1119
+ color = "foreground",
1120
+ className
1121
+ } = props;
1076
1122
  return /* @__PURE__ */ jsx(
1077
1123
  "span",
1078
1124
  {
@@ -1080,7 +1126,8 @@ var Text = ({
1080
1126
  textSizeMap[size],
1081
1127
  fontWeightMap[weight],
1082
1128
  textAlignMap[align],
1083
- colorTextMap[color]
1129
+ colorTextMap[color],
1130
+ className
1084
1131
  ),
1085
1132
  children: value
1086
1133
  }
@@ -1094,12 +1141,12 @@ var Heading = ({
1094
1141
  }) => {
1095
1142
  const Tag = `h${level}`;
1096
1143
  const levelClasses = {
1097
- h1: "text-3xl font-bold tracking-tight",
1098
- h2: "text-2xl font-semibold tracking-tight",
1099
- h3: "text-xl font-semibold tracking-tight",
1100
- h4: "text-lg font-semibold tracking-tight",
1101
- h5: "text-base font-semibold",
1102
- h6: "text-sm font-semibold"
1144
+ h1: "text-2xl font-bold tracking-tight",
1145
+ h2: "text-xl font-semibold tracking-tight",
1146
+ h3: "text-lg font-semibold tracking-tight",
1147
+ h4: "text-base font-semibold tracking-tight",
1148
+ h5: "text-sm font-semibold",
1149
+ h6: "text-xs font-semibold"
1103
1150
  };
1104
1151
  return /* @__PURE__ */ jsx(
1105
1152
  Tag,
@@ -1946,27 +1993,17 @@ function Button({
1946
1993
  }
1947
1994
  );
1948
1995
  }
1949
-
1950
- // src/elements/helpers.ts
1951
- var widthMap2 = {
1952
- full: "w-full",
1953
- auto: "w-auto",
1954
- "1/2": "w-1/2",
1955
- "1/3": "w-1/3",
1956
- "2/3": "w-2/3",
1957
- "1/4": "w-1/4",
1958
- "3/4": "w-3/4"
1959
- };
1960
- var Button2 = ({
1961
- type = "button",
1962
- label,
1963
- variant = "primary",
1964
- size = "md",
1965
- disabled = false,
1966
- width,
1967
- onClickAction,
1968
- justify = "center"
1969
- }) => {
1996
+ var Button2 = (props) => {
1997
+ const {
1998
+ type = "button",
1999
+ label,
2000
+ variant = "primary",
2001
+ size = "md",
2002
+ disabled = false,
2003
+ width,
2004
+ onClickAction,
2005
+ justify = "center"
2006
+ } = props;
1970
2007
  const { send } = useMelony();
1971
2008
  const variantMap = {
1972
2009
  primary: "default",
@@ -1985,7 +2022,7 @@ var Button2 = ({
1985
2022
  variant: variantMap[variant] || "default",
1986
2023
  size: size === "md" ? "default" : size,
1987
2024
  disabled,
1988
- className: cn(width && widthMap2[width], justifyMap[justify]),
2025
+ className: cn(width && widthMap[width], justifyMap[justify]),
1989
2026
  onClick: () => {
1990
2027
  if (onClickAction) {
1991
2028
  send(onClickAction);
@@ -2265,7 +2302,7 @@ function Composer({
2265
2302
  onSubmit();
2266
2303
  }
2267
2304
  };
2268
- return /* @__PURE__ */ jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col w-full border-input border-[1.5px] rounded-3xl bg-background shadow-sm focus-within:border-ring transition-all p-2", children: [
2305
+ return /* @__PURE__ */ jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col w-full border-border/60 border rounded-[26px] bg-muted/30 focus-within:bg-background focus-within:border-border focus-within:ring-[3px] focus-within:ring-primary/5 transition-all p-1.5 px-2", children: [
2269
2306
  /* @__PURE__ */ jsx(
2270
2307
  Textarea,
2271
2308
  {
@@ -2273,32 +2310,34 @@ function Composer({
2273
2310
  onChange: (e) => onChange(e.target.value),
2274
2311
  onKeyDown: handleKeyDown,
2275
2312
  placeholder,
2276
- 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",
2313
+ 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 leading-relaxed",
2277
2314
  autoFocus
2278
2315
  }
2279
2316
  ),
2280
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
2281
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1" }),
2317
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center pb-1", children: [
2318
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 px-2" }),
2282
2319
  streaming ? /* @__PURE__ */ jsx(
2283
2320
  Button,
2284
2321
  {
2285
2322
  type: "button",
2286
- variant: "outline",
2287
- size: "default",
2323
+ variant: "ghost",
2324
+ size: "icon",
2325
+ className: "h-8 w-8 rounded-full border border-border/40 hover:bg-muted",
2288
2326
  onClick: () => onStop?.(),
2289
- children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
2290
- /* @__PURE__ */ jsx("span", { className: "w-2.5 h-2.5 bg-foreground rounded-[2px]" }),
2291
- "Stop"
2292
- ] })
2327
+ children: /* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 bg-foreground rounded-[1px]" })
2293
2328
  }
2294
2329
  ) : /* @__PURE__ */ jsx(
2295
2330
  Button,
2296
2331
  {
2297
2332
  type: "submit",
2298
2333
  disabled: !value.trim(),
2299
- size: "default",
2334
+ size: "icon",
2335
+ className: cn(
2336
+ "h-8 w-8 rounded-full transition-all duration-300",
2337
+ value.trim() ? "bg-foreground text-background hover:opacity-90" : "bg-muted text-muted-foreground opacity-50"
2338
+ ),
2300
2339
  onClick: () => onSubmit(),
2301
- children: /* @__PURE__ */ jsx("span", { children: "Send" })
2340
+ children: /* @__PURE__ */ jsx(Icon, { name: "ArrowUp", size: 18 })
2302
2341
  }
2303
2342
  )
2304
2343
  ] })
@@ -2310,7 +2349,7 @@ function MessageContent({ content }) {
2310
2349
  const flushText = (key) => {
2311
2350
  if (currentTextBlock.length > 0) {
2312
2351
  elements.push(
2313
- /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap", children: currentTextBlock.join("") }, `text-${key}`)
2352
+ /* @__PURE__ */ jsx("div", { className: "prose prose-sm dark:prose-invert max-w-none break-words [&>p]:mb-2 [&>p:last-child]:mb-0 [&>ul]:list-disc [&>ul]:pl-4 [&>ol]:list-decimal [&>ol]:pl-4 [&>li]:mb-1 [&>h1]:text-xl [&>h1]:font-bold [&>h1]:mb-2 [&>h2]:text-lg [&>h2]:font-bold [&>h2]:mb-2 [&>h3]:text-base [&>h3]:font-bold [&>h3]:mb-2 [&>pre]:bg-muted [&>pre]:p-2 [&>pre]:rounded [&>pre]:overflow-x-auto [&>pre]:mb-2 [&>code]:bg-muted [&>code]:px-1 [&>code]:py-0.5 [&>code]:rounded [&>code]:font-mono [&>code]:text-sm", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm, remarkBreaks], children: currentTextBlock.join("") }) }, `text-${key}`)
2314
2353
  );
2315
2354
  currentTextBlock = [];
2316
2355
  }
@@ -2330,16 +2369,16 @@ function MessageContent({ content }) {
2330
2369
  }
2331
2370
  });
2332
2371
  flushText(content.length);
2333
- return /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-4", children: elements });
2372
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-2.5", children: elements });
2334
2373
  }
2335
2374
  function MessageBubble({ message }) {
2336
2375
  const isUser = message.role === "user";
2337
- return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", isUser ? "items-end" : "items-start"), children: /* @__PURE__ */ jsx(
2376
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col w-full", isUser ? "items-end" : "items-start"), children: /* @__PURE__ */ jsx(
2338
2377
  "div",
2339
2378
  {
2340
2379
  className: cn(
2341
- "flex flex-col items-start max-w-[85%] rounded-2xl px-4 py-2 space-y-4 whitespace-pre-wrap",
2342
- isUser ? "bg-primary text-primary-foreground" : "px-0 py-0 text-foreground"
2380
+ "flex flex-col items-start max-w-[85%] transition-all duration-200",
2381
+ isUser ? "bg-muted/80 text-foreground px-3 py-1.5 rounded-lg" : "px-0 py-0 text-foreground w-full"
2343
2382
  ),
2344
2383
  children: /* @__PURE__ */ jsx(MessageContent, { content: message.content })
2345
2384
  }
@@ -2364,9 +2403,7 @@ function Thread({
2364
2403
  placeholder = "Type a message...",
2365
2404
  messages: propMessages,
2366
2405
  autoFocus = false,
2367
- welcomeTitle,
2368
- welcomeMessage,
2369
- suggestions
2406
+ children
2370
2407
  }) {
2371
2408
  const {
2372
2409
  streaming,
@@ -2395,30 +2432,15 @@ function Thread({
2395
2432
  data: { content: text || "" }
2396
2433
  });
2397
2434
  };
2398
- return /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col h-full bg-background flex-1 overflow-hidden", children: [
2435
+ return /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col h-full flex-1 overflow-hidden", children: [
2399
2436
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-4 pb-36", children: [
2400
2437
  /* @__PURE__ */ jsx(
2401
2438
  "div",
2402
2439
  {
2403
2440
  className: cn(
2404
- "max-w-3xl mx-auto w-full p-8"
2441
+ "max-w-3xl mx-auto w-full p-4"
2405
2442
  ),
2406
- children: messages.length === 0 && !streaming && (welcomeTitle || welcomeMessage || suggestions) ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start justify-center min-h-[50vh] space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-1000", children: [
2407
- welcomeTitle && /* @__PURE__ */ jsx("h1", { className: "text-4xl md:text-5xl font-bold pb-2", children: welcomeTitle }),
2408
- welcomeMessage && /* @__PURE__ */ jsx("p", { className: "text-xl text-muted-foreground max-w-lg", children: welcomeMessage }),
2409
- suggestions && suggestions.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3 w-full max-w-2xl mt-8", children: suggestions.map((suggestion, i) => /* @__PURE__ */ jsxs(
2410
- "button",
2411
- {
2412
- onClick: () => handleSubmit({}, suggestion),
2413
- className: "flex items-center justify-between p-4 rounded-2xl border bg-card hover:bg-accent hover:border-accent-foreground/20 transition-all text-left group",
2414
- children: [
2415
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: suggestion }),
2416
- /* @__PURE__ */ jsx(Icon, { name: "\u2728", size: "sm", className: "text-muted-foreground group-hover:text-primary transition-colors" })
2417
- ]
2418
- },
2419
- i
2420
- )) })
2421
- ] }) : /* @__PURE__ */ jsx(
2443
+ children: messages.length === 0 && !streaming && children ? /* @__PURE__ */ jsx("div", { className: "flex flex-col items-start justify-center min-h-[50vh] space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-1000", children }) : /* @__PURE__ */ jsx(
2422
2444
  MessageList,
2423
2445
  {
2424
2446
  messages,
@@ -2433,18 +2455,21 @@ function Thread({
2433
2455
  ),
2434
2456
  /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
2435
2457
  ] }),
2436
- /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 p-4 w-full", children: /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto", children: /* @__PURE__ */ jsx(
2437
- Composer,
2438
- {
2439
- value: input,
2440
- onChange: setInput,
2441
- onSubmit: handleSubmit,
2442
- onStop: stop,
2443
- placeholder,
2444
- streaming,
2445
- autoFocus
2446
- }
2447
- ) }) })
2458
+ /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 p-4 w-full bg-gradient-to-t from-background via-background/90 to-transparent", children: /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto", children: [
2459
+ /* @__PURE__ */ jsx(
2460
+ Composer,
2461
+ {
2462
+ value: input,
2463
+ onChange: setInput,
2464
+ onSubmit: handleSubmit,
2465
+ onStop: stop,
2466
+ placeholder,
2467
+ streaming,
2468
+ autoFocus
2469
+ }
2470
+ ),
2471
+ /* @__PURE__ */ jsx("div", { className: "mt-2 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground/60", children: "Melony can make mistakes. Check important info." }) })
2472
+ ] }) })
2448
2473
  ] });
2449
2474
  }
2450
2475
  var ThemeContext = createContext(void 0);
@@ -2499,6 +2524,31 @@ function useTheme() {
2499
2524
  }
2500
2525
  return context;
2501
2526
  }
2527
+ function ThemeToggle() {
2528
+ const { theme, setTheme } = useTheme();
2529
+ const themes = [
2530
+ { name: "light", icon: "Sun", label: "Light" },
2531
+ { name: "dark", icon: "Moon", label: "Dark" },
2532
+ { name: "system", icon: "Monitor", label: "System" }
2533
+ ];
2534
+ return /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-1 rounded-full border bg-muted/50 p-1", children: themes.map((t) => /* @__PURE__ */ jsxs(
2535
+ Button,
2536
+ {
2537
+ variant: theme === t.name ? "secondary" : "ghost",
2538
+ size: "icon-xs",
2539
+ onClick: () => setTheme(t.name),
2540
+ className: cn(
2541
+ "rounded-full transition-all",
2542
+ theme === t.name && "shadow-xs bg-background hover:bg-background"
2543
+ ),
2544
+ children: [
2545
+ /* @__PURE__ */ jsx(Icon, { name: t.icon, size: "sm" }),
2546
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t.label })
2547
+ ]
2548
+ },
2549
+ t.name
2550
+ )) });
2551
+ }
2502
2552
 
2503
2553
  // src/index.ts
2504
2554
  var shadcnElements = {
@@ -2530,7 +2580,8 @@ var shadcnElements = {
2530
2580
  label: Label2,
2531
2581
  upload: Upload,
2532
2582
  dropdown: Dropdown,
2533
- thread: Thread
2583
+ thread: Thread,
2584
+ themeToggle: ThemeToggle
2534
2585
  };
2535
2586
  var ThemeProvider2 = ThemeProvider;
2536
2587
  var useTheme2 = useTheme;