@melony/react 0.1.46 → 0.1.49

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
@@ -1,5 +1,5 @@
1
- import * as React12 from 'react';
2
- import React12__default, { createContext, useContext, useRef, useEffect, useState, useCallback, useMemo } from 'react';
1
+ import * as React3 from 'react';
2
+ import React3__default, { createContext, useContext, useRef, useEffect, useState, useCallback, useMemo } from 'react';
3
3
  import { convertEventsToMessages } from 'melony';
4
4
  import { NuqsAdapter } from 'nuqs/adapters/react';
5
5
  import { QueryClient, QueryClientProvider, useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
@@ -9,16 +9,17 @@ import { twMerge } from 'tailwind-merge';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
10
  import * as ICONS from '@tabler/icons-react';
11
11
  import { IconX, IconChevronLeft, IconChevronRight, IconLoader2, IconCheck, IconUpload, IconUser, IconLogout, IconBrandGoogle, IconFileText, IconFile, IconPaperclip, IconChevronDown, IconArrowUp, IconDotsVertical, IconTrash, IconHistory, IconPlus, IconArrowLeft, IconMessage, IconLayoutSidebarLeftExpand, IconLayoutSidebarLeftCollapse, IconLayoutSidebarRightExpand, IconLayoutSidebarRightCollapse, IconDeviceDesktop, IconMoon, IconSun, IconSelector, IconChevronUp } from '@tabler/icons-react';
12
+ export * from '@tabler/icons-react';
12
13
  import { Separator as Separator$1 } from '@base-ui/react/separator';
13
14
  import { mergeProps } from '@base-ui/react/merge-props';
14
15
  import { useRender } from '@base-ui/react/use-render';
15
16
  import { cva } from 'class-variance-authority';
16
17
  import { Input as Input$1 } from '@base-ui/react/input';
17
18
  import { Select as Select$1 } from '@base-ui/react/select';
19
+ import { createPortal } from 'react-dom';
18
20
  import { Button as Button$1 } from '@base-ui/react/button';
19
21
  import { Menu } from '@base-ui/react/menu';
20
22
  import { useQueryState, parseAsString } from 'nuqs';
21
- import { createPortal } from 'react-dom';
22
23
  import { useHotkeys } from 'react-hotkeys-hook';
23
24
 
24
25
  // src/providers/melony-provider.tsx
@@ -534,7 +535,6 @@ var Image = ({
534
535
  src,
535
536
  alt,
536
537
  size = "sm",
537
- groupId,
538
538
  className,
539
539
  style
540
540
  }) => {
@@ -1426,6 +1426,321 @@ var Checkbox = ({
1426
1426
  var Hidden = ({ name, value }) => {
1427
1427
  return /* @__PURE__ */ jsx("input", { type: "hidden", name, value });
1428
1428
  };
1429
+ var PopoverContext = React3.createContext(
1430
+ void 0
1431
+ );
1432
+ function usePopoverContext() {
1433
+ const context = React3.useContext(PopoverContext);
1434
+ if (!context) {
1435
+ throw new Error("Popover components must be used within a Popover");
1436
+ }
1437
+ return context;
1438
+ }
1439
+ function Popover({
1440
+ children,
1441
+ defaultOpen = false,
1442
+ open: controlledOpen,
1443
+ onOpenChange
1444
+ }) {
1445
+ const [internalOpen, setInternalOpen] = React3.useState(defaultOpen);
1446
+ const triggerRef = React3.useRef(null);
1447
+ const open = controlledOpen ?? internalOpen;
1448
+ const setOpen = React3.useCallback(
1449
+ (newOpen) => {
1450
+ if (controlledOpen === void 0) {
1451
+ setInternalOpen(newOpen);
1452
+ }
1453
+ onOpenChange?.(newOpen);
1454
+ },
1455
+ [controlledOpen, onOpenChange]
1456
+ );
1457
+ const value = React3.useMemo(
1458
+ () => ({
1459
+ open,
1460
+ setOpen,
1461
+ triggerRef
1462
+ }),
1463
+ [open, setOpen]
1464
+ );
1465
+ return /* @__PURE__ */ jsx(PopoverContext.Provider, { value, children });
1466
+ }
1467
+ var PopoverTrigger = React3.forwardRef(
1468
+ ({ asChild, className, children, ...props }, ref) => {
1469
+ const { setOpen, triggerRef } = usePopoverContext();
1470
+ const handleClick = (e) => {
1471
+ setOpen(true);
1472
+ props.onClick?.(e);
1473
+ };
1474
+ if (asChild && React3.isValidElement(children)) {
1475
+ return React3.cloneElement(children, {
1476
+ ref: (node) => {
1477
+ triggerRef.current = node;
1478
+ if (typeof children.ref === "function") {
1479
+ children.ref(node);
1480
+ } else if (children.ref) {
1481
+ children.ref.current = node;
1482
+ }
1483
+ },
1484
+ onClick: handleClick
1485
+ });
1486
+ }
1487
+ return /* @__PURE__ */ jsx(
1488
+ "button",
1489
+ {
1490
+ ref: (node) => {
1491
+ triggerRef.current = node;
1492
+ if (typeof ref === "function") {
1493
+ ref(node);
1494
+ } else if (ref) {
1495
+ ref.current = node;
1496
+ }
1497
+ },
1498
+ className,
1499
+ onClick: handleClick,
1500
+ ...props,
1501
+ children
1502
+ }
1503
+ );
1504
+ }
1505
+ );
1506
+ PopoverTrigger.displayName = "PopoverTrigger";
1507
+ var PopoverContent = React3.forwardRef(
1508
+ ({
1509
+ className,
1510
+ side = "bottom",
1511
+ align = "start",
1512
+ sideOffset = 4,
1513
+ alignOffset = 0,
1514
+ children,
1515
+ ...props
1516
+ }, ref) => {
1517
+ const { open, setOpen, triggerRef } = usePopoverContext();
1518
+ const [position, setPosition] = React3.useState({ top: 0, left: 0 });
1519
+ const contentRef = React3.useRef(null);
1520
+ React3.useEffect(() => {
1521
+ if (!open || !triggerRef.current) return;
1522
+ const updatePosition = () => {
1523
+ if (!triggerRef.current || !contentRef.current) return;
1524
+ const triggerRect = triggerRef.current.getBoundingClientRect();
1525
+ const contentRect = contentRef.current.getBoundingClientRect();
1526
+ const scrollX = window.scrollX;
1527
+ const scrollY = window.scrollY;
1528
+ let top = 0;
1529
+ let left = 0;
1530
+ switch (side) {
1531
+ case "bottom":
1532
+ top = triggerRect.bottom + sideOffset + scrollY;
1533
+ break;
1534
+ case "top":
1535
+ top = triggerRect.top - contentRect.height - sideOffset + scrollY;
1536
+ break;
1537
+ case "right":
1538
+ top = triggerRect.top + scrollY;
1539
+ left = triggerRect.right + sideOffset + scrollX;
1540
+ break;
1541
+ case "left":
1542
+ top = triggerRect.top + scrollY;
1543
+ left = triggerRect.left - contentRect.width - sideOffset + scrollX;
1544
+ break;
1545
+ }
1546
+ switch (align) {
1547
+ case "start":
1548
+ if (side === "top" || side === "bottom") {
1549
+ left = triggerRect.left + scrollX + alignOffset;
1550
+ } else {
1551
+ top += alignOffset;
1552
+ }
1553
+ break;
1554
+ case "center":
1555
+ if (side === "top" || side === "bottom") {
1556
+ left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2 + scrollX + alignOffset;
1557
+ } else {
1558
+ top += triggerRect.height / 2 - contentRect.height / 2 + alignOffset;
1559
+ }
1560
+ break;
1561
+ case "end":
1562
+ if (side === "top" || side === "bottom") {
1563
+ left = triggerRect.left + triggerRect.width - contentRect.width + scrollX + alignOffset;
1564
+ } else {
1565
+ top += triggerRect.height - contentRect.height + alignOffset;
1566
+ }
1567
+ break;
1568
+ }
1569
+ setPosition({ top, left });
1570
+ };
1571
+ requestAnimationFrame(() => {
1572
+ updatePosition();
1573
+ });
1574
+ window.addEventListener("resize", updatePosition);
1575
+ window.addEventListener("scroll", updatePosition, true);
1576
+ return () => {
1577
+ window.removeEventListener("resize", updatePosition);
1578
+ window.removeEventListener("scroll", updatePosition, true);
1579
+ };
1580
+ }, [open, side, align, sideOffset, alignOffset, triggerRef]);
1581
+ React3.useEffect(() => {
1582
+ if (!open) return;
1583
+ const handleClickOutside = (event) => {
1584
+ if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
1585
+ setOpen(false);
1586
+ }
1587
+ };
1588
+ const handleEscape = (event) => {
1589
+ if (event.key === "Escape") {
1590
+ setOpen(false);
1591
+ }
1592
+ };
1593
+ document.addEventListener("mousedown", handleClickOutside);
1594
+ document.addEventListener("keydown", handleEscape);
1595
+ return () => {
1596
+ document.removeEventListener("mousedown", handleClickOutside);
1597
+ document.removeEventListener("keydown", handleEscape);
1598
+ };
1599
+ }, [open, setOpen, triggerRef]);
1600
+ if (!open) return null;
1601
+ const content = /* @__PURE__ */ jsx(
1602
+ "div",
1603
+ {
1604
+ ref: (node) => {
1605
+ contentRef.current = node;
1606
+ if (typeof ref === "function") {
1607
+ ref(node);
1608
+ } else if (ref) {
1609
+ ref.current = node;
1610
+ }
1611
+ },
1612
+ className: cn(
1613
+ "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",
1614
+ className
1615
+ ),
1616
+ style: {
1617
+ position: "absolute",
1618
+ top: `${position.top}px`,
1619
+ left: `${position.left}px`
1620
+ },
1621
+ ...props,
1622
+ children
1623
+ }
1624
+ );
1625
+ return createPortal(content, document.body);
1626
+ }
1627
+ );
1628
+ PopoverContent.displayName = "PopoverContent";
1629
+ var PRESET_COLORS = [
1630
+ "#000000",
1631
+ "#ffffff",
1632
+ "#f44336",
1633
+ "#e91e63",
1634
+ "#9c27b0",
1635
+ "#673ab7",
1636
+ "#3f51b5",
1637
+ "#2196f3",
1638
+ "#03a9f4",
1639
+ "#00bcd4",
1640
+ "#009688",
1641
+ "#4caf50",
1642
+ "#8bc34a",
1643
+ "#cddc39",
1644
+ "#ffeb3b",
1645
+ "#ffc107",
1646
+ "#ff9800",
1647
+ "#ff5722",
1648
+ "#795548",
1649
+ "#9e9e9e",
1650
+ "#607d8b"
1651
+ ];
1652
+ var ColorPicker = ({
1653
+ name,
1654
+ label,
1655
+ defaultValue = "#000000",
1656
+ value: controlledValue,
1657
+ onChangeAction,
1658
+ disabled,
1659
+ className,
1660
+ style
1661
+ }) => {
1662
+ const { sendEvent } = useMelony();
1663
+ const [color, setColor] = useState(controlledValue || defaultValue);
1664
+ useEffect(() => {
1665
+ if (controlledValue !== void 0) {
1666
+ setColor(controlledValue);
1667
+ }
1668
+ }, [controlledValue]);
1669
+ const handleColorChange = (newColor) => {
1670
+ setColor(newColor);
1671
+ if (onChangeAction) {
1672
+ sendEvent({
1673
+ ...onChangeAction,
1674
+ data: {
1675
+ name: name || "",
1676
+ value: newColor
1677
+ }
1678
+ });
1679
+ }
1680
+ };
1681
+ return /* @__PURE__ */ jsxs(Field, { className: cn("w-full", className), style, children: [
1682
+ label && /* @__PURE__ */ jsx(FieldTitle, { children: label }),
1683
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1684
+ /* @__PURE__ */ jsxs(Popover, { children: [
1685
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1686
+ "button",
1687
+ {
1688
+ type: "button",
1689
+ disabled,
1690
+ className: cn(
1691
+ "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",
1692
+ "flex items-center justify-center p-1"
1693
+ ),
1694
+ children: /* @__PURE__ */ jsx(
1695
+ "div",
1696
+ {
1697
+ className: "w-full h-full rounded-md",
1698
+ style: { backgroundColor: color }
1699
+ }
1700
+ )
1701
+ }
1702
+ ) }),
1703
+ /* @__PURE__ */ jsx(PopoverContent, { className: "p-3 w-64", side: "bottom", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1704
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: PRESET_COLORS.map((preset) => /* @__PURE__ */ jsx(
1705
+ "button",
1706
+ {
1707
+ type: "button",
1708
+ className: cn(
1709
+ "w-6 h-6 rounded-md border border-border transition-transform hover:scale-110 active:scale-90",
1710
+ color === preset && "ring-2 ring-primary ring-offset-1"
1711
+ ),
1712
+ style: { backgroundColor: preset },
1713
+ onClick: () => handleColorChange(preset)
1714
+ },
1715
+ preset
1716
+ )) }),
1717
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1718
+ /* @__PURE__ */ jsx(
1719
+ "input",
1720
+ {
1721
+ type: "color",
1722
+ value: color,
1723
+ onChange: (e) => handleColorChange(e.target.value),
1724
+ className: "w-8 h-8 rounded border-none p-0 cursor-pointer"
1725
+ }
1726
+ ),
1727
+ /* @__PURE__ */ jsx(
1728
+ "input",
1729
+ {
1730
+ type: "text",
1731
+ value: color,
1732
+ onChange: (e) => handleColorChange(e.target.value),
1733
+ 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"
1734
+ }
1735
+ )
1736
+ ] })
1737
+ ] }) })
1738
+ ] }),
1739
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-mono uppercase text-muted-foreground", children: color })
1740
+ ] }),
1741
+ /* @__PURE__ */ jsx("input", { type: "hidden", name, value: color })
1742
+ ] });
1743
+ };
1429
1744
  var RadioGroup = ({
1430
1745
  name,
1431
1746
  options,
@@ -1591,12 +1906,19 @@ var Upload = ({
1591
1906
  accept,
1592
1907
  onUploadAction,
1593
1908
  className,
1594
- style
1909
+ style,
1910
+ initialFiles,
1911
+ mode = "append"
1595
1912
  }) => {
1596
1913
  const { sendEvent, events } = useMelony();
1597
1914
  const fileInputRef = useRef(null);
1598
1915
  const [isUploading, setIsUploading] = useState(false);
1599
1916
  const [status, setStatus] = useState("idle");
1917
+ const uploadedFilesEvents = events.filter(
1918
+ (event) => event.type === "uploaded-files"
1919
+ );
1920
+ const displayEvents = mode === "replace" && uploadedFilesEvents.length > 0 ? [uploadedFilesEvents[uploadedFilesEvents.length - 1]] : uploadedFilesEvents;
1921
+ const showInitialFiles = mode === "replace" ? displayEvents.length === 0 : true;
1600
1922
  const handleFileChange = async (e) => {
1601
1923
  const files = Array.from(e.target.files || []);
1602
1924
  if (files.length === 0) return;
@@ -1669,23 +1991,26 @@ var Upload = ({
1669
1991
  disabled: isUploading
1670
1992
  }
1671
1993
  ),
1672
- events.filter((event) => event.type === "files-uploaded" && !!event.ui).map(
1673
- (event, index) => event.ui ? /* @__PURE__ */ jsx(UIRenderer, { node: event.ui }, index) : null
1674
- ),
1675
- /* @__PURE__ */ jsxs(
1676
- Button,
1677
- {
1678
- type: "button",
1679
- disabled: isUploading,
1680
- onClick: () => fileInputRef.current?.click(),
1681
- className: "gap-2",
1682
- variant: status === "error" ? "destructive" : status === "success" ? "outline" : "default",
1683
- children: [
1684
- isUploading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-4 w-4 animate-spin" }) : status === "success" ? /* @__PURE__ */ jsx(IconCheck, { className: "h-4 w-4 text-green-500" }) : status === "error" ? /* @__PURE__ */ jsx(IconX, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconUpload, { className: "h-4 w-4" }),
1685
- status === "success" ? "Uploaded" : status === "error" ? "Failed" : label
1686
- ]
1687
- }
1688
- )
1994
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 mb-2 items-center", children: [
1995
+ showInitialFiles && initialFiles?.map((file, index) => /* @__PURE__ */ jsx(Image, { src: file.url, alt: file.name, size: "md" }, index)),
1996
+ displayEvents.map(
1997
+ (event, index) => event.ui ? /* @__PURE__ */ jsx(UIRenderer, { node: event.ui }, index) : null
1998
+ ),
1999
+ /* @__PURE__ */ jsxs(
2000
+ Button,
2001
+ {
2002
+ type: "button",
2003
+ disabled: isUploading,
2004
+ onClick: () => fileInputRef.current?.click(),
2005
+ className: "gap-2",
2006
+ variant: status === "error" ? "destructive" : status === "success" ? "outline" : "default",
2007
+ children: [
2008
+ isUploading ? /* @__PURE__ */ jsx(IconLoader2, { className: "h-4 w-4 animate-spin" }) : status === "success" ? /* @__PURE__ */ jsx(IconCheck, { className: "h-4 w-4 text-green-500" }) : status === "error" ? /* @__PURE__ */ jsx(IconX, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconUpload, { className: "h-4 w-4" }),
2009
+ status === "success" ? "Uploaded" : status === "error" ? "Failed" : label
2010
+ ]
2011
+ }
2012
+ )
2013
+ ] })
1689
2014
  ] });
1690
2015
  };
1691
2016
  var Form = ({
@@ -1754,6 +2079,7 @@ function UIRenderer({ node }) {
1754
2079
  select: Select2,
1755
2080
  checkbox: Checkbox,
1756
2081
  radioGroup: RadioGroup,
2082
+ colorPicker: ColorPicker,
1757
2083
  spacer: Spacer,
1758
2084
  divider: Divider,
1759
2085
  box: Box,
@@ -2071,10 +2397,10 @@ var AccountButton = ({
2071
2397
  size
2072
2398
  }) => {
2073
2399
  const { isLoading, isAuthenticated, user, login, logout } = useAuth();
2074
- const [open, setOpen] = React12.useState(false);
2075
- const [accountInfoOpen, setAccountInfoOpen] = React12.useState(false);
2076
- const [error, setError] = React12.useState(null);
2077
- const initials = React12.useMemo(() => {
2400
+ const [open, setOpen] = React3.useState(false);
2401
+ const [accountInfoOpen, setAccountInfoOpen] = React3.useState(false);
2402
+ const [error, setError] = React3.useState(null);
2403
+ const initials = React3.useMemo(() => {
2078
2404
  const name = user?.displayName || user?.name;
2079
2405
  if (!name) return "";
2080
2406
  return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
@@ -2650,13 +2976,13 @@ function Composer({
2650
2976
  const accept = fileAttachments?.accept;
2651
2977
  const maxFiles = fileAttachments?.maxFiles ?? 10;
2652
2978
  const maxFileSize = fileAttachments?.maxFileSize ?? 10 * 1024 * 1024;
2653
- const [selectedOptions, setSelectedOptions] = React12__default.useState(
2979
+ const [selectedOptions, setSelectedOptions] = React3__default.useState(
2654
2980
  () => new Set(defaultSelectedIds)
2655
2981
  );
2656
- const [attachedFiles, setAttachedFiles] = React12__default.useState([]);
2657
- const [previews, setPreviews] = React12__default.useState([]);
2658
- const fileInputRef = React12__default.useRef(null);
2659
- React12__default.useEffect(() => {
2982
+ const [attachedFiles, setAttachedFiles] = React3__default.useState([]);
2983
+ const [previews, setPreviews] = React3__default.useState([]);
2984
+ const fileInputRef = React3__default.useRef(null);
2985
+ React3__default.useEffect(() => {
2660
2986
  const newPreviews = attachedFiles.map((file) => ({
2661
2987
  name: file.name,
2662
2988
  type: file.type,
@@ -3227,7 +3553,7 @@ var Dropdown = ({
3227
3553
  };
3228
3554
  var ThreadList = ({ className }) => {
3229
3555
  const { threads, activeThreadId, deleteThread } = useThreads();
3230
- const sortedThreads = React12.useMemo(() => {
3556
+ const sortedThreads = React3.useMemo(() => {
3231
3557
  return [...threads].sort((a, b) => {
3232
3558
  const dateA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
3233
3559
  const dateB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
@@ -3455,206 +3781,6 @@ function SidebarToggle({ side, className }) {
3455
3781
  }
3456
3782
  return null;
3457
3783
  }
3458
- var PopoverContext = React12.createContext(
3459
- void 0
3460
- );
3461
- function usePopoverContext() {
3462
- const context = React12.useContext(PopoverContext);
3463
- if (!context) {
3464
- throw new Error("Popover components must be used within a Popover");
3465
- }
3466
- return context;
3467
- }
3468
- function Popover({
3469
- children,
3470
- defaultOpen = false,
3471
- open: controlledOpen,
3472
- onOpenChange
3473
- }) {
3474
- const [internalOpen, setInternalOpen] = React12.useState(defaultOpen);
3475
- const triggerRef = React12.useRef(null);
3476
- const open = controlledOpen ?? internalOpen;
3477
- const setOpen = React12.useCallback(
3478
- (newOpen) => {
3479
- if (controlledOpen === void 0) {
3480
- setInternalOpen(newOpen);
3481
- }
3482
- onOpenChange?.(newOpen);
3483
- },
3484
- [controlledOpen, onOpenChange]
3485
- );
3486
- const value = React12.useMemo(
3487
- () => ({
3488
- open,
3489
- setOpen,
3490
- triggerRef
3491
- }),
3492
- [open, setOpen]
3493
- );
3494
- return /* @__PURE__ */ jsx(PopoverContext.Provider, { value, children });
3495
- }
3496
- var PopoverTrigger = React12.forwardRef(
3497
- ({ asChild, className, children, ...props }, ref) => {
3498
- const { setOpen, triggerRef } = usePopoverContext();
3499
- const handleClick = (e) => {
3500
- setOpen(true);
3501
- props.onClick?.(e);
3502
- };
3503
- if (asChild && React12.isValidElement(children)) {
3504
- return React12.cloneElement(children, {
3505
- ref: (node) => {
3506
- triggerRef.current = node;
3507
- if (typeof children.ref === "function") {
3508
- children.ref(node);
3509
- } else if (children.ref) {
3510
- children.ref.current = node;
3511
- }
3512
- },
3513
- onClick: handleClick
3514
- });
3515
- }
3516
- return /* @__PURE__ */ jsx(
3517
- "button",
3518
- {
3519
- ref: (node) => {
3520
- triggerRef.current = node;
3521
- if (typeof ref === "function") {
3522
- ref(node);
3523
- } else if (ref) {
3524
- ref.current = node;
3525
- }
3526
- },
3527
- className,
3528
- onClick: handleClick,
3529
- ...props,
3530
- children
3531
- }
3532
- );
3533
- }
3534
- );
3535
- PopoverTrigger.displayName = "PopoverTrigger";
3536
- var PopoverContent = React12.forwardRef(
3537
- ({
3538
- className,
3539
- side = "bottom",
3540
- align = "start",
3541
- sideOffset = 4,
3542
- alignOffset = 0,
3543
- children,
3544
- ...props
3545
- }, ref) => {
3546
- const { open, setOpen, triggerRef } = usePopoverContext();
3547
- const [position, setPosition] = React12.useState({ top: 0, left: 0 });
3548
- const contentRef = React12.useRef(null);
3549
- React12.useEffect(() => {
3550
- if (!open || !triggerRef.current) return;
3551
- const updatePosition = () => {
3552
- if (!triggerRef.current || !contentRef.current) return;
3553
- const triggerRect = triggerRef.current.getBoundingClientRect();
3554
- const contentRect = contentRef.current.getBoundingClientRect();
3555
- const scrollX = window.scrollX;
3556
- const scrollY = window.scrollY;
3557
- let top = 0;
3558
- let left = 0;
3559
- switch (side) {
3560
- case "bottom":
3561
- top = triggerRect.bottom + sideOffset + scrollY;
3562
- break;
3563
- case "top":
3564
- top = triggerRect.top - contentRect.height - sideOffset + scrollY;
3565
- break;
3566
- case "right":
3567
- top = triggerRect.top + scrollY;
3568
- left = triggerRect.right + sideOffset + scrollX;
3569
- break;
3570
- case "left":
3571
- top = triggerRect.top + scrollY;
3572
- left = triggerRect.left - contentRect.width - sideOffset + scrollX;
3573
- break;
3574
- }
3575
- switch (align) {
3576
- case "start":
3577
- if (side === "top" || side === "bottom") {
3578
- left = triggerRect.left + scrollX + alignOffset;
3579
- } else {
3580
- top += alignOffset;
3581
- }
3582
- break;
3583
- case "center":
3584
- if (side === "top" || side === "bottom") {
3585
- left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2 + scrollX + alignOffset;
3586
- } else {
3587
- top += triggerRect.height / 2 - contentRect.height / 2 + alignOffset;
3588
- }
3589
- break;
3590
- case "end":
3591
- if (side === "top" || side === "bottom") {
3592
- left = triggerRect.left + triggerRect.width - contentRect.width + scrollX + alignOffset;
3593
- } else {
3594
- top += triggerRect.height - contentRect.height + alignOffset;
3595
- }
3596
- break;
3597
- }
3598
- setPosition({ top, left });
3599
- };
3600
- requestAnimationFrame(() => {
3601
- updatePosition();
3602
- });
3603
- window.addEventListener("resize", updatePosition);
3604
- window.addEventListener("scroll", updatePosition, true);
3605
- return () => {
3606
- window.removeEventListener("resize", updatePosition);
3607
- window.removeEventListener("scroll", updatePosition, true);
3608
- };
3609
- }, [open, side, align, sideOffset, alignOffset, triggerRef]);
3610
- React12.useEffect(() => {
3611
- if (!open) return;
3612
- const handleClickOutside = (event) => {
3613
- if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
3614
- setOpen(false);
3615
- }
3616
- };
3617
- const handleEscape = (event) => {
3618
- if (event.key === "Escape") {
3619
- setOpen(false);
3620
- }
3621
- };
3622
- document.addEventListener("mousedown", handleClickOutside);
3623
- document.addEventListener("keydown", handleEscape);
3624
- return () => {
3625
- document.removeEventListener("mousedown", handleClickOutside);
3626
- document.removeEventListener("keydown", handleEscape);
3627
- };
3628
- }, [open, setOpen, triggerRef]);
3629
- if (!open) return null;
3630
- const content = /* @__PURE__ */ jsx(
3631
- "div",
3632
- {
3633
- ref: (node) => {
3634
- contentRef.current = node;
3635
- if (typeof ref === "function") {
3636
- ref(node);
3637
- } else if (ref) {
3638
- ref.current = node;
3639
- }
3640
- },
3641
- className: cn(
3642
- "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",
3643
- className
3644
- ),
3645
- style: {
3646
- position: "absolute",
3647
- top: `${position.top}px`,
3648
- left: `${position.left}px`
3649
- },
3650
- ...props,
3651
- children
3652
- }
3653
- );
3654
- return createPortal(content, document.body);
3655
- }
3656
- );
3657
- PopoverContent.displayName = "PopoverContent";
3658
3784
  var ThreadPopover = ({
3659
3785
  className,
3660
3786
  buttonClassName,
@@ -3662,7 +3788,7 @@ var ThreadPopover = ({
3662
3788
  buttonSize = "icon",
3663
3789
  emptyState
3664
3790
  }) => {
3665
- const [isOpen, setIsOpen] = React12.useState(false);
3791
+ const [isOpen, setIsOpen] = React3.useState(false);
3666
3792
  useHotkeys(
3667
3793
  "h",
3668
3794
  (e) => {
@@ -3705,7 +3831,7 @@ var CreateThreadButton = ({
3705
3831
  onThreadCreated
3706
3832
  }) => {
3707
3833
  const { createThread } = useThreads();
3708
- const [isCreating, setIsCreating] = React12.useState(false);
3834
+ const [isCreating, setIsCreating] = React3.useState(false);
3709
3835
  const handleCreateThread = async () => {
3710
3836
  if (isCreating) return;
3711
3837
  try {
@@ -3787,7 +3913,7 @@ var CreateThreadListItem = ({
3787
3913
  className
3788
3914
  }) => {
3789
3915
  const { createThread } = useThreads();
3790
- const [isCreating, setIsCreating] = React12.useState(false);
3916
+ const [isCreating, setIsCreating] = React3.useState(false);
3791
3917
  const handleCreateThread = async () => {
3792
3918
  if (isCreating) return;
3793
3919
  try {
@@ -3830,6 +3956,6 @@ var CreateThreadListItem = ({
3830
3956
  );
3831
3957
  };
3832
3958
 
3833
- export { AccountButton, AuthContext, AuthProvider, Badge2 as Badge, Box, Button2 as Button, Card2 as Card, Chart, ChatHeader, Checkbox, Col, Composer, CreateThreadButton, CreateThreadListItem, Divider, Dropdown, Form, FullChat, Heading, Image, Input2 as Input, Label2 as Label, List, ListItem, MelonyContext, MelonyProvider, PopupChat, RadioGroup, Row, Select2 as Select, Sidebar, SidebarContext, SidebarProvider, SidebarToggle, Spacer, Text, Textarea2 as Textarea, ThemeProvider, ThemeToggle, Thread, ThreadContext, ThreadList, ThreadPopover, ThreadProvider, UIRenderer, Upload, WelcomeScreen, useAuth, useMelony, useScreenSize, useSidebar, useTheme, useThreads };
3959
+ export { AccountButton, AuthContext, AuthProvider, Badge2 as Badge, Box, Button2 as Button, Card2 as Card, Chart, ChatHeader, Checkbox, Col, ColorPicker, Composer, CreateThreadButton, CreateThreadListItem, Divider, Dropdown, Form, FullChat, Heading, Hidden, Image, Input2 as Input, Label2 as Label, List, ListItem, MelonyContext, MelonyProvider, PopupChat, RadioGroup, Row, Select2 as Select, Sidebar, SidebarContext, SidebarProvider, SidebarToggle, Spacer, Text, Textarea2 as Textarea, ThemeProvider, ThemeToggle, Thread, ThreadContext, ThreadList, ThreadPopover, ThreadProvider, UIRenderer, Upload, WelcomeScreen, useAuth, useMelony, useScreenSize, useSidebar, useTheme, useThreads };
3834
3960
  //# sourceMappingURL=index.js.map
3835
3961
  //# sourceMappingURL=index.js.map