@mieweb/ui 0.9.0-dev.5 → 0.9.0-dev.6

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.
Files changed (33) hide show
  1. package/dist/{chunk-QWJGEDHV.js → chunk-22CYDCXA.js} +13 -1183
  2. package/dist/chunk-22CYDCXA.js.map +1 -0
  3. package/dist/chunk-3SD7PDCV.js +1878 -0
  4. package/dist/chunk-3SD7PDCV.js.map +1 -0
  5. package/dist/{chunk-PL6TFCYR.js → chunk-NORSXAXL.js} +374 -300
  6. package/dist/chunk-NORSXAXL.js.map +1 -0
  7. package/dist/chunk-T6PTKWM6.cjs +1912 -0
  8. package/dist/chunk-T6PTKWM6.cjs.map +1 -0
  9. package/dist/{chunk-XJUIZA4G.cjs → chunk-WIAQQNFU.cjs} +12 -1184
  10. package/dist/chunk-WIAQQNFU.cjs.map +1 -0
  11. package/dist/{chunk-ZXRVVNT5.cjs → chunk-XCNDZNY7.cjs} +384 -309
  12. package/dist/chunk-XCNDZNY7.cjs.map +1 -0
  13. package/dist/components/SuperChat/index.cjs +8 -8
  14. package/dist/components/SuperChat/index.js +2 -2
  15. package/dist/components/SuperChat/plugins/index.cjs +10 -3
  16. package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
  17. package/dist/components/SuperChat/plugins/index.js +9 -2
  18. package/dist/components/SuperChat/plugins/index.js.map +1 -1
  19. package/dist/index.cjs +92 -120
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +38 -4
  22. package/dist/index.d.ts +38 -4
  23. package/dist/index.js +17 -48
  24. package/dist/index.js.map +1 -1
  25. package/package.json +1 -1
  26. package/dist/chunk-H3GRO43Z.cjs +0 -735
  27. package/dist/chunk-H3GRO43Z.cjs.map +0 -1
  28. package/dist/chunk-MD3ZY4UO.js +0 -705
  29. package/dist/chunk-MD3ZY4UO.js.map +0 -1
  30. package/dist/chunk-PL6TFCYR.js.map +0 -1
  31. package/dist/chunk-QWJGEDHV.js.map +0 -1
  32. package/dist/chunk-XJUIZA4G.cjs.map +0 -1
  33. package/dist/chunk-ZXRVVNT5.cjs.map +0 -1
@@ -1,18 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkH3GRO43Z_cjs = require('./chunk-H3GRO43Z.cjs');
4
- var chunkRXPEZXAB_cjs = require('./chunk-RXPEZXAB.cjs');
5
3
  var chunkPJ6CC53R_cjs = require('./chunk-PJ6CC53R.cjs');
6
- var chunkL7L5S2HO_cjs = require('./chunk-L7L5S2HO.cjs');
7
4
  var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
8
- var chunkFHY3K6PL_cjs = require('./chunk-FHY3K6PL.cjs');
9
- var chunkFSGEDDF2_cjs = require('./chunk-FSGEDDF2.cjs');
10
- var chunkAOHJILLU_cjs = require('./chunk-AOHJILLU.cjs');
11
5
  var jsxRuntime = require('react/jsx-runtime');
12
- var React3 = require('react');
6
+ var React2 = require('react');
13
7
  var classVarianceAuthority = require('class-variance-authority');
14
- var reactDom = require('react-dom');
15
- var lucideReact = require('lucide-react');
16
8
 
17
9
  function _interopNamespace(e) {
18
10
  if (e && e.__esModule) return e;
@@ -32,7 +24,7 @@ function _interopNamespace(e) {
32
24
  return Object.freeze(n);
33
25
  }
34
26
 
35
- var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
27
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
36
28
 
37
29
  var sizeClasses = {
38
30
  sm: "h-4 w-4",
@@ -245,9 +237,9 @@ function CollapsiblePill({
245
237
  children
246
238
  }) {
247
239
  const hasContent = Boolean(children);
248
- const [isOpen, setIsOpen] = React3__namespace.useState(defaultOpen);
249
- const contentId = React3__namespace.useId();
250
- React3__namespace.useEffect(() => {
240
+ const [isOpen, setIsOpen] = React2__namespace.useState(defaultOpen);
241
+ const contentId = React2__namespace.useId();
242
+ React2__namespace.useEffect(() => {
251
243
  setIsOpen(defaultOpen);
252
244
  }, [defaultOpen]);
253
245
  const toggle = () => {
@@ -1104,10 +1096,10 @@ function ThinkingBlock({
1104
1096
  streaming,
1105
1097
  defaultCollapsed = false
1106
1098
  }) {
1107
- const startedAt = React3__namespace.useRef(Date.now());
1108
- const [elapsed, setElapsed] = React3__namespace.useState(null);
1109
- const prevStreaming = React3__namespace.useRef(streaming);
1110
- React3__namespace.useEffect(() => {
1099
+ const startedAt = React2__namespace.useRef(Date.now());
1100
+ const [elapsed, setElapsed] = React2__namespace.useState(null);
1101
+ const prevStreaming = React2__namespace.useRef(streaming);
1102
+ React2__namespace.useEffect(() => {
1111
1103
  if (prevStreaming.current && !streaming) {
1112
1104
  setElapsed(Math.round((Date.now() - startedAt.current) / 1e3));
1113
1105
  }
@@ -1311,7 +1303,7 @@ var bubbleVariants = classVarianceAuthority.cva("rounded-2xl px-4 py-2.5 w-fit m
1311
1303
  variant: "assistant"
1312
1304
  }
1313
1305
  });
1314
- var ChatBubble = React3__namespace.forwardRef(
1306
+ var ChatBubble = React2__namespace.forwardRef(
1315
1307
  ({ className, variant, hasError, accent, style, children, ...props }, ref) => {
1316
1308
  return /* @__PURE__ */ jsxRuntime.jsx(
1317
1309
  "div",
@@ -1427,1178 +1419,14 @@ function AIMessageDisplay({
1427
1419
  }
1428
1420
  );
1429
1421
  }
1430
- var MENU_OFFSET_PX = 6;
1431
- var MENU_MAX_HEIGHT_PX = 320;
1432
- function optionKey(option) {
1433
- return `${option.provider}\0${option.model}`;
1434
- }
1435
- function renderedOptionKey(option, index) {
1436
- return `${option.id ?? optionKey(option)}\0${index}`;
1437
- }
1438
- function groupByProvider(models) {
1439
- const groups = /* @__PURE__ */ new Map();
1440
- for (const model of models) {
1441
- const group = groups.get(model.provider);
1442
- if (group) {
1443
- group.push(model);
1444
- } else {
1445
- groups.set(model.provider, [model]);
1446
- }
1447
- }
1448
- return Array.from(groups, ([provider, options]) => ({ provider, options }));
1449
- }
1450
- function getProviderLabel(models, provider) {
1451
- return models.find((model) => model.provider === provider && model.providerLabel)?.providerLabel ?? provider;
1452
- }
1453
- function ComposerModelSelector({
1454
- models,
1455
- value,
1456
- providerFilter,
1457
- onProviderFilterChange,
1458
- onChange,
1459
- disabled = false,
1460
- variant = "default",
1461
- className,
1462
- boundaryRef,
1463
- placeholder = "Model",
1464
- anyLabel = "Any",
1465
- emptyLabel = "No models",
1466
- ariaLabel = "Model",
1467
- effortOptions,
1468
- effort = null,
1469
- defaultEffort,
1470
- onEffortChange,
1471
- effortLabel = "Effort",
1472
- effortHint,
1473
- defaultBadgeLabel = "Default",
1474
- backLabel = "Back"
1475
- }) {
1476
- const [open, setOpen] = React3__namespace.useState(false);
1477
- const [view, setView] = React3__namespace.useState("models");
1478
- const [effortHighlight, setEffortHighlight] = React3__namespace.useState(0);
1479
- const [internalProviderFilter, setInternalProviderFilter] = React3__namespace.useState(null);
1480
- const [highlightedIndex, setHighlightedIndex] = React3__namespace.useState(0);
1481
- const listRef = React3__namespace.useRef(null);
1482
- const effortListRef = React3__namespace.useRef(null);
1483
- const menuId = React3__namespace.useId();
1484
- const {
1485
- anchorRef: triggerRef,
1486
- floatingRef: menuRef,
1487
- style: menuStyle
1488
- } = chunkAOHJILLU_cjs.useAnchoredPosition({
1489
- open,
1490
- placement: "top-start",
1491
- offset: MENU_OFFSET_PX,
1492
- matchMinWidth: true,
1493
- maxHeight: MENU_MAX_HEIGHT_PX,
1494
- allowFlip: false,
1495
- boundaryRef
1496
- });
1497
- const activeProviderFilter = providerFilter === void 0 ? internalProviderFilter : providerFilter;
1498
- const selectedKey = value ? optionKey(value) : null;
1499
- const selectedOption = models.find(
1500
- (model) => optionKey(model) === selectedKey
1501
- );
1502
- const providers = React3__namespace.useMemo(
1503
- () => Array.from(new Set(models.map((model) => model.provider))),
1504
- [models]
1505
- );
1506
- const providerLabels = React3__namespace.useMemo(
1507
- () => new Map(
1508
- providers.map((provider) => [
1509
- provider,
1510
- getProviderLabel(models, provider)
1511
- ])
1512
- ),
1513
- [models, providers]
1514
- );
1515
- const filteredModels = React3__namespace.useMemo(
1516
- () => activeProviderFilter === null ? models : models.filter((model) => model.provider === activeProviderFilter),
1517
- [activeProviderFilter, models]
1518
- );
1519
- const groupedModels = React3__namespace.useMemo(
1520
- () => groupByProvider(filteredModels),
1521
- [filteredModels]
1522
- );
1523
- const groupedRenderedModels = React3__namespace.useMemo(() => {
1524
- let index = 0;
1525
- return groupedModels.map((group) => ({
1526
- provider: group.provider,
1527
- options: group.options.map((option) => {
1528
- const rendered = {
1529
- option,
1530
- index,
1531
- key: renderedOptionKey(option, index)
1532
- };
1533
- index += 1;
1534
- return rendered;
1535
- })
1536
- }));
1537
- }, [groupedModels]);
1538
- const renderedModels = React3__namespace.useMemo(
1539
- () => groupedRenderedModels.flatMap((group) => group.options),
1540
- [groupedRenderedModels]
1541
- );
1542
- const getOptionId = React3__namespace.useCallback(
1543
- (index) => `${menuId}-option-${index}`,
1544
- [menuId]
1545
- );
1546
- const getEffortOptionId = React3__namespace.useCallback(
1547
- (index) => `${menuId}-effort-option-${index}`,
1548
- [menuId]
1549
- );
1550
- const activeOptionId = open && renderedModels[highlightedIndex] ? getOptionId(highlightedIndex) : void 0;
1551
- const selectedRenderedIndex = React3__namespace.useMemo(
1552
- () => selectedKey ? renderedModels.findIndex(
1553
- (renderedModel) => optionKey(renderedModel.option) === selectedKey
1554
- ) : -1,
1555
- [renderedModels, selectedKey]
1556
- );
1557
- const setProvider = React3__namespace.useCallback(
1558
- (provider) => {
1559
- if (providerFilter === void 0) {
1560
- setInternalProviderFilter(provider);
1561
- }
1562
- onProviderFilterChange?.(provider);
1563
- },
1564
- [onProviderFilterChange, providerFilter]
1565
- );
1566
- const close = React3__namespace.useCallback(
1567
- (restoreFocus = true) => {
1568
- setOpen(false);
1569
- if (restoreFocus) {
1570
- triggerRef.current?.focus({ preventScroll: true });
1571
- }
1572
- },
1573
- [triggerRef]
1574
- );
1575
- const selectModel = React3__namespace.useCallback(
1576
- (model) => {
1577
- onChange({ provider: model.provider, model: model.model });
1578
- close();
1579
- },
1580
- [close, onChange]
1581
- );
1582
- const efforts = React3__namespace.useMemo(() => effortOptions ?? [], [effortOptions]);
1583
- const activeEffortOptionId = open && efforts[effortHighlight] ? getEffortOptionId(effortHighlight) : void 0;
1584
- const selectedEffortOption = efforts.find(
1585
- (option) => option.value === effort
1586
- );
1587
- const selectEffort = React3__namespace.useCallback(
1588
- (value2) => {
1589
- onEffortChange?.(value2);
1590
- close();
1591
- },
1592
- [close, onEffortChange]
1593
- );
1594
- const handleEffortKeyDown = (event) => {
1595
- if (efforts.length === 0) return;
1596
- if (event.key === "ArrowDown") {
1597
- event.preventDefault();
1598
- setEffortHighlight((current) => (current + 1) % efforts.length);
1599
- }
1600
- if (event.key === "ArrowUp") {
1601
- event.preventDefault();
1602
- setEffortHighlight(
1603
- (current) => (current - 1 + efforts.length) % efforts.length
1604
- );
1605
- }
1606
- if (event.key === "Home") {
1607
- event.preventDefault();
1608
- setEffortHighlight(0);
1609
- }
1610
- if (event.key === "End") {
1611
- event.preventDefault();
1612
- setEffortHighlight(efforts.length - 1);
1613
- }
1614
- if (event.key === "ArrowLeft" || event.key === "Backspace") {
1615
- event.preventDefault();
1616
- setView("models");
1617
- }
1618
- if (event.key === "Enter" || event.key === " ") {
1619
- event.preventDefault();
1620
- const highlighted = efforts[effortHighlight];
1621
- if (highlighted) selectEffort(highlighted.value);
1622
- }
1623
- };
1624
- const outsideRefs = React3__namespace.useMemo(
1625
- () => [triggerRef, menuRef],
1626
- [triggerRef, menuRef]
1627
- );
1628
- chunkFSGEDDF2_cjs.useClickOutside(outsideRefs, () => close(false), open);
1629
- chunkFHY3K6PL_cjs.useEscapeKey(close, open);
1630
- React3__namespace.useEffect(() => {
1631
- if (!open) return;
1632
- setHighlightedIndex(selectedRenderedIndex >= 0 ? selectedRenderedIndex : 0);
1633
- }, [activeProviderFilter, open, selectedRenderedIndex]);
1634
- React3__namespace.useEffect(() => {
1635
- if (!open) return;
1636
- setView("models");
1637
- }, [open]);
1638
- React3__namespace.useEffect(() => {
1639
- if (!open) return;
1640
- const current = efforts.findIndex((option) => option.value === effort);
1641
- setEffortHighlight(current >= 0 ? current : 0);
1642
- }, [effort, efforts, open]);
1643
- React3__namespace.useEffect(() => {
1644
- if (!open) return;
1645
- setHighlightedIndex(
1646
- (current) => Math.min(current, Math.max(renderedModels.length - 1, 0))
1647
- );
1648
- }, [open, renderedModels.length]);
1649
- React3__namespace.useEffect(() => {
1650
- if (!open) return;
1651
- requestAnimationFrame(() => {
1652
- const target = view === "effort" ? effortListRef.current : listRef.current;
1653
- target?.focus({ preventScroll: true });
1654
- });
1655
- }, [open, view]);
1656
- const handleTriggerKeyDown = (event) => {
1657
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1658
- event.preventDefault();
1659
- setOpen(true);
1660
- }
1661
- };
1662
- const handleMenuKeyDown = (event) => {
1663
- if (renderedModels.length === 0) return;
1664
- if (event.key === "ArrowDown") {
1665
- event.preventDefault();
1666
- setHighlightedIndex((current) => (current + 1) % renderedModels.length);
1667
- }
1668
- if (event.key === "ArrowUp") {
1669
- event.preventDefault();
1670
- setHighlightedIndex(
1671
- (current) => (current - 1 + renderedModels.length) % renderedModels.length
1672
- );
1673
- }
1674
- if (event.key === "Home") {
1675
- event.preventDefault();
1676
- setHighlightedIndex(0);
1677
- }
1678
- if (event.key === "End") {
1679
- event.preventDefault();
1680
- setHighlightedIndex(renderedModels.length - 1);
1681
- }
1682
- if (event.key === "Enter" || event.key === " ") {
1683
- event.preventDefault();
1684
- const highlightedModel = renderedModels[highlightedIndex]?.option;
1685
- if (highlightedModel) {
1686
- selectModel(highlightedModel);
1687
- }
1688
- }
1689
- };
1690
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1691
- /* @__PURE__ */ jsxRuntime.jsxs(
1692
- "button",
1693
- {
1694
- ref: triggerRef,
1695
- type: "button",
1696
- disabled,
1697
- "aria-haspopup": "listbox",
1698
- "aria-expanded": open,
1699
- "aria-controls": open ? menuId : void 0,
1700
- onClick: () => setOpen((current) => !current),
1701
- onKeyDown: handleTriggerKeyDown,
1702
- "data-slot": "composer-model-selector-trigger",
1703
- className: chunkS5RVSXDV_cjs.cn(
1704
- variant === "ghost" ? [
1705
- "inline-flex max-w-full min-w-0 items-center gap-1 rounded-md px-2 py-1 text-xs",
1706
- "text-neutral-600 dark:text-neutral-400",
1707
- "transition-colors duration-150",
1708
- "hover:bg-neutral-100 hover:text-neutral-900 dark:hover:bg-neutral-700 dark:hover:text-white",
1709
- "focus-visible:ring-primary-500 focus-visible:ring-2 focus-visible:outline-none",
1710
- "disabled:pointer-events-none disabled:opacity-40"
1711
- ] : [
1712
- "inline-flex h-8 max-w-full items-center gap-1.5 rounded-full border px-2.5 text-sm font-medium",
1713
- "border-border bg-background text-foreground shadow-sm",
1714
- "hover:bg-muted/50",
1715
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
1716
- "disabled:cursor-not-allowed disabled:opacity-50"
1717
- ],
1718
- className
1719
- ),
1720
- children: [
1721
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: selectedOption?.label ?? selectedOption?.model ?? placeholder }),
1722
- selectedEffortOption && /* @__PURE__ */ jsxRuntime.jsx(
1723
- "span",
1724
- {
1725
- "data-slot": "composer-model-selector-trigger-effort",
1726
- className: "text-muted-foreground min-w-0 truncate font-normal",
1727
- children: selectedEffortOption.label
1728
- }
1729
- ),
1730
- /* @__PURE__ */ jsxRuntime.jsx(
1731
- lucideReact.ChevronUp,
1732
- {
1733
- "aria-hidden": "true",
1734
- className: chunkS5RVSXDV_cjs.cn(
1735
- "shrink-0",
1736
- variant === "ghost" ? "h-3 w-3" : "h-3.5 w-3.5"
1737
- )
1738
- }
1739
- )
1740
- ]
1741
- }
1742
- ),
1743
- open && reactDom.createPortal(
1744
- /* @__PURE__ */ jsxRuntime.jsxs(
1745
- "div",
1746
- {
1747
- ref: menuRef,
1748
- style: menuStyle,
1749
- "data-slot": "composer-model-selector-menu",
1750
- className: chunkS5RVSXDV_cjs.cn(
1751
- "border-border bg-card text-card-foreground flex w-80 max-w-full flex-col rounded-lg border shadow-lg",
1752
- "animate-in fade-in overflow-hidden duration-100"
1753
- ),
1754
- children: [
1755
- view === "models" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1756
- /* @__PURE__ */ jsxRuntime.jsx(
1757
- "div",
1758
- {
1759
- "data-slot": "composer-model-selector-provider-filter",
1760
- className: "border-border flex min-h-9 items-center gap-1 overflow-x-auto overflow-y-hidden border-b p-2",
1761
- children: [null, ...providers].map((provider) => {
1762
- const selected = activeProviderFilter === provider;
1763
- return /* @__PURE__ */ jsxRuntime.jsx(
1764
- "button",
1765
- {
1766
- type: "button",
1767
- "aria-pressed": selected,
1768
- onMouseDown: (event) => event.preventDefault(),
1769
- onClick: () => setProvider(provider),
1770
- className: chunkS5RVSXDV_cjs.cn(
1771
- "inline-flex h-6 shrink-0 items-center justify-center rounded-full px-2.5 text-xs font-medium whitespace-nowrap transition-colors",
1772
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
1773
- selected ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground"
1774
- ),
1775
- children: provider === null ? anyLabel : providerLabels.get(provider) ?? provider
1776
- },
1777
- provider ?? "all-providers"
1778
- );
1779
- })
1780
- }
1781
- ),
1782
- /* @__PURE__ */ jsxRuntime.jsx(
1783
- "div",
1784
- {
1785
- ref: listRef,
1786
- id: menuId,
1787
- role: "listbox",
1788
- "aria-label": ariaLabel,
1789
- "aria-activedescendant": activeOptionId,
1790
- tabIndex: -1,
1791
- onKeyDown: handleMenuKeyDown,
1792
- className: "min-h-0 flex-1 overflow-y-auto p-1",
1793
- children: groupedModels.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground px-3 py-4 text-center text-sm", children: emptyLabel }) : groupedRenderedModels.map((group) => /* @__PURE__ */ jsxRuntime.jsxs(
1794
- "div",
1795
- {
1796
- role: "group",
1797
- "aria-label": providerLabels.get(group.provider) ?? group.provider,
1798
- children: [
1799
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground px-3 py-1.5 text-xs font-semibold uppercase", children: providerLabels.get(group.provider) ?? group.provider }),
1800
- group.options.map((renderedModel) => {
1801
- const { index, key, option: model } = renderedModel;
1802
- const selected = optionKey(model) === selectedKey;
1803
- const highlighted = index === highlightedIndex;
1804
- return /* @__PURE__ */ jsxRuntime.jsxs(
1805
- "button",
1806
- {
1807
- id: getOptionId(index),
1808
- type: "button",
1809
- role: "option",
1810
- "aria-selected": selected,
1811
- onMouseDown: (event) => event.preventDefault(),
1812
- onClick: () => selectModel(model),
1813
- onMouseEnter: () => setHighlightedIndex(index),
1814
- className: chunkS5RVSXDV_cjs.cn(
1815
- "flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm",
1816
- "focus-visible:ring-ring transition-colors focus-visible:ring-2 focus-visible:outline-none",
1817
- highlighted && "bg-muted",
1818
- selected && "bg-primary/10 text-primary"
1819
- ),
1820
- children: [
1821
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: model.label ?? model.model }),
1822
- selected && /* @__PURE__ */ jsxRuntime.jsx(
1823
- lucideReact.Check,
1824
- {
1825
- "aria-hidden": "true",
1826
- className: "text-primary h-4 w-4 shrink-0"
1827
- }
1828
- )
1829
- ]
1830
- },
1831
- key
1832
- );
1833
- })
1834
- ]
1835
- },
1836
- group.provider
1837
- ))
1838
- }
1839
- ),
1840
- efforts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border border-t p-1", children: /* @__PURE__ */ jsxRuntime.jsxs(
1841
- "button",
1842
- {
1843
- type: "button",
1844
- "data-slot": "composer-model-selector-effort-row",
1845
- "aria-haspopup": "listbox",
1846
- onMouseDown: (event) => event.preventDefault(),
1847
- onClick: () => setView("effort"),
1848
- className: chunkS5RVSXDV_cjs.cn(
1849
- "flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm",
1850
- "hover:bg-muted transition-colors",
1851
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"
1852
- ),
1853
- children: [
1854
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: effortLabel }),
1855
- selectedEffortOption && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground min-w-0 truncate", children: selectedEffortOption.label }),
1856
- /* @__PURE__ */ jsxRuntime.jsx(
1857
- lucideReact.ChevronRight,
1858
- {
1859
- "aria-hidden": "true",
1860
- className: "text-muted-foreground h-4 w-4 shrink-0 rtl:-scale-x-100"
1861
- }
1862
- )
1863
- ]
1864
- }
1865
- ) })
1866
- ] }),
1867
- view === "effort" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1868
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border flex items-center gap-1 border-b p-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
1869
- "button",
1870
- {
1871
- type: "button",
1872
- "data-slot": "composer-model-selector-effort-back",
1873
- "aria-label": backLabel,
1874
- onMouseDown: (event) => event.preventDefault(),
1875
- onClick: () => setView("models"),
1876
- className: chunkS5RVSXDV_cjs.cn(
1877
- "inline-flex h-6 shrink-0 items-center gap-1 rounded-full px-2 text-xs font-medium",
1878
- "text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",
1879
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"
1880
- ),
1881
- children: [
1882
- /* @__PURE__ */ jsxRuntime.jsx(
1883
- lucideReact.ChevronLeft,
1884
- {
1885
- "aria-hidden": "true",
1886
- className: "h-3.5 w-3.5 rtl:-scale-x-100"
1887
- }
1888
- ),
1889
- effortLabel
1890
- ]
1891
- }
1892
- ) }),
1893
- effortHint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground px-3 pt-2 text-xs", children: effortHint }),
1894
- /* @__PURE__ */ jsxRuntime.jsx(
1895
- "div",
1896
- {
1897
- ref: effortListRef,
1898
- id: menuId,
1899
- role: "listbox",
1900
- "aria-label": effortLabel,
1901
- "aria-activedescendant": activeEffortOptionId,
1902
- tabIndex: -1,
1903
- onKeyDown: handleEffortKeyDown,
1904
- className: "min-h-0 flex-1 overflow-y-auto p-1",
1905
- children: efforts.map((option, index) => {
1906
- const selected = option.value === effort;
1907
- const highlighted = index === effortHighlight;
1908
- return /* @__PURE__ */ jsxRuntime.jsxs(
1909
- "button",
1910
- {
1911
- id: getEffortOptionId(index),
1912
- type: "button",
1913
- role: "option",
1914
- "aria-selected": selected,
1915
- onMouseDown: (event) => event.preventDefault(),
1916
- onClick: () => selectEffort(option.value),
1917
- onMouseEnter: () => setEffortHighlight(index),
1918
- className: chunkS5RVSXDV_cjs.cn(
1919
- "flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm",
1920
- "focus-visible:ring-ring transition-colors focus-visible:ring-2 focus-visible:outline-none",
1921
- highlighted && "bg-muted",
1922
- selected && "bg-primary/10 text-primary"
1923
- ),
1924
- children: [
1925
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1926
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate", children: option.label }),
1927
- option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground block truncate text-xs", children: option.description })
1928
- ] }),
1929
- option.value === defaultEffort && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-muted text-muted-foreground shrink-0 rounded px-1.5 py-0.5 text-xs", children: defaultBadgeLabel }),
1930
- selected && /* @__PURE__ */ jsxRuntime.jsx(
1931
- lucideReact.Check,
1932
- {
1933
- "aria-hidden": "true",
1934
- className: "text-primary h-4 w-4 shrink-0"
1935
- }
1936
- )
1937
- ]
1938
- },
1939
- option.value
1940
- );
1941
- })
1942
- }
1943
- )
1944
- ] })
1945
- ]
1946
- }
1947
- ),
1948
- document.body
1949
- )
1950
- ] });
1951
- }
1952
- ComposerModelSelector.displayName = "ComposerModelSelector";
1953
- var iconButtonClasses = chunkS5RVSXDV_cjs.cn(
1954
- "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg",
1955
- "text-neutral-500 dark:text-neutral-400",
1956
- "transition-colors duration-150",
1957
- "hover:bg-neutral-100 hover:text-neutral-900 dark:hover:bg-neutral-700 dark:hover:text-white",
1958
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500",
1959
- "disabled:pointer-events-none disabled:opacity-40"
1960
- );
1961
- var selectorTriggerClasses = chunkS5RVSXDV_cjs.cn(
1962
- "flex min-w-0 items-center gap-1 rounded-md px-2 py-1 text-xs",
1963
- "text-neutral-600 dark:text-neutral-400",
1964
- "transition-colors duration-150",
1965
- "hover:bg-neutral-100 hover:text-neutral-900 dark:hover:bg-neutral-700 dark:hover:text-white",
1966
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500",
1967
- "disabled:pointer-events-none disabled:opacity-40"
1968
- );
1969
- var MAX_INPUT_HEIGHT = 160;
1970
- var ChatComposer = React3__namespace.forwardRef(function ChatComposer2({
1971
- onSend,
1972
- value: controlledValue,
1973
- onValueChange,
1974
- placeholder = "Type a message\u2026",
1975
- disabled = false,
1976
- isSending = false,
1977
- autoFocus = false,
1978
- maxLength,
1979
- showCharacterCount = false,
1980
- canSendWhenEmpty = false,
1981
- maxHeight = MAX_INPUT_HEIGHT,
1982
- textareaProps,
1983
- addMenuItems,
1984
- allowAttachments = true,
1985
- acceptedFileTypes,
1986
- maxFileSize,
1987
- maxAttachments = 10,
1988
- mentionOptions,
1989
- replyTo = null,
1990
- onCancelReply,
1991
- showMic = false,
1992
- onMicClick,
1993
- micSlot,
1994
- micBehavior = "always",
1995
- isStreaming = false,
1996
- onStop,
1997
- showAgentSelector = false,
1998
- agents = [],
1999
- selectedAgent = null,
2000
- onAgentChange,
2001
- showModelSelector = false,
2002
- modelSelectorProps,
2003
- readOnly = false,
2004
- readOnlyMessage = "You have read-only access and cannot send messages.",
2005
- onError,
2006
- attachmentLimitLabel,
2007
- sendFailedLabel = "Failed to send message",
2008
- sendingLabel = "Sending message\u2026",
2009
- inputLabel = "Message input",
2010
- addMenuLabel = "Add to message",
2011
- attachFilesLabel = "Attach files",
2012
- micLabel = "Start voice input",
2013
- sendLabel = "Send message",
2014
- stopLabel = "Stop generating",
2015
- agentSelectorLabel = "Select agent",
2016
- mentionListLabel = "Mention",
2017
- dropFilesLabel = "Drop files here",
2018
- replyingToLabel = "Replying to",
2019
- cancelReplyLabel = "Cancel reply",
2020
- className
2021
- }, ref) {
2022
- const [internalValue, setInternalValue] = React3__namespace.useState("");
2023
- const isControlled = controlledValue !== void 0;
2024
- const value = isControlled ? controlledValue : internalValue;
2025
- const [attachments, setAttachments] = React3__namespace.useState([]);
2026
- const attachmentsRef = React3__namespace.useRef(attachments);
2027
- attachmentsRef.current = attachments;
2028
- const textareaRef = React3__namespace.useRef(null);
2029
- const fileInputRef = React3__namespace.useRef(null);
2030
- const [addMenuOpen, setAddMenuOpen] = React3__namespace.useState(false);
2031
- const [agentMenuOpen, setAgentMenuOpen] = React3__namespace.useState(false);
2032
- const replyToId = replyTo?.id;
2033
- React3__namespace.useEffect(() => {
2034
- if (replyToId !== void 0) {
2035
- textareaRef.current?.focus();
2036
- }
2037
- }, [replyToId]);
2038
- const hasText = value.trim().length > 0;
2039
- const hasContent = hasText || attachments.length > 0;
2040
- const isOverLimit = maxLength !== void 0 && value.length > maxLength;
2041
- const canSend = (hasContent || canSendWhenEmpty) && onSend !== void 0 && !disabled && !isSending && !isStreaming && !isOverLimit;
2042
- const setValue = React3__namespace.useCallback(
2043
- (next) => {
2044
- if (!isControlled) setInternalValue(next);
2045
- onValueChange?.(next);
2046
- },
2047
- [isControlled, onValueChange]
2048
- );
2049
- const mention = chunkH3GRO43Z_cjs.useMentionAutocomplete({
2050
- options: mentionOptions,
2051
- value,
2052
- setValue,
2053
- textareaRef
2054
- });
2055
- const resizeTextarea = React3__namespace.useCallback(() => {
2056
- const textarea = textareaRef.current;
2057
- if (!textarea) return;
2058
- textarea.style.height = "auto";
2059
- if (textarea.scrollHeight === 0) return;
2060
- textarea.style.height = `${textarea.scrollHeight}px`;
2061
- }, []);
2062
- React3__namespace.useLayoutEffect(resizeTextarea, [resizeTextarea, value]);
2063
- React3__namespace.useEffect(() => {
2064
- const textarea = textareaRef.current;
2065
- if (!textarea || typeof ResizeObserver === "undefined") return;
2066
- let frame = 0;
2067
- const observer = new ResizeObserver(() => {
2068
- cancelAnimationFrame(frame);
2069
- frame = requestAnimationFrame(resizeTextarea);
2070
- });
2071
- observer.observe(textarea);
2072
- return () => {
2073
- cancelAnimationFrame(frame);
2074
- observer.disconnect();
2075
- };
2076
- }, [resizeTextarea]);
2077
- const addFiles = React3__namespace.useCallback(
2078
- (files) => {
2079
- if (!allowAttachments || files.length === 0) return;
2080
- const limitMessage = attachmentLimitLabel ?? `Attachment limit reached (max ${maxAttachments})`;
2081
- const room = maxAttachments - attachmentsRef.current.length;
2082
- if (files.length > room) {
2083
- onError?.(limitMessage, { reason: "attachment-limit" });
2084
- if (room <= 0) return;
2085
- }
2086
- const staged = [];
2087
- for (const file of files.slice(0, Math.max(room, 0))) {
2088
- const typeCheck = chunkH3GRO43Z_cjs.validateFile(file, acceptedFileTypes, void 0);
2089
- if (!typeCheck.valid) {
2090
- onError?.(`${file.name}: ${typeCheck.error}`, {
2091
- reason: "file-type",
2092
- file
2093
- });
2094
- continue;
2095
- }
2096
- const sizeCheck = chunkH3GRO43Z_cjs.validateFile(file, void 0, maxFileSize);
2097
- if (!sizeCheck.valid) {
2098
- onError?.(`${file.name}: ${sizeCheck.error}`, {
2099
- reason: "file-size",
2100
- file
2101
- });
2102
- continue;
2103
- }
2104
- const type = chunkH3GRO43Z_cjs.getFileType(file.type);
2105
- staged.push({
2106
- id: chunkH3GRO43Z_cjs.generateAttachmentId(),
2107
- file,
2108
- type,
2109
- previewUrl: type === "image" || type === "video" ? URL.createObjectURL(file) : void 0
2110
- });
2111
- }
2112
- if (staged.length > 0) {
2113
- attachmentsRef.current = [...attachmentsRef.current, ...staged];
2114
- setAttachments((current) => [...current, ...staged]);
2115
- }
2116
- },
2117
- [
2118
- allowAttachments,
2119
- maxAttachments,
2120
- acceptedFileTypes,
2121
- maxFileSize,
2122
- onError,
2123
- attachmentLimitLabel
2124
- ]
2125
- );
2126
- const removeAttachment = React3__namespace.useCallback((id) => {
2127
- const target = attachmentsRef.current.find(
2128
- (attachment) => attachment.id === id
2129
- );
2130
- if (target?.previewUrl) URL.revokeObjectURL(target.previewUrl);
2131
- attachmentsRef.current = attachmentsRef.current.filter(
2132
- (attachment) => attachment.id !== id
2133
- );
2134
- setAttachments(
2135
- (current) => current.filter((attachment) => attachment.id !== id)
2136
- );
2137
- }, []);
2138
- React3__namespace.useEffect(() => {
2139
- return () => {
2140
- for (const attachment of attachmentsRef.current) {
2141
- if (attachment.previewUrl) URL.revokeObjectURL(attachment.previewUrl);
2142
- }
2143
- };
2144
- }, []);
2145
- const handleFileInputChange = (event) => {
2146
- const files = Array.from(event.target.files ?? []);
2147
- addFiles(files);
2148
- event.target.value = "";
2149
- };
2150
- const handlePaste = (event) => {
2151
- if (!allowAttachments) return;
2152
- const files = Array.from(event.clipboardData.files);
2153
- if (files.length > 0) {
2154
- event.preventDefault();
2155
- addFiles(files);
2156
- }
2157
- };
2158
- React3__namespace.useImperativeHandle(
2159
- ref,
2160
- () => ({
2161
- addFiles,
2162
- focus: () => textareaRef.current?.focus(),
2163
- getTextarea: () => textareaRef.current
2164
- }),
2165
- [addFiles]
2166
- );
2167
- const handleSend = () => {
2168
- if (!canSend || !onSend) return;
2169
- const message = {
2170
- content: value.trim(),
2171
- attachments: attachments.map((attachment) => attachment.file),
2172
- // Only add the key when replying — hosts may key-check the payload.
2173
- ...replyTo ? { replyToId: replyTo.id } : {}
2174
- };
2175
- for (const attachment of attachments) {
2176
- if (attachment.previewUrl) URL.revokeObjectURL(attachment.previewUrl);
2177
- }
2178
- attachmentsRef.current = [];
2179
- setAttachments([]);
2180
- setValue("");
2181
- try {
2182
- Promise.resolve(onSend(message)).catch(() => {
2183
- onError?.(sendFailedLabel, { reason: "send-failed" });
2184
- });
2185
- } catch {
2186
- onError?.(sendFailedLabel, { reason: "send-failed" });
2187
- }
2188
- textareaRef.current?.focus();
2189
- };
2190
- const handleKeyDown = (event) => {
2191
- if (mention.handleKeyDown(event)) return;
2192
- if (event.key === "Enter" && !event.shiftKey) {
2193
- event.preventDefault();
2194
- handleSend();
2195
- }
2196
- };
2197
- if (readOnly) {
2198
- return /* @__PURE__ */ jsxRuntime.jsxs(
2199
- "div",
2200
- {
2201
- "data-slot": "chat-composer",
2202
- role: "status",
2203
- className: chunkS5RVSXDV_cjs.cn(
2204
- "flex items-center gap-2 rounded-xl border px-4 py-3 text-sm",
2205
- "border-amber-300 bg-amber-50 text-amber-900",
2206
- "dark:border-amber-700 dark:bg-amber-950 dark:text-amber-200",
2207
- className
2208
- ),
2209
- children: [
2210
- /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.AlertTriangle, { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
2211
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "chat-composer-readonly", children: readOnlyMessage })
2212
- ]
2213
- }
2214
- );
2215
- }
2216
- const showAddMenu = allowAttachments || addMenuItems && addMenuItems.length > 0;
2217
- const micVisible = (showMic || onMicClick !== void 0 || micSlot !== void 0) && (micBehavior === "always" || !hasContent);
2218
- const showSelectorRow = showAgentSelector || showModelSelector;
2219
- const selectedAgentOption = agents.find((agent) => agent.id === selectedAgent) ?? null;
2220
- const cells = {
2221
- input: "col-span-3 col-start-1 row-start-1 px-1 pt-1 md:col-span-1 md:col-start-2 md:self-end md:px-0 md:py-1.5",
2222
- textarea: "px-2 pt-2 pb-1 md:py-1.5",
2223
- add: "col-start-1 row-start-2 pb-2 ps-2 md:row-start-1 md:self-end md:p-1.5 md:pe-0.5",
2224
- actions: "col-start-3 row-start-2 flex items-center gap-1 pb-2 pe-2 md:row-start-1 md:self-end md:gap-0.5 md:p-1.5 md:ps-0.5"
2225
- };
2226
- const composerCard = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2227
- replyTo && /* @__PURE__ */ jsxRuntime.jsxs(
2228
- "div",
2229
- {
2230
- "data-slot": "chat-composer-reply-preview",
2231
- className: chunkS5RVSXDV_cjs.cn(
2232
- "flex items-center gap-2 rounded-t-2xl px-4 py-2",
2233
- "bg-neutral-50 dark:bg-neutral-800/50",
2234
- "border-b border-neutral-200 dark:border-neutral-700",
2235
- "border-s-primary-500 border-s-4"
2236
- ),
2237
- children: [
2238
- /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "status", className: "min-w-0 flex-1", children: [
2239
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-primary-800 dark:text-primary-400 block text-xs font-medium", children: [
2240
- replyingToLabel,
2241
- " ",
2242
- replyTo.senderName
2243
- ] }),
2244
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm text-neutral-600 dark:text-neutral-300", children: replyTo.content })
2245
- ] }),
2246
- /* @__PURE__ */ jsxRuntime.jsx(
2247
- "button",
2248
- {
2249
- type: "button",
2250
- "data-slot": "chat-composer-cancel-reply",
2251
- "aria-label": cancelReplyLabel,
2252
- disabled,
2253
- onClick: onCancelReply,
2254
- className: iconButtonClasses,
2255
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.X2, { className: "h-4 w-4", "aria-hidden": "true" })
2256
- }
2257
- )
2258
- ]
2259
- }
2260
- ),
2261
- attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
2262
- "div",
2263
- {
2264
- "data-slot": "chat-composer-attachments",
2265
- className: "flex flex-wrap gap-2 px-3 pt-3",
2266
- children: attachments.map((attachment) => /* @__PURE__ */ jsxRuntime.jsx(
2267
- chunkH3GRO43Z_cjs.AttachmentPreviewItem,
2268
- {
2269
- attachment: { ...attachment, state: "pending" },
2270
- onRemove: () => removeAttachment(attachment.id),
2271
- disabled
2272
- },
2273
- attachment.id
2274
- ))
2275
- }
2276
- ),
2277
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto]", children: [
2278
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cells.input, ref: mention.anchorRef, children: [
2279
- /* @__PURE__ */ jsxRuntime.jsx(
2280
- chunkH3GRO43Z_cjs.MentionMenu,
2281
- {
2282
- mention,
2283
- label: mentionListLabel,
2284
- dataSlot: "chat-composer-mention-list"
2285
- }
2286
- ),
2287
- /* @__PURE__ */ jsxRuntime.jsx(
2288
- "textarea",
2289
- {
2290
- ...textareaProps,
2291
- ref: textareaRef,
2292
- "data-slot": "chat-composer-input",
2293
- value,
2294
- onChange: (event) => {
2295
- textareaProps?.onChange?.(event);
2296
- setValue(event.target.value);
2297
- mention.sync(
2298
- event.target.value,
2299
- event.target.selectionStart ?? event.target.value.length
2300
- );
2301
- },
2302
- onKeyDown: (event) => {
2303
- textareaProps?.onKeyDown?.(event);
2304
- if (event.defaultPrevented) return;
2305
- handleKeyDown(event);
2306
- },
2307
- onClick: (event) => {
2308
- textareaProps?.onClick?.(event);
2309
- if (event.defaultPrevented) return;
2310
- const el = event.currentTarget;
2311
- mention.sync(el.value, el.selectionStart ?? el.value.length);
2312
- },
2313
- onPaste: (event) => {
2314
- textareaProps?.onPaste?.(event);
2315
- if (event.defaultPrevented) return;
2316
- handlePaste(event);
2317
- },
2318
- placeholder,
2319
- disabled,
2320
- autoFocus,
2321
- rows: 1,
2322
- "aria-label": inputLabel,
2323
- ...mention.inputProps,
2324
- style: {
2325
- ...textareaProps?.style,
2326
- maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight
2327
- },
2328
- className: chunkS5RVSXDV_cjs.cn(
2329
- "block w-full resize-none bg-transparent",
2330
- "rounded-lg text-sm",
2331
- cells.textarea,
2332
- "text-neutral-900 placeholder:text-neutral-400 dark:text-white dark:placeholder:text-neutral-500",
2333
- // Ring the input itself on focus rather than the whole shell.
2334
- "focus:ring-primary-500 focus:ring-1 focus:outline-none",
2335
- "disabled:cursor-not-allowed",
2336
- textareaProps?.className
2337
- )
2338
- }
2339
- )
2340
- ] }),
2341
- showAddMenu && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cells.add, children: /* @__PURE__ */ jsxRuntime.jsxs(
2342
- chunkRXPEZXAB_cjs.Dropdown,
2343
- {
2344
- placement: "top-start",
2345
- open: addMenuOpen,
2346
- onOpenChange: setAddMenuOpen,
2347
- trigger: /* @__PURE__ */ jsxRuntime.jsx(
2348
- "button",
2349
- {
2350
- type: "button",
2351
- "data-slot": "chat-composer-add-button",
2352
- "aria-label": addMenuLabel,
2353
- disabled,
2354
- className: iconButtonClasses,
2355
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.Plus, { className: "h-4 w-4", "aria-hidden": "true" })
2356
- }
2357
- ),
2358
- children: [
2359
- allowAttachments && /* @__PURE__ */ jsxRuntime.jsx(
2360
- chunkRXPEZXAB_cjs.DropdownItem,
2361
- {
2362
- icon: /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.Paperclip, { className: "h-4 w-4", "aria-hidden": "true" }),
2363
- onClick: () => {
2364
- setAddMenuOpen(false);
2365
- fileInputRef.current?.click();
2366
- },
2367
- children: attachFilesLabel
2368
- }
2369
- ),
2370
- allowAttachments && addMenuItems && addMenuItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(chunkRXPEZXAB_cjs.DropdownSeparator, {}),
2371
- addMenuItems?.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
2372
- chunkRXPEZXAB_cjs.DropdownItem,
2373
- {
2374
- icon: item.icon,
2375
- disabled: item.disabled,
2376
- variant: item.variant,
2377
- checked: item.checked,
2378
- onClick: () => {
2379
- setAddMenuOpen(false);
2380
- item.onSelect?.();
2381
- },
2382
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: item.label })
2383
- },
2384
- item.id
2385
- ))
2386
- ]
2387
- }
2388
- ) }),
2389
- allowAttachments && /* @__PURE__ */ jsxRuntime.jsx(
2390
- "input",
2391
- {
2392
- ref: fileInputRef,
2393
- type: "file",
2394
- multiple: true,
2395
- accept: acceptedFileTypes?.join(","),
2396
- onChange: handleFileInputChange,
2397
- className: "hidden",
2398
- "aria-hidden": "true",
2399
- tabIndex: -1
2400
- }
2401
- ),
2402
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cells.actions, children: [
2403
- showCharacterCount && maxLength !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
2404
- "span",
2405
- {
2406
- "data-slot": "chat-composer-char-count",
2407
- "aria-live": "polite",
2408
- className: chunkS5RVSXDV_cjs.cn(
2409
- "pe-1 text-xs tabular-nums",
2410
- isOverLimit ? "font-medium text-red-700 dark:text-red-400" : "text-neutral-500 dark:text-neutral-400"
2411
- ),
2412
- children: [
2413
- value.length,
2414
- "/",
2415
- maxLength
2416
- ]
2417
- }
2418
- ),
2419
- micVisible && (micSlot != null ? (
2420
- // Normalize slot content (e.g. a RecordButton) to the 32px
2421
- // control row: taller content overflow-centers instead of
2422
- // inflating the pill and pushing the other cells apart. A div
2423
- // so block-level slot content stays valid HTML.
2424
- /* @__PURE__ */ jsxRuntime.jsx(
2425
- "div",
2426
- {
2427
- "data-slot": "chat-composer-mic-slot",
2428
- className: "flex h-8 shrink-0 items-center",
2429
- children: micSlot
2430
- }
2431
- )
2432
- ) : /* @__PURE__ */ jsxRuntime.jsx(
2433
- "button",
2434
- {
2435
- type: "button",
2436
- "data-slot": "chat-composer-mic-button",
2437
- "aria-label": micLabel,
2438
- disabled,
2439
- onClick: onMicClick,
2440
- className: iconButtonClasses,
2441
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.Mic, { className: "h-4 w-4", "aria-hidden": "true" })
2442
- }
2443
- )),
2444
- isStreaming && onStop ? /* @__PURE__ */ jsxRuntime.jsx(
2445
- "button",
2446
- {
2447
- type: "button",
2448
- "data-slot": "chat-composer-stop-button",
2449
- "aria-label": stopLabel,
2450
- disabled,
2451
- onClick: onStop,
2452
- className: chunkS5RVSXDV_cjs.cn(
2453
- iconButtonClasses,
2454
- "text-neutral-700 dark:text-neutral-200"
2455
- ),
2456
- children: /* @__PURE__ */ jsxRuntime.jsx(
2457
- chunkL7L5S2HO_cjs.Square,
2458
- {
2459
- className: "h-3.5 w-3.5 fill-current",
2460
- "aria-hidden": "true"
2461
- }
2462
- )
2463
- }
2464
- ) : /* @__PURE__ */ jsxRuntime.jsx(
2465
- "button",
2466
- {
2467
- type: "button",
2468
- "data-slot": "chat-composer-send-button",
2469
- "aria-label": isSending ? sendingLabel : sendLabel,
2470
- "aria-busy": isSending || void 0,
2471
- disabled: !canSend,
2472
- onClick: handleSend,
2473
- className: chunkS5RVSXDV_cjs.cn(
2474
- iconButtonClasses,
2475
- canSend && "bg-primary-800 hover:bg-primary-700 dark:bg-primary-600 dark:hover:bg-primary-500 text-white hover:text-white dark:hover:text-white"
2476
- ),
2477
- children: isSending ? /* @__PURE__ */ jsxRuntime.jsx(
2478
- chunkL7L5S2HO_cjs.Loader2,
2479
- {
2480
- className: "h-4 w-4 animate-spin",
2481
- "aria-hidden": "true"
2482
- }
2483
- ) : /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.ArrowUp, { className: "h-4 w-4", "aria-hidden": "true" })
2484
- }
2485
- )
2486
- ] })
2487
- ] })
2488
- ] });
2489
- const selectorsRow = showSelectorRow && /* @__PURE__ */ jsxRuntime.jsxs(
2490
- "div",
2491
- {
2492
- "data-slot": "chat-composer-selectors",
2493
- className: "flex items-center justify-between gap-2 px-2 pt-1",
2494
- children: [
2495
- showAgentSelector ? /* @__PURE__ */ jsxRuntime.jsx(
2496
- chunkRXPEZXAB_cjs.Dropdown,
2497
- {
2498
- placement: "top-start",
2499
- open: agentMenuOpen,
2500
- onOpenChange: setAgentMenuOpen,
2501
- trigger: /* @__PURE__ */ jsxRuntime.jsxs(
2502
- "button",
2503
- {
2504
- type: "button",
2505
- "data-slot": "chat-composer-agent-trigger",
2506
- "aria-label": selectedAgentOption ? `${agentSelectorLabel}: ${selectedAgentOption.label}` : agentSelectorLabel,
2507
- disabled,
2508
- className: selectorTriggerClasses,
2509
- children: [
2510
- selectedAgentOption?.icon ?? /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.Bot, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2511
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: selectedAgentOption?.label ?? agentSelectorLabel }),
2512
- /* @__PURE__ */ jsxRuntime.jsx(chunkL7L5S2HO_cjs.ChevronUp, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" })
2513
- ]
2514
- }
2515
- ),
2516
- children: agents.map((agent) => /* @__PURE__ */ jsxRuntime.jsx(
2517
- chunkRXPEZXAB_cjs.DropdownItem,
2518
- {
2519
- icon: agent.icon,
2520
- role: "menuitemradio",
2521
- "aria-checked": agent.id === selectedAgent,
2522
- onClick: () => {
2523
- setAgentMenuOpen(false);
2524
- onAgentChange?.(agent.id);
2525
- },
2526
- children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex w-full items-center justify-between gap-2", children: [
2527
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
2528
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate", children: agent.label }),
2529
- agent.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-xs text-neutral-500 dark:text-neutral-400", children: agent.description })
2530
- ] }),
2531
- agent.id === selectedAgent && /* @__PURE__ */ jsxRuntime.jsx(
2532
- chunkL7L5S2HO_cjs.Check,
2533
- {
2534
- className: "text-primary-600 dark:text-primary-400 h-4 w-4 shrink-0",
2535
- "aria-hidden": "true"
2536
- }
2537
- )
2538
- ] })
2539
- },
2540
- agent.id
2541
- ))
2542
- }
2543
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true" }),
2544
- showModelSelector && modelSelectorProps && /* @__PURE__ */ jsxRuntime.jsx(
2545
- ComposerModelSelector,
2546
- {
2547
- variant: "ghost",
2548
- ...modelSelectorProps,
2549
- disabled: disabled || modelSelectorProps.disabled
2550
- }
2551
- )
2552
- ]
2553
- }
2554
- );
2555
- const card = /* @__PURE__ */ jsxRuntime.jsx(
2556
- "div",
2557
- {
2558
- "data-slot": "chat-composer-card",
2559
- className: chunkS5RVSXDV_cjs.cn(
2560
- "rounded-2xl border border-neutral-200 bg-white shadow-sm",
2561
- "dark:border-[#2e2e30] dark:bg-[#1c1c1e]"
2562
- ),
2563
- children: composerCard
2564
- }
2565
- );
2566
- return /* @__PURE__ */ jsxRuntime.jsxs(
2567
- "div",
2568
- {
2569
- "data-slot": "chat-composer",
2570
- className: chunkS5RVSXDV_cjs.cn(
2571
- "flex w-full flex-col",
2572
- disabled && "opacity-60",
2573
- className
2574
- ),
2575
- children: [
2576
- allowAttachments ? /* @__PURE__ */ jsxRuntime.jsx(
2577
- chunkH3GRO43Z_cjs.DragDropZone,
2578
- {
2579
- onFilesDropped: addFiles,
2580
- maxFiles: Number.MAX_SAFE_INTEGER,
2581
- disabled,
2582
- overlayLabel: dropFilesLabel,
2583
- children: card
2584
- }
2585
- ) : card,
2586
- selectorsRow
2587
- ]
2588
- }
2589
- );
2590
- });
2591
- ChatComposer.displayName = "ChatComposer";
2592
1422
 
2593
1423
  exports.AILogoIcon = AILogoIcon;
2594
1424
  exports.AIMessageDisplay = AIMessageDisplay;
2595
1425
  exports.AITypingIndicator = AITypingIndicator;
2596
1426
  exports.ChatBubble = ChatBubble;
2597
- exports.ChatComposer = ChatComposer;
2598
1427
  exports.ChevronIcon = ChevronIcon;
2599
1428
  exports.CloseIcon = CloseIcon;
2600
1429
  exports.CollapsiblePill = CollapsiblePill;
2601
- exports.ComposerModelSelector = ComposerModelSelector;
2602
1430
  exports.MCPToolCallDisplay = MCPToolCallDisplay;
2603
1431
  exports.MessageAvatar = MessageAvatar;
2604
1432
  exports.RefreshIcon = RefreshIcon;
@@ -2608,5 +1436,5 @@ exports.SparklesIcon = SparklesIcon;
2608
1436
  exports.SpinnerIcon = SpinnerIcon;
2609
1437
  exports.ToolStatusIcon = ToolStatusIcon;
2610
1438
  exports.getToolIcon = getToolIcon;
2611
- //# sourceMappingURL=chunk-XJUIZA4G.cjs.map
2612
- //# sourceMappingURL=chunk-XJUIZA4G.cjs.map
1439
+ //# sourceMappingURL=chunk-WIAQQNFU.cjs.map
1440
+ //# sourceMappingURL=chunk-WIAQQNFU.cjs.map