@natoe/colab 0.1.6 → 0.1.8
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 +15 -9
- package/dist/index.d.ts +15 -9
- package/dist/index.js +467 -177
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +468 -178
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React4, { createContext, forwardRef, useRef, useImperativeHandle, useEffect, useCallback, useState, useContext, useId, useMemo } from 'react';
|
|
1
|
+
import React4, { createContext, forwardRef, useRef, useImperativeHandle, useEffect, useCallback, useState, useLayoutEffect, useContext, useId, useMemo } from 'react';
|
|
2
2
|
import { Socket, Presence } from 'phoenix';
|
|
3
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
4
5
|
|
|
5
6
|
// src/components/CollabPanel.tsx
|
|
6
7
|
|
|
@@ -1144,71 +1145,190 @@ function useDeepLinks() {
|
|
|
1144
1145
|
function escapeRegex(string) {
|
|
1145
1146
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1146
1147
|
}
|
|
1148
|
+
function DicomIcon({ size = 18, color = "currentColor" }) {
|
|
1149
|
+
return /* @__PURE__ */ jsxs(
|
|
1150
|
+
"svg",
|
|
1151
|
+
{
|
|
1152
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1153
|
+
width: size,
|
|
1154
|
+
height: size,
|
|
1155
|
+
viewBox: "0 0 24 24",
|
|
1156
|
+
fill: "none",
|
|
1157
|
+
stroke: color,
|
|
1158
|
+
strokeWidth: "2",
|
|
1159
|
+
strokeLinecap: "round",
|
|
1160
|
+
strokeLinejoin: "round",
|
|
1161
|
+
"aria-hidden": "true",
|
|
1162
|
+
children: [
|
|
1163
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "13", height: "13", rx: "2" }),
|
|
1164
|
+
/* @__PURE__ */ jsx("path", { d: "M7 7h13a2 2 0 0 1 2 2v11", opacity: "0.6" }),
|
|
1165
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9.5", r: "1.2", fill: color, stroke: "none" }),
|
|
1166
|
+
/* @__PURE__ */ jsx("path", { d: "M5 14l3-3 4 4 2-2 3 3" })
|
|
1167
|
+
]
|
|
1168
|
+
}
|
|
1169
|
+
);
|
|
1170
|
+
}
|
|
1171
|
+
function SettingsIcon({ size = 18, color = "currentColor" }) {
|
|
1172
|
+
return /* @__PURE__ */ jsx(
|
|
1173
|
+
"svg",
|
|
1174
|
+
{
|
|
1175
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1176
|
+
width: size,
|
|
1177
|
+
height: size,
|
|
1178
|
+
viewBox: "0 0 24 24",
|
|
1179
|
+
fill: color,
|
|
1180
|
+
"aria-hidden": "true",
|
|
1181
|
+
children: /* @__PURE__ */ jsx("path", { d: "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.488.488 0 0 0-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 0 0-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z" })
|
|
1182
|
+
}
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
function BackIcon({ size = 22, color = "currentColor" }) {
|
|
1186
|
+
return /* @__PURE__ */ jsx(
|
|
1187
|
+
"svg",
|
|
1188
|
+
{
|
|
1189
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1190
|
+
width: size,
|
|
1191
|
+
height: size,
|
|
1192
|
+
viewBox: "0 0 24 24",
|
|
1193
|
+
fill: color,
|
|
1194
|
+
"aria-hidden": "true",
|
|
1195
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" })
|
|
1196
|
+
}
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1147
1199
|
function PatientHeader({
|
|
1148
1200
|
patientData,
|
|
1149
1201
|
onOpenDicom,
|
|
1150
1202
|
onOpenSettings,
|
|
1203
|
+
onBack,
|
|
1151
1204
|
className
|
|
1152
1205
|
}) {
|
|
1153
1206
|
const hasDicom = !!(patientData.studyId && patientData.storageId);
|
|
1207
|
+
const meta = [];
|
|
1208
|
+
if (patientData.patientAge) meta.push({ label: "Age", value: String(patientData.patientAge) });
|
|
1209
|
+
if (patientData.patientSex) meta.push({ label: "Sex", value: String(patientData.patientSex) });
|
|
1210
|
+
if (patientData.studyType) meta.push({ label: "Modality", value: patientData.studyType });
|
|
1211
|
+
if (patientData.bodyParts && patientData.bodyParts.length > 0) {
|
|
1212
|
+
meta.push({ label: "Body part", value: patientData.bodyParts.join(", ") });
|
|
1213
|
+
}
|
|
1214
|
+
if (patientData.referringPhysician) {
|
|
1215
|
+
meta.push({ label: "Ref", value: patientData.referringPhysician });
|
|
1216
|
+
}
|
|
1154
1217
|
return /* @__PURE__ */ jsxs("div", { className, style: styles.container, children: [
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1218
|
+
/* @__PURE__ */ jsxs("div", { style: styles.nameRow, children: [
|
|
1219
|
+
onBack && /* @__PURE__ */ jsx(
|
|
1220
|
+
"button",
|
|
1221
|
+
{
|
|
1222
|
+
type: "button",
|
|
1223
|
+
onClick: onBack,
|
|
1224
|
+
style: styles.backButton,
|
|
1225
|
+
"aria-label": "Back to conversations",
|
|
1226
|
+
title: "Back to conversations",
|
|
1227
|
+
children: /* @__PURE__ */ jsx(BackIcon, { size: 22, color: "#1f2937" })
|
|
1228
|
+
}
|
|
1229
|
+
),
|
|
1230
|
+
/* @__PURE__ */ jsx("span", { style: styles.nameText, children: buildChannelName(patientData) })
|
|
1167
1231
|
] }),
|
|
1168
|
-
/* @__PURE__ */
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1232
|
+
meta.length > 0 && /* @__PURE__ */ jsx("div", { style: styles.metaRow, children: meta.map((item) => /* @__PURE__ */ jsxs("span", { style: styles.metaItem, children: [
|
|
1233
|
+
/* @__PURE__ */ jsxs("span", { style: styles.metaLabel, children: [
|
|
1234
|
+
item.label,
|
|
1235
|
+
":"
|
|
1236
|
+
] }),
|
|
1237
|
+
" ",
|
|
1238
|
+
/* @__PURE__ */ jsx("span", { style: styles.metaValue, children: item.value })
|
|
1239
|
+
] }, item.label)) }),
|
|
1240
|
+
hasDicom && onOpenDicom || onOpenSettings ? /* @__PURE__ */ jsxs("div", { style: styles.actions, children: [
|
|
1241
|
+
hasDicom && onOpenDicom && /* @__PURE__ */ jsxs(
|
|
1242
|
+
"button",
|
|
1243
|
+
{
|
|
1244
|
+
onClick: onOpenDicom,
|
|
1245
|
+
style: styles.dicomButton,
|
|
1246
|
+
type: "button",
|
|
1247
|
+
"aria-label": "View DICOM study",
|
|
1248
|
+
children: [
|
|
1249
|
+
/* @__PURE__ */ jsx(DicomIcon, { size: 18, color: "#ffffff" }),
|
|
1250
|
+
/* @__PURE__ */ jsx("span", { children: "View DICOM" })
|
|
1251
|
+
]
|
|
1252
|
+
}
|
|
1253
|
+
),
|
|
1254
|
+
onOpenSettings && /* @__PURE__ */ jsxs(
|
|
1255
|
+
"button",
|
|
1256
|
+
{
|
|
1257
|
+
onClick: onOpenSettings,
|
|
1258
|
+
style: styles.settingsButton,
|
|
1259
|
+
type: "button",
|
|
1260
|
+
"aria-label": "Open channel settings",
|
|
1261
|
+
children: [
|
|
1262
|
+
/* @__PURE__ */ jsx(SettingsIcon, { size: 18, color: "#374151" }),
|
|
1263
|
+
/* @__PURE__ */ jsx("span", { children: "Settings" })
|
|
1264
|
+
]
|
|
1265
|
+
}
|
|
1266
|
+
)
|
|
1267
|
+
] }) : null
|
|
1172
1268
|
] });
|
|
1173
1269
|
}
|
|
1174
1270
|
var styles = {
|
|
1175
1271
|
container: {
|
|
1176
|
-
padding: "
|
|
1272
|
+
padding: "14px 16px",
|
|
1177
1273
|
borderBottom: "1px solid #e5e7eb",
|
|
1178
1274
|
backgroundColor: "#f9fafb"
|
|
1179
1275
|
},
|
|
1180
|
-
|
|
1276
|
+
nameRow: {
|
|
1181
1277
|
display: "flex",
|
|
1182
|
-
|
|
1183
|
-
|
|
1278
|
+
alignItems: "center",
|
|
1279
|
+
gap: "6px"
|
|
1184
1280
|
},
|
|
1185
|
-
|
|
1281
|
+
backButton: {
|
|
1282
|
+
width: "36px",
|
|
1283
|
+
height: "36px",
|
|
1186
1284
|
display: "flex",
|
|
1187
1285
|
alignItems: "center",
|
|
1188
|
-
|
|
1189
|
-
|
|
1286
|
+
justifyContent: "center",
|
|
1287
|
+
marginLeft: "-8px",
|
|
1288
|
+
backgroundColor: "transparent",
|
|
1289
|
+
border: "none",
|
|
1290
|
+
borderRadius: "50%",
|
|
1291
|
+
cursor: "pointer",
|
|
1292
|
+
flexShrink: 0
|
|
1190
1293
|
},
|
|
1191
|
-
|
|
1294
|
+
nameText: {
|
|
1295
|
+
fontSize: "18px",
|
|
1192
1296
|
fontWeight: 600,
|
|
1193
|
-
|
|
1194
|
-
|
|
1297
|
+
color: "#111827",
|
|
1298
|
+
lineHeight: 1.3,
|
|
1299
|
+
minWidth: 0,
|
|
1300
|
+
overflow: "hidden",
|
|
1301
|
+
textOverflow: "ellipsis",
|
|
1302
|
+
whiteSpace: "nowrap"
|
|
1195
1303
|
},
|
|
1196
|
-
|
|
1304
|
+
metaRow: {
|
|
1197
1305
|
display: "flex",
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1306
|
+
flexWrap: "wrap",
|
|
1307
|
+
columnGap: "14px",
|
|
1308
|
+
rowGap: "4px",
|
|
1309
|
+
marginTop: "6px"
|
|
1201
1310
|
},
|
|
1202
|
-
|
|
1311
|
+
metaItem: {
|
|
1203
1312
|
fontSize: "13px",
|
|
1204
|
-
color: "#
|
|
1313
|
+
color: "#374151",
|
|
1314
|
+
whiteSpace: "nowrap"
|
|
1315
|
+
},
|
|
1316
|
+
metaLabel: {
|
|
1317
|
+
color: "#6b7280",
|
|
1318
|
+
fontWeight: 500
|
|
1319
|
+
},
|
|
1320
|
+
metaValue: {
|
|
1321
|
+
color: "#111827"
|
|
1205
1322
|
},
|
|
1206
1323
|
actions: {
|
|
1207
1324
|
display: "flex",
|
|
1208
1325
|
gap: "8px",
|
|
1209
|
-
marginTop: "
|
|
1326
|
+
marginTop: "10px"
|
|
1210
1327
|
},
|
|
1211
1328
|
dicomButton: {
|
|
1329
|
+
display: "inline-flex",
|
|
1330
|
+
alignItems: "center",
|
|
1331
|
+
gap: "8px",
|
|
1212
1332
|
minHeight: "40px",
|
|
1213
1333
|
padding: "8px 16px",
|
|
1214
1334
|
fontSize: "14px",
|
|
@@ -1220,6 +1340,9 @@ var styles = {
|
|
|
1220
1340
|
cursor: "pointer"
|
|
1221
1341
|
},
|
|
1222
1342
|
settingsButton: {
|
|
1343
|
+
display: "inline-flex",
|
|
1344
|
+
alignItems: "center",
|
|
1345
|
+
gap: "8px",
|
|
1223
1346
|
minHeight: "40px",
|
|
1224
1347
|
padding: "8px 16px",
|
|
1225
1348
|
fontSize: "14px",
|
|
@@ -1436,6 +1559,8 @@ function MoreIcon({ size = 18, color = "currentColor" }) {
|
|
|
1436
1559
|
}
|
|
1437
1560
|
);
|
|
1438
1561
|
}
|
|
1562
|
+
var VIEWPORT_MARGIN = 8;
|
|
1563
|
+
var TRIGGER_GAP = 4;
|
|
1439
1564
|
function MessageActionsMenu({
|
|
1440
1565
|
message,
|
|
1441
1566
|
onReply,
|
|
@@ -1447,16 +1572,43 @@ function MessageActionsMenu({
|
|
|
1447
1572
|
className
|
|
1448
1573
|
}) {
|
|
1449
1574
|
const [isOpen, setIsOpen] = useState(false);
|
|
1450
|
-
const
|
|
1575
|
+
const [coords, setCoords] = useState(null);
|
|
1451
1576
|
const triggerRef = useRef(null);
|
|
1577
|
+
const menuRef = useRef(null);
|
|
1452
1578
|
const isPinned = !!message.isPinned;
|
|
1453
1579
|
const canCopy = message.type === "text" && !!message.body;
|
|
1580
|
+
useLayoutEffect(() => {
|
|
1581
|
+
if (!isOpen) {
|
|
1582
|
+
setCoords(null);
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
const trigger = triggerRef.current;
|
|
1586
|
+
const menu2 = menuRef.current;
|
|
1587
|
+
if (!trigger || !menu2) return;
|
|
1588
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
1589
|
+
const menuRect = menu2.getBoundingClientRect();
|
|
1590
|
+
const vw = window.innerWidth;
|
|
1591
|
+
const vh = window.innerHeight;
|
|
1592
|
+
const spaceBelow = vh - triggerRect.bottom;
|
|
1593
|
+
const spaceAbove = triggerRect.top;
|
|
1594
|
+
const placeAbove = spaceBelow < menuRect.height + TRIGGER_GAP + VIEWPORT_MARGIN && spaceAbove > spaceBelow;
|
|
1595
|
+
const top = placeAbove ? triggerRect.top - menuRect.height - TRIGGER_GAP : triggerRect.bottom + TRIGGER_GAP;
|
|
1596
|
+
const preferredLeft = anchorRight ? triggerRect.right - menuRect.width : triggerRect.left;
|
|
1597
|
+
const left = Math.max(
|
|
1598
|
+
VIEWPORT_MARGIN,
|
|
1599
|
+
Math.min(preferredLeft, vw - menuRect.width - VIEWPORT_MARGIN)
|
|
1600
|
+
);
|
|
1601
|
+
const clampedTop = Math.max(
|
|
1602
|
+
VIEWPORT_MARGIN,
|
|
1603
|
+
Math.min(top, vh - menuRect.height - VIEWPORT_MARGIN)
|
|
1604
|
+
);
|
|
1605
|
+
setCoords({ top: clampedTop, left });
|
|
1606
|
+
}, [isOpen, anchorRight]);
|
|
1454
1607
|
useEffect(() => {
|
|
1455
1608
|
if (!isOpen) return;
|
|
1609
|
+
const isInside = (node) => !!node && (triggerRef.current?.contains(node) === true || menuRef.current?.contains(node) === true);
|
|
1456
1610
|
const handleClick = (e) => {
|
|
1457
|
-
if (!
|
|
1458
|
-
setIsOpen(false);
|
|
1459
|
-
}
|
|
1611
|
+
if (!isInside(e.target)) setIsOpen(false);
|
|
1460
1612
|
};
|
|
1461
1613
|
const handleKey = (e) => {
|
|
1462
1614
|
if (e.key === "Escape") {
|
|
@@ -1464,18 +1616,100 @@ function MessageActionsMenu({
|
|
|
1464
1616
|
triggerRef.current?.focus();
|
|
1465
1617
|
}
|
|
1466
1618
|
};
|
|
1619
|
+
const handleScroll = (e) => {
|
|
1620
|
+
if (!isInside(e.target)) setIsOpen(false);
|
|
1621
|
+
};
|
|
1622
|
+
const handleResize = () => setIsOpen(false);
|
|
1467
1623
|
document.addEventListener("mousedown", handleClick);
|
|
1468
1624
|
document.addEventListener("keydown", handleKey);
|
|
1625
|
+
window.addEventListener("resize", handleResize);
|
|
1626
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
1469
1627
|
return () => {
|
|
1470
1628
|
document.removeEventListener("mousedown", handleClick);
|
|
1471
1629
|
document.removeEventListener("keydown", handleKey);
|
|
1630
|
+
window.removeEventListener("resize", handleResize);
|
|
1631
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
1472
1632
|
};
|
|
1473
1633
|
}, [isOpen]);
|
|
1474
1634
|
const run = (fn) => {
|
|
1475
1635
|
setIsOpen(false);
|
|
1476
1636
|
fn();
|
|
1477
1637
|
};
|
|
1478
|
-
|
|
1638
|
+
const menu = isOpen ? /* @__PURE__ */ jsxs(
|
|
1639
|
+
"div",
|
|
1640
|
+
{
|
|
1641
|
+
ref: menuRef,
|
|
1642
|
+
role: "menu",
|
|
1643
|
+
"aria-label": "Message actions",
|
|
1644
|
+
style: {
|
|
1645
|
+
...styles4.menu,
|
|
1646
|
+
// Render off-screen on first paint so we can measure before placing,
|
|
1647
|
+
// then snap to computed coords on the next layout pass.
|
|
1648
|
+
top: coords?.top ?? -9999,
|
|
1649
|
+
left: coords?.left ?? -9999,
|
|
1650
|
+
visibility: coords ? "visible" : "hidden"
|
|
1651
|
+
},
|
|
1652
|
+
children: [
|
|
1653
|
+
/* @__PURE__ */ jsxs(
|
|
1654
|
+
"button",
|
|
1655
|
+
{
|
|
1656
|
+
type: "button",
|
|
1657
|
+
role: "menuitem",
|
|
1658
|
+
onClick: () => run(() => onReply(message)),
|
|
1659
|
+
style: styles4.item,
|
|
1660
|
+
children: [
|
|
1661
|
+
/* @__PURE__ */ jsx(ReplyIcon, { size: 18, color: "#374151" }),
|
|
1662
|
+
/* @__PURE__ */ jsx("span", { children: "Reply" })
|
|
1663
|
+
]
|
|
1664
|
+
}
|
|
1665
|
+
),
|
|
1666
|
+
isPinned ? /* @__PURE__ */ jsxs(
|
|
1667
|
+
"button",
|
|
1668
|
+
{
|
|
1669
|
+
type: "button",
|
|
1670
|
+
role: "menuitem",
|
|
1671
|
+
onClick: () => run(() => onUnpin(message.id)),
|
|
1672
|
+
style: styles4.item,
|
|
1673
|
+
children: [
|
|
1674
|
+
/* @__PURE__ */ jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1675
|
+
/* @__PURE__ */ jsx("span", { children: "Unpin" })
|
|
1676
|
+
]
|
|
1677
|
+
}
|
|
1678
|
+
) : /* @__PURE__ */ jsxs(
|
|
1679
|
+
"button",
|
|
1680
|
+
{
|
|
1681
|
+
type: "button",
|
|
1682
|
+
role: "menuitem",
|
|
1683
|
+
onClick: () => run(() => onPin(message.id)),
|
|
1684
|
+
disabled: pinDisabled,
|
|
1685
|
+
style: {
|
|
1686
|
+
...styles4.item,
|
|
1687
|
+
...pinDisabled ? styles4.itemDisabled : {}
|
|
1688
|
+
},
|
|
1689
|
+
title: pinDisabled ? "Pin limit reached (max 3)" : void 0,
|
|
1690
|
+
children: [
|
|
1691
|
+
/* @__PURE__ */ jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1692
|
+
/* @__PURE__ */ jsx("span", { children: pinDisabled ? "Pin (limit reached)" : "Pin" })
|
|
1693
|
+
]
|
|
1694
|
+
}
|
|
1695
|
+
),
|
|
1696
|
+
canCopy && onCopy && /* @__PURE__ */ jsxs(
|
|
1697
|
+
"button",
|
|
1698
|
+
{
|
|
1699
|
+
type: "button",
|
|
1700
|
+
role: "menuitem",
|
|
1701
|
+
onClick: () => run(() => onCopy(message.body)),
|
|
1702
|
+
style: styles4.item,
|
|
1703
|
+
children: [
|
|
1704
|
+
/* @__PURE__ */ jsx(CopyIcon, { size: 16, color: "#374151" }),
|
|
1705
|
+
/* @__PURE__ */ jsx("span", { children: "Copy text" })
|
|
1706
|
+
]
|
|
1707
|
+
}
|
|
1708
|
+
)
|
|
1709
|
+
]
|
|
1710
|
+
}
|
|
1711
|
+
) : null;
|
|
1712
|
+
return /* @__PURE__ */ jsxs("div", { className, style: styles4.wrapper, children: [
|
|
1479
1713
|
/* @__PURE__ */ jsx(
|
|
1480
1714
|
"button",
|
|
1481
1715
|
{
|
|
@@ -1493,75 +1727,7 @@ function MessageActionsMenu({
|
|
|
1493
1727
|
children: /* @__PURE__ */ jsx(MoreIcon, { size: 18, color: "#4b5563" })
|
|
1494
1728
|
}
|
|
1495
1729
|
),
|
|
1496
|
-
|
|
1497
|
-
"div",
|
|
1498
|
-
{
|
|
1499
|
-
role: "menu",
|
|
1500
|
-
"aria-label": "Message actions",
|
|
1501
|
-
style: {
|
|
1502
|
-
...styles4.menu,
|
|
1503
|
-
...anchorRight ? styles4.menuRight : styles4.menuLeft
|
|
1504
|
-
},
|
|
1505
|
-
children: [
|
|
1506
|
-
/* @__PURE__ */ jsxs(
|
|
1507
|
-
"button",
|
|
1508
|
-
{
|
|
1509
|
-
type: "button",
|
|
1510
|
-
role: "menuitem",
|
|
1511
|
-
onClick: () => run(() => onReply(message)),
|
|
1512
|
-
style: styles4.item,
|
|
1513
|
-
children: [
|
|
1514
|
-
/* @__PURE__ */ jsx(ReplyIcon, { size: 18, color: "#374151" }),
|
|
1515
|
-
/* @__PURE__ */ jsx("span", { children: "Reply" })
|
|
1516
|
-
]
|
|
1517
|
-
}
|
|
1518
|
-
),
|
|
1519
|
-
isPinned ? /* @__PURE__ */ jsxs(
|
|
1520
|
-
"button",
|
|
1521
|
-
{
|
|
1522
|
-
type: "button",
|
|
1523
|
-
role: "menuitem",
|
|
1524
|
-
onClick: () => run(() => onUnpin(message.id)),
|
|
1525
|
-
style: styles4.item,
|
|
1526
|
-
children: [
|
|
1527
|
-
/* @__PURE__ */ jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1528
|
-
/* @__PURE__ */ jsx("span", { children: "Unpin" })
|
|
1529
|
-
]
|
|
1530
|
-
}
|
|
1531
|
-
) : /* @__PURE__ */ jsxs(
|
|
1532
|
-
"button",
|
|
1533
|
-
{
|
|
1534
|
-
type: "button",
|
|
1535
|
-
role: "menuitem",
|
|
1536
|
-
onClick: () => run(() => onPin(message.id)),
|
|
1537
|
-
disabled: pinDisabled,
|
|
1538
|
-
style: {
|
|
1539
|
-
...styles4.item,
|
|
1540
|
-
...pinDisabled ? styles4.itemDisabled : {}
|
|
1541
|
-
},
|
|
1542
|
-
title: pinDisabled ? "Pin limit reached (max 3)" : void 0,
|
|
1543
|
-
children: [
|
|
1544
|
-
/* @__PURE__ */ jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1545
|
-
/* @__PURE__ */ jsx("span", { children: pinDisabled ? "Pin (limit reached)" : "Pin" })
|
|
1546
|
-
]
|
|
1547
|
-
}
|
|
1548
|
-
),
|
|
1549
|
-
canCopy && onCopy && /* @__PURE__ */ jsxs(
|
|
1550
|
-
"button",
|
|
1551
|
-
{
|
|
1552
|
-
type: "button",
|
|
1553
|
-
role: "menuitem",
|
|
1554
|
-
onClick: () => run(() => onCopy(message.body)),
|
|
1555
|
-
style: styles4.item,
|
|
1556
|
-
children: [
|
|
1557
|
-
/* @__PURE__ */ jsx(CopyIcon, { size: 16, color: "#374151" }),
|
|
1558
|
-
/* @__PURE__ */ jsx("span", { children: "Copy text" })
|
|
1559
|
-
]
|
|
1560
|
-
}
|
|
1561
|
-
)
|
|
1562
|
-
]
|
|
1563
|
-
}
|
|
1564
|
-
)
|
|
1730
|
+
menu && typeof document !== "undefined" ? createPortal(menu, document.body) : null
|
|
1565
1731
|
] });
|
|
1566
1732
|
}
|
|
1567
1733
|
var styles4 = {
|
|
@@ -1582,22 +1748,15 @@ var styles4 = {
|
|
|
1582
1748
|
color: "#4b5563"
|
|
1583
1749
|
},
|
|
1584
1750
|
menu: {
|
|
1585
|
-
position: "
|
|
1586
|
-
top: "100%",
|
|
1587
|
-
marginTop: "4px",
|
|
1751
|
+
position: "fixed",
|
|
1588
1752
|
minWidth: "160px",
|
|
1589
1753
|
backgroundColor: "#ffffff",
|
|
1590
1754
|
border: "1px solid #e5e7eb",
|
|
1591
1755
|
borderRadius: "10px",
|
|
1592
1756
|
boxShadow: "0 6px 18px rgba(0, 0, 0, 0.12)",
|
|
1593
1757
|
padding: "4px",
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
menuLeft: {
|
|
1597
|
-
left: 0
|
|
1598
|
-
},
|
|
1599
|
-
menuRight: {
|
|
1600
|
-
right: 0
|
|
1758
|
+
// Above the floating popup (z-index 9999) but below any future modal.
|
|
1759
|
+
zIndex: 1e4
|
|
1601
1760
|
},
|
|
1602
1761
|
item: {
|
|
1603
1762
|
display: "flex",
|
|
@@ -2250,31 +2409,34 @@ var MessageList = forwardRef(function MessageList2({
|
|
|
2250
2409
|
/* @__PURE__ */ jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation \u2014 everyone on this case will see what you write." })
|
|
2251
2410
|
] }),
|
|
2252
2411
|
messages.length === 0 && isLoading && /* @__PURE__ */ jsx("div", { style: styles6.firstLoad, children: /* @__PURE__ */ jsx(Spinner, { size: 20 }) }),
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
/* @__PURE__ */
|
|
2260
|
-
|
|
2261
|
-
{
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2412
|
+
(() => {
|
|
2413
|
+
let lastValidBucket = null;
|
|
2414
|
+
return messages.map((message) => {
|
|
2415
|
+
const currentBucket = dayBucketKey(message.insertedAt);
|
|
2416
|
+
const showDivider = !!currentBucket && currentBucket !== lastValidBucket;
|
|
2417
|
+
if (currentBucket) lastValidBucket = currentBucket;
|
|
2418
|
+
return /* @__PURE__ */ jsxs(React4.Fragment, { children: [
|
|
2419
|
+
showDivider && /* @__PURE__ */ jsx("div", { style: styles6.dayDivider, role: "separator", "aria-label": "Date", children: /* @__PURE__ */ jsx("span", { style: styles6.dayDividerPill, children: formatDayDivider(message.insertedAt) }) }),
|
|
2420
|
+
/* @__PURE__ */ jsx("div", { "data-message-id": message.id, "data-natoe-message-bubble": true, style: styles6.bubbleSlot, children: /* @__PURE__ */ jsx(
|
|
2421
|
+
MessageBubble,
|
|
2422
|
+
{
|
|
2423
|
+
message,
|
|
2424
|
+
isOwn: message.senderId === currentUserId,
|
|
2425
|
+
participants,
|
|
2426
|
+
currentUserId,
|
|
2427
|
+
showSeenBy,
|
|
2428
|
+
onDeepLinkClick,
|
|
2429
|
+
onReply,
|
|
2430
|
+
onPin,
|
|
2431
|
+
onUnpin,
|
|
2432
|
+
onCopy,
|
|
2433
|
+
onRetry,
|
|
2434
|
+
pinDisabled
|
|
2435
|
+
}
|
|
2436
|
+
) })
|
|
2437
|
+
] }, message.id);
|
|
2438
|
+
});
|
|
2439
|
+
})(),
|
|
2278
2440
|
typingUsers.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles6.typingIndicator, children: [
|
|
2279
2441
|
typingUsers.map((t) => t.userName ?? "Someone").join(", "),
|
|
2280
2442
|
typingUsers.length === 1 ? " is " : " are ",
|
|
@@ -2354,7 +2516,11 @@ var styles6 = {
|
|
|
2354
2516
|
dayDivider: {
|
|
2355
2517
|
display: "flex",
|
|
2356
2518
|
justifyContent: "center",
|
|
2357
|
-
margin: "12px 0 8px"
|
|
2519
|
+
margin: "12px 0 8px",
|
|
2520
|
+
position: "sticky",
|
|
2521
|
+
top: "4px",
|
|
2522
|
+
zIndex: 1,
|
|
2523
|
+
pointerEvents: "none"
|
|
2358
2524
|
},
|
|
2359
2525
|
dayDividerPill: {
|
|
2360
2526
|
display: "inline-block",
|
|
@@ -2364,7 +2530,11 @@ var styles6 = {
|
|
|
2364
2530
|
color: "#334155",
|
|
2365
2531
|
backgroundColor: "#e2e8f0",
|
|
2366
2532
|
borderRadius: "12px",
|
|
2367
|
-
letterSpacing: "0.2px"
|
|
2533
|
+
letterSpacing: "0.2px",
|
|
2534
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.04)"
|
|
2535
|
+
},
|
|
2536
|
+
bubbleSlot: {
|
|
2537
|
+
animation: "natoe-colab-message-in 180ms ease-out"
|
|
2368
2538
|
}
|
|
2369
2539
|
};
|
|
2370
2540
|
function ReplyPreview({ message, onCancel, className }) {
|
|
@@ -2515,6 +2685,7 @@ function MessageInput({
|
|
|
2515
2685
|
}) {
|
|
2516
2686
|
const [text, setText] = useState("");
|
|
2517
2687
|
const [isSending, setIsSending] = useState(false);
|
|
2688
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
2518
2689
|
const [fileError, setFileError] = useState(null);
|
|
2519
2690
|
const fileInputRef = useRef(null);
|
|
2520
2691
|
const typingTimeoutRef = useRef(null);
|
|
@@ -2578,10 +2749,12 @@ function MessageInput({
|
|
|
2578
2749
|
return;
|
|
2579
2750
|
}
|
|
2580
2751
|
setIsSending(true);
|
|
2752
|
+
setIsUploading(true);
|
|
2581
2753
|
try {
|
|
2582
2754
|
await onSendFile(file);
|
|
2583
2755
|
} finally {
|
|
2584
2756
|
setIsSending(false);
|
|
2757
|
+
setIsUploading(false);
|
|
2585
2758
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
2586
2759
|
}
|
|
2587
2760
|
},
|
|
@@ -2589,6 +2762,10 @@ function MessageInput({
|
|
|
2589
2762
|
);
|
|
2590
2763
|
return /* @__PURE__ */ jsxs("div", { className, style: styles8.container, children: [
|
|
2591
2764
|
replyTo && onCancelReply && /* @__PURE__ */ jsx(ReplyPreview, { message: replyTo, onCancel: onCancelReply }),
|
|
2765
|
+
isUploading && /* @__PURE__ */ jsxs("div", { style: styles8.uploadBanner, children: [
|
|
2766
|
+
/* @__PURE__ */ jsx("span", { style: styles8.uploadSpinner }),
|
|
2767
|
+
"Uploading file\u2026"
|
|
2768
|
+
] }),
|
|
2592
2769
|
fileError && /* @__PURE__ */ jsxs("div", { style: styles8.error, role: "alert", children: [
|
|
2593
2770
|
/* @__PURE__ */ jsx("span", { style: styles8.errorText, children: fileError }),
|
|
2594
2771
|
/* @__PURE__ */ jsx(
|
|
@@ -2674,6 +2851,26 @@ var styles8 = {
|
|
|
2674
2851
|
borderTop: "1px solid #e5e7eb",
|
|
2675
2852
|
backgroundColor: "#ffffff"
|
|
2676
2853
|
},
|
|
2854
|
+
uploadBanner: {
|
|
2855
|
+
display: "flex",
|
|
2856
|
+
alignItems: "center",
|
|
2857
|
+
gap: "8px",
|
|
2858
|
+
padding: "6px 14px",
|
|
2859
|
+
fontSize: "12px",
|
|
2860
|
+
color: "#6b7280",
|
|
2861
|
+
backgroundColor: "#f9fafb",
|
|
2862
|
+
borderBottom: "1px solid #e5e7eb"
|
|
2863
|
+
},
|
|
2864
|
+
uploadSpinner: {
|
|
2865
|
+
display: "inline-block",
|
|
2866
|
+
width: "12px",
|
|
2867
|
+
height: "12px",
|
|
2868
|
+
border: "2px solid #d1d5db",
|
|
2869
|
+
borderTopColor: "#7c3aed",
|
|
2870
|
+
borderRadius: "50%",
|
|
2871
|
+
animation: "natoe-colab-spin 0.7s linear infinite",
|
|
2872
|
+
flexShrink: 0
|
|
2873
|
+
},
|
|
2677
2874
|
error: {
|
|
2678
2875
|
display: "flex",
|
|
2679
2876
|
alignItems: "center",
|
|
@@ -3416,11 +3613,52 @@ var styles12 = {
|
|
|
3416
3613
|
letterSpacing: "0.4px"
|
|
3417
3614
|
}
|
|
3418
3615
|
};
|
|
3616
|
+
|
|
3617
|
+
// src/core/styles.ts
|
|
3618
|
+
var FONT_STACK = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
3619
|
+
var ROOT_CLASS = "natoe-colab-root";
|
|
3620
|
+
var GLOBAL_STYLE_ID = "natoe-colab-global-styles";
|
|
3621
|
+
var GLOBAL_CSS = `
|
|
3622
|
+
@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }
|
|
3623
|
+
|
|
3624
|
+
@keyframes natoe-colab-message-in {
|
|
3625
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
3626
|
+
to { opacity: 1; transform: translateY(0); }
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3629
|
+
/* High-contrast adjustments \u2014 older users on OS-level high-contrast mode
|
|
3630
|
+
get heavier borders and stronger text without losing the package look. */
|
|
3631
|
+
@media (prefers-contrast: more) {
|
|
3632
|
+
.${ROOT_CLASS} {
|
|
3633
|
+
color: #000000;
|
|
3634
|
+
}
|
|
3635
|
+
.${ROOT_CLASS} button {
|
|
3636
|
+
outline: 1px solid currentColor;
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
|
|
3640
|
+
/* Honour reduced-motion preferences by killing entry animations. */
|
|
3641
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3642
|
+
.${ROOT_CLASS} [data-natoe-message-bubble] {
|
|
3643
|
+
animation: none !important;
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
`;
|
|
3647
|
+
function ensureGlobalStyles() {
|
|
3648
|
+
if (typeof document === "undefined") return;
|
|
3649
|
+
if (document.getElementById(GLOBAL_STYLE_ID)) return;
|
|
3650
|
+
const style = document.createElement("style");
|
|
3651
|
+
style.id = GLOBAL_STYLE_ID;
|
|
3652
|
+
style.textContent = GLOBAL_CSS;
|
|
3653
|
+
document.head.appendChild(style);
|
|
3654
|
+
}
|
|
3655
|
+
ensureGlobalStyles();
|
|
3419
3656
|
function CollabPanel({
|
|
3420
3657
|
orderId,
|
|
3421
3658
|
patientData,
|
|
3422
3659
|
participantIds,
|
|
3423
3660
|
showSeenBy = true,
|
|
3661
|
+
onBack,
|
|
3424
3662
|
className,
|
|
3425
3663
|
style
|
|
3426
3664
|
}) {
|
|
@@ -3494,13 +3732,13 @@ function CollabPanel({
|
|
|
3494
3732
|
};
|
|
3495
3733
|
const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;
|
|
3496
3734
|
if (error) {
|
|
3497
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxs("div", { style: panelStyles.errorState, children: [
|
|
3735
|
+
return /* @__PURE__ */ jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxs("div", { style: panelStyles.errorState, children: [
|
|
3498
3736
|
/* @__PURE__ */ jsx("p", { style: panelStyles.errorTitle, children: "Unable to load conversation" }),
|
|
3499
3737
|
/* @__PURE__ */ jsx("p", { style: panelStyles.errorMessage, children: error })
|
|
3500
3738
|
] }) });
|
|
3501
3739
|
}
|
|
3502
3740
|
if (isLoading && !conversation) {
|
|
3503
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
|
|
3741
|
+
return /* @__PURE__ */ jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
|
|
3504
3742
|
}
|
|
3505
3743
|
return /* @__PURE__ */ jsxs("div", { className, style: { ...panelStyles.container, ...style }, children: [
|
|
3506
3744
|
showSettings && conversation ? /* @__PURE__ */ jsx(
|
|
@@ -3528,7 +3766,8 @@ function CollabPanel({
|
|
|
3528
3766
|
patientData,
|
|
3529
3767
|
participants,
|
|
3530
3768
|
onOpenDicom: handleOpenDicom,
|
|
3531
|
-
onOpenSettings: () => setShowSettings(true)
|
|
3769
|
+
onOpenSettings: () => setShowSettings(true),
|
|
3770
|
+
onBack
|
|
3532
3771
|
}
|
|
3533
3772
|
),
|
|
3534
3773
|
pinnedMessages.length > 0 && /* @__PURE__ */ jsx(
|
|
@@ -3586,7 +3825,7 @@ var panelStyles = {
|
|
|
3586
3825
|
borderRadius: "8px",
|
|
3587
3826
|
overflow: "hidden",
|
|
3588
3827
|
border: "1px solid #e5e7eb",
|
|
3589
|
-
fontFamily:
|
|
3828
|
+
fontFamily: FONT_STACK
|
|
3590
3829
|
},
|
|
3591
3830
|
loadingState: {
|
|
3592
3831
|
display: "flex",
|
|
@@ -3645,6 +3884,7 @@ function ExpandIcon({ size = 18, color = "currentColor" }) {
|
|
|
3645
3884
|
}
|
|
3646
3885
|
);
|
|
3647
3886
|
}
|
|
3887
|
+
ensureGlobalStyles();
|
|
3648
3888
|
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
3649
3889
|
function CollabPopup({
|
|
3650
3890
|
orderId,
|
|
@@ -3746,7 +3986,7 @@ function CollabPopup({
|
|
|
3746
3986
|
"div",
|
|
3747
3987
|
{
|
|
3748
3988
|
ref: containerRef,
|
|
3749
|
-
className,
|
|
3989
|
+
className: [ROOT_CLASS, className].filter(Boolean).join(" "),
|
|
3750
3990
|
role: "dialog",
|
|
3751
3991
|
"aria-modal": "true",
|
|
3752
3992
|
"aria-labelledby": titleId,
|
|
@@ -3815,7 +4055,8 @@ var styles13 = {
|
|
|
3815
4055
|
flexDirection: "column",
|
|
3816
4056
|
backgroundColor: "#ffffff",
|
|
3817
4057
|
border: "1px solid #e5e7eb",
|
|
3818
|
-
transition: "height 0.2s ease"
|
|
4058
|
+
transition: "height 0.2s ease",
|
|
4059
|
+
fontFamily: FONT_STACK
|
|
3819
4060
|
},
|
|
3820
4061
|
titleBar: {
|
|
3821
4062
|
display: "flex",
|
|
@@ -4087,6 +4328,7 @@ function useInlineCollab({
|
|
|
4087
4328
|
containerRef
|
|
4088
4329
|
};
|
|
4089
4330
|
}
|
|
4331
|
+
ensureGlobalStyles();
|
|
4090
4332
|
function CollabInline({
|
|
4091
4333
|
orderId,
|
|
4092
4334
|
patientData,
|
|
@@ -4109,9 +4351,9 @@ function CollabInline({
|
|
|
4109
4351
|
containerRef
|
|
4110
4352
|
} = useInlineCollab({ orderId, patientData, participantIds, messageLimit });
|
|
4111
4353
|
if (isLoading && !hasConversation) {
|
|
4112
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
4354
|
+
return /* @__PURE__ */ jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
4113
4355
|
}
|
|
4114
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, style: { ...styles14.container, ...style }, children: [
|
|
4356
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...styles14.container, ...style }, children: [
|
|
4115
4357
|
hasConversation && messages.length > 0 && /* @__PURE__ */ jsx("div", { style: styles14.preview, children: messages.slice(-messageLimit).map((message) => /* @__PURE__ */ jsx(InlineMessageRow, { message }, message.id)) }),
|
|
4116
4358
|
error && /* @__PURE__ */ jsx("div", { style: styles14.error, children: error }),
|
|
4117
4359
|
/* @__PURE__ */ jsx(
|
|
@@ -4327,7 +4569,7 @@ var styles14 = {
|
|
|
4327
4569
|
backgroundColor: "#ffffff",
|
|
4328
4570
|
border: "1px solid #e5e7eb",
|
|
4329
4571
|
borderRadius: "8px",
|
|
4330
|
-
fontFamily:
|
|
4572
|
+
fontFamily: FONT_STACK
|
|
4331
4573
|
},
|
|
4332
4574
|
loadingState: {
|
|
4333
4575
|
padding: "8px",
|
|
@@ -4957,6 +5199,8 @@ var styles16 = {
|
|
|
4957
5199
|
textAlign: "center"
|
|
4958
5200
|
}
|
|
4959
5201
|
};
|
|
5202
|
+
ensureGlobalStyles();
|
|
5203
|
+
var COMPACT_BREAKPOINT = 720;
|
|
4960
5204
|
function CollabInbox({
|
|
4961
5205
|
initialConversationId,
|
|
4962
5206
|
onSelectConversation,
|
|
@@ -4966,37 +5210,70 @@ function CollabInbox({
|
|
|
4966
5210
|
}) {
|
|
4967
5211
|
const { conversations, isLoading, error } = useConversationList();
|
|
4968
5212
|
const [selectedId, setSelectedId] = useState(initialConversationId ?? null);
|
|
5213
|
+
const [isCompact, setIsCompact] = useState(
|
|
5214
|
+
() => typeof window === "undefined" ? false : window.innerWidth < COMPACT_BREAKPOINT
|
|
5215
|
+
);
|
|
5216
|
+
useEffect(() => {
|
|
5217
|
+
if (typeof window === "undefined") return;
|
|
5218
|
+
const mq = window.matchMedia(`(max-width: ${COMPACT_BREAKPOINT - 1}px)`);
|
|
5219
|
+
const sync = () => setIsCompact(mq.matches);
|
|
5220
|
+
sync();
|
|
5221
|
+
mq.addEventListener("change", sync);
|
|
5222
|
+
return () => mq.removeEventListener("change", sync);
|
|
5223
|
+
}, []);
|
|
4969
5224
|
const selected = conversations.find((c) => c.id === selectedId) || null;
|
|
4970
5225
|
const handleSelect = (item) => {
|
|
4971
5226
|
setSelectedId(item.id);
|
|
4972
5227
|
onSelectConversation?.(item);
|
|
4973
5228
|
};
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
5229
|
+
const showDetail = !isCompact || isCompact && !!selected;
|
|
5230
|
+
const showList = !isCompact || isCompact && !selected;
|
|
5231
|
+
return /* @__PURE__ */ jsxs(
|
|
5232
|
+
"div",
|
|
5233
|
+
{
|
|
5234
|
+
className: [ROOT_CLASS, className].filter(Boolean).join(" "),
|
|
5235
|
+
style: { ...styles17.container, ...style },
|
|
5236
|
+
children: [
|
|
5237
|
+
showList && /* @__PURE__ */ jsx("div", { style: isCompact ? styles17.sidebarCompact : styles17.sidebar, children: /* @__PURE__ */ jsx(
|
|
5238
|
+
ConversationList,
|
|
5239
|
+
{
|
|
5240
|
+
conversations,
|
|
5241
|
+
selectedId,
|
|
5242
|
+
isLoading,
|
|
5243
|
+
error,
|
|
5244
|
+
onSelect: handleSelect,
|
|
5245
|
+
title
|
|
5246
|
+
}
|
|
5247
|
+
) }),
|
|
5248
|
+
showDetail && /* @__PURE__ */ jsx("div", { style: isCompact ? styles17.mainCompact : styles17.main, children: selected ? /* @__PURE__ */ jsx(
|
|
5249
|
+
CollabPanel,
|
|
5250
|
+
{
|
|
5251
|
+
orderId: selected.orderId,
|
|
5252
|
+
patientData: buildPatientData(selected),
|
|
5253
|
+
showSeenBy: true,
|
|
5254
|
+
style: styles17.panel,
|
|
5255
|
+
onBack: isCompact ? () => setSelectedId(null) : void 0
|
|
5256
|
+
},
|
|
5257
|
+
selected.id
|
|
5258
|
+
) : /* @__PURE__ */ jsx(EmptyState, { hasAny: conversations.length > 0 }) })
|
|
5259
|
+
]
|
|
5260
|
+
}
|
|
5261
|
+
);
|
|
4997
5262
|
}
|
|
4998
5263
|
function buildPatientData(item) {
|
|
4999
5264
|
if (item.patientSnapshot) return item.patientSnapshot;
|
|
5265
|
+
const parts = item.name.split(" - ");
|
|
5266
|
+
if (parts.length >= 3) {
|
|
5267
|
+
const last4 = parts[parts.length - 1];
|
|
5268
|
+
const labName = parts[parts.length - 2];
|
|
5269
|
+
const patientName = parts.slice(0, parts.length - 2).join(" - ");
|
|
5270
|
+
return {
|
|
5271
|
+
patientName,
|
|
5272
|
+
labName: labName || void 0,
|
|
5273
|
+
orderId: item.orderId,
|
|
5274
|
+
displayOrderId: last4
|
|
5275
|
+
};
|
|
5276
|
+
}
|
|
5000
5277
|
return {
|
|
5001
5278
|
patientName: item.name,
|
|
5002
5279
|
orderId: item.orderId
|
|
@@ -5015,7 +5292,7 @@ var styles17 = {
|
|
|
5015
5292
|
height: "100%",
|
|
5016
5293
|
width: "100%",
|
|
5017
5294
|
backgroundColor: "#ffffff",
|
|
5018
|
-
fontFamily:
|
|
5295
|
+
fontFamily: FONT_STACK
|
|
5019
5296
|
},
|
|
5020
5297
|
sidebar: {
|
|
5021
5298
|
width: "320px",
|
|
@@ -5024,6 +5301,12 @@ var styles17 = {
|
|
|
5024
5301
|
display: "flex",
|
|
5025
5302
|
flexDirection: "column"
|
|
5026
5303
|
},
|
|
5304
|
+
sidebarCompact: {
|
|
5305
|
+
width: "100%",
|
|
5306
|
+
flex: 1,
|
|
5307
|
+
display: "flex",
|
|
5308
|
+
flexDirection: "column"
|
|
5309
|
+
},
|
|
5027
5310
|
main: {
|
|
5028
5311
|
flex: 1,
|
|
5029
5312
|
display: "flex",
|
|
@@ -5032,6 +5315,13 @@ var styles17 = {
|
|
|
5032
5315
|
padding: "12px",
|
|
5033
5316
|
backgroundColor: "#f3f4f6"
|
|
5034
5317
|
},
|
|
5318
|
+
mainCompact: {
|
|
5319
|
+
flex: 1,
|
|
5320
|
+
display: "flex",
|
|
5321
|
+
flexDirection: "column",
|
|
5322
|
+
minWidth: 0,
|
|
5323
|
+
backgroundColor: "#f3f4f6"
|
|
5324
|
+
},
|
|
5035
5325
|
panel: {
|
|
5036
5326
|
height: "100%",
|
|
5037
5327
|
width: "100%"
|