@natoe/colab 0.1.2 → 0.1.4

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.mjs CHANGED
@@ -828,6 +828,7 @@ function useConversation({
828
828
  body,
829
829
  type: "text",
830
830
  insertedAt: (/* @__PURE__ */ new Date()).toISOString(),
831
+ status: "sending",
831
832
  ...replyTo ? {
832
833
  replyToId: replyTo.id,
833
834
  replyToSnapshot: {
@@ -843,7 +844,9 @@ function useConversation({
843
844
  try {
844
845
  await socket.sendMessage(conv.id, payload);
845
846
  } catch (err) {
846
- setMessages((prev) => prev.filter((m) => m.id !== optimistic.id));
847
+ setMessages(
848
+ (prev) => prev.map((m) => m.id === optimistic.id ? { ...m, status: "failed" } : m)
849
+ );
847
850
  config.onError?.({
848
851
  code: "SEND_FAILED",
849
852
  message: "Failed to send message",
@@ -853,6 +856,34 @@ function useConversation({
853
856
  },
854
857
  [ensureConversation, socket, replyTo, config]
855
858
  );
859
+ const retryMessage = useCallback(
860
+ async (messageId) => {
861
+ if (!conversation) return;
862
+ const target = messages.find((m) => m.id === messageId);
863
+ if (!target || target.status !== "failed" || target.type !== "text") return;
864
+ setMessages(
865
+ (prev) => prev.map((m) => m.id === messageId ? { ...m, status: "sending" } : m)
866
+ );
867
+ const payload = {
868
+ body: target.body,
869
+ type: "text",
870
+ ...target.replyToId ? { replyToId: target.replyToId } : {}
871
+ };
872
+ try {
873
+ await socket.sendMessage(conversation.id, payload);
874
+ } catch (err) {
875
+ setMessages(
876
+ (prev) => prev.map((m) => m.id === messageId ? { ...m, status: "failed" } : m)
877
+ );
878
+ config.onError?.({
879
+ code: "SEND_FAILED",
880
+ message: "Failed to send message",
881
+ details: err
882
+ });
883
+ }
884
+ },
885
+ [conversation, messages, socket, config]
886
+ );
856
887
  const sendAudioMessage = useCallback(
857
888
  async (audioBlob, duration) => {
858
889
  if (!config.onUploadFile) return;
@@ -945,6 +976,7 @@ function useConversation({
945
976
  message: "Failed to pin message",
946
977
  details: err
947
978
  });
979
+ throw err;
948
980
  }
949
981
  },
950
982
  [conversation, pinMessageApi, config]
@@ -960,6 +992,7 @@ function useConversation({
960
992
  message: "Failed to unpin message",
961
993
  details: err
962
994
  });
995
+ throw err;
963
996
  }
964
997
  },
965
998
  [conversation, unpinMessageApi, config]
@@ -977,6 +1010,7 @@ function useConversation({
977
1010
  replyTo,
978
1011
  setReplyTo,
979
1012
  sendMessage,
1013
+ retryMessage,
980
1014
  sendAudioMessage,
981
1015
  sendFileMessage,
982
1016
  sendDeepLink,
@@ -1153,7 +1187,7 @@ var styles = {
1153
1187
  },
1154
1188
  patientName: {
1155
1189
  fontWeight: 600,
1156
- fontSize: "15px",
1190
+ fontSize: "17px",
1157
1191
  color: "#111827"
1158
1192
  },
1159
1193
  secondaryRow: {
@@ -1163,8 +1197,8 @@ var styles = {
1163
1197
  alignItems: "center"
1164
1198
  },
1165
1199
  secondary: {
1166
- fontSize: "12px",
1167
- color: "#6b7280"
1200
+ fontSize: "13px",
1201
+ color: "#4b5563"
1168
1202
  },
1169
1203
  actions: {
1170
1204
  display: "flex",
@@ -1172,8 +1206,9 @@ var styles = {
1172
1206
  marginTop: "8px"
1173
1207
  },
1174
1208
  dicomButton: {
1175
- padding: "6px 12px",
1176
- fontSize: "13px",
1209
+ minHeight: "40px",
1210
+ padding: "8px 16px",
1211
+ fontSize: "14px",
1177
1212
  fontWeight: 500,
1178
1213
  color: "#ffffff",
1179
1214
  backgroundColor: "#2563eb",
@@ -1182,8 +1217,9 @@ var styles = {
1182
1217
  cursor: "pointer"
1183
1218
  },
1184
1219
  settingsButton: {
1185
- padding: "6px 12px",
1186
- fontSize: "13px",
1220
+ minHeight: "40px",
1221
+ padding: "8px 16px",
1222
+ fontSize: "14px",
1187
1223
  fontWeight: 500,
1188
1224
  color: "#374151",
1189
1225
  backgroundColor: "#ffffff",
@@ -1424,6 +1460,82 @@ var styles4 = {
1424
1460
  cursor: "pointer"
1425
1461
  }
1426
1462
  };
1463
+ function FileIcon({ size = 18, color = "currentColor" }) {
1464
+ return /* @__PURE__ */ jsx(
1465
+ "svg",
1466
+ {
1467
+ xmlns: "http://www.w3.org/2000/svg",
1468
+ width: size,
1469
+ height: size,
1470
+ viewBox: "0 0 24 24",
1471
+ fill: color,
1472
+ "aria-hidden": "true",
1473
+ children: /* @__PURE__ */ jsx("path", { d: "M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z" })
1474
+ }
1475
+ );
1476
+ }
1477
+ function PinIcon({ size = 14, color = "currentColor" }) {
1478
+ return /* @__PURE__ */ jsx(
1479
+ "svg",
1480
+ {
1481
+ xmlns: "http://www.w3.org/2000/svg",
1482
+ width: size,
1483
+ height: size,
1484
+ viewBox: "0 0 24 24",
1485
+ fill: color,
1486
+ "aria-hidden": "true",
1487
+ children: /* @__PURE__ */ jsx("path", { d: "M16 9V4l1 0c.55 0 1-.45 1-1s-.45-1-1-1H7c-.55 0-1 .45-1 1s.45 1 1 1l1 0v5c0 1.66-1.34 3-3 3v2h5.97v7l1 1 1-1v-7H19v-2c-1.66 0-3-1.34-3-3z" })
1488
+ }
1489
+ );
1490
+ }
1491
+ function AlertIcon({ size = 14, color = "currentColor" }) {
1492
+ return /* @__PURE__ */ jsx(
1493
+ "svg",
1494
+ {
1495
+ xmlns: "http://www.w3.org/2000/svg",
1496
+ width: size,
1497
+ height: size,
1498
+ viewBox: "0 0 24 24",
1499
+ fill: color,
1500
+ "aria-hidden": "true",
1501
+ children: /* @__PURE__ */ jsx("path", { d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" })
1502
+ }
1503
+ );
1504
+ }
1505
+ function Spinner({ size = 16, color = "#6b7280", thickness = 2 }) {
1506
+ return /* @__PURE__ */ jsx(
1507
+ "span",
1508
+ {
1509
+ role: "status",
1510
+ "aria-label": "Loading",
1511
+ style: {
1512
+ display: "inline-block",
1513
+ width: size,
1514
+ height: size,
1515
+ border: `${thickness}px solid ${color}33`,
1516
+ borderTopColor: color,
1517
+ borderRadius: "50%",
1518
+ animation: "natoe-colab-spin 800ms linear infinite",
1519
+ verticalAlign: "middle"
1520
+ }
1521
+ }
1522
+ );
1523
+ }
1524
+ if (typeof document !== "undefined") {
1525
+ const existing = document.getElementById("natoe-colab-spin-keyframes");
1526
+ if (!existing) {
1527
+ const style = document.createElement("style");
1528
+ style.id = "natoe-colab-spin-keyframes";
1529
+ style.textContent = `@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }`;
1530
+ document.head.appendChild(style);
1531
+ }
1532
+ }
1533
+ var ROLE_LABELS = {
1534
+ radiologist: "Radiologist",
1535
+ lab: "Imaging Center",
1536
+ physician: "Physician",
1537
+ admin: "Admin"
1538
+ };
1427
1539
  function MessageBubble({
1428
1540
  message,
1429
1541
  isOwn,
@@ -1436,6 +1548,7 @@ function MessageBubble({
1436
1548
  onUnpin,
1437
1549
  onCopy,
1438
1550
  onReplyJumpTo,
1551
+ onRetry,
1439
1552
  pinDisabled = false,
1440
1553
  className
1441
1554
  }) {
@@ -1463,7 +1576,10 @@ function MessageBubble({
1463
1576
  ...isOwn ? styles5.ownBubble : styles5.otherBubble
1464
1577
  },
1465
1578
  children: [
1466
- message.isPinned && /* @__PURE__ */ jsx("div", { style: styles5.pinnedBadge, children: "\u{1F4CC} Pinned" }),
1579
+ message.isPinned && /* @__PURE__ */ jsxs("div", { style: styles5.pinnedBadge, children: [
1580
+ /* @__PURE__ */ jsx(PinIcon, { size: 12 }),
1581
+ /* @__PURE__ */ jsx("span", { children: "Pinned" })
1582
+ ] }),
1467
1583
  message.replyToSnapshot && /* @__PURE__ */ jsx(
1468
1584
  ReplyQuoteBlock,
1469
1585
  {
@@ -1482,7 +1598,25 @@ function MessageBubble({
1482
1598
  message.type === "file" && /* @__PURE__ */ jsx(FileContent, { mediaUrl: message.mediaUrl, fileName: message.fileName }),
1483
1599
  message.type === "deep_link" && /* @__PURE__ */ jsx(DeepLinkContent, { body: message.body, metadata: message.metadata, onDeepLinkClick }),
1484
1600
  /* @__PURE__ */ jsx("div", { style: styles5.timestamp, children: formatTime(message.insertedAt) }),
1485
- showSeenBy && isOwn && /* @__PURE__ */ jsx(
1601
+ isOwn && message.status === "sending" && /* @__PURE__ */ jsxs("div", { style: styles5.statusRow, children: [
1602
+ /* @__PURE__ */ jsx(Spinner, { size: 12, color: "rgba(255,255,255,0.85)" }),
1603
+ /* @__PURE__ */ jsx("span", { style: styles5.statusText, children: "Sending\u2026" })
1604
+ ] }),
1605
+ isOwn && message.status === "failed" && /* @__PURE__ */ jsxs("div", { style: styles5.statusRow, children: [
1606
+ /* @__PURE__ */ jsx(AlertIcon, { size: 12, color: "#fecaca" }),
1607
+ /* @__PURE__ */ jsx("span", { style: styles5.statusText, children: "Not sent" }),
1608
+ onRetry && /* @__PURE__ */ jsx(
1609
+ "button",
1610
+ {
1611
+ type: "button",
1612
+ onClick: () => onRetry(message.id),
1613
+ style: styles5.retryButton,
1614
+ "aria-label": "Retry sending message",
1615
+ children: "Retry"
1616
+ }
1617
+ )
1618
+ ] }),
1619
+ showSeenBy && isOwn && !message.status && /* @__PURE__ */ jsx(
1486
1620
  SeenByIndicator,
1487
1621
  {
1488
1622
  readBy: message.readBy ?? [],
@@ -1558,7 +1692,7 @@ function ImageContent({ mediaUrl, fileName }) {
1558
1692
  function FileContent({ mediaUrl, fileName }) {
1559
1693
  if (!mediaUrl) return null;
1560
1694
  return /* @__PURE__ */ jsxs("a", { href: mediaUrl, target: "_blank", rel: "noopener noreferrer", style: styles5.fileLink, children: [
1561
- /* @__PURE__ */ jsx("span", { style: styles5.fileIcon, children: "\u{1F4C4}" }),
1695
+ /* @__PURE__ */ jsx(FileIcon, { size: 20 }),
1562
1696
  /* @__PURE__ */ jsx("span", { style: styles5.fileName, children: fileName || "Download file" })
1563
1697
  ] });
1564
1698
  }
@@ -1596,7 +1730,7 @@ function RoleBadge({ role }) {
1596
1730
  physician: "#059669",
1597
1731
  admin: "#dc2626"
1598
1732
  };
1599
- return /* @__PURE__ */ jsx("span", { style: { ...styles5.roleBadge, backgroundColor: `${colors[role]}15`, color: colors[role] }, children: role });
1733
+ return /* @__PURE__ */ jsx("span", { style: { ...styles5.roleBadge, backgroundColor: `${colors[role]}15`, color: colors[role] }, children: ROLE_LABELS[role] ?? role });
1600
1734
  }
1601
1735
  function formatTime(iso) {
1602
1736
  try {
@@ -1625,7 +1759,7 @@ var styles5 = {
1625
1759
  maxWidth: "75%"
1626
1760
  },
1627
1761
  bubble: {
1628
- padding: "8px 12px",
1762
+ padding: "10px 14px",
1629
1763
  borderRadius: "12px",
1630
1764
  wordBreak: "break-word"
1631
1765
  },
@@ -1640,11 +1774,13 @@ var styles5 = {
1640
1774
  borderBottomLeftRadius: "4px"
1641
1775
  },
1642
1776
  pinnedBadge: {
1643
- display: "inline-block",
1644
- fontSize: "10px",
1777
+ display: "inline-flex",
1778
+ alignItems: "center",
1779
+ gap: "4px",
1780
+ fontSize: "12px",
1645
1781
  fontWeight: 600,
1646
1782
  marginBottom: "4px",
1647
- opacity: 0.7
1783
+ color: "#6b7280"
1648
1784
  },
1649
1785
  senderRow: {
1650
1786
  display: "flex",
@@ -1653,27 +1789,50 @@ var styles5 = {
1653
1789
  marginBottom: "4px"
1654
1790
  },
1655
1791
  senderName: {
1656
- fontSize: "12px",
1792
+ fontSize: "13px",
1657
1793
  fontWeight: 600,
1658
1794
  color: "#374151"
1659
1795
  },
1660
1796
  roleBadge: {
1661
- fontSize: "10px",
1662
- fontWeight: 500,
1663
- padding: "1px 6px",
1797
+ fontSize: "11px",
1798
+ fontWeight: 600,
1799
+ padding: "2px 8px",
1664
1800
  borderRadius: "4px"
1665
1801
  },
1666
1802
  textBody: {
1667
1803
  margin: 0,
1668
- fontSize: "14px",
1669
- lineHeight: "1.4"
1804
+ fontSize: "15px",
1805
+ lineHeight: "1.45"
1670
1806
  },
1671
1807
  timestamp: {
1672
- fontSize: "10px",
1673
- opacity: 0.7,
1808
+ fontSize: "12px",
1809
+ color: "inherit",
1810
+ opacity: 0.8,
1674
1811
  marginTop: "4px",
1675
1812
  textAlign: "right"
1676
1813
  },
1814
+ statusRow: {
1815
+ display: "flex",
1816
+ alignItems: "center",
1817
+ gap: "6px",
1818
+ marginTop: "4px",
1819
+ fontSize: "12px",
1820
+ justifyContent: "flex-end",
1821
+ color: "rgba(255, 255, 255, 0.9)"
1822
+ },
1823
+ statusText: {
1824
+ opacity: 0.9
1825
+ },
1826
+ retryButton: {
1827
+ background: "transparent",
1828
+ border: "none",
1829
+ color: "#ffffff",
1830
+ fontWeight: 600,
1831
+ fontSize: "12px",
1832
+ textDecoration: "underline",
1833
+ cursor: "pointer",
1834
+ padding: "0 2px"
1835
+ },
1677
1836
  actionsWrapper: {
1678
1837
  position: "absolute",
1679
1838
  top: "50%",
@@ -1709,9 +1868,6 @@ var styles5 = {
1709
1868
  color: "inherit",
1710
1869
  padding: "6px 0"
1711
1870
  },
1712
- fileIcon: {
1713
- fontSize: "18px"
1714
- },
1715
1871
  fileName: {
1716
1872
  fontSize: "13px",
1717
1873
  textDecoration: "underline"
@@ -1746,15 +1902,53 @@ var styles5 = {
1746
1902
  justifyContent: "center",
1747
1903
  alignItems: "center",
1748
1904
  gap: "8px",
1749
- padding: "4px 16px",
1750
- fontSize: "12px",
1751
- color: "#9ca3af"
1905
+ padding: "6px 16px",
1906
+ fontSize: "13px",
1907
+ color: "#6b7280"
1752
1908
  },
1753
1909
  systemTime: {
1754
- fontSize: "10px",
1755
- color: "#d1d5db"
1910
+ fontSize: "12px",
1911
+ color: "#9ca3af"
1756
1912
  }
1757
1913
  };
1914
+ function ChatIllustration({ size = 96 }) {
1915
+ return /* @__PURE__ */ jsxs(
1916
+ "svg",
1917
+ {
1918
+ xmlns: "http://www.w3.org/2000/svg",
1919
+ width: size,
1920
+ height: size,
1921
+ viewBox: "0 0 120 120",
1922
+ fill: "none",
1923
+ "aria-hidden": "true",
1924
+ children: [
1925
+ /* @__PURE__ */ jsx("circle", { cx: "60", cy: "60", r: "56", fill: "#eff6ff" }),
1926
+ /* @__PURE__ */ jsx(
1927
+ "path",
1928
+ {
1929
+ d: "M28 44a10 10 0 0 1 10-10h28a10 10 0 0 1 10 10v18a10 10 0 0 1-10 10H46l-10 8v-8h2a10 10 0 0 1-10-10V44Z",
1930
+ fill: "#ffffff",
1931
+ stroke: "#2563eb",
1932
+ strokeWidth: "2.5"
1933
+ }
1934
+ ),
1935
+ /* @__PURE__ */ jsx(
1936
+ "path",
1937
+ {
1938
+ d: "M52 60a8 8 0 0 1 8-8h26a8 8 0 0 1 8 8v14a8 8 0 0 1-8 8H72l8 8v-8h6a8 8 0 0 0 0-30Z",
1939
+ fill: "#dbeafe",
1940
+ stroke: "#2563eb",
1941
+ strokeWidth: "2.5"
1942
+ }
1943
+ ),
1944
+ /* @__PURE__ */ jsx("circle", { cx: "48", cy: "53", r: "2.5", fill: "#2563eb" }),
1945
+ /* @__PURE__ */ jsx("circle", { cx: "58", cy: "53", r: "2.5", fill: "#2563eb" }),
1946
+ /* @__PURE__ */ jsx("circle", { cx: "68", cy: "68", r: "2.5", fill: "#2563eb" }),
1947
+ /* @__PURE__ */ jsx("circle", { cx: "78", cy: "68", r: "2.5", fill: "#2563eb" })
1948
+ ]
1949
+ }
1950
+ );
1951
+ }
1758
1952
 
1759
1953
  // src/core/dateLabels.ts
1760
1954
  var SHORT_MONTHS = [
@@ -1846,6 +2040,7 @@ var MessageList = forwardRef(function MessageList2({
1846
2040
  onPin,
1847
2041
  onUnpin,
1848
2042
  onCopy,
2043
+ onRetry,
1849
2044
  pinDisabled,
1850
2045
  className
1851
2046
  }, ref) {
@@ -1910,12 +2105,17 @@ var MessageList = forwardRef(function MessageList2({
1910
2105
  style: styles6.container,
1911
2106
  onScroll: handleScroll,
1912
2107
  children: [
1913
- isLoading && /* @__PURE__ */ jsx("div", { style: styles6.loadingMore, children: "Loading earlier messages..." }),
2108
+ isLoading && messages.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles6.loadingMore, children: [
2109
+ /* @__PURE__ */ jsx(Spinner, { size: 14 }),
2110
+ /* @__PURE__ */ jsx("span", { children: "Loading earlier messages\u2026" })
2111
+ ] }),
1914
2112
  hasMore && !isLoading && messages.length > 0 && /* @__PURE__ */ jsx("button", { onClick: onLoadMore, style: styles6.loadMoreButton, type: "button", children: "Load earlier messages" }),
1915
2113
  messages.length === 0 && !isLoading && /* @__PURE__ */ jsxs("div", { style: styles6.empty, children: [
2114
+ /* @__PURE__ */ jsx(ChatIllustration, { size: 104 }),
1916
2115
  /* @__PURE__ */ jsx("p", { style: styles6.emptyTitle, children: "No messages yet" }),
1917
- /* @__PURE__ */ jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation about this study" })
2116
+ /* @__PURE__ */ jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation \u2014 everyone on this case will see what you write." })
1918
2117
  ] }),
2118
+ messages.length === 0 && isLoading && /* @__PURE__ */ jsx("div", { style: styles6.firstLoad, children: /* @__PURE__ */ jsx(Spinner, { size: 20 }) }),
1919
2119
  messages.map((message, index) => {
1920
2120
  const currentBucket = dayBucketKey(message.insertedAt);
1921
2121
  const prevBucket = index === 0 ? null : dayBucketKey(messages[index - 1].insertedAt);
@@ -1935,6 +2135,7 @@ var MessageList = forwardRef(function MessageList2({
1935
2135
  onPin,
1936
2136
  onUnpin,
1937
2137
  onCopy,
2138
+ onRetry,
1938
2139
  pinDisabled
1939
2140
  }
1940
2141
  ) })
@@ -1963,20 +2164,30 @@ var styles6 = {
1963
2164
  paddingBottom: "8px"
1964
2165
  },
1965
2166
  loadingMore: {
1966
- textAlign: "center",
2167
+ display: "flex",
2168
+ alignItems: "center",
2169
+ justifyContent: "center",
2170
+ gap: "8px",
1967
2171
  padding: "12px",
1968
- fontSize: "13px",
1969
- color: "#9ca3af"
2172
+ fontSize: "14px",
2173
+ color: "#6b7280"
2174
+ },
2175
+ firstLoad: {
2176
+ display: "flex",
2177
+ alignItems: "center",
2178
+ justifyContent: "center",
2179
+ padding: "48px 16px"
1970
2180
  },
1971
2181
  loadMoreButton: {
1972
2182
  display: "block",
1973
2183
  margin: "0 auto 12px",
1974
- padding: "6px 16px",
1975
- fontSize: "12px",
1976
- color: "#6b7280",
2184
+ minHeight: "36px",
2185
+ padding: "8px 18px",
2186
+ fontSize: "13px",
2187
+ color: "#374151",
1977
2188
  backgroundColor: "transparent",
1978
- border: "1px solid #e5e7eb",
1979
- borderRadius: "16px",
2189
+ border: "1px solid #d1d5db",
2190
+ borderRadius: "18px",
1980
2191
  cursor: "pointer"
1981
2192
  },
1982
2193
  empty: {
@@ -1985,21 +2196,25 @@ var styles6 = {
1985
2196
  alignItems: "center",
1986
2197
  justifyContent: "center",
1987
2198
  padding: "48px 16px",
1988
- color: "#9ca3af"
2199
+ color: "#6b7280"
1989
2200
  },
1990
2201
  emptyTitle: {
1991
- fontSize: "15px",
1992
- fontWeight: 500,
1993
- margin: "0 0 4px"
2202
+ fontSize: "16px",
2203
+ fontWeight: 600,
2204
+ color: "#374151",
2205
+ margin: "14px 0 4px"
1994
2206
  },
1995
2207
  emptySubtitle: {
1996
- fontSize: "13px",
1997
- margin: 0
2208
+ fontSize: "14px",
2209
+ margin: 0,
2210
+ maxWidth: "280px",
2211
+ lineHeight: 1.45,
2212
+ textAlign: "center"
1998
2213
  },
1999
2214
  typingIndicator: {
2000
2215
  padding: "4px 16px 8px",
2001
- fontSize: "12px",
2002
- color: "#9ca3af",
2216
+ fontSize: "13px",
2217
+ color: "#6b7280",
2003
2218
  fontStyle: "italic"
2004
2219
  },
2005
2220
  dayDivider: {
@@ -2009,12 +2224,11 @@ var styles6 = {
2009
2224
  },
2010
2225
  dayDividerPill: {
2011
2226
  display: "inline-block",
2012
- padding: "4px 12px",
2013
- fontSize: "12px",
2227
+ padding: "5px 14px",
2228
+ fontSize: "13px",
2014
2229
  fontWeight: 500,
2015
- color: "#475569",
2016
- backgroundColor: "#f1f5f9",
2017
- border: "1px solid #e2e8f0",
2230
+ color: "#334155",
2231
+ backgroundColor: "#e2e8f0",
2018
2232
  borderRadius: "12px",
2019
2233
  letterSpacing: "0.2px"
2020
2234
  }
@@ -2111,6 +2325,48 @@ var styles7 = {
2111
2325
  flexShrink: 0
2112
2326
  }
2113
2327
  };
2328
+ function AttachIcon({ size = 20, color = "currentColor" }) {
2329
+ return /* @__PURE__ */ jsx(
2330
+ "svg",
2331
+ {
2332
+ xmlns: "http://www.w3.org/2000/svg",
2333
+ width: size,
2334
+ height: size,
2335
+ viewBox: "0 0 24 24",
2336
+ fill: color,
2337
+ "aria-hidden": "true",
2338
+ children: /* @__PURE__ */ jsx("path", { d: "M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z" })
2339
+ }
2340
+ );
2341
+ }
2342
+ function SendIcon({ size = 20, color = "currentColor" }) {
2343
+ return /* @__PURE__ */ jsx(
2344
+ "svg",
2345
+ {
2346
+ xmlns: "http://www.w3.org/2000/svg",
2347
+ width: size,
2348
+ height: size,
2349
+ viewBox: "0 0 24 24",
2350
+ fill: color,
2351
+ "aria-hidden": "true",
2352
+ children: /* @__PURE__ */ jsx("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" })
2353
+ }
2354
+ );
2355
+ }
2356
+ function CloseIcon({ size = 18, color = "currentColor" }) {
2357
+ return /* @__PURE__ */ jsx(
2358
+ "svg",
2359
+ {
2360
+ xmlns: "http://www.w3.org/2000/svg",
2361
+ width: size,
2362
+ height: size,
2363
+ viewBox: "0 0 24 24",
2364
+ fill: color,
2365
+ "aria-hidden": "true",
2366
+ children: /* @__PURE__ */ jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })
2367
+ }
2368
+ );
2369
+ }
2114
2370
  function MessageInput({
2115
2371
  onSendText,
2116
2372
  // MIC DISABLED — onSendAudio still accepted but unused.
@@ -2199,7 +2455,19 @@ function MessageInput({
2199
2455
  );
2200
2456
  return /* @__PURE__ */ jsxs("div", { className, style: styles8.container, children: [
2201
2457
  replyTo && onCancelReply && /* @__PURE__ */ jsx(ReplyPreview, { message: replyTo, onCancel: onCancelReply }),
2202
- fileError && /* @__PURE__ */ jsx("div", { style: styles8.error, children: fileError }),
2458
+ fileError && /* @__PURE__ */ jsxs("div", { style: styles8.error, role: "alert", children: [
2459
+ /* @__PURE__ */ jsx("span", { style: styles8.errorText, children: fileError }),
2460
+ /* @__PURE__ */ jsx(
2461
+ "button",
2462
+ {
2463
+ type: "button",
2464
+ onClick: () => setFileError(null),
2465
+ "aria-label": "Dismiss error",
2466
+ style: styles8.errorDismiss,
2467
+ children: /* @__PURE__ */ jsx(CloseIcon, { size: 16 })
2468
+ }
2469
+ )
2470
+ ] }),
2203
2471
  /* @__PURE__ */ jsxs("div", { style: styles8.inputBar, children: [
2204
2472
  /* @__PURE__ */ jsx(
2205
2473
  "button",
@@ -2207,9 +2475,10 @@ function MessageInput({
2207
2475
  onClick: () => fileInputRef.current?.click(),
2208
2476
  disabled: disabled || isSending,
2209
2477
  style: styles8.iconButton,
2478
+ "aria-label": "Attach file",
2210
2479
  title: "Attach file",
2211
2480
  type: "button",
2212
- children: "\u{1F4CE}"
2481
+ children: /* @__PURE__ */ jsx(AttachIcon, { size: 22, color: "#374151" })
2213
2482
  }
2214
2483
  ),
2215
2484
  /* @__PURE__ */ jsx(
@@ -2242,12 +2511,14 @@ function MessageInput({
2242
2511
  {
2243
2512
  onClick: handleSendText,
2244
2513
  disabled: disabled || isSending || !text.trim(),
2514
+ "aria-label": "Send message",
2515
+ title: "Send message",
2245
2516
  style: {
2246
2517
  ...styles8.sendButton,
2247
2518
  opacity: text.trim() ? 1 : 0.4
2248
2519
  },
2249
2520
  type: "button",
2250
- children: "\u27A4"
2521
+ children: /* @__PURE__ */ jsx(SendIcon, { size: 20, color: "#ffffff" })
2251
2522
  }
2252
2523
  )
2253
2524
  ] })
@@ -2259,24 +2530,45 @@ var styles8 = {
2259
2530
  backgroundColor: "#ffffff"
2260
2531
  },
2261
2532
  error: {
2262
- padding: "6px 16px",
2263
- fontSize: "12px",
2264
- color: "#dc2626",
2265
- backgroundColor: "#fef2f2"
2533
+ display: "flex",
2534
+ alignItems: "center",
2535
+ justifyContent: "space-between",
2536
+ gap: "8px",
2537
+ padding: "8px 12px 8px 16px",
2538
+ fontSize: "13px",
2539
+ color: "#b91c1c",
2540
+ backgroundColor: "#fef2f2",
2541
+ borderTop: "1px solid #fecaca"
2542
+ },
2543
+ errorText: {
2544
+ flex: 1,
2545
+ minWidth: 0
2546
+ },
2547
+ errorDismiss: {
2548
+ width: "28px",
2549
+ height: "28px",
2550
+ display: "flex",
2551
+ alignItems: "center",
2552
+ justifyContent: "center",
2553
+ backgroundColor: "transparent",
2554
+ border: "none",
2555
+ color: "#b91c1c",
2556
+ borderRadius: "4px",
2557
+ cursor: "pointer",
2558
+ flexShrink: 0
2266
2559
  },
2267
2560
  inputBar: {
2268
2561
  display: "flex",
2269
2562
  alignItems: "flex-end",
2270
- gap: "4px",
2271
- padding: "8px 12px"
2563
+ gap: "6px",
2564
+ padding: "10px 12px"
2272
2565
  },
2273
2566
  iconButton: {
2274
- width: "36px",
2275
- height: "36px",
2567
+ width: "44px",
2568
+ height: "44px",
2276
2569
  display: "flex",
2277
2570
  alignItems: "center",
2278
2571
  justifyContent: "center",
2279
- fontSize: "18px",
2280
2572
  backgroundColor: "transparent",
2281
2573
  border: "none",
2282
2574
  borderRadius: "50%",
@@ -2285,23 +2577,23 @@ var styles8 = {
2285
2577
  },
2286
2578
  textarea: {
2287
2579
  flex: 1,
2288
- padding: "8px 12px",
2289
- fontSize: "14px",
2290
- lineHeight: "1.4",
2291
- border: "1px solid #e5e7eb",
2292
- borderRadius: "20px",
2580
+ padding: "10px 14px",
2581
+ fontSize: "15px",
2582
+ lineHeight: "1.45",
2583
+ border: "1px solid #d1d5db",
2584
+ borderRadius: "22px",
2293
2585
  resize: "none",
2294
2586
  outline: "none",
2295
2587
  fontFamily: "inherit",
2296
- maxHeight: "120px"
2588
+ maxHeight: "120px",
2589
+ minHeight: "44px"
2297
2590
  },
2298
2591
  sendButton: {
2299
- width: "36px",
2300
- height: "36px",
2592
+ width: "44px",
2593
+ height: "44px",
2301
2594
  display: "flex",
2302
2595
  alignItems: "center",
2303
2596
  justifyContent: "center",
2304
- fontSize: "18px",
2305
2597
  backgroundColor: "#2563eb",
2306
2598
  color: "#ffffff",
2307
2599
  border: "none",
@@ -2921,6 +3213,64 @@ var styles11 = {
2921
3213
  flexShrink: 0
2922
3214
  }
2923
3215
  };
3216
+ function Toast({ toast, onDismiss, durationMs = 4e3 }) {
3217
+ useEffect(() => {
3218
+ if (!toast) return;
3219
+ const timer = setTimeout(onDismiss, durationMs);
3220
+ return () => clearTimeout(timer);
3221
+ }, [toast, onDismiss, durationMs]);
3222
+ if (!toast) return null;
3223
+ return /* @__PURE__ */ jsxs("div", { style: styles12.container, role: "status", "aria-live": "polite", children: [
3224
+ /* @__PURE__ */ jsx("span", { style: styles12.message, children: toast.message }),
3225
+ toast.actionLabel && toast.onAction && /* @__PURE__ */ jsx(
3226
+ "button",
3227
+ {
3228
+ type: "button",
3229
+ onClick: () => {
3230
+ toast.onAction?.();
3231
+ onDismiss();
3232
+ },
3233
+ style: styles12.action,
3234
+ children: toast.actionLabel
3235
+ }
3236
+ )
3237
+ ] });
3238
+ }
3239
+ var styles12 = {
3240
+ container: {
3241
+ position: "absolute",
3242
+ bottom: "76px",
3243
+ left: "50%",
3244
+ transform: "translateX(-50%)",
3245
+ display: "flex",
3246
+ alignItems: "center",
3247
+ gap: "12px",
3248
+ padding: "10px 14px",
3249
+ backgroundColor: "#1e293b",
3250
+ color: "#ffffff",
3251
+ borderRadius: "8px",
3252
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.18)",
3253
+ fontSize: "14px",
3254
+ maxWidth: "90%",
3255
+ zIndex: 20
3256
+ },
3257
+ message: {
3258
+ whiteSpace: "nowrap",
3259
+ overflow: "hidden",
3260
+ textOverflow: "ellipsis"
3261
+ },
3262
+ action: {
3263
+ background: "transparent",
3264
+ border: "none",
3265
+ color: "#93c5fd",
3266
+ fontWeight: 600,
3267
+ fontSize: "14px",
3268
+ cursor: "pointer",
3269
+ padding: "4px 6px",
3270
+ textTransform: "uppercase",
3271
+ letterSpacing: "0.4px"
3272
+ }
3273
+ };
2924
3274
  function CollabPanel({
2925
3275
  orderId,
2926
3276
  patientData,
@@ -2931,6 +3281,7 @@ function CollabPanel({
2931
3281
  }) {
2932
3282
  const { config } = useCollab();
2933
3283
  const [showSettings, setShowSettings] = useState(false);
3284
+ const [toast, setToast] = useState(null);
2934
3285
  const messageListRef = useRef(null);
2935
3286
  const {
2936
3287
  conversation,
@@ -2944,6 +3295,7 @@ function CollabPanel({
2944
3295
  replyTo,
2945
3296
  setReplyTo,
2946
3297
  sendMessage,
3298
+ retryMessage,
2947
3299
  sendAudioMessage,
2948
3300
  sendFileMessage,
2949
3301
  sendTyping,
@@ -2968,10 +3320,33 @@ function CollabPanel({
2968
3320
  try {
2969
3321
  if (navigator.clipboard) {
2970
3322
  await navigator.clipboard.writeText(text);
3323
+ setToast({ message: "Copied to clipboard" });
2971
3324
  }
2972
3325
  } catch {
2973
3326
  }
2974
3327
  };
3328
+ const handlePin = async (messageId) => {
3329
+ try {
3330
+ await pinMessage(messageId);
3331
+ setToast({
3332
+ message: "Pinned",
3333
+ actionLabel: "Undo",
3334
+ onAction: () => {
3335
+ void unpinMessage(messageId);
3336
+ }
3337
+ });
3338
+ } catch {
3339
+ setToast({ message: "Could not pin message" });
3340
+ }
3341
+ };
3342
+ const handleUnpin = async (messageId) => {
3343
+ try {
3344
+ await unpinMessage(messageId);
3345
+ setToast({ message: "Unpinned" });
3346
+ } catch {
3347
+ setToast({ message: "Could not unpin message" });
3348
+ }
3349
+ };
2975
3350
  const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;
2976
3351
  if (error) {
2977
3352
  return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxs("div", { style: panelStyles.errorState, children: [
@@ -2982,78 +3357,83 @@ function CollabPanel({
2982
3357
  if (isLoading && !conversation) {
2983
3358
  return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
2984
3359
  }
2985
- return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: showSettings && conversation ? /* @__PURE__ */ jsx(
2986
- ChannelSettings,
2987
- {
2988
- conversationId: conversation.id,
2989
- channelName: conversation.name,
2990
- channelPicture: conversation.picture,
2991
- participants,
2992
- currentUserId: config.userId,
2993
- isAdmin: channelSettings.isAdmin,
2994
- isUpdating: channelSettings.isUpdating,
2995
- error: channelSettings.error,
2996
- onUpdateChannel: channelSettings.updateChannel,
2997
- onInviteUser: channelSettings.inviteUser,
2998
- onRemoveUser: channelSettings.removeUser,
2999
- onLeaveChannel: channelSettings.leaveChannel,
3000
- onDeleteChannel: channelSettings.deleteChannel,
3001
- onClose: () => setShowSettings(false)
3002
- }
3003
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
3004
- /* @__PURE__ */ jsx(
3005
- PatientHeader,
3360
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...panelStyles.container, ...style }, children: [
3361
+ showSettings && conversation ? /* @__PURE__ */ jsx(
3362
+ ChannelSettings,
3006
3363
  {
3007
- patientData,
3364
+ conversationId: conversation.id,
3365
+ channelName: conversation.name,
3366
+ channelPicture: conversation.picture,
3008
3367
  participants,
3009
- onOpenDicom: handleOpenDicom,
3010
- onOpenSettings: () => setShowSettings(true)
3011
- }
3012
- ),
3013
- pinnedMessages.length > 0 && /* @__PURE__ */ jsx(
3014
- PinnedMessagesBar,
3015
- {
3016
- pinnedMessages,
3017
- onJumpTo: handleJumpToMessage,
3018
- onUnpin: unpinMessage
3019
- }
3020
- ),
3021
- /* @__PURE__ */ jsx(
3022
- MessageList,
3023
- {
3024
- ref: messageListRef,
3025
- messages,
3026
3368
  currentUserId: config.userId,
3027
- participants,
3028
- showSeenBy,
3029
- typingUsers,
3030
- hasMore,
3031
- isLoading,
3032
- onLoadMore: loadMoreMessages,
3033
- onDeepLinkClick: handleDeepLink,
3034
- onMessageVisible: markAsRead,
3035
- onReply: setReplyTo,
3036
- onPin: pinMessage,
3037
- onUnpin: unpinMessage,
3038
- onCopy: handleCopy,
3039
- pinDisabled
3040
- }
3041
- ),
3042
- /* @__PURE__ */ jsx(
3043
- MessageInput,
3044
- {
3045
- onSendText: sendMessage,
3046
- onSendAudio: sendAudioMessage,
3047
- onSendFile: sendFileMessage,
3048
- onTyping: sendTyping,
3049
- replyTo,
3050
- onCancelReply: () => setReplyTo(null)
3369
+ isAdmin: channelSettings.isAdmin,
3370
+ isUpdating: channelSettings.isUpdating,
3371
+ error: channelSettings.error,
3372
+ onUpdateChannel: channelSettings.updateChannel,
3373
+ onInviteUser: channelSettings.inviteUser,
3374
+ onRemoveUser: channelSettings.removeUser,
3375
+ onLeaveChannel: channelSettings.leaveChannel,
3376
+ onDeleteChannel: channelSettings.deleteChannel,
3377
+ onClose: () => setShowSettings(false)
3051
3378
  }
3052
- )
3053
- ] }) });
3379
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
3380
+ /* @__PURE__ */ jsx(
3381
+ PatientHeader,
3382
+ {
3383
+ patientData,
3384
+ participants,
3385
+ onOpenDicom: handleOpenDicom,
3386
+ onOpenSettings: () => setShowSettings(true)
3387
+ }
3388
+ ),
3389
+ pinnedMessages.length > 0 && /* @__PURE__ */ jsx(
3390
+ PinnedMessagesBar,
3391
+ {
3392
+ pinnedMessages,
3393
+ onJumpTo: handleJumpToMessage,
3394
+ onUnpin: handleUnpin
3395
+ }
3396
+ ),
3397
+ /* @__PURE__ */ jsx(
3398
+ MessageList,
3399
+ {
3400
+ ref: messageListRef,
3401
+ messages,
3402
+ currentUserId: config.userId,
3403
+ participants,
3404
+ showSeenBy,
3405
+ typingUsers,
3406
+ hasMore,
3407
+ isLoading,
3408
+ onLoadMore: loadMoreMessages,
3409
+ onDeepLinkClick: handleDeepLink,
3410
+ onMessageVisible: markAsRead,
3411
+ onReply: setReplyTo,
3412
+ onPin: handlePin,
3413
+ onUnpin: handleUnpin,
3414
+ onCopy: handleCopy,
3415
+ onRetry: retryMessage,
3416
+ pinDisabled
3417
+ }
3418
+ ),
3419
+ /* @__PURE__ */ jsx(
3420
+ MessageInput,
3421
+ {
3422
+ onSendText: sendMessage,
3423
+ onSendAudio: sendAudioMessage,
3424
+ onSendFile: sendFileMessage,
3425
+ onTyping: sendTyping,
3426
+ replyTo,
3427
+ onCancelReply: () => setReplyTo(null)
3428
+ }
3429
+ )
3430
+ ] }),
3431
+ /* @__PURE__ */ jsx(Toast, { toast, onDismiss: () => setToast(null) })
3432
+ ] });
3054
3433
  }
3055
3434
  var panelStyles = {
3056
3435
  container: {
3436
+ position: "relative",
3057
3437
  display: "flex",
3058
3438
  flexDirection: "column",
3059
3439
  height: "100%",
@@ -3092,6 +3472,34 @@ var panelStyles = {
3092
3472
  margin: 0
3093
3473
  }
3094
3474
  };
3475
+ function MinimizeIcon({ size = 18, color = "currentColor" }) {
3476
+ return /* @__PURE__ */ jsx(
3477
+ "svg",
3478
+ {
3479
+ xmlns: "http://www.w3.org/2000/svg",
3480
+ width: size,
3481
+ height: size,
3482
+ viewBox: "0 0 24 24",
3483
+ fill: color,
3484
+ "aria-hidden": "true",
3485
+ children: /* @__PURE__ */ jsx("path", { d: "M6 19h12v2H6z" })
3486
+ }
3487
+ );
3488
+ }
3489
+ function ExpandIcon({ size = 18, color = "currentColor" }) {
3490
+ return /* @__PURE__ */ jsx(
3491
+ "svg",
3492
+ {
3493
+ xmlns: "http://www.w3.org/2000/svg",
3494
+ width: size,
3495
+ height: size,
3496
+ viewBox: "0 0 24 24",
3497
+ fill: color,
3498
+ "aria-hidden": "true",
3499
+ children: /* @__PURE__ */ jsx("path", { d: "M4 4h16v16H4V4zm2 4v10h12V8H6z" })
3500
+ }
3501
+ );
3502
+ }
3095
3503
  function CollabPopup({
3096
3504
  orderId,
3097
3505
  patientData,
@@ -3140,7 +3548,7 @@ function CollabPopup({
3140
3548
  const handleMouseMove = (e) => {
3141
3549
  setPosition({
3142
3550
  x: Math.max(0, Math.min(e.clientX - dragOffset.current.x, window.innerWidth - width)),
3143
- y: Math.max(0, Math.min(e.clientY - dragOffset.current.y, window.innerHeight - (isMinimized ? 48 : height)))
3551
+ y: Math.max(0, Math.min(e.clientY - dragOffset.current.y, window.innerHeight - (isMinimized ? 52 : height)))
3144
3552
  });
3145
3553
  };
3146
3554
  const handleMouseUp = () => {
@@ -3160,37 +3568,48 @@ function CollabPopup({
3160
3568
  ref: containerRef,
3161
3569
  className,
3162
3570
  style: {
3163
- ...styles12.container,
3571
+ ...styles13.container,
3164
3572
  left: position.x,
3165
3573
  top: position.y,
3166
3574
  width,
3167
- height: isMinimized ? 48 : height,
3575
+ height: isMinimized ? 52 : height,
3168
3576
  cursor: isDragging ? "grabbing" : "default"
3169
3577
  },
3170
3578
  onMouseDown: handleMouseDown,
3171
3579
  children: [
3172
- /* @__PURE__ */ jsxs("div", { "data-drag-handle": true, style: styles12.titleBar, children: [
3173
- /* @__PURE__ */ jsx("span", { style: styles12.titleText, children: buildChannelName(patientData) }),
3174
- /* @__PURE__ */ jsxs("div", { style: styles12.titleActions, children: [
3580
+ /* @__PURE__ */ jsxs("div", { "data-drag-handle": true, style: styles13.titleBar, children: [
3581
+ /* @__PURE__ */ jsx("span", { style: styles13.titleText, children: buildChannelName(patientData) }),
3582
+ /* @__PURE__ */ jsxs("div", { style: styles13.titleActions, children: [
3175
3583
  /* @__PURE__ */ jsx(
3176
3584
  "button",
3177
3585
  {
3178
3586
  onClick: () => setIsMinimized(!isMinimized),
3179
- style: styles12.titleButton,
3587
+ style: styles13.titleButton,
3588
+ "aria-label": isMinimized ? "Expand chat" : "Minimize chat",
3180
3589
  title: isMinimized ? "Expand" : "Minimize",
3181
3590
  type: "button",
3182
- children: isMinimized ? "\u25A2" : "\u2014"
3591
+ children: isMinimized ? /* @__PURE__ */ jsx(ExpandIcon, { size: 16, color: "#cbd5e1" }) : /* @__PURE__ */ jsx(MinimizeIcon, { size: 16, color: "#cbd5e1" })
3183
3592
  }
3184
3593
  ),
3185
- /* @__PURE__ */ jsx("button", { onClick: onClose, style: styles12.titleButton, title: "Close", type: "button", children: "\u2715" })
3594
+ /* @__PURE__ */ jsx(
3595
+ "button",
3596
+ {
3597
+ onClick: onClose,
3598
+ style: styles13.titleButton,
3599
+ "aria-label": "Close chat",
3600
+ title: "Close",
3601
+ type: "button",
3602
+ children: /* @__PURE__ */ jsx(CloseIcon, { size: 16, color: "#cbd5e1" })
3603
+ }
3604
+ )
3186
3605
  ] })
3187
3606
  ] }),
3188
- !isMinimized && /* @__PURE__ */ jsx("div", { style: styles12.panelWrapper, children: /* @__PURE__ */ jsx(CollabPanel, { orderId, patientData, participantIds }) })
3607
+ !isMinimized && /* @__PURE__ */ jsx("div", { style: styles13.panelWrapper, children: /* @__PURE__ */ jsx(CollabPanel, { orderId, patientData, participantIds }) })
3189
3608
  ]
3190
3609
  }
3191
3610
  );
3192
3611
  }
3193
- var styles12 = {
3612
+ var styles13 = {
3194
3613
  container: {
3195
3614
  position: "fixed",
3196
3615
  zIndex: 9999,
@@ -3207,15 +3626,15 @@ var styles12 = {
3207
3626
  display: "flex",
3208
3627
  justifyContent: "space-between",
3209
3628
  alignItems: "center",
3210
- padding: "0 12px",
3211
- height: "48px",
3629
+ padding: "0 8px 0 14px",
3630
+ height: "52px",
3212
3631
  backgroundColor: "#1e293b",
3213
3632
  cursor: "grab",
3214
3633
  userSelect: "none",
3215
3634
  flexShrink: 0
3216
3635
  },
3217
3636
  titleText: {
3218
- fontSize: "13px",
3637
+ fontSize: "15px",
3219
3638
  fontWeight: 500,
3220
3639
  color: "#ffffff",
3221
3640
  overflow: "hidden",
@@ -3228,17 +3647,16 @@ var styles12 = {
3228
3647
  flexShrink: 0
3229
3648
  },
3230
3649
  titleButton: {
3231
- width: "28px",
3232
- height: "28px",
3650
+ width: "40px",
3651
+ height: "40px",
3233
3652
  display: "flex",
3234
3653
  alignItems: "center",
3235
3654
  justifyContent: "center",
3236
3655
  backgroundColor: "transparent",
3237
3656
  border: "none",
3238
- borderRadius: "4px",
3657
+ borderRadius: "6px",
3239
3658
  cursor: "pointer",
3240
- fontSize: "13px",
3241
- color: "#94a3b8"
3659
+ color: "#cbd5e1"
3242
3660
  },
3243
3661
  panelWrapper: {
3244
3662
  flex: 1,
@@ -3496,11 +3914,11 @@ function CollabInline({
3496
3914
  containerRef
3497
3915
  } = useInlineCollab({ orderId, patientData, participantIds, messageLimit });
3498
3916
  if (isLoading && !hasConversation) {
3499
- return /* @__PURE__ */ jsx("div", { className, style: { ...styles13.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles13.loadingState, children: "Loading..." }) });
3917
+ return /* @__PURE__ */ jsx("div", { className, style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
3500
3918
  }
3501
- return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, style: { ...styles13.container, ...style }, children: [
3502
- hasConversation && messages.length > 0 && /* @__PURE__ */ jsx("div", { style: styles13.preview, children: messages.slice(-messageLimit).map((message) => /* @__PURE__ */ jsx(InlineMessageRow, { message }, message.id)) }),
3503
- error && /* @__PURE__ */ jsx("div", { style: styles13.error, children: error }),
3919
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, style: { ...styles14.container, ...style }, children: [
3920
+ hasConversation && messages.length > 0 && /* @__PURE__ */ jsx("div", { style: styles14.preview, children: messages.slice(-messageLimit).map((message) => /* @__PURE__ */ jsx(InlineMessageRow, { message }, message.id)) }),
3921
+ error && /* @__PURE__ */ jsx("div", { style: styles14.error, children: error }),
3504
3922
  /* @__PURE__ */ jsx(
3505
3923
  InlineInputBar,
3506
3924
  {
@@ -3517,12 +3935,12 @@ function CollabInline({
3517
3935
  }
3518
3936
  function InlineMessageRow({ message }) {
3519
3937
  if (message.type === "system") {
3520
- return /* @__PURE__ */ jsx("div", { style: styles13.systemRow, children: /* @__PURE__ */ jsx("span", { style: styles13.systemText, children: message.body }) });
3938
+ return /* @__PURE__ */ jsx("div", { style: styles14.systemRow, children: /* @__PURE__ */ jsx("span", { style: styles14.systemText, children: message.body }) });
3521
3939
  }
3522
3940
  if (message.type === "audio" && message.mediaUrl) {
3523
- return /* @__PURE__ */ jsxs("div", { style: styles13.messageRow, children: [
3941
+ return /* @__PURE__ */ jsxs("div", { style: styles14.messageRow, children: [
3524
3942
  /* @__PURE__ */ jsx(RoleDot, { role: message.senderRole }),
3525
- /* @__PURE__ */ jsxs("span", { style: styles13.senderName, children: [
3943
+ /* @__PURE__ */ jsxs("span", { style: styles14.senderName, children: [
3526
3944
  message.senderName,
3527
3945
  ":"
3528
3946
  ] }),
@@ -3530,13 +3948,13 @@ function InlineMessageRow({ message }) {
3530
3948
  ] });
3531
3949
  }
3532
3950
  const preview = renderMessagePreview(message);
3533
- return /* @__PURE__ */ jsxs("div", { style: styles13.messageRow, children: [
3951
+ return /* @__PURE__ */ jsxs("div", { style: styles14.messageRow, children: [
3534
3952
  /* @__PURE__ */ jsx(RoleDot, { role: message.senderRole }),
3535
- /* @__PURE__ */ jsxs("span", { style: styles13.senderName, children: [
3953
+ /* @__PURE__ */ jsxs("span", { style: styles14.senderName, children: [
3536
3954
  message.senderName,
3537
3955
  ":"
3538
3956
  ] }),
3539
- /* @__PURE__ */ jsx("span", { style: styles13.messageText, children: preview })
3957
+ /* @__PURE__ */ jsx("span", { style: styles14.messageText, children: preview })
3540
3958
  ] });
3541
3959
  }
3542
3960
  function RoleDot({ role }) {
@@ -3546,7 +3964,7 @@ function RoleDot({ role }) {
3546
3964
  physician: "#059669",
3547
3965
  admin: "#dc2626"
3548
3966
  };
3549
- return /* @__PURE__ */ jsx("span", { style: { ...styles13.roleDot, backgroundColor: colors[role] } });
3967
+ return /* @__PURE__ */ jsx("span", { style: { ...styles14.roleDot, backgroundColor: colors[role] } });
3550
3968
  }
3551
3969
  function InlineAudioPlayer({ url, duration }) {
3552
3970
  const audioRef = useRef(null);
@@ -3590,27 +4008,27 @@ function InlineAudioPlayer({ url, duration }) {
3590
4008
  const total = duration ?? 0;
3591
4009
  const remaining = Math.max(0, total - Math.floor(currentTime));
3592
4010
  const displayTime = isPlaying ? remaining : total;
3593
- return /* @__PURE__ */ jsxs("span", { style: styles13.audioPlayer, children: [
4011
+ return /* @__PURE__ */ jsxs("span", { style: styles14.audioPlayer, children: [
3594
4012
  /* @__PURE__ */ jsx(
3595
4013
  "button",
3596
4014
  {
3597
4015
  onClick: toggle,
3598
- style: styles13.audioButton,
4016
+ style: styles14.audioButton,
3599
4017
  title: isPlaying ? "Pause" : "Play",
3600
4018
  type: "button",
3601
4019
  children: isPlaying ? "\u23F8" : "\u25B6"
3602
4020
  }
3603
4021
  ),
3604
- /* @__PURE__ */ jsxs("span", { style: styles13.audioWaveform, children: [
3605
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "40%" } }),
3606
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "80%" } }),
3607
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "60%" } }),
3608
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "90%" } }),
3609
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "50%" } }),
3610
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "70%" } }),
3611
- /* @__PURE__ */ jsx("span", { style: { ...styles13.waveBar, height: "40%" } })
4022
+ /* @__PURE__ */ jsxs("span", { style: styles14.audioWaveform, children: [
4023
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "40%" } }),
4024
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "80%" } }),
4025
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "60%" } }),
4026
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "90%" } }),
4027
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "50%" } }),
4028
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "70%" } }),
4029
+ /* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "40%" } })
3612
4030
  ] }),
3613
- /* @__PURE__ */ jsx("span", { style: styles13.audioDuration, children: formatDuration2(displayTime) }),
4031
+ /* @__PURE__ */ jsx("span", { style: styles14.audioDuration, children: formatDuration2(displayTime) }),
3614
4032
  /* @__PURE__ */ jsx("audio", { ref: audioRef, src: url, preload: "metadata" })
3615
4033
  ] });
3616
4034
  }
@@ -3666,7 +4084,7 @@ function InlineInputBar({
3666
4084
  },
3667
4085
  [handleSend]
3668
4086
  );
3669
- return /* @__PURE__ */ jsxs("div", { style: styles13.inputBar, children: [
4087
+ return /* @__PURE__ */ jsxs("div", { style: styles14.inputBar, children: [
3670
4088
  /* @__PURE__ */ jsx(
3671
4089
  "input",
3672
4090
  {
@@ -3677,17 +4095,17 @@ function InlineInputBar({
3677
4095
  onKeyDown: handleKeyDown,
3678
4096
  placeholder,
3679
4097
  disabled: isSending,
3680
- style: styles13.input
4098
+ style: styles14.input
3681
4099
  }
3682
4100
  ),
3683
- unreadCount > 0 && /* @__PURE__ */ jsx("span", { style: styles13.unreadBadge, title: `${unreadCount} unread`, children: unreadCount > 99 ? "99+" : unreadCount }),
3684
- isLive && /* @__PURE__ */ jsx("span", { style: styles13.liveDot, title: "Live updates active" }),
4101
+ unreadCount > 0 && /* @__PURE__ */ jsx("span", { style: styles14.unreadBadge, title: `${unreadCount} unread`, children: unreadCount > 99 ? "99+" : unreadCount }),
4102
+ isLive && /* @__PURE__ */ jsx("span", { style: styles14.liveDot, title: "Live updates active" }),
3685
4103
  text.trim() && /* @__PURE__ */ jsx(
3686
4104
  "button",
3687
4105
  {
3688
4106
  onClick: handleSend,
3689
4107
  disabled: isSending,
3690
- style: styles13.sendButton,
4108
+ style: styles14.sendButton,
3691
4109
  title: "Send message",
3692
4110
  type: "button",
3693
4111
  children: "\u27A4"
@@ -3697,7 +4115,7 @@ function InlineInputBar({
3697
4115
  "button",
3698
4116
  {
3699
4117
  onClick: onExpand,
3700
- style: styles13.expandButton,
4118
+ style: styles14.expandButton,
3701
4119
  title: "Expand to full chat",
3702
4120
  type: "button",
3703
4121
  children: "\u26F6"
@@ -3705,7 +4123,7 @@ function InlineInputBar({
3705
4123
  )
3706
4124
  ] });
3707
4125
  }
3708
- var styles13 = {
4126
+ var styles14 = {
3709
4127
  container: {
3710
4128
  display: "flex",
3711
4129
  flexDirection: "column",
@@ -3972,24 +4390,24 @@ function ConversationListItem({
3972
4390
  className,
3973
4391
  onClick,
3974
4392
  style: {
3975
- ...styles14.container,
3976
- ...isSelected ? styles14.selected : {},
3977
- ...hasUnread ? styles14.unread : {}
4393
+ ...styles15.container,
4394
+ ...isSelected ? styles15.selected : {},
4395
+ ...hasUnread ? styles15.unread : {}
3978
4396
  },
3979
4397
  type: "button",
3980
4398
  children: [
3981
- /* @__PURE__ */ jsxs("div", { style: styles14.avatarWrapper, children: [
3982
- item.picture ? /* @__PURE__ */ jsx("img", { src: item.picture, alt: "", style: styles14.avatar }) : /* @__PURE__ */ jsx("div", { style: styles14.avatarFallback, children: (displayName).charAt(0).toUpperCase() }),
3983
- hasUnread && /* @__PURE__ */ jsx("span", { style: styles14.unreadDot })
4399
+ /* @__PURE__ */ jsxs("div", { style: styles15.avatarWrapper, children: [
4400
+ item.picture ? /* @__PURE__ */ jsx("img", { src: item.picture, alt: "", style: styles15.avatar }) : /* @__PURE__ */ jsx("div", { style: styles15.avatarFallback, children: (displayName).charAt(0).toUpperCase() }),
4401
+ hasUnread && /* @__PURE__ */ jsx("span", { style: styles15.unreadDot })
3984
4402
  ] }),
3985
- /* @__PURE__ */ jsxs("div", { style: styles14.content, children: [
3986
- /* @__PURE__ */ jsxs("div", { style: styles14.topRow, children: [
4403
+ /* @__PURE__ */ jsxs("div", { style: styles15.content, children: [
4404
+ /* @__PURE__ */ jsxs("div", { style: styles15.topRow, children: [
3987
4405
  /* @__PURE__ */ jsx(
3988
4406
  "span",
3989
4407
  {
3990
4408
  style: {
3991
- ...styles14.name,
3992
- ...hasUnread ? styles14.nameUnread : {}
4409
+ ...styles15.name,
4410
+ ...hasUnread ? styles15.nameUnread : {}
3993
4411
  },
3994
4412
  children: displayName
3995
4413
  }
@@ -3998,25 +4416,25 @@ function ConversationListItem({
3998
4416
  "span",
3999
4417
  {
4000
4418
  style: {
4001
- ...styles14.time,
4002
- ...hasUnread ? styles14.timeUnread : {}
4419
+ ...styles15.time,
4420
+ ...hasUnread ? styles15.timeUnread : {}
4003
4421
  },
4004
4422
  children: formatInboxTimestamp(item.lastActivityAt)
4005
4423
  }
4006
4424
  )
4007
4425
  ] }),
4008
- /* @__PURE__ */ jsxs("div", { style: styles14.bottomRow, children: [
4426
+ /* @__PURE__ */ jsxs("div", { style: styles15.bottomRow, children: [
4009
4427
  /* @__PURE__ */ jsx(
4010
4428
  "span",
4011
4429
  {
4012
4430
  style: {
4013
- ...styles14.preview,
4014
- ...hasUnread ? styles14.previewUnread : {}
4431
+ ...styles15.preview,
4432
+ ...hasUnread ? styles15.previewUnread : {}
4015
4433
  },
4016
4434
  children: renderLastMessagePreview(item.lastMessage)
4017
4435
  }
4018
4436
  ),
4019
- hasUnread && /* @__PURE__ */ jsx("span", { style: styles14.badge, children: item.unreadCount > 99 ? "99+" : item.unreadCount })
4437
+ hasUnread && /* @__PURE__ */ jsx("span", { style: styles15.badge, children: item.unreadCount > 99 ? "99+" : item.unreadCount })
4020
4438
  ] })
4021
4439
  ] })
4022
4440
  ]
@@ -4044,7 +4462,7 @@ function renderLastMessagePreview(message) {
4044
4462
  }
4045
4463
  }
4046
4464
  }
4047
- var styles14 = {
4465
+ var styles15 = {
4048
4466
  container: {
4049
4467
  display: "flex",
4050
4468
  alignItems: "center",
@@ -4109,7 +4527,7 @@ var styles14 = {
4109
4527
  gap: "8px"
4110
4528
  },
4111
4529
  name: {
4112
- fontSize: "14px",
4530
+ fontSize: "15px",
4113
4531
  fontWeight: 500,
4114
4532
  color: "#111827",
4115
4533
  overflow: "hidden",
@@ -4122,8 +4540,8 @@ var styles14 = {
4122
4540
  fontWeight: 700
4123
4541
  },
4124
4542
  time: {
4125
- fontSize: "11px",
4126
- color: "#9ca3af",
4543
+ fontSize: "12px",
4544
+ color: "#6b7280",
4127
4545
  flexShrink: 0
4128
4546
  },
4129
4547
  timeUnread: {
@@ -4137,8 +4555,8 @@ var styles14 = {
4137
4555
  gap: "8px"
4138
4556
  },
4139
4557
  preview: {
4140
- fontSize: "13px",
4141
- color: "#6b7280",
4558
+ fontSize: "14px",
4559
+ color: "#4b5563",
4142
4560
  overflow: "hidden",
4143
4561
  textOverflow: "ellipsis",
4144
4562
  whiteSpace: "nowrap",
@@ -4191,30 +4609,30 @@ function ConversationList({
4191
4609
  return result;
4192
4610
  }, [conversations, query, showUnreadOnly]);
4193
4611
  const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);
4194
- return /* @__PURE__ */ jsxs("div", { className, style: styles15.container, children: [
4195
- /* @__PURE__ */ jsxs("div", { style: styles15.header, children: [
4196
- /* @__PURE__ */ jsxs("div", { style: styles15.titleRow, children: [
4197
- /* @__PURE__ */ jsx("h3", { style: styles15.title, children: title }),
4198
- totalUnread > 0 && /* @__PURE__ */ jsx("span", { style: styles15.totalBadge, children: totalUnread })
4612
+ return /* @__PURE__ */ jsxs("div", { className, style: styles16.container, children: [
4613
+ /* @__PURE__ */ jsxs("div", { style: styles16.header, children: [
4614
+ /* @__PURE__ */ jsxs("div", { style: styles16.titleRow, children: [
4615
+ /* @__PURE__ */ jsx("h3", { style: styles16.title, children: title }),
4616
+ totalUnread > 0 && /* @__PURE__ */ jsx("span", { style: styles16.totalBadge, children: totalUnread })
4199
4617
  ] }),
4200
- /* @__PURE__ */ jsx("div", { style: styles15.searchRow, children: /* @__PURE__ */ jsx(
4618
+ /* @__PURE__ */ jsx("div", { style: styles16.searchRow, children: /* @__PURE__ */ jsx(
4201
4619
  "input",
4202
4620
  {
4203
4621
  type: "text",
4204
4622
  value: query,
4205
4623
  onChange: (e) => setQuery(e.target.value),
4206
4624
  placeholder: "Search patients or channels...",
4207
- style: styles15.searchInput
4625
+ style: styles16.searchInput
4208
4626
  }
4209
4627
  ) }),
4210
- /* @__PURE__ */ jsxs("div", { style: styles15.filterRow, children: [
4628
+ /* @__PURE__ */ jsxs("div", { style: styles16.filterRow, children: [
4211
4629
  /* @__PURE__ */ jsx(
4212
4630
  "button",
4213
4631
  {
4214
4632
  onClick: () => setShowUnreadOnly(false),
4215
4633
  style: {
4216
- ...styles15.filterButton,
4217
- ...!showUnreadOnly ? styles15.filterButtonActive : {}
4634
+ ...styles16.filterButton,
4635
+ ...!showUnreadOnly ? styles16.filterButtonActive : {}
4218
4636
  },
4219
4637
  type: "button",
4220
4638
  children: "All"
@@ -4225,8 +4643,8 @@ function ConversationList({
4225
4643
  {
4226
4644
  onClick: () => setShowUnreadOnly(true),
4227
4645
  style: {
4228
- ...styles15.filterButton,
4229
- ...showUnreadOnly ? styles15.filterButtonActive : {}
4646
+ ...styles16.filterButton,
4647
+ ...showUnreadOnly ? styles16.filterButtonActive : {}
4230
4648
  },
4231
4649
  type: "button",
4232
4650
  children: [
@@ -4237,10 +4655,10 @@ function ConversationList({
4237
4655
  )
4238
4656
  ] })
4239
4657
  ] }),
4240
- /* @__PURE__ */ jsxs("div", { style: styles15.list, children: [
4241
- isLoading && /* @__PURE__ */ jsx("div", { style: styles15.state, children: "Loading conversations..." }),
4242
- error && /* @__PURE__ */ jsx("div", { style: styles15.errorState, children: error }),
4243
- !isLoading && !error && filtered.length === 0 && /* @__PURE__ */ jsx("div", { style: styles15.state, children: query ? "No matching conversations" : "No conversations yet" }),
4658
+ /* @__PURE__ */ jsxs("div", { style: styles16.list, children: [
4659
+ isLoading && /* @__PURE__ */ jsx("div", { style: styles16.state, children: "Loading conversations..." }),
4660
+ error && /* @__PURE__ */ jsx("div", { style: styles16.errorState, children: error }),
4661
+ !isLoading && !error && filtered.length === 0 && /* @__PURE__ */ jsx("div", { style: styles16.state, children: query ? "No matching conversations" : "No conversations yet" }),
4244
4662
  filtered.map((item) => /* @__PURE__ */ jsx(
4245
4663
  ConversationListItem,
4246
4664
  {
@@ -4253,7 +4671,7 @@ function ConversationList({
4253
4671
  ] })
4254
4672
  ] });
4255
4673
  }
4256
- var styles15 = {
4674
+ var styles16 = {
4257
4675
  container: {
4258
4676
  display: "flex",
4259
4677
  flexDirection: "column",
@@ -4358,8 +4776,8 @@ function CollabInbox({
4358
4776
  setSelectedId(item.id);
4359
4777
  onSelectConversation?.(item);
4360
4778
  };
4361
- return /* @__PURE__ */ jsxs("div", { className, style: { ...styles16.container, ...style }, children: [
4362
- /* @__PURE__ */ jsx("div", { style: styles16.sidebar, children: /* @__PURE__ */ jsx(
4779
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...styles17.container, ...style }, children: [
4780
+ /* @__PURE__ */ jsx("div", { style: styles17.sidebar, children: /* @__PURE__ */ jsx(
4363
4781
  ConversationList,
4364
4782
  {
4365
4783
  conversations,
@@ -4370,13 +4788,13 @@ function CollabInbox({
4370
4788
  title
4371
4789
  }
4372
4790
  ) }),
4373
- /* @__PURE__ */ jsx("div", { style: styles16.main, children: selected ? /* @__PURE__ */ jsx(
4791
+ /* @__PURE__ */ jsx("div", { style: styles17.main, children: selected ? /* @__PURE__ */ jsx(
4374
4792
  CollabPanel,
4375
4793
  {
4376
4794
  orderId: selected.orderId,
4377
4795
  patientData: buildPatientData(selected),
4378
4796
  showSeenBy: true,
4379
- style: styles16.panel
4797
+ style: styles17.panel
4380
4798
  },
4381
4799
  selected.id
4382
4800
  ) : /* @__PURE__ */ jsx(EmptyState, { hasAny: conversations.length > 0 }) })
@@ -4390,13 +4808,13 @@ function buildPatientData(item) {
4390
4808
  };
4391
4809
  }
4392
4810
  function EmptyState({ hasAny }) {
4393
- return /* @__PURE__ */ jsxs("div", { style: styles16.empty, children: [
4394
- /* @__PURE__ */ jsx("div", { style: styles16.emptyIcon, children: "\u{1F4AC}" }),
4395
- /* @__PURE__ */ jsx("h3", { style: styles16.emptyTitle, children: hasAny ? "Select a conversation" : "No conversations yet" }),
4396
- /* @__PURE__ */ jsx("p", { style: styles16.emptySubtitle, children: hasAny ? "Pick a patient from the list to start collaborating" : "Conversations appear here once you start messaging about a case" })
4811
+ return /* @__PURE__ */ jsxs("div", { style: styles17.empty, children: [
4812
+ /* @__PURE__ */ jsx("div", { style: styles17.emptyIcon, children: "\u{1F4AC}" }),
4813
+ /* @__PURE__ */ jsx("h3", { style: styles17.emptyTitle, children: hasAny ? "Select a conversation" : "No conversations yet" }),
4814
+ /* @__PURE__ */ jsx("p", { style: styles17.emptySubtitle, children: hasAny ? "Pick a patient from the list to start collaborating" : "Conversations appear here once you start messaging about a case" })
4397
4815
  ] });
4398
4816
  }
4399
- var styles16 = {
4817
+ var styles17 = {
4400
4818
  container: {
4401
4819
  display: "flex",
4402
4820
  height: "100%",