@natoe/colab 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +24 -6
- package/dist/index.d.ts +24 -6
- package/dist/index.js +687 -245
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +688 -246
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React4, { createContext, forwardRef, useRef, useImperativeHandle, useEffect, useCallback, useState, useContext, useMemo } from 'react';
|
|
1
|
+
import React4, { createContext, forwardRef, useRef, useImperativeHandle, useEffect, useCallback, useState, useContext, useId, useMemo } from 'react';
|
|
2
2
|
import { Socket, Presence } from 'phoenix';
|
|
3
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -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(
|
|
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,
|
|
@@ -1339,91 +1373,247 @@ var styles3 = {
|
|
|
1339
1373
|
textDecoration: "underline"
|
|
1340
1374
|
}
|
|
1341
1375
|
};
|
|
1376
|
+
function ReplyIcon({ size = 18, color = "currentColor" }) {
|
|
1377
|
+
return /* @__PURE__ */ jsx(
|
|
1378
|
+
"svg",
|
|
1379
|
+
{
|
|
1380
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1381
|
+
width: size,
|
|
1382
|
+
height: size,
|
|
1383
|
+
viewBox: "0 0 24 24",
|
|
1384
|
+
fill: color,
|
|
1385
|
+
"aria-hidden": "true",
|
|
1386
|
+
children: /* @__PURE__ */ jsx("path", { d: "M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z" })
|
|
1387
|
+
}
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
function PinIcon({ size = 14, color = "currentColor" }) {
|
|
1391
|
+
return /* @__PURE__ */ jsx(
|
|
1392
|
+
"svg",
|
|
1393
|
+
{
|
|
1394
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1395
|
+
width: size,
|
|
1396
|
+
height: size,
|
|
1397
|
+
viewBox: "0 0 24 24",
|
|
1398
|
+
fill: color,
|
|
1399
|
+
"aria-hidden": "true",
|
|
1400
|
+
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" })
|
|
1401
|
+
}
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
function CopyIcon({ size = 18, color = "currentColor" }) {
|
|
1405
|
+
return /* @__PURE__ */ jsx(
|
|
1406
|
+
"svg",
|
|
1407
|
+
{
|
|
1408
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1409
|
+
width: size,
|
|
1410
|
+
height: size,
|
|
1411
|
+
viewBox: "0 0 24 24",
|
|
1412
|
+
fill: color,
|
|
1413
|
+
"aria-hidden": "true",
|
|
1414
|
+
children: /* @__PURE__ */ jsx("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" })
|
|
1415
|
+
}
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
function MoreIcon({ size = 18, color = "currentColor" }) {
|
|
1419
|
+
return /* @__PURE__ */ jsxs(
|
|
1420
|
+
"svg",
|
|
1421
|
+
{
|
|
1422
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1423
|
+
width: size,
|
|
1424
|
+
height: size,
|
|
1425
|
+
viewBox: "0 0 24 24",
|
|
1426
|
+
fill: color,
|
|
1427
|
+
"aria-hidden": "true",
|
|
1428
|
+
children: [
|
|
1429
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "2" }),
|
|
1430
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "2" }),
|
|
1431
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "2" })
|
|
1432
|
+
]
|
|
1433
|
+
}
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1342
1436
|
function MessageActionsMenu({
|
|
1343
1437
|
message,
|
|
1344
1438
|
onReply,
|
|
1345
1439
|
onPin,
|
|
1346
1440
|
onUnpin,
|
|
1347
1441
|
onCopy,
|
|
1348
|
-
visible,
|
|
1349
1442
|
pinDisabled = false,
|
|
1443
|
+
anchorRight = false,
|
|
1350
1444
|
className
|
|
1351
1445
|
}) {
|
|
1352
|
-
|
|
1446
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1447
|
+
const wrapperRef = useRef(null);
|
|
1448
|
+
const triggerRef = useRef(null);
|
|
1353
1449
|
const isPinned = !!message.isPinned;
|
|
1354
1450
|
const canCopy = message.type === "text" && !!message.body;
|
|
1355
|
-
|
|
1356
|
-
if (!
|
|
1357
|
-
|
|
1451
|
+
useEffect(() => {
|
|
1452
|
+
if (!isOpen) return;
|
|
1453
|
+
const handleClick = (e) => {
|
|
1454
|
+
if (!wrapperRef.current?.contains(e.target)) {
|
|
1455
|
+
setIsOpen(false);
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
const handleKey = (e) => {
|
|
1459
|
+
if (e.key === "Escape") {
|
|
1460
|
+
setIsOpen(false);
|
|
1461
|
+
triggerRef.current?.focus();
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
document.addEventListener("mousedown", handleClick);
|
|
1465
|
+
document.addEventListener("keydown", handleKey);
|
|
1466
|
+
return () => {
|
|
1467
|
+
document.removeEventListener("mousedown", handleClick);
|
|
1468
|
+
document.removeEventListener("keydown", handleKey);
|
|
1469
|
+
};
|
|
1470
|
+
}, [isOpen]);
|
|
1471
|
+
const run = (fn) => {
|
|
1472
|
+
setIsOpen(false);
|
|
1473
|
+
fn();
|
|
1358
1474
|
};
|
|
1359
|
-
return /* @__PURE__ */ jsxs("div", { className, style: styles4.
|
|
1475
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className, style: styles4.wrapper, children: [
|
|
1360
1476
|
/* @__PURE__ */ jsx(
|
|
1361
1477
|
"button",
|
|
1362
1478
|
{
|
|
1363
|
-
|
|
1364
|
-
style: styles4.button,
|
|
1365
|
-
title: "Reply",
|
|
1479
|
+
ref: triggerRef,
|
|
1366
1480
|
type: "button",
|
|
1367
|
-
|
|
1481
|
+
onClick: (e) => {
|
|
1482
|
+
e.stopPropagation();
|
|
1483
|
+
setIsOpen((v) => !v);
|
|
1484
|
+
},
|
|
1485
|
+
"aria-label": "Message actions",
|
|
1486
|
+
"aria-haspopup": "menu",
|
|
1487
|
+
"aria-expanded": isOpen ? "true" : "false",
|
|
1488
|
+
title: "Message actions",
|
|
1489
|
+
style: styles4.trigger,
|
|
1490
|
+
children: /* @__PURE__ */ jsx(MoreIcon, { size: 18, color: "#4b5563" })
|
|
1368
1491
|
}
|
|
1369
1492
|
),
|
|
1370
|
-
|
|
1371
|
-
"
|
|
1372
|
-
{
|
|
1373
|
-
onClick: () => onUnpin(message.id),
|
|
1374
|
-
style: styles4.button,
|
|
1375
|
-
title: "Unpin",
|
|
1376
|
-
type: "button",
|
|
1377
|
-
children: "\u{1F4CC}"
|
|
1378
|
-
}
|
|
1379
|
-
) : /* @__PURE__ */ jsx(
|
|
1380
|
-
"button",
|
|
1493
|
+
isOpen && /* @__PURE__ */ jsxs(
|
|
1494
|
+
"div",
|
|
1381
1495
|
{
|
|
1382
|
-
|
|
1496
|
+
role: "menu",
|
|
1497
|
+
"aria-label": "Message actions",
|
|
1383
1498
|
style: {
|
|
1384
|
-
...styles4.
|
|
1385
|
-
|
|
1386
|
-
cursor: pinDisabled ? "not-allowed" : "pointer"
|
|
1499
|
+
...styles4.menu,
|
|
1500
|
+
...anchorRight ? styles4.menuRight : styles4.menuLeft
|
|
1387
1501
|
},
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1502
|
+
children: [
|
|
1503
|
+
/* @__PURE__ */ jsxs(
|
|
1504
|
+
"button",
|
|
1505
|
+
{
|
|
1506
|
+
type: "button",
|
|
1507
|
+
role: "menuitem",
|
|
1508
|
+
onClick: () => run(() => onReply(message)),
|
|
1509
|
+
style: styles4.item,
|
|
1510
|
+
children: [
|
|
1511
|
+
/* @__PURE__ */ jsx(ReplyIcon, { size: 18, color: "#374151" }),
|
|
1512
|
+
/* @__PURE__ */ jsx("span", { children: "Reply" })
|
|
1513
|
+
]
|
|
1514
|
+
}
|
|
1515
|
+
),
|
|
1516
|
+
isPinned ? /* @__PURE__ */ jsxs(
|
|
1517
|
+
"button",
|
|
1518
|
+
{
|
|
1519
|
+
type: "button",
|
|
1520
|
+
role: "menuitem",
|
|
1521
|
+
onClick: () => run(() => onUnpin(message.id)),
|
|
1522
|
+
style: styles4.item,
|
|
1523
|
+
children: [
|
|
1524
|
+
/* @__PURE__ */ jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1525
|
+
/* @__PURE__ */ jsx("span", { children: "Unpin" })
|
|
1526
|
+
]
|
|
1527
|
+
}
|
|
1528
|
+
) : /* @__PURE__ */ jsxs(
|
|
1529
|
+
"button",
|
|
1530
|
+
{
|
|
1531
|
+
type: "button",
|
|
1532
|
+
role: "menuitem",
|
|
1533
|
+
onClick: () => run(() => onPin(message.id)),
|
|
1534
|
+
disabled: pinDisabled,
|
|
1535
|
+
style: {
|
|
1536
|
+
...styles4.item,
|
|
1537
|
+
...pinDisabled ? styles4.itemDisabled : {}
|
|
1538
|
+
},
|
|
1539
|
+
title: pinDisabled ? "Pin limit reached (max 3)" : void 0,
|
|
1540
|
+
children: [
|
|
1541
|
+
/* @__PURE__ */ jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1542
|
+
/* @__PURE__ */ jsx("span", { children: pinDisabled ? "Pin (limit reached)" : "Pin" })
|
|
1543
|
+
]
|
|
1544
|
+
}
|
|
1545
|
+
),
|
|
1546
|
+
canCopy && onCopy && /* @__PURE__ */ jsxs(
|
|
1547
|
+
"button",
|
|
1548
|
+
{
|
|
1549
|
+
type: "button",
|
|
1550
|
+
role: "menuitem",
|
|
1551
|
+
onClick: () => run(() => onCopy(message.body)),
|
|
1552
|
+
style: styles4.item,
|
|
1553
|
+
children: [
|
|
1554
|
+
/* @__PURE__ */ jsx(CopyIcon, { size: 16, color: "#374151" }),
|
|
1555
|
+
/* @__PURE__ */ jsx("span", { children: "Copy text" })
|
|
1556
|
+
]
|
|
1557
|
+
}
|
|
1558
|
+
)
|
|
1559
|
+
]
|
|
1402
1560
|
}
|
|
1403
1561
|
)
|
|
1404
1562
|
] });
|
|
1405
1563
|
}
|
|
1406
1564
|
var styles4 = {
|
|
1407
|
-
|
|
1565
|
+
wrapper: {
|
|
1566
|
+
position: "relative",
|
|
1567
|
+
display: "inline-block"
|
|
1568
|
+
},
|
|
1569
|
+
trigger: {
|
|
1570
|
+
width: "36px",
|
|
1571
|
+
height: "36px",
|
|
1408
1572
|
display: "flex",
|
|
1409
|
-
|
|
1410
|
-
|
|
1573
|
+
alignItems: "center",
|
|
1574
|
+
justifyContent: "center",
|
|
1575
|
+
backgroundColor: "transparent",
|
|
1576
|
+
border: "none",
|
|
1577
|
+
borderRadius: "50%",
|
|
1578
|
+
cursor: "pointer",
|
|
1579
|
+
color: "#4b5563"
|
|
1580
|
+
},
|
|
1581
|
+
menu: {
|
|
1582
|
+
position: "absolute",
|
|
1583
|
+
top: "100%",
|
|
1584
|
+
marginTop: "4px",
|
|
1585
|
+
minWidth: "160px",
|
|
1411
1586
|
backgroundColor: "#ffffff",
|
|
1412
1587
|
border: "1px solid #e5e7eb",
|
|
1413
|
-
borderRadius: "
|
|
1414
|
-
boxShadow: "0
|
|
1588
|
+
borderRadius: "10px",
|
|
1589
|
+
boxShadow: "0 6px 18px rgba(0, 0, 0, 0.12)",
|
|
1590
|
+
padding: "4px",
|
|
1591
|
+
zIndex: 20
|
|
1415
1592
|
},
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1593
|
+
menuLeft: {
|
|
1594
|
+
left: 0
|
|
1595
|
+
},
|
|
1596
|
+
menuRight: {
|
|
1597
|
+
right: 0
|
|
1598
|
+
},
|
|
1599
|
+
item: {
|
|
1419
1600
|
display: "flex",
|
|
1420
1601
|
alignItems: "center",
|
|
1421
|
-
|
|
1422
|
-
|
|
1602
|
+
gap: "10px",
|
|
1603
|
+
width: "100%",
|
|
1604
|
+
minHeight: "40px",
|
|
1605
|
+
padding: "8px 12px",
|
|
1606
|
+
fontSize: "14px",
|
|
1607
|
+
color: "#111827",
|
|
1423
1608
|
backgroundColor: "transparent",
|
|
1424
1609
|
border: "none",
|
|
1425
|
-
borderRadius: "
|
|
1426
|
-
cursor: "pointer"
|
|
1610
|
+
borderRadius: "6px",
|
|
1611
|
+
cursor: "pointer",
|
|
1612
|
+
textAlign: "left"
|
|
1613
|
+
},
|
|
1614
|
+
itemDisabled: {
|
|
1615
|
+
color: "#9ca3af",
|
|
1616
|
+
cursor: "not-allowed"
|
|
1427
1617
|
}
|
|
1428
1618
|
};
|
|
1429
1619
|
function FileIcon({ size = 18, color = "currentColor" }) {
|
|
@@ -1440,7 +1630,7 @@ function FileIcon({ size = 18, color = "currentColor" }) {
|
|
|
1440
1630
|
}
|
|
1441
1631
|
);
|
|
1442
1632
|
}
|
|
1443
|
-
function
|
|
1633
|
+
function AlertIcon({ size = 14, color = "currentColor" }) {
|
|
1444
1634
|
return /* @__PURE__ */ jsx(
|
|
1445
1635
|
"svg",
|
|
1446
1636
|
{
|
|
@@ -1450,10 +1640,38 @@ function PinIcon({ size = 14, color = "currentColor" }) {
|
|
|
1450
1640
|
viewBox: "0 0 24 24",
|
|
1451
1641
|
fill: color,
|
|
1452
1642
|
"aria-hidden": "true",
|
|
1453
|
-
children: /* @__PURE__ */ jsx("path", { d: "
|
|
1643
|
+
children: /* @__PURE__ */ jsx("path", { d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" })
|
|
1454
1644
|
}
|
|
1455
1645
|
);
|
|
1456
1646
|
}
|
|
1647
|
+
function Spinner({ size = 16, color = "#6b7280", thickness = 2 }) {
|
|
1648
|
+
return /* @__PURE__ */ jsx(
|
|
1649
|
+
"span",
|
|
1650
|
+
{
|
|
1651
|
+
role: "status",
|
|
1652
|
+
"aria-label": "Loading",
|
|
1653
|
+
style: {
|
|
1654
|
+
display: "inline-block",
|
|
1655
|
+
width: size,
|
|
1656
|
+
height: size,
|
|
1657
|
+
border: `${thickness}px solid ${color}33`,
|
|
1658
|
+
borderTopColor: color,
|
|
1659
|
+
borderRadius: "50%",
|
|
1660
|
+
animation: "natoe-colab-spin 800ms linear infinite",
|
|
1661
|
+
verticalAlign: "middle"
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
if (typeof document !== "undefined") {
|
|
1667
|
+
const existing = document.getElementById("natoe-colab-spin-keyframes");
|
|
1668
|
+
if (!existing) {
|
|
1669
|
+
const style = document.createElement("style");
|
|
1670
|
+
style.id = "natoe-colab-spin-keyframes";
|
|
1671
|
+
style.textContent = `@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }`;
|
|
1672
|
+
document.head.appendChild(style);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1457
1675
|
var ROLE_LABELS = {
|
|
1458
1676
|
radiologist: "Radiologist",
|
|
1459
1677
|
lab: "Imaging Center",
|
|
@@ -1472,15 +1690,30 @@ function MessageBubble({
|
|
|
1472
1690
|
onUnpin,
|
|
1473
1691
|
onCopy,
|
|
1474
1692
|
onReplyJumpTo,
|
|
1693
|
+
onRetry,
|
|
1475
1694
|
pinDisabled = false,
|
|
1476
1695
|
className
|
|
1477
1696
|
}) {
|
|
1478
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
1479
1697
|
if (message.type === "system") {
|
|
1480
1698
|
return /* @__PURE__ */ jsx(SystemBubble, { message });
|
|
1481
1699
|
}
|
|
1482
1700
|
const hasActions = !!(onReply || onPin || onUnpin || onCopy);
|
|
1483
|
-
|
|
1701
|
+
const actionsSlot = hasActions ? /* @__PURE__ */ jsx("div", { style: styles5.actionsSlot, children: /* @__PURE__ */ jsx(
|
|
1702
|
+
MessageActionsMenu,
|
|
1703
|
+
{
|
|
1704
|
+
message,
|
|
1705
|
+
onReply: onReply ?? (() => {
|
|
1706
|
+
}),
|
|
1707
|
+
onPin: onPin ?? (() => {
|
|
1708
|
+
}),
|
|
1709
|
+
onUnpin: onUnpin ?? (() => {
|
|
1710
|
+
}),
|
|
1711
|
+
onCopy,
|
|
1712
|
+
pinDisabled,
|
|
1713
|
+
anchorRight: !isOwn
|
|
1714
|
+
}
|
|
1715
|
+
) }) : null;
|
|
1716
|
+
return /* @__PURE__ */ jsxs(
|
|
1484
1717
|
"div",
|
|
1485
1718
|
{
|
|
1486
1719
|
className,
|
|
@@ -1488,10 +1721,9 @@ function MessageBubble({
|
|
|
1488
1721
|
...styles5.wrapper,
|
|
1489
1722
|
justifyContent: isOwn ? "flex-end" : "flex-start"
|
|
1490
1723
|
},
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
/* @__PURE__ */ jsxs(
|
|
1724
|
+
children: [
|
|
1725
|
+
isOwn && actionsSlot,
|
|
1726
|
+
/* @__PURE__ */ jsx("div", { style: styles5.bubbleWrapper, children: /* @__PURE__ */ jsxs(
|
|
1495
1727
|
"div",
|
|
1496
1728
|
{
|
|
1497
1729
|
style: {
|
|
@@ -1521,7 +1753,25 @@ function MessageBubble({
|
|
|
1521
1753
|
message.type === "file" && /* @__PURE__ */ jsx(FileContent, { mediaUrl: message.mediaUrl, fileName: message.fileName }),
|
|
1522
1754
|
message.type === "deep_link" && /* @__PURE__ */ jsx(DeepLinkContent, { body: message.body, metadata: message.metadata, onDeepLinkClick }),
|
|
1523
1755
|
/* @__PURE__ */ jsx("div", { style: styles5.timestamp, children: formatTime(message.insertedAt) }),
|
|
1524
|
-
|
|
1756
|
+
isOwn && message.status === "sending" && /* @__PURE__ */ jsxs("div", { style: styles5.statusRow, children: [
|
|
1757
|
+
/* @__PURE__ */ jsx(Spinner, { size: 12, color: "rgba(255,255,255,0.85)" }),
|
|
1758
|
+
/* @__PURE__ */ jsx("span", { style: styles5.statusText, children: "Sending\u2026" })
|
|
1759
|
+
] }),
|
|
1760
|
+
isOwn && message.status === "failed" && /* @__PURE__ */ jsxs("div", { style: styles5.statusRow, children: [
|
|
1761
|
+
/* @__PURE__ */ jsx(AlertIcon, { size: 12, color: "#fecaca" }),
|
|
1762
|
+
/* @__PURE__ */ jsx("span", { style: styles5.statusText, children: "Not sent" }),
|
|
1763
|
+
onRetry && /* @__PURE__ */ jsx(
|
|
1764
|
+
"button",
|
|
1765
|
+
{
|
|
1766
|
+
type: "button",
|
|
1767
|
+
onClick: () => onRetry(message.id),
|
|
1768
|
+
style: styles5.retryButton,
|
|
1769
|
+
"aria-label": "Retry sending message",
|
|
1770
|
+
children: "Retry"
|
|
1771
|
+
}
|
|
1772
|
+
)
|
|
1773
|
+
] }),
|
|
1774
|
+
showSeenBy && isOwn && !message.status && /* @__PURE__ */ jsx(
|
|
1525
1775
|
SeenByIndicator,
|
|
1526
1776
|
{
|
|
1527
1777
|
readBy: message.readBy ?? [],
|
|
@@ -1532,33 +1782,9 @@ function MessageBubble({
|
|
|
1532
1782
|
)
|
|
1533
1783
|
]
|
|
1534
1784
|
}
|
|
1535
|
-
),
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
{
|
|
1539
|
-
style: {
|
|
1540
|
-
...styles5.actionsWrapper,
|
|
1541
|
-
[isOwn ? "right" : "left"]: "100%",
|
|
1542
|
-
[isOwn ? "marginRight" : "marginLeft"]: "6px"
|
|
1543
|
-
},
|
|
1544
|
-
children: /* @__PURE__ */ jsx(
|
|
1545
|
-
MessageActionsMenu,
|
|
1546
|
-
{
|
|
1547
|
-
message,
|
|
1548
|
-
onReply: onReply ?? (() => {
|
|
1549
|
-
}),
|
|
1550
|
-
onPin: onPin ?? (() => {
|
|
1551
|
-
}),
|
|
1552
|
-
onUnpin: onUnpin ?? (() => {
|
|
1553
|
-
}),
|
|
1554
|
-
onCopy,
|
|
1555
|
-
visible: isHovered,
|
|
1556
|
-
pinDisabled
|
|
1557
|
-
}
|
|
1558
|
-
)
|
|
1559
|
-
}
|
|
1560
|
-
)
|
|
1561
|
-
] })
|
|
1785
|
+
) }),
|
|
1786
|
+
!isOwn && actionsSlot
|
|
1787
|
+
]
|
|
1562
1788
|
}
|
|
1563
1789
|
);
|
|
1564
1790
|
}
|
|
@@ -1655,6 +1881,8 @@ function escapeRegex2(string) {
|
|
|
1655
1881
|
var styles5 = {
|
|
1656
1882
|
wrapper: {
|
|
1657
1883
|
display: "flex",
|
|
1884
|
+
alignItems: "flex-end",
|
|
1885
|
+
gap: "4px",
|
|
1658
1886
|
marginBottom: "8px",
|
|
1659
1887
|
paddingLeft: "16px",
|
|
1660
1888
|
paddingRight: "16px"
|
|
@@ -1663,6 +1891,10 @@ var styles5 = {
|
|
|
1663
1891
|
position: "relative",
|
|
1664
1892
|
maxWidth: "75%"
|
|
1665
1893
|
},
|
|
1894
|
+
actionsSlot: {
|
|
1895
|
+
flexShrink: 0,
|
|
1896
|
+
alignSelf: "flex-end"
|
|
1897
|
+
},
|
|
1666
1898
|
bubble: {
|
|
1667
1899
|
padding: "10px 14px",
|
|
1668
1900
|
borderRadius: "12px",
|
|
@@ -1716,11 +1948,27 @@ var styles5 = {
|
|
|
1716
1948
|
marginTop: "4px",
|
|
1717
1949
|
textAlign: "right"
|
|
1718
1950
|
},
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1951
|
+
statusRow: {
|
|
1952
|
+
display: "flex",
|
|
1953
|
+
alignItems: "center",
|
|
1954
|
+
gap: "6px",
|
|
1955
|
+
marginTop: "4px",
|
|
1956
|
+
fontSize: "12px",
|
|
1957
|
+
justifyContent: "flex-end",
|
|
1958
|
+
color: "rgba(255, 255, 255, 0.9)"
|
|
1959
|
+
},
|
|
1960
|
+
statusText: {
|
|
1961
|
+
opacity: 0.9
|
|
1962
|
+
},
|
|
1963
|
+
retryButton: {
|
|
1964
|
+
background: "transparent",
|
|
1965
|
+
border: "none",
|
|
1966
|
+
color: "#ffffff",
|
|
1967
|
+
fontWeight: 600,
|
|
1968
|
+
fontSize: "12px",
|
|
1969
|
+
textDecoration: "underline",
|
|
1970
|
+
cursor: "pointer",
|
|
1971
|
+
padding: "0 2px"
|
|
1724
1972
|
},
|
|
1725
1973
|
audioContainer: {
|
|
1726
1974
|
display: "flex",
|
|
@@ -1794,6 +2042,44 @@ var styles5 = {
|
|
|
1794
2042
|
color: "#9ca3af"
|
|
1795
2043
|
}
|
|
1796
2044
|
};
|
|
2045
|
+
function ChatIllustration({ size = 96 }) {
|
|
2046
|
+
return /* @__PURE__ */ jsxs(
|
|
2047
|
+
"svg",
|
|
2048
|
+
{
|
|
2049
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2050
|
+
width: size,
|
|
2051
|
+
height: size,
|
|
2052
|
+
viewBox: "0 0 120 120",
|
|
2053
|
+
fill: "none",
|
|
2054
|
+
"aria-hidden": "true",
|
|
2055
|
+
children: [
|
|
2056
|
+
/* @__PURE__ */ jsx("circle", { cx: "60", cy: "60", r: "56", fill: "#eff6ff" }),
|
|
2057
|
+
/* @__PURE__ */ jsx(
|
|
2058
|
+
"path",
|
|
2059
|
+
{
|
|
2060
|
+
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",
|
|
2061
|
+
fill: "#ffffff",
|
|
2062
|
+
stroke: "#2563eb",
|
|
2063
|
+
strokeWidth: "2.5"
|
|
2064
|
+
}
|
|
2065
|
+
),
|
|
2066
|
+
/* @__PURE__ */ jsx(
|
|
2067
|
+
"path",
|
|
2068
|
+
{
|
|
2069
|
+
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",
|
|
2070
|
+
fill: "#dbeafe",
|
|
2071
|
+
stroke: "#2563eb",
|
|
2072
|
+
strokeWidth: "2.5"
|
|
2073
|
+
}
|
|
2074
|
+
),
|
|
2075
|
+
/* @__PURE__ */ jsx("circle", { cx: "48", cy: "53", r: "2.5", fill: "#2563eb" }),
|
|
2076
|
+
/* @__PURE__ */ jsx("circle", { cx: "58", cy: "53", r: "2.5", fill: "#2563eb" }),
|
|
2077
|
+
/* @__PURE__ */ jsx("circle", { cx: "68", cy: "68", r: "2.5", fill: "#2563eb" }),
|
|
2078
|
+
/* @__PURE__ */ jsx("circle", { cx: "78", cy: "68", r: "2.5", fill: "#2563eb" })
|
|
2079
|
+
]
|
|
2080
|
+
}
|
|
2081
|
+
);
|
|
2082
|
+
}
|
|
1797
2083
|
|
|
1798
2084
|
// src/core/dateLabels.ts
|
|
1799
2085
|
var SHORT_MONTHS = [
|
|
@@ -1885,6 +2171,7 @@ var MessageList = forwardRef(function MessageList2({
|
|
|
1885
2171
|
onPin,
|
|
1886
2172
|
onUnpin,
|
|
1887
2173
|
onCopy,
|
|
2174
|
+
onRetry,
|
|
1888
2175
|
pinDisabled,
|
|
1889
2176
|
className
|
|
1890
2177
|
}, ref) {
|
|
@@ -1949,12 +2236,17 @@ var MessageList = forwardRef(function MessageList2({
|
|
|
1949
2236
|
style: styles6.container,
|
|
1950
2237
|
onScroll: handleScroll,
|
|
1951
2238
|
children: [
|
|
1952
|
-
isLoading && /* @__PURE__ */
|
|
2239
|
+
isLoading && messages.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles6.loadingMore, children: [
|
|
2240
|
+
/* @__PURE__ */ jsx(Spinner, { size: 14 }),
|
|
2241
|
+
/* @__PURE__ */ jsx("span", { children: "Loading earlier messages\u2026" })
|
|
2242
|
+
] }),
|
|
1953
2243
|
hasMore && !isLoading && messages.length > 0 && /* @__PURE__ */ jsx("button", { onClick: onLoadMore, style: styles6.loadMoreButton, type: "button", children: "Load earlier messages" }),
|
|
1954
2244
|
messages.length === 0 && !isLoading && /* @__PURE__ */ jsxs("div", { style: styles6.empty, children: [
|
|
2245
|
+
/* @__PURE__ */ jsx(ChatIllustration, { size: 104 }),
|
|
1955
2246
|
/* @__PURE__ */ jsx("p", { style: styles6.emptyTitle, children: "No messages yet" }),
|
|
1956
|
-
/* @__PURE__ */ jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation
|
|
2247
|
+
/* @__PURE__ */ jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation \u2014 everyone on this case will see what you write." })
|
|
1957
2248
|
] }),
|
|
2249
|
+
messages.length === 0 && isLoading && /* @__PURE__ */ jsx("div", { style: styles6.firstLoad, children: /* @__PURE__ */ jsx(Spinner, { size: 20 }) }),
|
|
1958
2250
|
messages.map((message, index) => {
|
|
1959
2251
|
const currentBucket = dayBucketKey(message.insertedAt);
|
|
1960
2252
|
const prevBucket = index === 0 ? null : dayBucketKey(messages[index - 1].insertedAt);
|
|
@@ -1974,6 +2266,7 @@ var MessageList = forwardRef(function MessageList2({
|
|
|
1974
2266
|
onPin,
|
|
1975
2267
|
onUnpin,
|
|
1976
2268
|
onCopy,
|
|
2269
|
+
onRetry,
|
|
1977
2270
|
pinDisabled
|
|
1978
2271
|
}
|
|
1979
2272
|
) })
|
|
@@ -2002,11 +2295,20 @@ var styles6 = {
|
|
|
2002
2295
|
paddingBottom: "8px"
|
|
2003
2296
|
},
|
|
2004
2297
|
loadingMore: {
|
|
2005
|
-
|
|
2298
|
+
display: "flex",
|
|
2299
|
+
alignItems: "center",
|
|
2300
|
+
justifyContent: "center",
|
|
2301
|
+
gap: "8px",
|
|
2006
2302
|
padding: "12px",
|
|
2007
2303
|
fontSize: "14px",
|
|
2008
2304
|
color: "#6b7280"
|
|
2009
2305
|
},
|
|
2306
|
+
firstLoad: {
|
|
2307
|
+
display: "flex",
|
|
2308
|
+
alignItems: "center",
|
|
2309
|
+
justifyContent: "center",
|
|
2310
|
+
padding: "48px 16px"
|
|
2311
|
+
},
|
|
2010
2312
|
loadMoreButton: {
|
|
2011
2313
|
display: "block",
|
|
2012
2314
|
margin: "0 auto 12px",
|
|
@@ -2031,11 +2333,14 @@ var styles6 = {
|
|
|
2031
2333
|
fontSize: "16px",
|
|
2032
2334
|
fontWeight: 600,
|
|
2033
2335
|
color: "#374151",
|
|
2034
|
-
margin: "
|
|
2336
|
+
margin: "14px 0 4px"
|
|
2035
2337
|
},
|
|
2036
2338
|
emptySubtitle: {
|
|
2037
2339
|
fontSize: "14px",
|
|
2038
|
-
margin: 0
|
|
2340
|
+
margin: 0,
|
|
2341
|
+
maxWidth: "280px",
|
|
2342
|
+
lineHeight: 1.45,
|
|
2343
|
+
textAlign: "center"
|
|
2039
2344
|
},
|
|
2040
2345
|
typingIndicator: {
|
|
2041
2346
|
padding: "4px 16px 8px",
|
|
@@ -2314,7 +2619,18 @@ function MessageInput({
|
|
|
2314
2619
|
type: "file",
|
|
2315
2620
|
onChange: handleFileSelect,
|
|
2316
2621
|
style: { display: "none" },
|
|
2317
|
-
accept: [
|
|
2622
|
+
accept: [
|
|
2623
|
+
...SUPPORTED_IMAGE_TYPES,
|
|
2624
|
+
"application/pdf",
|
|
2625
|
+
".doc",
|
|
2626
|
+
".docx",
|
|
2627
|
+
".xls",
|
|
2628
|
+
".xlsx",
|
|
2629
|
+
".csv",
|
|
2630
|
+
".txt",
|
|
2631
|
+
".heic",
|
|
2632
|
+
".heif"
|
|
2633
|
+
].join(",")
|
|
2318
2634
|
}
|
|
2319
2635
|
),
|
|
2320
2636
|
/* @__PURE__ */ jsx(
|
|
@@ -3039,6 +3355,64 @@ var styles11 = {
|
|
|
3039
3355
|
flexShrink: 0
|
|
3040
3356
|
}
|
|
3041
3357
|
};
|
|
3358
|
+
function Toast({ toast, onDismiss, durationMs = 4e3 }) {
|
|
3359
|
+
useEffect(() => {
|
|
3360
|
+
if (!toast) return;
|
|
3361
|
+
const timer = setTimeout(onDismiss, durationMs);
|
|
3362
|
+
return () => clearTimeout(timer);
|
|
3363
|
+
}, [toast, onDismiss, durationMs]);
|
|
3364
|
+
if (!toast) return null;
|
|
3365
|
+
return /* @__PURE__ */ jsxs("div", { style: styles12.container, role: "status", "aria-live": "polite", children: [
|
|
3366
|
+
/* @__PURE__ */ jsx("span", { style: styles12.message, children: toast.message }),
|
|
3367
|
+
toast.actionLabel && toast.onAction && /* @__PURE__ */ jsx(
|
|
3368
|
+
"button",
|
|
3369
|
+
{
|
|
3370
|
+
type: "button",
|
|
3371
|
+
onClick: () => {
|
|
3372
|
+
toast.onAction?.();
|
|
3373
|
+
onDismiss();
|
|
3374
|
+
},
|
|
3375
|
+
style: styles12.action,
|
|
3376
|
+
children: toast.actionLabel
|
|
3377
|
+
}
|
|
3378
|
+
)
|
|
3379
|
+
] });
|
|
3380
|
+
}
|
|
3381
|
+
var styles12 = {
|
|
3382
|
+
container: {
|
|
3383
|
+
position: "absolute",
|
|
3384
|
+
bottom: "76px",
|
|
3385
|
+
left: "50%",
|
|
3386
|
+
transform: "translateX(-50%)",
|
|
3387
|
+
display: "flex",
|
|
3388
|
+
alignItems: "center",
|
|
3389
|
+
gap: "12px",
|
|
3390
|
+
padding: "10px 14px",
|
|
3391
|
+
backgroundColor: "#1e293b",
|
|
3392
|
+
color: "#ffffff",
|
|
3393
|
+
borderRadius: "8px",
|
|
3394
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.18)",
|
|
3395
|
+
fontSize: "14px",
|
|
3396
|
+
maxWidth: "90%",
|
|
3397
|
+
zIndex: 20
|
|
3398
|
+
},
|
|
3399
|
+
message: {
|
|
3400
|
+
whiteSpace: "nowrap",
|
|
3401
|
+
overflow: "hidden",
|
|
3402
|
+
textOverflow: "ellipsis"
|
|
3403
|
+
},
|
|
3404
|
+
action: {
|
|
3405
|
+
background: "transparent",
|
|
3406
|
+
border: "none",
|
|
3407
|
+
color: "#93c5fd",
|
|
3408
|
+
fontWeight: 600,
|
|
3409
|
+
fontSize: "14px",
|
|
3410
|
+
cursor: "pointer",
|
|
3411
|
+
padding: "4px 6px",
|
|
3412
|
+
textTransform: "uppercase",
|
|
3413
|
+
letterSpacing: "0.4px"
|
|
3414
|
+
}
|
|
3415
|
+
};
|
|
3042
3416
|
function CollabPanel({
|
|
3043
3417
|
orderId,
|
|
3044
3418
|
patientData,
|
|
@@ -3049,6 +3423,7 @@ function CollabPanel({
|
|
|
3049
3423
|
}) {
|
|
3050
3424
|
const { config } = useCollab();
|
|
3051
3425
|
const [showSettings, setShowSettings] = useState(false);
|
|
3426
|
+
const [toast, setToast] = useState(null);
|
|
3052
3427
|
const messageListRef = useRef(null);
|
|
3053
3428
|
const {
|
|
3054
3429
|
conversation,
|
|
@@ -3062,6 +3437,7 @@ function CollabPanel({
|
|
|
3062
3437
|
replyTo,
|
|
3063
3438
|
setReplyTo,
|
|
3064
3439
|
sendMessage,
|
|
3440
|
+
retryMessage,
|
|
3065
3441
|
sendAudioMessage,
|
|
3066
3442
|
sendFileMessage,
|
|
3067
3443
|
sendTyping,
|
|
@@ -3086,10 +3462,33 @@ function CollabPanel({
|
|
|
3086
3462
|
try {
|
|
3087
3463
|
if (navigator.clipboard) {
|
|
3088
3464
|
await navigator.clipboard.writeText(text);
|
|
3465
|
+
setToast({ message: "Copied to clipboard" });
|
|
3089
3466
|
}
|
|
3090
3467
|
} catch {
|
|
3091
3468
|
}
|
|
3092
3469
|
};
|
|
3470
|
+
const handlePin = async (messageId) => {
|
|
3471
|
+
try {
|
|
3472
|
+
await pinMessage(messageId);
|
|
3473
|
+
setToast({
|
|
3474
|
+
message: "Pinned",
|
|
3475
|
+
actionLabel: "Undo",
|
|
3476
|
+
onAction: () => {
|
|
3477
|
+
void unpinMessage(messageId);
|
|
3478
|
+
}
|
|
3479
|
+
});
|
|
3480
|
+
} catch {
|
|
3481
|
+
setToast({ message: "Could not pin message" });
|
|
3482
|
+
}
|
|
3483
|
+
};
|
|
3484
|
+
const handleUnpin = async (messageId) => {
|
|
3485
|
+
try {
|
|
3486
|
+
await unpinMessage(messageId);
|
|
3487
|
+
setToast({ message: "Unpinned" });
|
|
3488
|
+
} catch {
|
|
3489
|
+
setToast({ message: "Could not unpin message" });
|
|
3490
|
+
}
|
|
3491
|
+
};
|
|
3093
3492
|
const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;
|
|
3094
3493
|
if (error) {
|
|
3095
3494
|
return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxs("div", { style: panelStyles.errorState, children: [
|
|
@@ -3100,78 +3499,83 @@ function CollabPanel({
|
|
|
3100
3499
|
if (isLoading && !conversation) {
|
|
3101
3500
|
return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
|
|
3102
3501
|
}
|
|
3103
|
-
return /* @__PURE__ */
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
conversationId: conversation.id,
|
|
3107
|
-
channelName: conversation.name,
|
|
3108
|
-
channelPicture: conversation.picture,
|
|
3109
|
-
participants,
|
|
3110
|
-
currentUserId: config.userId,
|
|
3111
|
-
isAdmin: channelSettings.isAdmin,
|
|
3112
|
-
isUpdating: channelSettings.isUpdating,
|
|
3113
|
-
error: channelSettings.error,
|
|
3114
|
-
onUpdateChannel: channelSettings.updateChannel,
|
|
3115
|
-
onInviteUser: channelSettings.inviteUser,
|
|
3116
|
-
onRemoveUser: channelSettings.removeUser,
|
|
3117
|
-
onLeaveChannel: channelSettings.leaveChannel,
|
|
3118
|
-
onDeleteChannel: channelSettings.deleteChannel,
|
|
3119
|
-
onClose: () => setShowSettings(false)
|
|
3120
|
-
}
|
|
3121
|
-
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3122
|
-
/* @__PURE__ */ jsx(
|
|
3123
|
-
PatientHeader,
|
|
3502
|
+
return /* @__PURE__ */ jsxs("div", { className, style: { ...panelStyles.container, ...style }, children: [
|
|
3503
|
+
showSettings && conversation ? /* @__PURE__ */ jsx(
|
|
3504
|
+
ChannelSettings,
|
|
3124
3505
|
{
|
|
3125
|
-
|
|
3506
|
+
conversationId: conversation.id,
|
|
3507
|
+
channelName: conversation.name,
|
|
3508
|
+
channelPicture: conversation.picture,
|
|
3126
3509
|
participants,
|
|
3127
|
-
onOpenDicom: handleOpenDicom,
|
|
3128
|
-
onOpenSettings: () => setShowSettings(true)
|
|
3129
|
-
}
|
|
3130
|
-
),
|
|
3131
|
-
pinnedMessages.length > 0 && /* @__PURE__ */ jsx(
|
|
3132
|
-
PinnedMessagesBar,
|
|
3133
|
-
{
|
|
3134
|
-
pinnedMessages,
|
|
3135
|
-
onJumpTo: handleJumpToMessage,
|
|
3136
|
-
onUnpin: unpinMessage
|
|
3137
|
-
}
|
|
3138
|
-
),
|
|
3139
|
-
/* @__PURE__ */ jsx(
|
|
3140
|
-
MessageList,
|
|
3141
|
-
{
|
|
3142
|
-
ref: messageListRef,
|
|
3143
|
-
messages,
|
|
3144
3510
|
currentUserId: config.userId,
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
onPin: pinMessage,
|
|
3155
|
-
onUnpin: unpinMessage,
|
|
3156
|
-
onCopy: handleCopy,
|
|
3157
|
-
pinDisabled
|
|
3511
|
+
isAdmin: channelSettings.isAdmin,
|
|
3512
|
+
isUpdating: channelSettings.isUpdating,
|
|
3513
|
+
error: channelSettings.error,
|
|
3514
|
+
onUpdateChannel: channelSettings.updateChannel,
|
|
3515
|
+
onInviteUser: channelSettings.inviteUser,
|
|
3516
|
+
onRemoveUser: channelSettings.removeUser,
|
|
3517
|
+
onLeaveChannel: channelSettings.leaveChannel,
|
|
3518
|
+
onDeleteChannel: channelSettings.deleteChannel,
|
|
3519
|
+
onClose: () => setShowSettings(false)
|
|
3158
3520
|
}
|
|
3159
|
-
),
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3521
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3522
|
+
/* @__PURE__ */ jsx(
|
|
3523
|
+
PatientHeader,
|
|
3524
|
+
{
|
|
3525
|
+
patientData,
|
|
3526
|
+
participants,
|
|
3527
|
+
onOpenDicom: handleOpenDicom,
|
|
3528
|
+
onOpenSettings: () => setShowSettings(true)
|
|
3529
|
+
}
|
|
3530
|
+
),
|
|
3531
|
+
pinnedMessages.length > 0 && /* @__PURE__ */ jsx(
|
|
3532
|
+
PinnedMessagesBar,
|
|
3533
|
+
{
|
|
3534
|
+
pinnedMessages,
|
|
3535
|
+
onJumpTo: handleJumpToMessage,
|
|
3536
|
+
onUnpin: handleUnpin
|
|
3537
|
+
}
|
|
3538
|
+
),
|
|
3539
|
+
/* @__PURE__ */ jsx(
|
|
3540
|
+
MessageList,
|
|
3541
|
+
{
|
|
3542
|
+
ref: messageListRef,
|
|
3543
|
+
messages,
|
|
3544
|
+
currentUserId: config.userId,
|
|
3545
|
+
participants,
|
|
3546
|
+
showSeenBy,
|
|
3547
|
+
typingUsers,
|
|
3548
|
+
hasMore,
|
|
3549
|
+
isLoading,
|
|
3550
|
+
onLoadMore: loadMoreMessages,
|
|
3551
|
+
onDeepLinkClick: handleDeepLink,
|
|
3552
|
+
onMessageVisible: markAsRead,
|
|
3553
|
+
onReply: setReplyTo,
|
|
3554
|
+
onPin: handlePin,
|
|
3555
|
+
onUnpin: handleUnpin,
|
|
3556
|
+
onCopy: handleCopy,
|
|
3557
|
+
onRetry: retryMessage,
|
|
3558
|
+
pinDisabled
|
|
3559
|
+
}
|
|
3560
|
+
),
|
|
3561
|
+
/* @__PURE__ */ jsx(
|
|
3562
|
+
MessageInput,
|
|
3563
|
+
{
|
|
3564
|
+
onSendText: sendMessage,
|
|
3565
|
+
onSendAudio: sendAudioMessage,
|
|
3566
|
+
onSendFile: sendFileMessage,
|
|
3567
|
+
onTyping: sendTyping,
|
|
3568
|
+
replyTo,
|
|
3569
|
+
onCancelReply: () => setReplyTo(null)
|
|
3570
|
+
}
|
|
3571
|
+
)
|
|
3572
|
+
] }),
|
|
3573
|
+
/* @__PURE__ */ jsx(Toast, { toast, onDismiss: () => setToast(null) })
|
|
3574
|
+
] });
|
|
3172
3575
|
}
|
|
3173
3576
|
var panelStyles = {
|
|
3174
3577
|
container: {
|
|
3578
|
+
position: "relative",
|
|
3175
3579
|
display: "flex",
|
|
3176
3580
|
flexDirection: "column",
|
|
3177
3581
|
height: "100%",
|
|
@@ -3238,6 +3642,7 @@ function ExpandIcon({ size = 18, color = "currentColor" }) {
|
|
|
3238
3642
|
}
|
|
3239
3643
|
);
|
|
3240
3644
|
}
|
|
3645
|
+
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
3241
3646
|
function CollabPopup({
|
|
3242
3647
|
orderId,
|
|
3243
3648
|
patientData,
|
|
@@ -3259,6 +3664,8 @@ function CollabPopup({
|
|
|
3259
3664
|
const [isMinimized, setIsMinimized] = useState(false);
|
|
3260
3665
|
const dragOffset = useRef({ x: 0, y: 0 });
|
|
3261
3666
|
const containerRef = useRef(null);
|
|
3667
|
+
const previouslyFocused = useRef(null);
|
|
3668
|
+
const titleId = useId();
|
|
3262
3669
|
const handleMouseDown = useCallback(
|
|
3263
3670
|
(e) => {
|
|
3264
3671
|
if (!e.target.closest("[data-drag-handle]")) return;
|
|
@@ -3273,13 +3680,44 @@ function CollabPopup({
|
|
|
3273
3680
|
);
|
|
3274
3681
|
useEffect(() => {
|
|
3275
3682
|
if (!isOpen) return;
|
|
3683
|
+
previouslyFocused.current = document.activeElement;
|
|
3684
|
+
const focusFirst = () => {
|
|
3685
|
+
const root = containerRef.current;
|
|
3686
|
+
if (!root) return;
|
|
3687
|
+
const first = root.querySelector(FOCUSABLE_SELECTOR);
|
|
3688
|
+
(first ?? root).focus();
|
|
3689
|
+
};
|
|
3690
|
+
const raf = requestAnimationFrame(focusFirst);
|
|
3276
3691
|
const handleKey = (e) => {
|
|
3277
3692
|
if (e.key === "Escape") {
|
|
3278
3693
|
onClose();
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
if (e.key !== "Tab") return;
|
|
3697
|
+
const root = containerRef.current;
|
|
3698
|
+
if (!root) return;
|
|
3699
|
+
const focusables = Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
3700
|
+
if (focusables.length === 0) {
|
|
3701
|
+
e.preventDefault();
|
|
3702
|
+
return;
|
|
3703
|
+
}
|
|
3704
|
+
const first = focusables[0];
|
|
3705
|
+
const last = focusables[focusables.length - 1];
|
|
3706
|
+
const active = document.activeElement;
|
|
3707
|
+
if (e.shiftKey && active === first) {
|
|
3708
|
+
e.preventDefault();
|
|
3709
|
+
last.focus();
|
|
3710
|
+
} else if (!e.shiftKey && active === last) {
|
|
3711
|
+
e.preventDefault();
|
|
3712
|
+
first.focus();
|
|
3279
3713
|
}
|
|
3280
3714
|
};
|
|
3281
3715
|
window.addEventListener("keydown", handleKey);
|
|
3282
|
-
return () =>
|
|
3716
|
+
return () => {
|
|
3717
|
+
cancelAnimationFrame(raf);
|
|
3718
|
+
window.removeEventListener("keydown", handleKey);
|
|
3719
|
+
previouslyFocused.current?.focus?.();
|
|
3720
|
+
};
|
|
3283
3721
|
}, [isOpen, onClose]);
|
|
3284
3722
|
useEffect(() => {
|
|
3285
3723
|
if (!isDragging) return;
|
|
@@ -3305,8 +3743,12 @@ function CollabPopup({
|
|
|
3305
3743
|
{
|
|
3306
3744
|
ref: containerRef,
|
|
3307
3745
|
className,
|
|
3746
|
+
role: "dialog",
|
|
3747
|
+
"aria-modal": "true",
|
|
3748
|
+
"aria-labelledby": titleId,
|
|
3749
|
+
tabIndex: -1,
|
|
3308
3750
|
style: {
|
|
3309
|
-
...
|
|
3751
|
+
...styles13.container,
|
|
3310
3752
|
left: position.x,
|
|
3311
3753
|
top: position.y,
|
|
3312
3754
|
width,
|
|
@@ -3315,14 +3757,14 @@ function CollabPopup({
|
|
|
3315
3757
|
},
|
|
3316
3758
|
onMouseDown: handleMouseDown,
|
|
3317
3759
|
children: [
|
|
3318
|
-
/* @__PURE__ */ jsxs("div", { "data-drag-handle": true, style:
|
|
3319
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
3320
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
3760
|
+
/* @__PURE__ */ jsxs("div", { "data-drag-handle": true, style: styles13.titleBar, children: [
|
|
3761
|
+
/* @__PURE__ */ jsx("span", { id: titleId, style: styles13.titleText, children: buildChannelName(patientData) }),
|
|
3762
|
+
/* @__PURE__ */ jsxs("div", { style: styles13.titleActions, children: [
|
|
3321
3763
|
/* @__PURE__ */ jsx(
|
|
3322
3764
|
"button",
|
|
3323
3765
|
{
|
|
3324
3766
|
onClick: () => setIsMinimized(!isMinimized),
|
|
3325
|
-
style:
|
|
3767
|
+
style: styles13.titleButton,
|
|
3326
3768
|
"aria-label": isMinimized ? "Expand chat" : "Minimize chat",
|
|
3327
3769
|
title: isMinimized ? "Expand" : "Minimize",
|
|
3328
3770
|
type: "button",
|
|
@@ -3333,7 +3775,7 @@ function CollabPopup({
|
|
|
3333
3775
|
"button",
|
|
3334
3776
|
{
|
|
3335
3777
|
onClick: onClose,
|
|
3336
|
-
style:
|
|
3778
|
+
style: styles13.titleButton,
|
|
3337
3779
|
"aria-label": "Close chat",
|
|
3338
3780
|
title: "Close",
|
|
3339
3781
|
type: "button",
|
|
@@ -3342,12 +3784,12 @@ function CollabPopup({
|
|
|
3342
3784
|
)
|
|
3343
3785
|
] })
|
|
3344
3786
|
] }),
|
|
3345
|
-
!isMinimized && /* @__PURE__ */ jsx("div", { style:
|
|
3787
|
+
!isMinimized && /* @__PURE__ */ jsx("div", { style: styles13.panelWrapper, children: /* @__PURE__ */ jsx(CollabPanel, { orderId, patientData, participantIds }) })
|
|
3346
3788
|
]
|
|
3347
3789
|
}
|
|
3348
3790
|
);
|
|
3349
3791
|
}
|
|
3350
|
-
var
|
|
3792
|
+
var styles13 = {
|
|
3351
3793
|
container: {
|
|
3352
3794
|
position: "fixed",
|
|
3353
3795
|
zIndex: 9999,
|
|
@@ -3652,11 +4094,11 @@ function CollabInline({
|
|
|
3652
4094
|
containerRef
|
|
3653
4095
|
} = useInlineCollab({ orderId, patientData, participantIds, messageLimit });
|
|
3654
4096
|
if (isLoading && !hasConversation) {
|
|
3655
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...
|
|
4097
|
+
return /* @__PURE__ */ jsx("div", { className, style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
3656
4098
|
}
|
|
3657
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, style: { ...
|
|
3658
|
-
hasConversation && messages.length > 0 && /* @__PURE__ */ jsx("div", { style:
|
|
3659
|
-
error && /* @__PURE__ */ jsx("div", { style:
|
|
4099
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, style: { ...styles14.container, ...style }, children: [
|
|
4100
|
+
hasConversation && messages.length > 0 && /* @__PURE__ */ jsx("div", { style: styles14.preview, children: messages.slice(-messageLimit).map((message) => /* @__PURE__ */ jsx(InlineMessageRow, { message }, message.id)) }),
|
|
4101
|
+
error && /* @__PURE__ */ jsx("div", { style: styles14.error, children: error }),
|
|
3660
4102
|
/* @__PURE__ */ jsx(
|
|
3661
4103
|
InlineInputBar,
|
|
3662
4104
|
{
|
|
@@ -3673,12 +4115,12 @@ function CollabInline({
|
|
|
3673
4115
|
}
|
|
3674
4116
|
function InlineMessageRow({ message }) {
|
|
3675
4117
|
if (message.type === "system") {
|
|
3676
|
-
return /* @__PURE__ */ jsx("div", { style:
|
|
4118
|
+
return /* @__PURE__ */ jsx("div", { style: styles14.systemRow, children: /* @__PURE__ */ jsx("span", { style: styles14.systemText, children: message.body }) });
|
|
3677
4119
|
}
|
|
3678
4120
|
if (message.type === "audio" && message.mediaUrl) {
|
|
3679
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
4121
|
+
return /* @__PURE__ */ jsxs("div", { style: styles14.messageRow, children: [
|
|
3680
4122
|
/* @__PURE__ */ jsx(RoleDot, { role: message.senderRole }),
|
|
3681
|
-
/* @__PURE__ */ jsxs("span", { style:
|
|
4123
|
+
/* @__PURE__ */ jsxs("span", { style: styles14.senderName, children: [
|
|
3682
4124
|
message.senderName,
|
|
3683
4125
|
":"
|
|
3684
4126
|
] }),
|
|
@@ -3686,13 +4128,13 @@ function InlineMessageRow({ message }) {
|
|
|
3686
4128
|
] });
|
|
3687
4129
|
}
|
|
3688
4130
|
const preview = renderMessagePreview(message);
|
|
3689
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
4131
|
+
return /* @__PURE__ */ jsxs("div", { style: styles14.messageRow, children: [
|
|
3690
4132
|
/* @__PURE__ */ jsx(RoleDot, { role: message.senderRole }),
|
|
3691
|
-
/* @__PURE__ */ jsxs("span", { style:
|
|
4133
|
+
/* @__PURE__ */ jsxs("span", { style: styles14.senderName, children: [
|
|
3692
4134
|
message.senderName,
|
|
3693
4135
|
":"
|
|
3694
4136
|
] }),
|
|
3695
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
4137
|
+
/* @__PURE__ */ jsx("span", { style: styles14.messageText, children: preview })
|
|
3696
4138
|
] });
|
|
3697
4139
|
}
|
|
3698
4140
|
function RoleDot({ role }) {
|
|
@@ -3702,7 +4144,7 @@ function RoleDot({ role }) {
|
|
|
3702
4144
|
physician: "#059669",
|
|
3703
4145
|
admin: "#dc2626"
|
|
3704
4146
|
};
|
|
3705
|
-
return /* @__PURE__ */ jsx("span", { style: { ...
|
|
4147
|
+
return /* @__PURE__ */ jsx("span", { style: { ...styles14.roleDot, backgroundColor: colors[role] } });
|
|
3706
4148
|
}
|
|
3707
4149
|
function InlineAudioPlayer({ url, duration }) {
|
|
3708
4150
|
const audioRef = useRef(null);
|
|
@@ -3746,27 +4188,27 @@ function InlineAudioPlayer({ url, duration }) {
|
|
|
3746
4188
|
const total = duration ?? 0;
|
|
3747
4189
|
const remaining = Math.max(0, total - Math.floor(currentTime));
|
|
3748
4190
|
const displayTime = isPlaying ? remaining : total;
|
|
3749
|
-
return /* @__PURE__ */ jsxs("span", { style:
|
|
4191
|
+
return /* @__PURE__ */ jsxs("span", { style: styles14.audioPlayer, children: [
|
|
3750
4192
|
/* @__PURE__ */ jsx(
|
|
3751
4193
|
"button",
|
|
3752
4194
|
{
|
|
3753
4195
|
onClick: toggle,
|
|
3754
|
-
style:
|
|
4196
|
+
style: styles14.audioButton,
|
|
3755
4197
|
title: isPlaying ? "Pause" : "Play",
|
|
3756
4198
|
type: "button",
|
|
3757
4199
|
children: isPlaying ? "\u23F8" : "\u25B6"
|
|
3758
4200
|
}
|
|
3759
4201
|
),
|
|
3760
|
-
/* @__PURE__ */ jsxs("span", { style:
|
|
3761
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
3762
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
3763
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
3764
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
3765
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
3766
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
3767
|
-
/* @__PURE__ */ jsx("span", { style: { ...
|
|
4202
|
+
/* @__PURE__ */ jsxs("span", { style: styles14.audioWaveform, children: [
|
|
4203
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "40%" } }),
|
|
4204
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "80%" } }),
|
|
4205
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "60%" } }),
|
|
4206
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "90%" } }),
|
|
4207
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "50%" } }),
|
|
4208
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "70%" } }),
|
|
4209
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles14.waveBar, height: "40%" } })
|
|
3768
4210
|
] }),
|
|
3769
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
4211
|
+
/* @__PURE__ */ jsx("span", { style: styles14.audioDuration, children: formatDuration2(displayTime) }),
|
|
3770
4212
|
/* @__PURE__ */ jsx("audio", { ref: audioRef, src: url, preload: "metadata" })
|
|
3771
4213
|
] });
|
|
3772
4214
|
}
|
|
@@ -3822,7 +4264,7 @@ function InlineInputBar({
|
|
|
3822
4264
|
},
|
|
3823
4265
|
[handleSend]
|
|
3824
4266
|
);
|
|
3825
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
4267
|
+
return /* @__PURE__ */ jsxs("div", { style: styles14.inputBar, children: [
|
|
3826
4268
|
/* @__PURE__ */ jsx(
|
|
3827
4269
|
"input",
|
|
3828
4270
|
{
|
|
@@ -3833,17 +4275,17 @@ function InlineInputBar({
|
|
|
3833
4275
|
onKeyDown: handleKeyDown,
|
|
3834
4276
|
placeholder,
|
|
3835
4277
|
disabled: isSending,
|
|
3836
|
-
style:
|
|
4278
|
+
style: styles14.input
|
|
3837
4279
|
}
|
|
3838
4280
|
),
|
|
3839
|
-
unreadCount > 0 && /* @__PURE__ */ jsx("span", { style:
|
|
3840
|
-
isLive && /* @__PURE__ */ jsx("span", { style:
|
|
4281
|
+
unreadCount > 0 && /* @__PURE__ */ jsx("span", { style: styles14.unreadBadge, title: `${unreadCount} unread`, children: unreadCount > 99 ? "99+" : unreadCount }),
|
|
4282
|
+
isLive && /* @__PURE__ */ jsx("span", { style: styles14.liveDot, title: "Live updates active" }),
|
|
3841
4283
|
text.trim() && /* @__PURE__ */ jsx(
|
|
3842
4284
|
"button",
|
|
3843
4285
|
{
|
|
3844
4286
|
onClick: handleSend,
|
|
3845
4287
|
disabled: isSending,
|
|
3846
|
-
style:
|
|
4288
|
+
style: styles14.sendButton,
|
|
3847
4289
|
title: "Send message",
|
|
3848
4290
|
type: "button",
|
|
3849
4291
|
children: "\u27A4"
|
|
@@ -3853,7 +4295,7 @@ function InlineInputBar({
|
|
|
3853
4295
|
"button",
|
|
3854
4296
|
{
|
|
3855
4297
|
onClick: onExpand,
|
|
3856
|
-
style:
|
|
4298
|
+
style: styles14.expandButton,
|
|
3857
4299
|
title: "Expand to full chat",
|
|
3858
4300
|
type: "button",
|
|
3859
4301
|
children: "\u26F6"
|
|
@@ -3861,7 +4303,7 @@ function InlineInputBar({
|
|
|
3861
4303
|
)
|
|
3862
4304
|
] });
|
|
3863
4305
|
}
|
|
3864
|
-
var
|
|
4306
|
+
var styles14 = {
|
|
3865
4307
|
container: {
|
|
3866
4308
|
display: "flex",
|
|
3867
4309
|
flexDirection: "column",
|
|
@@ -4128,24 +4570,24 @@ function ConversationListItem({
|
|
|
4128
4570
|
className,
|
|
4129
4571
|
onClick,
|
|
4130
4572
|
style: {
|
|
4131
|
-
...
|
|
4132
|
-
...isSelected ?
|
|
4133
|
-
...hasUnread ?
|
|
4573
|
+
...styles15.container,
|
|
4574
|
+
...isSelected ? styles15.selected : {},
|
|
4575
|
+
...hasUnread ? styles15.unread : {}
|
|
4134
4576
|
},
|
|
4135
4577
|
type: "button",
|
|
4136
4578
|
children: [
|
|
4137
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4138
|
-
item.picture ? /* @__PURE__ */ jsx("img", { src: item.picture, alt: "", style:
|
|
4139
|
-
hasUnread && /* @__PURE__ */ jsx("span", { style:
|
|
4579
|
+
/* @__PURE__ */ jsxs("div", { style: styles15.avatarWrapper, children: [
|
|
4580
|
+
item.picture ? /* @__PURE__ */ jsx("img", { src: item.picture, alt: "", style: styles15.avatar }) : /* @__PURE__ */ jsx("div", { style: styles15.avatarFallback, children: (displayName).charAt(0).toUpperCase() }),
|
|
4581
|
+
hasUnread && /* @__PURE__ */ jsx("span", { style: styles15.unreadDot })
|
|
4140
4582
|
] }),
|
|
4141
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4142
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4583
|
+
/* @__PURE__ */ jsxs("div", { style: styles15.content, children: [
|
|
4584
|
+
/* @__PURE__ */ jsxs("div", { style: styles15.topRow, children: [
|
|
4143
4585
|
/* @__PURE__ */ jsx(
|
|
4144
4586
|
"span",
|
|
4145
4587
|
{
|
|
4146
4588
|
style: {
|
|
4147
|
-
...
|
|
4148
|
-
...hasUnread ?
|
|
4589
|
+
...styles15.name,
|
|
4590
|
+
...hasUnread ? styles15.nameUnread : {}
|
|
4149
4591
|
},
|
|
4150
4592
|
children: displayName
|
|
4151
4593
|
}
|
|
@@ -4154,25 +4596,25 @@ function ConversationListItem({
|
|
|
4154
4596
|
"span",
|
|
4155
4597
|
{
|
|
4156
4598
|
style: {
|
|
4157
|
-
...
|
|
4158
|
-
...hasUnread ?
|
|
4599
|
+
...styles15.time,
|
|
4600
|
+
...hasUnread ? styles15.timeUnread : {}
|
|
4159
4601
|
},
|
|
4160
4602
|
children: formatInboxTimestamp(item.lastActivityAt)
|
|
4161
4603
|
}
|
|
4162
4604
|
)
|
|
4163
4605
|
] }),
|
|
4164
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4606
|
+
/* @__PURE__ */ jsxs("div", { style: styles15.bottomRow, children: [
|
|
4165
4607
|
/* @__PURE__ */ jsx(
|
|
4166
4608
|
"span",
|
|
4167
4609
|
{
|
|
4168
4610
|
style: {
|
|
4169
|
-
...
|
|
4170
|
-
...hasUnread ?
|
|
4611
|
+
...styles15.preview,
|
|
4612
|
+
...hasUnread ? styles15.previewUnread : {}
|
|
4171
4613
|
},
|
|
4172
4614
|
children: renderLastMessagePreview(item.lastMessage)
|
|
4173
4615
|
}
|
|
4174
4616
|
),
|
|
4175
|
-
hasUnread && /* @__PURE__ */ jsx("span", { style:
|
|
4617
|
+
hasUnread && /* @__PURE__ */ jsx("span", { style: styles15.badge, children: item.unreadCount > 99 ? "99+" : item.unreadCount })
|
|
4176
4618
|
] })
|
|
4177
4619
|
] })
|
|
4178
4620
|
]
|
|
@@ -4200,7 +4642,7 @@ function renderLastMessagePreview(message) {
|
|
|
4200
4642
|
}
|
|
4201
4643
|
}
|
|
4202
4644
|
}
|
|
4203
|
-
var
|
|
4645
|
+
var styles15 = {
|
|
4204
4646
|
container: {
|
|
4205
4647
|
display: "flex",
|
|
4206
4648
|
alignItems: "center",
|
|
@@ -4347,30 +4789,30 @@ function ConversationList({
|
|
|
4347
4789
|
return result;
|
|
4348
4790
|
}, [conversations, query, showUnreadOnly]);
|
|
4349
4791
|
const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);
|
|
4350
|
-
return /* @__PURE__ */ jsxs("div", { className, style:
|
|
4351
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4352
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4353
|
-
/* @__PURE__ */ jsx("h3", { style:
|
|
4354
|
-
totalUnread > 0 && /* @__PURE__ */ jsx("span", { style:
|
|
4792
|
+
return /* @__PURE__ */ jsxs("div", { className, style: styles16.container, children: [
|
|
4793
|
+
/* @__PURE__ */ jsxs("div", { style: styles16.header, children: [
|
|
4794
|
+
/* @__PURE__ */ jsxs("div", { style: styles16.titleRow, children: [
|
|
4795
|
+
/* @__PURE__ */ jsx("h3", { style: styles16.title, children: title }),
|
|
4796
|
+
totalUnread > 0 && /* @__PURE__ */ jsx("span", { style: styles16.totalBadge, children: totalUnread })
|
|
4355
4797
|
] }),
|
|
4356
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
4798
|
+
/* @__PURE__ */ jsx("div", { style: styles16.searchRow, children: /* @__PURE__ */ jsx(
|
|
4357
4799
|
"input",
|
|
4358
4800
|
{
|
|
4359
4801
|
type: "text",
|
|
4360
4802
|
value: query,
|
|
4361
4803
|
onChange: (e) => setQuery(e.target.value),
|
|
4362
4804
|
placeholder: "Search patients or channels...",
|
|
4363
|
-
style:
|
|
4805
|
+
style: styles16.searchInput
|
|
4364
4806
|
}
|
|
4365
4807
|
) }),
|
|
4366
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4808
|
+
/* @__PURE__ */ jsxs("div", { style: styles16.filterRow, children: [
|
|
4367
4809
|
/* @__PURE__ */ jsx(
|
|
4368
4810
|
"button",
|
|
4369
4811
|
{
|
|
4370
4812
|
onClick: () => setShowUnreadOnly(false),
|
|
4371
4813
|
style: {
|
|
4372
|
-
...
|
|
4373
|
-
...!showUnreadOnly ?
|
|
4814
|
+
...styles16.filterButton,
|
|
4815
|
+
...!showUnreadOnly ? styles16.filterButtonActive : {}
|
|
4374
4816
|
},
|
|
4375
4817
|
type: "button",
|
|
4376
4818
|
children: "All"
|
|
@@ -4381,8 +4823,8 @@ function ConversationList({
|
|
|
4381
4823
|
{
|
|
4382
4824
|
onClick: () => setShowUnreadOnly(true),
|
|
4383
4825
|
style: {
|
|
4384
|
-
...
|
|
4385
|
-
...showUnreadOnly ?
|
|
4826
|
+
...styles16.filterButton,
|
|
4827
|
+
...showUnreadOnly ? styles16.filterButtonActive : {}
|
|
4386
4828
|
},
|
|
4387
4829
|
type: "button",
|
|
4388
4830
|
children: [
|
|
@@ -4393,10 +4835,10 @@ function ConversationList({
|
|
|
4393
4835
|
)
|
|
4394
4836
|
] })
|
|
4395
4837
|
] }),
|
|
4396
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
4397
|
-
isLoading && /* @__PURE__ */ jsx("div", { style:
|
|
4398
|
-
error && /* @__PURE__ */ jsx("div", { style:
|
|
4399
|
-
!isLoading && !error && filtered.length === 0 && /* @__PURE__ */ jsx("div", { style:
|
|
4838
|
+
/* @__PURE__ */ jsxs("div", { style: styles16.list, children: [
|
|
4839
|
+
isLoading && /* @__PURE__ */ jsx("div", { style: styles16.state, children: "Loading conversations..." }),
|
|
4840
|
+
error && /* @__PURE__ */ jsx("div", { style: styles16.errorState, children: error }),
|
|
4841
|
+
!isLoading && !error && filtered.length === 0 && /* @__PURE__ */ jsx("div", { style: styles16.state, children: query ? "No matching conversations" : "No conversations yet" }),
|
|
4400
4842
|
filtered.map((item) => /* @__PURE__ */ jsx(
|
|
4401
4843
|
ConversationListItem,
|
|
4402
4844
|
{
|
|
@@ -4409,7 +4851,7 @@ function ConversationList({
|
|
|
4409
4851
|
] })
|
|
4410
4852
|
] });
|
|
4411
4853
|
}
|
|
4412
|
-
var
|
|
4854
|
+
var styles16 = {
|
|
4413
4855
|
container: {
|
|
4414
4856
|
display: "flex",
|
|
4415
4857
|
flexDirection: "column",
|
|
@@ -4514,8 +4956,8 @@ function CollabInbox({
|
|
|
4514
4956
|
setSelectedId(item.id);
|
|
4515
4957
|
onSelectConversation?.(item);
|
|
4516
4958
|
};
|
|
4517
|
-
return /* @__PURE__ */ jsxs("div", { className, style: { ...
|
|
4518
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
4959
|
+
return /* @__PURE__ */ jsxs("div", { className, style: { ...styles17.container, ...style }, children: [
|
|
4960
|
+
/* @__PURE__ */ jsx("div", { style: styles17.sidebar, children: /* @__PURE__ */ jsx(
|
|
4519
4961
|
ConversationList,
|
|
4520
4962
|
{
|
|
4521
4963
|
conversations,
|
|
@@ -4526,13 +4968,13 @@ function CollabInbox({
|
|
|
4526
4968
|
title
|
|
4527
4969
|
}
|
|
4528
4970
|
) }),
|
|
4529
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
4971
|
+
/* @__PURE__ */ jsx("div", { style: styles17.main, children: selected ? /* @__PURE__ */ jsx(
|
|
4530
4972
|
CollabPanel,
|
|
4531
4973
|
{
|
|
4532
4974
|
orderId: selected.orderId,
|
|
4533
4975
|
patientData: buildPatientData(selected),
|
|
4534
4976
|
showSeenBy: true,
|
|
4535
|
-
style:
|
|
4977
|
+
style: styles17.panel
|
|
4536
4978
|
},
|
|
4537
4979
|
selected.id
|
|
4538
4980
|
) : /* @__PURE__ */ jsx(EmptyState, { hasAny: conversations.length > 0 }) })
|
|
@@ -4546,13 +4988,13 @@ function buildPatientData(item) {
|
|
|
4546
4988
|
};
|
|
4547
4989
|
}
|
|
4548
4990
|
function EmptyState({ hasAny }) {
|
|
4549
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
4550
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
4551
|
-
/* @__PURE__ */ jsx("h3", { style:
|
|
4552
|
-
/* @__PURE__ */ jsx("p", { style:
|
|
4991
|
+
return /* @__PURE__ */ jsxs("div", { style: styles17.empty, children: [
|
|
4992
|
+
/* @__PURE__ */ jsx("div", { style: styles17.emptyIcon, children: "\u{1F4AC}" }),
|
|
4993
|
+
/* @__PURE__ */ jsx("h3", { style: styles17.emptyTitle, children: hasAny ? "Select a conversation" : "No conversations yet" }),
|
|
4994
|
+
/* @__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" })
|
|
4553
4995
|
] });
|
|
4554
4996
|
}
|
|
4555
|
-
var
|
|
4997
|
+
var styles17 = {
|
|
4556
4998
|
container: {
|
|
4557
4999
|
display: "flex",
|
|
4558
5000
|
height: "100%",
|