@melony/react 0.1.46 → 0.1.47

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';
@@ -15,10 +15,10 @@ import { useRender } from '@base-ui/react/use-render';
15
15
  import { cva } from 'class-variance-authority';
16
16
  import { Input as Input$1 } from '@base-ui/react/input';
17
17
  import { Select as Select$1 } from '@base-ui/react/select';
18
+ import { createPortal } from 'react-dom';
18
19
  import { Button as Button$1 } from '@base-ui/react/button';
19
20
  import { Menu } from '@base-ui/react/menu';
20
21
  import { useQueryState, parseAsString } from 'nuqs';
21
- import { createPortal } from 'react-dom';
22
22
  import { useHotkeys } from 'react-hotkeys-hook';
23
23
 
24
24
  // src/providers/melony-provider.tsx
@@ -534,7 +534,6 @@ var Image = ({
534
534
  src,
535
535
  alt,
536
536
  size = "sm",
537
- groupId,
538
537
  className,
539
538
  style
540
539
  }) => {
@@ -1426,6 +1425,321 @@ var Checkbox = ({
1426
1425
  var Hidden = ({ name, value }) => {
1427
1426
  return /* @__PURE__ */ jsx("input", { type: "hidden", name, value });
1428
1427
  };
1428
+ var PopoverContext = React3.createContext(
1429
+ void 0
1430
+ );
1431
+ function usePopoverContext() {
1432
+ const context = React3.useContext(PopoverContext);
1433
+ if (!context) {
1434
+ throw new Error("Popover components must be used within a Popover");
1435
+ }
1436
+ return context;
1437
+ }
1438
+ function Popover({
1439
+ children,
1440
+ defaultOpen = false,
1441
+ open: controlledOpen,
1442
+ onOpenChange
1443
+ }) {
1444
+ const [internalOpen, setInternalOpen] = React3.useState(defaultOpen);
1445
+ const triggerRef = React3.useRef(null);
1446
+ const open = controlledOpen ?? internalOpen;
1447
+ const setOpen = React3.useCallback(
1448
+ (newOpen) => {
1449
+ if (controlledOpen === void 0) {
1450
+ setInternalOpen(newOpen);
1451
+ }
1452
+ onOpenChange?.(newOpen);
1453
+ },
1454
+ [controlledOpen, onOpenChange]
1455
+ );
1456
+ const value = React3.useMemo(
1457
+ () => ({
1458
+ open,
1459
+ setOpen,
1460
+ triggerRef
1461
+ }),
1462
+ [open, setOpen]
1463
+ );
1464
+ return /* @__PURE__ */ jsx(PopoverContext.Provider, { value, children });
1465
+ }
1466
+ var PopoverTrigger = React3.forwardRef(
1467
+ ({ asChild, className, children, ...props }, ref) => {
1468
+ const { setOpen, triggerRef } = usePopoverContext();
1469
+ const handleClick = (e) => {
1470
+ setOpen(true);
1471
+ props.onClick?.(e);
1472
+ };
1473
+ if (asChild && React3.isValidElement(children)) {
1474
+ return React3.cloneElement(children, {
1475
+ ref: (node) => {
1476
+ triggerRef.current = node;
1477
+ if (typeof children.ref === "function") {
1478
+ children.ref(node);
1479
+ } else if (children.ref) {
1480
+ children.ref.current = node;
1481
+ }
1482
+ },
1483
+ onClick: handleClick
1484
+ });
1485
+ }
1486
+ return /* @__PURE__ */ jsx(
1487
+ "button",
1488
+ {
1489
+ ref: (node) => {
1490
+ triggerRef.current = node;
1491
+ if (typeof ref === "function") {
1492
+ ref(node);
1493
+ } else if (ref) {
1494
+ ref.current = node;
1495
+ }
1496
+ },
1497
+ className,
1498
+ onClick: handleClick,
1499
+ ...props,
1500
+ children
1501
+ }
1502
+ );
1503
+ }
1504
+ );
1505
+ PopoverTrigger.displayName = "PopoverTrigger";
1506
+ var PopoverContent = React3.forwardRef(
1507
+ ({
1508
+ className,
1509
+ side = "bottom",
1510
+ align = "start",
1511
+ sideOffset = 4,
1512
+ alignOffset = 0,
1513
+ children,
1514
+ ...props
1515
+ }, ref) => {
1516
+ const { open, setOpen, triggerRef } = usePopoverContext();
1517
+ const [position, setPosition] = React3.useState({ top: 0, left: 0 });
1518
+ const contentRef = React3.useRef(null);
1519
+ React3.useEffect(() => {
1520
+ if (!open || !triggerRef.current) return;
1521
+ const updatePosition = () => {
1522
+ if (!triggerRef.current || !contentRef.current) return;
1523
+ const triggerRect = triggerRef.current.getBoundingClientRect();
1524
+ const contentRect = contentRef.current.getBoundingClientRect();
1525
+ const scrollX = window.scrollX;
1526
+ const scrollY = window.scrollY;
1527
+ let top = 0;
1528
+ let left = 0;
1529
+ switch (side) {
1530
+ case "bottom":
1531
+ top = triggerRect.bottom + sideOffset + scrollY;
1532
+ break;
1533
+ case "top":
1534
+ top = triggerRect.top - contentRect.height - sideOffset + scrollY;
1535
+ break;
1536
+ case "right":
1537
+ top = triggerRect.top + scrollY;
1538
+ left = triggerRect.right + sideOffset + scrollX;
1539
+ break;
1540
+ case "left":
1541
+ top = triggerRect.top + scrollY;
1542
+ left = triggerRect.left - contentRect.width - sideOffset + scrollX;
1543
+ break;
1544
+ }
1545
+ switch (align) {
1546
+ case "start":
1547
+ if (side === "top" || side === "bottom") {
1548
+ left = triggerRect.left + scrollX + alignOffset;
1549
+ } else {
1550
+ top += alignOffset;
1551
+ }
1552
+ break;
1553
+ case "center":
1554
+ if (side === "top" || side === "bottom") {
1555
+ left = triggerRect.left + triggerRect.width / 2 - contentRect.width / 2 + scrollX + alignOffset;
1556
+ } else {
1557
+ top += triggerRect.height / 2 - contentRect.height / 2 + alignOffset;
1558
+ }
1559
+ break;
1560
+ case "end":
1561
+ if (side === "top" || side === "bottom") {
1562
+ left = triggerRect.left + triggerRect.width - contentRect.width + scrollX + alignOffset;
1563
+ } else {
1564
+ top += triggerRect.height - contentRect.height + alignOffset;
1565
+ }
1566
+ break;
1567
+ }
1568
+ setPosition({ top, left });
1569
+ };
1570
+ requestAnimationFrame(() => {
1571
+ updatePosition();
1572
+ });
1573
+ window.addEventListener("resize", updatePosition);
1574
+ window.addEventListener("scroll", updatePosition, true);
1575
+ return () => {
1576
+ window.removeEventListener("resize", updatePosition);
1577
+ window.removeEventListener("scroll", updatePosition, true);
1578
+ };
1579
+ }, [open, side, align, sideOffset, alignOffset, triggerRef]);
1580
+ React3.useEffect(() => {
1581
+ if (!open) return;
1582
+ const handleClickOutside = (event) => {
1583
+ if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
1584
+ setOpen(false);
1585
+ }
1586
+ };
1587
+ const handleEscape = (event) => {
1588
+ if (event.key === "Escape") {
1589
+ setOpen(false);
1590
+ }
1591
+ };
1592
+ document.addEventListener("mousedown", handleClickOutside);
1593
+ document.addEventListener("keydown", handleEscape);
1594
+ return () => {
1595
+ document.removeEventListener("mousedown", handleClickOutside);
1596
+ document.removeEventListener("keydown", handleEscape);
1597
+ };
1598
+ }, [open, setOpen, triggerRef]);
1599
+ if (!open) return null;
1600
+ const content = /* @__PURE__ */ jsx(
1601
+ "div",
1602
+ {
1603
+ ref: (node) => {
1604
+ contentRef.current = node;
1605
+ if (typeof ref === "function") {
1606
+ ref(node);
1607
+ } else if (ref) {
1608
+ ref.current = node;
1609
+ }
1610
+ },
1611
+ className: cn(
1612
+ "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",
1613
+ className
1614
+ ),
1615
+ style: {
1616
+ position: "absolute",
1617
+ top: `${position.top}px`,
1618
+ left: `${position.left}px`
1619
+ },
1620
+ ...props,
1621
+ children
1622
+ }
1623
+ );
1624
+ return createPortal(content, document.body);
1625
+ }
1626
+ );
1627
+ PopoverContent.displayName = "PopoverContent";
1628
+ var PRESET_COLORS = [
1629
+ "#000000",
1630
+ "#ffffff",
1631
+ "#f44336",
1632
+ "#e91e63",
1633
+ "#9c27b0",
1634
+ "#673ab7",
1635
+ "#3f51b5",
1636
+ "#2196f3",
1637
+ "#03a9f4",
1638
+ "#00bcd4",
1639
+ "#009688",
1640
+ "#4caf50",
1641
+ "#8bc34a",
1642
+ "#cddc39",
1643
+ "#ffeb3b",
1644
+ "#ffc107",
1645
+ "#ff9800",
1646
+ "#ff5722",
1647
+ "#795548",
1648
+ "#9e9e9e",
1649
+ "#607d8b"
1650
+ ];
1651
+ var ColorPicker = ({
1652
+ name,
1653
+ label,
1654
+ defaultValue = "#000000",
1655
+ value: controlledValue,
1656
+ onChangeAction,
1657
+ disabled,
1658
+ className,
1659
+ style
1660
+ }) => {
1661
+ const { sendEvent } = useMelony();
1662
+ const [color, setColor] = useState(controlledValue || defaultValue);
1663
+ useEffect(() => {
1664
+ if (controlledValue !== void 0) {
1665
+ setColor(controlledValue);
1666
+ }
1667
+ }, [controlledValue]);
1668
+ const handleColorChange = (newColor) => {
1669
+ setColor(newColor);
1670
+ if (onChangeAction) {
1671
+ sendEvent({
1672
+ ...onChangeAction,
1673
+ data: {
1674
+ name: name || "",
1675
+ value: newColor
1676
+ }
1677
+ });
1678
+ }
1679
+ };
1680
+ return /* @__PURE__ */ jsxs(Field, { className: cn("w-full", className), style, children: [
1681
+ label && /* @__PURE__ */ jsx(FieldTitle, { children: label }),
1682
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1683
+ /* @__PURE__ */ jsxs(Popover, { children: [
1684
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1685
+ "button",
1686
+ {
1687
+ type: "button",
1688
+ disabled,
1689
+ className: cn(
1690
+ "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",
1691
+ "flex items-center justify-center p-1"
1692
+ ),
1693
+ children: /* @__PURE__ */ jsx(
1694
+ "div",
1695
+ {
1696
+ className: "w-full h-full rounded-md",
1697
+ style: { backgroundColor: color }
1698
+ }
1699
+ )
1700
+ }
1701
+ ) }),
1702
+ /* @__PURE__ */ jsx(PopoverContent, { className: "p-3 w-64", side: "bottom", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1703
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: PRESET_COLORS.map((preset) => /* @__PURE__ */ jsx(
1704
+ "button",
1705
+ {
1706
+ type: "button",
1707
+ className: cn(
1708
+ "w-6 h-6 rounded-md border border-border transition-transform hover:scale-110 active:scale-90",
1709
+ color === preset && "ring-2 ring-primary ring-offset-1"
1710
+ ),
1711
+ style: { backgroundColor: preset },
1712
+ onClick: () => handleColorChange(preset)
1713
+ },
1714
+ preset
1715
+ )) }),
1716
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1717
+ /* @__PURE__ */ jsx(
1718
+ "input",
1719
+ {
1720
+ type: "color",
1721
+ value: color,
1722
+ onChange: (e) => handleColorChange(e.target.value),
1723
+ className: "w-8 h-8 rounded border-none p-0 cursor-pointer"
1724
+ }
1725
+ ),
1726
+ /* @__PURE__ */ jsx(
1727
+ "input",
1728
+ {
1729
+ type: "text",
1730
+ value: color,
1731
+ onChange: (e) => handleColorChange(e.target.value),
1732
+ 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"
1733
+ }
1734
+ )
1735
+ ] })
1736
+ ] }) })
1737
+ ] }),
1738
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-mono uppercase text-muted-foreground", children: color })
1739
+ ] }),
1740
+ /* @__PURE__ */ jsx("input", { type: "hidden", name, value: color })
1741
+ ] });
1742
+ };
1429
1743
  var RadioGroup = ({
1430
1744
  name,
1431
1745
  options,
@@ -1591,12 +1905,19 @@ var Upload = ({
1591
1905
  accept,
1592
1906
  onUploadAction,
1593
1907
  className,
1594
- style
1908
+ style,
1909
+ initialFiles,
1910
+ mode = "append"
1595
1911
  }) => {
1596
1912
  const { sendEvent, events } = useMelony();
1597
1913
  const fileInputRef = useRef(null);
1598
1914
  const [isUploading, setIsUploading] = useState(false);
1599
1915
  const [status, setStatus] = useState("idle");
1916
+ const uploadedFilesEvents = events.filter(
1917
+ (event) => event.type === "uploaded-files"
1918
+ );
1919
+ const displayEvents = mode === "replace" && uploadedFilesEvents.length > 0 ? [uploadedFilesEvents[uploadedFilesEvents.length - 1]] : uploadedFilesEvents;
1920
+ const showInitialFiles = mode === "replace" ? displayEvents.length === 0 : true;
1600
1921
  const handleFileChange = async (e) => {
1601
1922
  const files = Array.from(e.target.files || []);
1602
1923
  if (files.length === 0) return;
@@ -1669,23 +1990,26 @@ var Upload = ({
1669
1990
  disabled: isUploading
1670
1991
  }
1671
1992
  ),
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
- )
1993
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 mb-2 items-center", children: [
1994
+ showInitialFiles && initialFiles?.map((file, index) => /* @__PURE__ */ jsx(Image, { src: file.url, alt: file.name, size: "md" }, index)),
1995
+ displayEvents.map(
1996
+ (event, index) => event.ui ? /* @__PURE__ */ jsx(UIRenderer, { node: event.ui }, index) : null
1997
+ ),
1998
+ /* @__PURE__ */ jsxs(
1999
+ Button,
2000
+ {
2001
+ type: "button",
2002
+ disabled: isUploading,
2003
+ onClick: () => fileInputRef.current?.click(),
2004
+ className: "gap-2",
2005
+ variant: status === "error" ? "destructive" : status === "success" ? "outline" : "default",
2006
+ children: [
2007
+ 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" }),
2008
+ status === "success" ? "Uploaded" : status === "error" ? "Failed" : label
2009
+ ]
2010
+ }
2011
+ )
2012
+ ] })
1689
2013
  ] });
1690
2014
  };
1691
2015
  var Form = ({
@@ -1754,6 +2078,7 @@ function UIRenderer({ node }) {
1754
2078
  select: Select2,
1755
2079
  checkbox: Checkbox,
1756
2080
  radioGroup: RadioGroup,
2081
+ colorPicker: ColorPicker,
1757
2082
  spacer: Spacer,
1758
2083
  divider: Divider,
1759
2084
  box: Box,
@@ -2071,10 +2396,10 @@ var AccountButton = ({
2071
2396
  size
2072
2397
  }) => {
2073
2398
  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(() => {
2399
+ const [open, setOpen] = React3.useState(false);
2400
+ const [accountInfoOpen, setAccountInfoOpen] = React3.useState(false);
2401
+ const [error, setError] = React3.useState(null);
2402
+ const initials = React3.useMemo(() => {
2078
2403
  const name = user?.displayName || user?.name;
2079
2404
  if (!name) return "";
2080
2405
  return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
@@ -2650,13 +2975,13 @@ function Composer({
2650
2975
  const accept = fileAttachments?.accept;
2651
2976
  const maxFiles = fileAttachments?.maxFiles ?? 10;
2652
2977
  const maxFileSize = fileAttachments?.maxFileSize ?? 10 * 1024 * 1024;
2653
- const [selectedOptions, setSelectedOptions] = React12__default.useState(
2978
+ const [selectedOptions, setSelectedOptions] = React3__default.useState(
2654
2979
  () => new Set(defaultSelectedIds)
2655
2980
  );
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(() => {
2981
+ const [attachedFiles, setAttachedFiles] = React3__default.useState([]);
2982
+ const [previews, setPreviews] = React3__default.useState([]);
2983
+ const fileInputRef = React3__default.useRef(null);
2984
+ React3__default.useEffect(() => {
2660
2985
  const newPreviews = attachedFiles.map((file) => ({
2661
2986
  name: file.name,
2662
2987
  type: file.type,
@@ -3227,7 +3552,7 @@ var Dropdown = ({
3227
3552
  };
3228
3553
  var ThreadList = ({ className }) => {
3229
3554
  const { threads, activeThreadId, deleteThread } = useThreads();
3230
- const sortedThreads = React12.useMemo(() => {
3555
+ const sortedThreads = React3.useMemo(() => {
3231
3556
  return [...threads].sort((a, b) => {
3232
3557
  const dateA = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
3233
3558
  const dateB = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
@@ -3455,206 +3780,6 @@ function SidebarToggle({ side, className }) {
3455
3780
  }
3456
3781
  return null;
3457
3782
  }
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
3783
  var ThreadPopover = ({
3659
3784
  className,
3660
3785
  buttonClassName,
@@ -3662,7 +3787,7 @@ var ThreadPopover = ({
3662
3787
  buttonSize = "icon",
3663
3788
  emptyState
3664
3789
  }) => {
3665
- const [isOpen, setIsOpen] = React12.useState(false);
3790
+ const [isOpen, setIsOpen] = React3.useState(false);
3666
3791
  useHotkeys(
3667
3792
  "h",
3668
3793
  (e) => {
@@ -3705,7 +3830,7 @@ var CreateThreadButton = ({
3705
3830
  onThreadCreated
3706
3831
  }) => {
3707
3832
  const { createThread } = useThreads();
3708
- const [isCreating, setIsCreating] = React12.useState(false);
3833
+ const [isCreating, setIsCreating] = React3.useState(false);
3709
3834
  const handleCreateThread = async () => {
3710
3835
  if (isCreating) return;
3711
3836
  try {
@@ -3787,7 +3912,7 @@ var CreateThreadListItem = ({
3787
3912
  className
3788
3913
  }) => {
3789
3914
  const { createThread } = useThreads();
3790
- const [isCreating, setIsCreating] = React12.useState(false);
3915
+ const [isCreating, setIsCreating] = React3.useState(false);
3791
3916
  const handleCreateThread = async () => {
3792
3917
  if (isCreating) return;
3793
3918
  try {