@melony/ui-shadcn 0.1.1 → 0.1.2

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.d.ts CHANGED
@@ -1,5 +1,19 @@
1
1
  import { MelonyComponents } from '@melony/ui-kit';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+
4
+ type Theme = "light" | "dark" | "system";
5
+ interface ThemeContextType {
6
+ theme: Theme;
7
+ setTheme: (theme: Theme) => void;
8
+ resolvedTheme: "light" | "dark";
9
+ }
10
+ declare function ThemeProvider$1({ children }: {
11
+ children: React.ReactNode;
12
+ }): react_jsx_runtime.JSX.Element;
13
+ declare function useTheme$1(): ThemeContextType;
2
14
 
3
15
  declare const shadcnElements: Partial<MelonyComponents>;
16
+ declare const ThemeProvider: typeof ThemeProvider$1;
17
+ declare const useTheme: typeof useTheme$1;
4
18
 
5
- export { shadcnElements };
19
+ export { ThemeProvider, shadcnElements, useTheme };
package/dist/index.js CHANGED
@@ -4,10 +4,8 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { Separator as Separator$1 } from '@base-ui/react/separator';
5
5
  import { useMelony } from '@melony/react';
6
6
  import * as React3 from 'react';
7
- import { useState, useRef, useEffect, useMemo } from 'react';
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 ICONS from '@tabler/icons-react';
10
- import { IconX, IconChevronLeft, IconChevronRight, IconLoader2, IconCheck, IconUpload, IconDotsVertical, IconSparkles, IconSelector, IconArrowUp, IconChevronUp, IconChevronDown } from '@tabler/icons-react';
11
9
  import { mergeProps } from '@base-ui/react/merge-props';
12
10
  import { useRender } from '@base-ui/react/use-render';
13
11
  import { cva } from 'class-variance-authority';
@@ -511,6 +509,38 @@ function DialogClose({ className, ...props }) {
511
509
  }
512
510
  );
513
511
  }
512
+ var Icon = ({
513
+ name,
514
+ size = "md",
515
+ color,
516
+ className
517
+ }) => {
518
+ const sizeMap = {
519
+ sm: "14px",
520
+ md: "18px",
521
+ lg: "24px"
522
+ };
523
+ const resolvedSize = typeof size === "number" ? `${size}px` : sizeMap[size] || "18px";
524
+ return /* @__PURE__ */ jsx(
525
+ "div",
526
+ {
527
+ className: cn(
528
+ "inline-flex items-center justify-center leading-none",
529
+ color && colorTextMap[color],
530
+ className
531
+ ),
532
+ style: {
533
+ fontSize: resolvedSize,
534
+ width: resolvedSize,
535
+ height: resolvedSize,
536
+ display: "inline-flex",
537
+ alignItems: "center",
538
+ justifyContent: "center"
539
+ },
540
+ children: name
541
+ }
542
+ );
543
+ };
514
544
  var Image = ({
515
545
  src,
516
546
  alt,
@@ -606,7 +636,7 @@ var Image = ({
606
636
  className: "max-w-[90vw] max-h-[90vh] p-0 bg-transparent border-none shadow-none outline-none",
607
637
  onClick: (e) => e.stopPropagation(),
608
638
  children: /* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center group/lightbox", children: [
609
- /* @__PURE__ */ jsx(DialogClose, { className: "absolute -top-12 right-0 text-white hover:text-gray-300 transition-colors z-50 bg-black/50 rounded-full p-2", children: /* @__PURE__ */ jsx(IconX, { size: 20 }) }),
639
+ /* @__PURE__ */ jsx(DialogClose, { className: "absolute -top-12 right-0 text-white hover:text-gray-300 transition-colors z-50 bg-black/50 rounded-full p-2", children: /* @__PURE__ */ jsx(Icon, { name: "\u274C", size: 20 }) }),
610
640
  hasMultiple && /* @__PURE__ */ jsxs(Fragment, { children: [
611
641
  /* @__PURE__ */ jsx(
612
642
  "button",
@@ -616,7 +646,7 @@ var Image = ({
616
646
  navigate(-1);
617
647
  },
618
648
  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",
619
- children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 28 })
649
+ children: /* @__PURE__ */ jsx(Icon, { name: "\u25C0\uFE0F", size: 28 })
620
650
  }
621
651
  ),
622
652
  /* @__PURE__ */ jsx(
@@ -627,7 +657,7 @@ var Image = ({
627
657
  navigate(1);
628
658
  },
629
659
  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",
630
- children: /* @__PURE__ */ jsx(IconChevronRight, { size: 28 })
660
+ children: /* @__PURE__ */ jsx(Icon, { name: "\u25B6\uFE0F", size: 28 })
631
661
  }
632
662
  )
633
663
  ] }),
@@ -693,32 +723,6 @@ var Video = ({
693
723
  }
694
724
  );
695
725
  };
696
- var Icon = ({
697
- name,
698
- size = "md",
699
- color,
700
- className
701
- }) => {
702
- const IconComponent = ICONS[name];
703
- if (!IconComponent) return null;
704
- const sizeMap = {
705
- sm: 16,
706
- md: 20,
707
- lg: 24
708
- };
709
- const resolvedSize = typeof size === "number" ? size : sizeMap[size] || 20;
710
- return /* @__PURE__ */ jsx(
711
- "div",
712
- {
713
- className: cn(
714
- "inline-flex items-center justify-center",
715
- color && colorTextMap[color],
716
- className
717
- ),
718
- children: /* @__PURE__ */ jsx(IconComponent, { size: resolvedSize, strokeWidth: 1.5 })
719
- }
720
- );
721
- };
722
726
  var badgeVariants = cva(
723
727
  "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",
724
728
  {
@@ -1253,7 +1257,7 @@ function SelectTrigger({
1253
1257
  /* @__PURE__ */ jsx(
1254
1258
  Select$1.Icon,
1255
1259
  {
1256
- render: /* @__PURE__ */ jsx(IconSelector, { className: "text-muted-foreground size-4 pointer-events-none" })
1260
+ render: /* @__PURE__ */ jsx(Icon, { name: "\u2195\uFE0F", className: "text-muted-foreground pointer-events-none" })
1257
1261
  }
1258
1262
  )
1259
1263
  ]
@@ -1318,7 +1322,7 @@ function SelectItem({
1318
1322
  Select$1.ItemIndicator,
1319
1323
  {
1320
1324
  render: /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }),
1321
- children: /* @__PURE__ */ jsx(IconCheck, { className: "pointer-events-none" })
1325
+ children: /* @__PURE__ */ jsx(Icon, { name: "\u2705", className: "pointer-events-none" })
1322
1326
  }
1323
1327
  )
1324
1328
  ]
@@ -1338,7 +1342,7 @@ function SelectScrollUpButton({
1338
1342
  className
1339
1343
  ),
1340
1344
  ...props,
1341
- children: /* @__PURE__ */ jsx(IconChevronUp, {})
1345
+ children: /* @__PURE__ */ jsx(Icon, { name: "\u{1F53C}" })
1342
1346
  }
1343
1347
  );
1344
1348
  }
@@ -1355,7 +1359,7 @@ function SelectScrollDownButton({
1355
1359
  className
1356
1360
  ),
1357
1361
  ...props,
1358
- children: /* @__PURE__ */ jsx(IconChevronDown, {})
1362
+ children: /* @__PURE__ */ jsx(Icon, { name: "\u{1F53D}" })
1359
1363
  }
1360
1364
  );
1361
1365
  }
@@ -2043,7 +2047,7 @@ var Upload = ({
2043
2047
  onClick: () => fileInputRef.current?.click(),
2044
2048
  variant: "default",
2045
2049
  children: [
2046
- isUploading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-4 w-4 animate-spin mr-2" }) : status === "success" ? /* @__PURE__ */ jsx(IconCheck, { className: "h-4 w-4 text-green-500 mr-2" }) : status === "error" ? /* @__PURE__ */ jsx(IconX, { className: "h-4 w-4 mr-2" }) : /* @__PURE__ */ jsx(IconUpload, { className: "h-4 w-4 mr-2" }),
2050
+ isUploading ? /* @__PURE__ */ jsx(Icon, { name: "\u23F3", size: "sm", className: "animate-spin mr-2" }) : status === "success" ? /* @__PURE__ */ jsx(Icon, { name: "\u2705", size: "sm", className: "mr-2" }) : status === "error" ? /* @__PURE__ */ jsx(Icon, { name: "\u274C", size: "sm", className: "mr-2" }) : /* @__PURE__ */ jsx(Icon, { name: "\u{1F4E4}", size: "sm", className: "mr-2" }),
2047
2051
  status === "success" ? "Uploaded" : status === "error" ? "Failed" : label
2048
2052
  ]
2049
2053
  }
@@ -2161,7 +2165,7 @@ var Dropdown = ({ items = [], children }) => {
2161
2165
  e.stopPropagation();
2162
2166
  props.onClick?.(e);
2163
2167
  },
2164
- children: children || /* @__PURE__ */ jsx(IconDotsVertical, { className: "size-3.5" })
2168
+ children: children || /* @__PURE__ */ jsx(Icon, { name: "\u22EE", size: "sm" })
2165
2169
  }
2166
2170
  )
2167
2171
  }
@@ -2188,6 +2192,7 @@ function Composer({
2188
2192
  value,
2189
2193
  onChange,
2190
2194
  onSubmit,
2195
+ onStop,
2191
2196
  placeholder = "Type a message...",
2192
2197
  streaming,
2193
2198
  className,
@@ -2213,14 +2218,26 @@ function Composer({
2213
2218
  ),
2214
2219
  /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-1", children: [
2215
2220
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1" }),
2216
- /* @__PURE__ */ jsx(
2221
+ streaming ? /* @__PURE__ */ jsx(
2222
+ Button,
2223
+ {
2224
+ type: "button",
2225
+ variant: "outline",
2226
+ size: "default",
2227
+ onClick: () => onStop?.(),
2228
+ children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
2229
+ /* @__PURE__ */ jsx("span", { className: "w-2.5 h-2.5 bg-foreground rounded-[2px]" }),
2230
+ "Stop"
2231
+ ] })
2232
+ }
2233
+ ) : /* @__PURE__ */ jsx(
2217
2234
  Button,
2218
2235
  {
2219
2236
  type: "submit",
2220
- disabled: !value.trim() || streaming,
2221
- size: "icon-lg",
2237
+ disabled: !value.trim(),
2238
+ size: "default",
2222
2239
  onClick: () => onSubmit(),
2223
- children: streaming ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsx(IconArrowUp, { className: "h-5 w-5" })
2240
+ children: /* @__PURE__ */ jsx("span", { children: "Send" })
2224
2241
  }
2225
2242
  )
2226
2243
  ] })
@@ -2294,6 +2311,7 @@ function Thread({
2294
2311
  streaming,
2295
2312
  error,
2296
2313
  send,
2314
+ stop,
2297
2315
  messages: melonyMessages
2298
2316
  } = useMelony();
2299
2317
  const messages = useMemo(() => {
@@ -2334,7 +2352,7 @@ function Thread({
2334
2352
  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",
2335
2353
  children: [
2336
2354
  /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: suggestion }),
2337
- /* @__PURE__ */ jsx(IconSparkles, { className: "h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" })
2355
+ /* @__PURE__ */ jsx(Icon, { name: "\u2728", size: "sm", className: "text-muted-foreground group-hover:text-primary transition-colors" })
2338
2356
  ]
2339
2357
  },
2340
2358
  i
@@ -2360,6 +2378,7 @@ function Thread({
2360
2378
  value: input,
2361
2379
  onChange: setInput,
2362
2380
  onSubmit: handleSubmit,
2381
+ onStop: stop,
2363
2382
  placeholder,
2364
2383
  streaming,
2365
2384
  autoFocus
@@ -2367,6 +2386,58 @@ function Thread({
2367
2386
  ) }) })
2368
2387
  ] });
2369
2388
  }
2389
+ var ThemeContext = createContext(void 0);
2390
+ function ThemeProvider({ children }) {
2391
+ const [theme, setThemeState] = useState("system");
2392
+ const [resolvedTheme, setResolvedTheme] = useState("light");
2393
+ useEffect(() => {
2394
+ if (typeof window !== "undefined") {
2395
+ const stored = localStorage.getItem("theme");
2396
+ if (stored) {
2397
+ setThemeState(stored);
2398
+ }
2399
+ }
2400
+ }, []);
2401
+ useEffect(() => {
2402
+ if (typeof window !== "undefined") {
2403
+ if (theme === "system") {
2404
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
2405
+ const updateResolvedTheme = () => {
2406
+ setResolvedTheme(mediaQuery.matches ? "dark" : "light");
2407
+ };
2408
+ updateResolvedTheme();
2409
+ mediaQuery.addEventListener("change", updateResolvedTheme);
2410
+ return () => mediaQuery.removeEventListener("change", updateResolvedTheme);
2411
+ } else {
2412
+ setResolvedTheme(theme);
2413
+ }
2414
+ }
2415
+ }, [theme]);
2416
+ useEffect(() => {
2417
+ if (typeof window !== "undefined") {
2418
+ const root = document.documentElement;
2419
+ if (resolvedTheme === "dark") {
2420
+ root.classList.add("dark");
2421
+ } else {
2422
+ root.classList.remove("dark");
2423
+ }
2424
+ }
2425
+ }, [resolvedTheme]);
2426
+ const setTheme = (newTheme) => {
2427
+ setThemeState(newTheme);
2428
+ if (typeof window !== "undefined") {
2429
+ localStorage.setItem("theme", newTheme);
2430
+ }
2431
+ };
2432
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { theme, setTheme, resolvedTheme }, children });
2433
+ }
2434
+ function useTheme() {
2435
+ const context = useContext(ThemeContext);
2436
+ if (context === void 0) {
2437
+ throw new Error("useTheme must be used within a ThemeProvider");
2438
+ }
2439
+ return context;
2440
+ }
2370
2441
 
2371
2442
  // src/index.ts
2372
2443
  var shadcnElements = {
@@ -2400,7 +2471,9 @@ var shadcnElements = {
2400
2471
  dropdown: Dropdown,
2401
2472
  thread: Thread
2402
2473
  };
2474
+ var ThemeProvider2 = ThemeProvider;
2475
+ var useTheme2 = useTheme;
2403
2476
 
2404
- export { shadcnElements };
2477
+ export { ThemeProvider2 as ThemeProvider, shadcnElements, useTheme2 as useTheme };
2405
2478
  //# sourceMappingURL=index.js.map
2406
2479
  //# sourceMappingURL=index.js.map