@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.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var React4 = require('react');
|
|
4
4
|
var phoenix = require('phoenix');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var reactDom = require('react-dom');
|
|
6
7
|
|
|
7
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
9
|
|
|
@@ -1150,71 +1151,190 @@ function useDeepLinks() {
|
|
|
1150
1151
|
function escapeRegex(string) {
|
|
1151
1152
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1152
1153
|
}
|
|
1154
|
+
function DicomIcon({ size = 18, color = "currentColor" }) {
|
|
1155
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1156
|
+
"svg",
|
|
1157
|
+
{
|
|
1158
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1159
|
+
width: size,
|
|
1160
|
+
height: size,
|
|
1161
|
+
viewBox: "0 0 24 24",
|
|
1162
|
+
fill: "none",
|
|
1163
|
+
stroke: color,
|
|
1164
|
+
strokeWidth: "2",
|
|
1165
|
+
strokeLinecap: "round",
|
|
1166
|
+
strokeLinejoin: "round",
|
|
1167
|
+
"aria-hidden": "true",
|
|
1168
|
+
children: [
|
|
1169
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "13", height: "13", rx: "2" }),
|
|
1170
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 7h13a2 2 0 0 1 2 2v11", opacity: "0.6" }),
|
|
1171
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9.5", r: "1.2", fill: color, stroke: "none" }),
|
|
1172
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 14l3-3 4 4 2-2 3 3" })
|
|
1173
|
+
]
|
|
1174
|
+
}
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
function SettingsIcon({ size = 18, color = "currentColor" }) {
|
|
1178
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1179
|
+
"svg",
|
|
1180
|
+
{
|
|
1181
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1182
|
+
width: size,
|
|
1183
|
+
height: size,
|
|
1184
|
+
viewBox: "0 0 24 24",
|
|
1185
|
+
fill: color,
|
|
1186
|
+
"aria-hidden": "true",
|
|
1187
|
+
children: /* @__PURE__ */ jsxRuntime.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" })
|
|
1188
|
+
}
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
function BackIcon({ size = 22, color = "currentColor" }) {
|
|
1192
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1193
|
+
"svg",
|
|
1194
|
+
{
|
|
1195
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1196
|
+
width: size,
|
|
1197
|
+
height: size,
|
|
1198
|
+
viewBox: "0 0 24 24",
|
|
1199
|
+
fill: color,
|
|
1200
|
+
"aria-hidden": "true",
|
|
1201
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" })
|
|
1202
|
+
}
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1153
1205
|
function PatientHeader({
|
|
1154
1206
|
patientData,
|
|
1155
1207
|
onOpenDicom,
|
|
1156
1208
|
onOpenSettings,
|
|
1209
|
+
onBack,
|
|
1157
1210
|
className
|
|
1158
1211
|
}) {
|
|
1159
1212
|
const hasDicom = !!(patientData.studyId && patientData.storageId);
|
|
1213
|
+
const meta = [];
|
|
1214
|
+
if (patientData.patientAge) meta.push({ label: "Age", value: String(patientData.patientAge) });
|
|
1215
|
+
if (patientData.patientSex) meta.push({ label: "Sex", value: String(patientData.patientSex) });
|
|
1216
|
+
if (patientData.studyType) meta.push({ label: "Modality", value: patientData.studyType });
|
|
1217
|
+
if (patientData.bodyParts && patientData.bodyParts.length > 0) {
|
|
1218
|
+
meta.push({ label: "Body part", value: patientData.bodyParts.join(", ") });
|
|
1219
|
+
}
|
|
1220
|
+
if (patientData.referringPhysician) {
|
|
1221
|
+
meta.push({ label: "Ref", value: patientData.referringPhysician });
|
|
1222
|
+
}
|
|
1160
1223
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles.container, children: [
|
|
1161
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1224
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.nameRow, children: [
|
|
1225
|
+
onBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1226
|
+
"button",
|
|
1227
|
+
{
|
|
1228
|
+
type: "button",
|
|
1229
|
+
onClick: onBack,
|
|
1230
|
+
style: styles.backButton,
|
|
1231
|
+
"aria-label": "Back to conversations",
|
|
1232
|
+
title: "Back to conversations",
|
|
1233
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(BackIcon, { size: 22, color: "#1f2937" })
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.nameText, children: buildChannelName(patientData) })
|
|
1173
1237
|
] }),
|
|
1174
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1238
|
+
meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.metaRow, children: meta.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles.metaItem, children: [
|
|
1239
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles.metaLabel, children: [
|
|
1240
|
+
item.label,
|
|
1241
|
+
":"
|
|
1242
|
+
] }),
|
|
1243
|
+
" ",
|
|
1244
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.metaValue, children: item.value })
|
|
1245
|
+
] }, item.label)) }),
|
|
1246
|
+
hasDicom && onOpenDicom || onOpenSettings ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.actions, children: [
|
|
1247
|
+
hasDicom && onOpenDicom && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1248
|
+
"button",
|
|
1249
|
+
{
|
|
1250
|
+
onClick: onOpenDicom,
|
|
1251
|
+
style: styles.dicomButton,
|
|
1252
|
+
type: "button",
|
|
1253
|
+
"aria-label": "View DICOM study",
|
|
1254
|
+
children: [
|
|
1255
|
+
/* @__PURE__ */ jsxRuntime.jsx(DicomIcon, { size: 18, color: "#ffffff" }),
|
|
1256
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "View DICOM" })
|
|
1257
|
+
]
|
|
1258
|
+
}
|
|
1259
|
+
),
|
|
1260
|
+
onOpenSettings && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1261
|
+
"button",
|
|
1262
|
+
{
|
|
1263
|
+
onClick: onOpenSettings,
|
|
1264
|
+
style: styles.settingsButton,
|
|
1265
|
+
type: "button",
|
|
1266
|
+
"aria-label": "Open channel settings",
|
|
1267
|
+
children: [
|
|
1268
|
+
/* @__PURE__ */ jsxRuntime.jsx(SettingsIcon, { size: 18, color: "#374151" }),
|
|
1269
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Settings" })
|
|
1270
|
+
]
|
|
1271
|
+
}
|
|
1272
|
+
)
|
|
1273
|
+
] }) : null
|
|
1178
1274
|
] });
|
|
1179
1275
|
}
|
|
1180
1276
|
var styles = {
|
|
1181
1277
|
container: {
|
|
1182
|
-
padding: "
|
|
1278
|
+
padding: "14px 16px",
|
|
1183
1279
|
borderBottom: "1px solid #e5e7eb",
|
|
1184
1280
|
backgroundColor: "#f9fafb"
|
|
1185
1281
|
},
|
|
1186
|
-
|
|
1282
|
+
nameRow: {
|
|
1187
1283
|
display: "flex",
|
|
1188
|
-
|
|
1189
|
-
|
|
1284
|
+
alignItems: "center",
|
|
1285
|
+
gap: "6px"
|
|
1190
1286
|
},
|
|
1191
|
-
|
|
1287
|
+
backButton: {
|
|
1288
|
+
width: "36px",
|
|
1289
|
+
height: "36px",
|
|
1192
1290
|
display: "flex",
|
|
1193
1291
|
alignItems: "center",
|
|
1194
|
-
|
|
1195
|
-
|
|
1292
|
+
justifyContent: "center",
|
|
1293
|
+
marginLeft: "-8px",
|
|
1294
|
+
backgroundColor: "transparent",
|
|
1295
|
+
border: "none",
|
|
1296
|
+
borderRadius: "50%",
|
|
1297
|
+
cursor: "pointer",
|
|
1298
|
+
flexShrink: 0
|
|
1196
1299
|
},
|
|
1197
|
-
|
|
1300
|
+
nameText: {
|
|
1301
|
+
fontSize: "18px",
|
|
1198
1302
|
fontWeight: 600,
|
|
1199
|
-
|
|
1200
|
-
|
|
1303
|
+
color: "#111827",
|
|
1304
|
+
lineHeight: 1.3,
|
|
1305
|
+
minWidth: 0,
|
|
1306
|
+
overflow: "hidden",
|
|
1307
|
+
textOverflow: "ellipsis",
|
|
1308
|
+
whiteSpace: "nowrap"
|
|
1201
1309
|
},
|
|
1202
|
-
|
|
1310
|
+
metaRow: {
|
|
1203
1311
|
display: "flex",
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1312
|
+
flexWrap: "wrap",
|
|
1313
|
+
columnGap: "14px",
|
|
1314
|
+
rowGap: "4px",
|
|
1315
|
+
marginTop: "6px"
|
|
1207
1316
|
},
|
|
1208
|
-
|
|
1317
|
+
metaItem: {
|
|
1209
1318
|
fontSize: "13px",
|
|
1210
|
-
color: "#
|
|
1319
|
+
color: "#374151",
|
|
1320
|
+
whiteSpace: "nowrap"
|
|
1321
|
+
},
|
|
1322
|
+
metaLabel: {
|
|
1323
|
+
color: "#6b7280",
|
|
1324
|
+
fontWeight: 500
|
|
1325
|
+
},
|
|
1326
|
+
metaValue: {
|
|
1327
|
+
color: "#111827"
|
|
1211
1328
|
},
|
|
1212
1329
|
actions: {
|
|
1213
1330
|
display: "flex",
|
|
1214
1331
|
gap: "8px",
|
|
1215
|
-
marginTop: "
|
|
1332
|
+
marginTop: "10px"
|
|
1216
1333
|
},
|
|
1217
1334
|
dicomButton: {
|
|
1335
|
+
display: "inline-flex",
|
|
1336
|
+
alignItems: "center",
|
|
1337
|
+
gap: "8px",
|
|
1218
1338
|
minHeight: "40px",
|
|
1219
1339
|
padding: "8px 16px",
|
|
1220
1340
|
fontSize: "14px",
|
|
@@ -1226,6 +1346,9 @@ var styles = {
|
|
|
1226
1346
|
cursor: "pointer"
|
|
1227
1347
|
},
|
|
1228
1348
|
settingsButton: {
|
|
1349
|
+
display: "inline-flex",
|
|
1350
|
+
alignItems: "center",
|
|
1351
|
+
gap: "8px",
|
|
1229
1352
|
minHeight: "40px",
|
|
1230
1353
|
padding: "8px 16px",
|
|
1231
1354
|
fontSize: "14px",
|
|
@@ -1442,6 +1565,8 @@ function MoreIcon({ size = 18, color = "currentColor" }) {
|
|
|
1442
1565
|
}
|
|
1443
1566
|
);
|
|
1444
1567
|
}
|
|
1568
|
+
var VIEWPORT_MARGIN = 8;
|
|
1569
|
+
var TRIGGER_GAP = 4;
|
|
1445
1570
|
function MessageActionsMenu({
|
|
1446
1571
|
message,
|
|
1447
1572
|
onReply,
|
|
@@ -1453,16 +1578,43 @@ function MessageActionsMenu({
|
|
|
1453
1578
|
className
|
|
1454
1579
|
}) {
|
|
1455
1580
|
const [isOpen, setIsOpen] = React4.useState(false);
|
|
1456
|
-
const
|
|
1581
|
+
const [coords, setCoords] = React4.useState(null);
|
|
1457
1582
|
const triggerRef = React4.useRef(null);
|
|
1583
|
+
const menuRef = React4.useRef(null);
|
|
1458
1584
|
const isPinned = !!message.isPinned;
|
|
1459
1585
|
const canCopy = message.type === "text" && !!message.body;
|
|
1586
|
+
React4.useLayoutEffect(() => {
|
|
1587
|
+
if (!isOpen) {
|
|
1588
|
+
setCoords(null);
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
const trigger = triggerRef.current;
|
|
1592
|
+
const menu2 = menuRef.current;
|
|
1593
|
+
if (!trigger || !menu2) return;
|
|
1594
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
1595
|
+
const menuRect = menu2.getBoundingClientRect();
|
|
1596
|
+
const vw = window.innerWidth;
|
|
1597
|
+
const vh = window.innerHeight;
|
|
1598
|
+
const spaceBelow = vh - triggerRect.bottom;
|
|
1599
|
+
const spaceAbove = triggerRect.top;
|
|
1600
|
+
const placeAbove = spaceBelow < menuRect.height + TRIGGER_GAP + VIEWPORT_MARGIN && spaceAbove > spaceBelow;
|
|
1601
|
+
const top = placeAbove ? triggerRect.top - menuRect.height - TRIGGER_GAP : triggerRect.bottom + TRIGGER_GAP;
|
|
1602
|
+
const preferredLeft = anchorRight ? triggerRect.right - menuRect.width : triggerRect.left;
|
|
1603
|
+
const left = Math.max(
|
|
1604
|
+
VIEWPORT_MARGIN,
|
|
1605
|
+
Math.min(preferredLeft, vw - menuRect.width - VIEWPORT_MARGIN)
|
|
1606
|
+
);
|
|
1607
|
+
const clampedTop = Math.max(
|
|
1608
|
+
VIEWPORT_MARGIN,
|
|
1609
|
+
Math.min(top, vh - menuRect.height - VIEWPORT_MARGIN)
|
|
1610
|
+
);
|
|
1611
|
+
setCoords({ top: clampedTop, left });
|
|
1612
|
+
}, [isOpen, anchorRight]);
|
|
1460
1613
|
React4.useEffect(() => {
|
|
1461
1614
|
if (!isOpen) return;
|
|
1615
|
+
const isInside = (node) => !!node && (triggerRef.current?.contains(node) === true || menuRef.current?.contains(node) === true);
|
|
1462
1616
|
const handleClick = (e) => {
|
|
1463
|
-
if (!
|
|
1464
|
-
setIsOpen(false);
|
|
1465
|
-
}
|
|
1617
|
+
if (!isInside(e.target)) setIsOpen(false);
|
|
1466
1618
|
};
|
|
1467
1619
|
const handleKey = (e) => {
|
|
1468
1620
|
if (e.key === "Escape") {
|
|
@@ -1470,18 +1622,100 @@ function MessageActionsMenu({
|
|
|
1470
1622
|
triggerRef.current?.focus();
|
|
1471
1623
|
}
|
|
1472
1624
|
};
|
|
1625
|
+
const handleScroll = (e) => {
|
|
1626
|
+
if (!isInside(e.target)) setIsOpen(false);
|
|
1627
|
+
};
|
|
1628
|
+
const handleResize = () => setIsOpen(false);
|
|
1473
1629
|
document.addEventListener("mousedown", handleClick);
|
|
1474
1630
|
document.addEventListener("keydown", handleKey);
|
|
1631
|
+
window.addEventListener("resize", handleResize);
|
|
1632
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
1475
1633
|
return () => {
|
|
1476
1634
|
document.removeEventListener("mousedown", handleClick);
|
|
1477
1635
|
document.removeEventListener("keydown", handleKey);
|
|
1636
|
+
window.removeEventListener("resize", handleResize);
|
|
1637
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
1478
1638
|
};
|
|
1479
1639
|
}, [isOpen]);
|
|
1480
1640
|
const run = (fn) => {
|
|
1481
1641
|
setIsOpen(false);
|
|
1482
1642
|
fn();
|
|
1483
1643
|
};
|
|
1484
|
-
|
|
1644
|
+
const menu = isOpen ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1645
|
+
"div",
|
|
1646
|
+
{
|
|
1647
|
+
ref: menuRef,
|
|
1648
|
+
role: "menu",
|
|
1649
|
+
"aria-label": "Message actions",
|
|
1650
|
+
style: {
|
|
1651
|
+
...styles4.menu,
|
|
1652
|
+
// Render off-screen on first paint so we can measure before placing,
|
|
1653
|
+
// then snap to computed coords on the next layout pass.
|
|
1654
|
+
top: coords?.top ?? -9999,
|
|
1655
|
+
left: coords?.left ?? -9999,
|
|
1656
|
+
visibility: coords ? "visible" : "hidden"
|
|
1657
|
+
},
|
|
1658
|
+
children: [
|
|
1659
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1660
|
+
"button",
|
|
1661
|
+
{
|
|
1662
|
+
type: "button",
|
|
1663
|
+
role: "menuitem",
|
|
1664
|
+
onClick: () => run(() => onReply(message)),
|
|
1665
|
+
style: styles4.item,
|
|
1666
|
+
children: [
|
|
1667
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReplyIcon, { size: 18, color: "#374151" }),
|
|
1668
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reply" })
|
|
1669
|
+
]
|
|
1670
|
+
}
|
|
1671
|
+
),
|
|
1672
|
+
isPinned ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1673
|
+
"button",
|
|
1674
|
+
{
|
|
1675
|
+
type: "button",
|
|
1676
|
+
role: "menuitem",
|
|
1677
|
+
onClick: () => run(() => onUnpin(message.id)),
|
|
1678
|
+
style: styles4.item,
|
|
1679
|
+
children: [
|
|
1680
|
+
/* @__PURE__ */ jsxRuntime.jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1681
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Unpin" })
|
|
1682
|
+
]
|
|
1683
|
+
}
|
|
1684
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1685
|
+
"button",
|
|
1686
|
+
{
|
|
1687
|
+
type: "button",
|
|
1688
|
+
role: "menuitem",
|
|
1689
|
+
onClick: () => run(() => onPin(message.id)),
|
|
1690
|
+
disabled: pinDisabled,
|
|
1691
|
+
style: {
|
|
1692
|
+
...styles4.item,
|
|
1693
|
+
...pinDisabled ? styles4.itemDisabled : {}
|
|
1694
|
+
},
|
|
1695
|
+
title: pinDisabled ? "Pin limit reached (max 3)" : void 0,
|
|
1696
|
+
children: [
|
|
1697
|
+
/* @__PURE__ */ jsxRuntime.jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1698
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: pinDisabled ? "Pin (limit reached)" : "Pin" })
|
|
1699
|
+
]
|
|
1700
|
+
}
|
|
1701
|
+
),
|
|
1702
|
+
canCopy && onCopy && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1703
|
+
"button",
|
|
1704
|
+
{
|
|
1705
|
+
type: "button",
|
|
1706
|
+
role: "menuitem",
|
|
1707
|
+
onClick: () => run(() => onCopy(message.body)),
|
|
1708
|
+
style: styles4.item,
|
|
1709
|
+
children: [
|
|
1710
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16, color: "#374151" }),
|
|
1711
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copy text" })
|
|
1712
|
+
]
|
|
1713
|
+
}
|
|
1714
|
+
)
|
|
1715
|
+
]
|
|
1716
|
+
}
|
|
1717
|
+
) : null;
|
|
1718
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles4.wrapper, children: [
|
|
1485
1719
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1486
1720
|
"button",
|
|
1487
1721
|
{
|
|
@@ -1499,75 +1733,7 @@ function MessageActionsMenu({
|
|
|
1499
1733
|
children: /* @__PURE__ */ jsxRuntime.jsx(MoreIcon, { size: 18, color: "#4b5563" })
|
|
1500
1734
|
}
|
|
1501
1735
|
),
|
|
1502
|
-
|
|
1503
|
-
"div",
|
|
1504
|
-
{
|
|
1505
|
-
role: "menu",
|
|
1506
|
-
"aria-label": "Message actions",
|
|
1507
|
-
style: {
|
|
1508
|
-
...styles4.menu,
|
|
1509
|
-
...anchorRight ? styles4.menuRight : styles4.menuLeft
|
|
1510
|
-
},
|
|
1511
|
-
children: [
|
|
1512
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1513
|
-
"button",
|
|
1514
|
-
{
|
|
1515
|
-
type: "button",
|
|
1516
|
-
role: "menuitem",
|
|
1517
|
-
onClick: () => run(() => onReply(message)),
|
|
1518
|
-
style: styles4.item,
|
|
1519
|
-
children: [
|
|
1520
|
-
/* @__PURE__ */ jsxRuntime.jsx(ReplyIcon, { size: 18, color: "#374151" }),
|
|
1521
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reply" })
|
|
1522
|
-
]
|
|
1523
|
-
}
|
|
1524
|
-
),
|
|
1525
|
-
isPinned ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1526
|
-
"button",
|
|
1527
|
-
{
|
|
1528
|
-
type: "button",
|
|
1529
|
-
role: "menuitem",
|
|
1530
|
-
onClick: () => run(() => onUnpin(message.id)),
|
|
1531
|
-
style: styles4.item,
|
|
1532
|
-
children: [
|
|
1533
|
-
/* @__PURE__ */ jsxRuntime.jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1534
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Unpin" })
|
|
1535
|
-
]
|
|
1536
|
-
}
|
|
1537
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1538
|
-
"button",
|
|
1539
|
-
{
|
|
1540
|
-
type: "button",
|
|
1541
|
-
role: "menuitem",
|
|
1542
|
-
onClick: () => run(() => onPin(message.id)),
|
|
1543
|
-
disabled: pinDisabled,
|
|
1544
|
-
style: {
|
|
1545
|
-
...styles4.item,
|
|
1546
|
-
...pinDisabled ? styles4.itemDisabled : {}
|
|
1547
|
-
},
|
|
1548
|
-
title: pinDisabled ? "Pin limit reached (max 3)" : void 0,
|
|
1549
|
-
children: [
|
|
1550
|
-
/* @__PURE__ */ jsxRuntime.jsx(PinIcon, { size: 16, color: "#374151" }),
|
|
1551
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: pinDisabled ? "Pin (limit reached)" : "Pin" })
|
|
1552
|
-
]
|
|
1553
|
-
}
|
|
1554
|
-
),
|
|
1555
|
-
canCopy && onCopy && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1556
|
-
"button",
|
|
1557
|
-
{
|
|
1558
|
-
type: "button",
|
|
1559
|
-
role: "menuitem",
|
|
1560
|
-
onClick: () => run(() => onCopy(message.body)),
|
|
1561
|
-
style: styles4.item,
|
|
1562
|
-
children: [
|
|
1563
|
-
/* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16, color: "#374151" }),
|
|
1564
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Copy text" })
|
|
1565
|
-
]
|
|
1566
|
-
}
|
|
1567
|
-
)
|
|
1568
|
-
]
|
|
1569
|
-
}
|
|
1570
|
-
)
|
|
1736
|
+
menu && typeof document !== "undefined" ? reactDom.createPortal(menu, document.body) : null
|
|
1571
1737
|
] });
|
|
1572
1738
|
}
|
|
1573
1739
|
var styles4 = {
|
|
@@ -1588,22 +1754,15 @@ var styles4 = {
|
|
|
1588
1754
|
color: "#4b5563"
|
|
1589
1755
|
},
|
|
1590
1756
|
menu: {
|
|
1591
|
-
position: "
|
|
1592
|
-
top: "100%",
|
|
1593
|
-
marginTop: "4px",
|
|
1757
|
+
position: "fixed",
|
|
1594
1758
|
minWidth: "160px",
|
|
1595
1759
|
backgroundColor: "#ffffff",
|
|
1596
1760
|
border: "1px solid #e5e7eb",
|
|
1597
1761
|
borderRadius: "10px",
|
|
1598
1762
|
boxShadow: "0 6px 18px rgba(0, 0, 0, 0.12)",
|
|
1599
1763
|
padding: "4px",
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
menuLeft: {
|
|
1603
|
-
left: 0
|
|
1604
|
-
},
|
|
1605
|
-
menuRight: {
|
|
1606
|
-
right: 0
|
|
1764
|
+
// Above the floating popup (z-index 9999) but below any future modal.
|
|
1765
|
+
zIndex: 1e4
|
|
1607
1766
|
},
|
|
1608
1767
|
item: {
|
|
1609
1768
|
display: "flex",
|
|
@@ -2256,31 +2415,34 @@ var MessageList = React4.forwardRef(function MessageList2({
|
|
|
2256
2415
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation \u2014 everyone on this case will see what you write." })
|
|
2257
2416
|
] }),
|
|
2258
2417
|
messages.length === 0 && isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles6.firstLoad, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 20 }) }),
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2266
|
-
|
|
2267
|
-
{
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2418
|
+
(() => {
|
|
2419
|
+
let lastValidBucket = null;
|
|
2420
|
+
return messages.map((message) => {
|
|
2421
|
+
const currentBucket = dayBucketKey(message.insertedAt);
|
|
2422
|
+
const showDivider = !!currentBucket && currentBucket !== lastValidBucket;
|
|
2423
|
+
if (currentBucket) lastValidBucket = currentBucket;
|
|
2424
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React4__default.default.Fragment, { children: [
|
|
2425
|
+
showDivider && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles6.dayDivider, role: "separator", "aria-label": "Date", children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles6.dayDividerPill, children: formatDayDivider(message.insertedAt) }) }),
|
|
2426
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-message-id": message.id, "data-natoe-message-bubble": true, style: styles6.bubbleSlot, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2427
|
+
MessageBubble,
|
|
2428
|
+
{
|
|
2429
|
+
message,
|
|
2430
|
+
isOwn: message.senderId === currentUserId,
|
|
2431
|
+
participants,
|
|
2432
|
+
currentUserId,
|
|
2433
|
+
showSeenBy,
|
|
2434
|
+
onDeepLinkClick,
|
|
2435
|
+
onReply,
|
|
2436
|
+
onPin,
|
|
2437
|
+
onUnpin,
|
|
2438
|
+
onCopy,
|
|
2439
|
+
onRetry,
|
|
2440
|
+
pinDisabled
|
|
2441
|
+
}
|
|
2442
|
+
) })
|
|
2443
|
+
] }, message.id);
|
|
2444
|
+
});
|
|
2445
|
+
})(),
|
|
2284
2446
|
typingUsers.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles6.typingIndicator, children: [
|
|
2285
2447
|
typingUsers.map((t) => t.userName ?? "Someone").join(", "),
|
|
2286
2448
|
typingUsers.length === 1 ? " is " : " are ",
|
|
@@ -2360,7 +2522,11 @@ var styles6 = {
|
|
|
2360
2522
|
dayDivider: {
|
|
2361
2523
|
display: "flex",
|
|
2362
2524
|
justifyContent: "center",
|
|
2363
|
-
margin: "12px 0 8px"
|
|
2525
|
+
margin: "12px 0 8px",
|
|
2526
|
+
position: "sticky",
|
|
2527
|
+
top: "4px",
|
|
2528
|
+
zIndex: 1,
|
|
2529
|
+
pointerEvents: "none"
|
|
2364
2530
|
},
|
|
2365
2531
|
dayDividerPill: {
|
|
2366
2532
|
display: "inline-block",
|
|
@@ -2370,7 +2536,11 @@ var styles6 = {
|
|
|
2370
2536
|
color: "#334155",
|
|
2371
2537
|
backgroundColor: "#e2e8f0",
|
|
2372
2538
|
borderRadius: "12px",
|
|
2373
|
-
letterSpacing: "0.2px"
|
|
2539
|
+
letterSpacing: "0.2px",
|
|
2540
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.04)"
|
|
2541
|
+
},
|
|
2542
|
+
bubbleSlot: {
|
|
2543
|
+
animation: "natoe-colab-message-in 180ms ease-out"
|
|
2374
2544
|
}
|
|
2375
2545
|
};
|
|
2376
2546
|
function ReplyPreview({ message, onCancel, className }) {
|
|
@@ -2521,6 +2691,7 @@ function MessageInput({
|
|
|
2521
2691
|
}) {
|
|
2522
2692
|
const [text, setText] = React4.useState("");
|
|
2523
2693
|
const [isSending, setIsSending] = React4.useState(false);
|
|
2694
|
+
const [isUploading, setIsUploading] = React4.useState(false);
|
|
2524
2695
|
const [fileError, setFileError] = React4.useState(null);
|
|
2525
2696
|
const fileInputRef = React4.useRef(null);
|
|
2526
2697
|
const typingTimeoutRef = React4.useRef(null);
|
|
@@ -2584,10 +2755,12 @@ function MessageInput({
|
|
|
2584
2755
|
return;
|
|
2585
2756
|
}
|
|
2586
2757
|
setIsSending(true);
|
|
2758
|
+
setIsUploading(true);
|
|
2587
2759
|
try {
|
|
2588
2760
|
await onSendFile(file);
|
|
2589
2761
|
} finally {
|
|
2590
2762
|
setIsSending(false);
|
|
2763
|
+
setIsUploading(false);
|
|
2591
2764
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
2592
2765
|
}
|
|
2593
2766
|
},
|
|
@@ -2595,6 +2768,10 @@ function MessageInput({
|
|
|
2595
2768
|
);
|
|
2596
2769
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles8.container, children: [
|
|
2597
2770
|
replyTo && onCancelReply && /* @__PURE__ */ jsxRuntime.jsx(ReplyPreview, { message: replyTo, onCancel: onCancelReply }),
|
|
2771
|
+
isUploading && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles8.uploadBanner, children: [
|
|
2772
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles8.uploadSpinner }),
|
|
2773
|
+
"Uploading file\u2026"
|
|
2774
|
+
] }),
|
|
2598
2775
|
fileError && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles8.error, role: "alert", children: [
|
|
2599
2776
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles8.errorText, children: fileError }),
|
|
2600
2777
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2680,6 +2857,26 @@ var styles8 = {
|
|
|
2680
2857
|
borderTop: "1px solid #e5e7eb",
|
|
2681
2858
|
backgroundColor: "#ffffff"
|
|
2682
2859
|
},
|
|
2860
|
+
uploadBanner: {
|
|
2861
|
+
display: "flex",
|
|
2862
|
+
alignItems: "center",
|
|
2863
|
+
gap: "8px",
|
|
2864
|
+
padding: "6px 14px",
|
|
2865
|
+
fontSize: "12px",
|
|
2866
|
+
color: "#6b7280",
|
|
2867
|
+
backgroundColor: "#f9fafb",
|
|
2868
|
+
borderBottom: "1px solid #e5e7eb"
|
|
2869
|
+
},
|
|
2870
|
+
uploadSpinner: {
|
|
2871
|
+
display: "inline-block",
|
|
2872
|
+
width: "12px",
|
|
2873
|
+
height: "12px",
|
|
2874
|
+
border: "2px solid #d1d5db",
|
|
2875
|
+
borderTopColor: "#7c3aed",
|
|
2876
|
+
borderRadius: "50%",
|
|
2877
|
+
animation: "natoe-colab-spin 0.7s linear infinite",
|
|
2878
|
+
flexShrink: 0
|
|
2879
|
+
},
|
|
2683
2880
|
error: {
|
|
2684
2881
|
display: "flex",
|
|
2685
2882
|
alignItems: "center",
|
|
@@ -3422,11 +3619,52 @@ var styles12 = {
|
|
|
3422
3619
|
letterSpacing: "0.4px"
|
|
3423
3620
|
}
|
|
3424
3621
|
};
|
|
3622
|
+
|
|
3623
|
+
// src/core/styles.ts
|
|
3624
|
+
var FONT_STACK = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
3625
|
+
var ROOT_CLASS = "natoe-colab-root";
|
|
3626
|
+
var GLOBAL_STYLE_ID = "natoe-colab-global-styles";
|
|
3627
|
+
var GLOBAL_CSS = `
|
|
3628
|
+
@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }
|
|
3629
|
+
|
|
3630
|
+
@keyframes natoe-colab-message-in {
|
|
3631
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
3632
|
+
to { opacity: 1; transform: translateY(0); }
|
|
3633
|
+
}
|
|
3634
|
+
|
|
3635
|
+
/* High-contrast adjustments \u2014 older users on OS-level high-contrast mode
|
|
3636
|
+
get heavier borders and stronger text without losing the package look. */
|
|
3637
|
+
@media (prefers-contrast: more) {
|
|
3638
|
+
.${ROOT_CLASS} {
|
|
3639
|
+
color: #000000;
|
|
3640
|
+
}
|
|
3641
|
+
.${ROOT_CLASS} button {
|
|
3642
|
+
outline: 1px solid currentColor;
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3646
|
+
/* Honour reduced-motion preferences by killing entry animations. */
|
|
3647
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3648
|
+
.${ROOT_CLASS} [data-natoe-message-bubble] {
|
|
3649
|
+
animation: none !important;
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
`;
|
|
3653
|
+
function ensureGlobalStyles() {
|
|
3654
|
+
if (typeof document === "undefined") return;
|
|
3655
|
+
if (document.getElementById(GLOBAL_STYLE_ID)) return;
|
|
3656
|
+
const style = document.createElement("style");
|
|
3657
|
+
style.id = GLOBAL_STYLE_ID;
|
|
3658
|
+
style.textContent = GLOBAL_CSS;
|
|
3659
|
+
document.head.appendChild(style);
|
|
3660
|
+
}
|
|
3661
|
+
ensureGlobalStyles();
|
|
3425
3662
|
function CollabPanel({
|
|
3426
3663
|
orderId,
|
|
3427
3664
|
patientData,
|
|
3428
3665
|
participantIds,
|
|
3429
3666
|
showSeenBy = true,
|
|
3667
|
+
onBack,
|
|
3430
3668
|
className,
|
|
3431
3669
|
style
|
|
3432
3670
|
}) {
|
|
@@ -3500,13 +3738,13 @@ function CollabPanel({
|
|
|
3500
3738
|
};
|
|
3501
3739
|
const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;
|
|
3502
3740
|
if (error) {
|
|
3503
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: panelStyles.errorState, children: [
|
|
3741
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: panelStyles.errorState, children: [
|
|
3504
3742
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: panelStyles.errorTitle, children: "Unable to load conversation" }),
|
|
3505
3743
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: panelStyles.errorMessage, children: error })
|
|
3506
3744
|
] }) });
|
|
3507
3745
|
}
|
|
3508
3746
|
if (isLoading && !conversation) {
|
|
3509
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
|
|
3747
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
|
|
3510
3748
|
}
|
|
3511
3749
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...panelStyles.container, ...style }, children: [
|
|
3512
3750
|
showSettings && conversation ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3534,7 +3772,8 @@ function CollabPanel({
|
|
|
3534
3772
|
patientData,
|
|
3535
3773
|
participants,
|
|
3536
3774
|
onOpenDicom: handleOpenDicom,
|
|
3537
|
-
onOpenSettings: () => setShowSettings(true)
|
|
3775
|
+
onOpenSettings: () => setShowSettings(true),
|
|
3776
|
+
onBack
|
|
3538
3777
|
}
|
|
3539
3778
|
),
|
|
3540
3779
|
pinnedMessages.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3592,7 +3831,7 @@ var panelStyles = {
|
|
|
3592
3831
|
borderRadius: "8px",
|
|
3593
3832
|
overflow: "hidden",
|
|
3594
3833
|
border: "1px solid #e5e7eb",
|
|
3595
|
-
fontFamily:
|
|
3834
|
+
fontFamily: FONT_STACK
|
|
3596
3835
|
},
|
|
3597
3836
|
loadingState: {
|
|
3598
3837
|
display: "flex",
|
|
@@ -3651,6 +3890,7 @@ function ExpandIcon({ size = 18, color = "currentColor" }) {
|
|
|
3651
3890
|
}
|
|
3652
3891
|
);
|
|
3653
3892
|
}
|
|
3893
|
+
ensureGlobalStyles();
|
|
3654
3894
|
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
3655
3895
|
function CollabPopup({
|
|
3656
3896
|
orderId,
|
|
@@ -3752,7 +3992,7 @@ function CollabPopup({
|
|
|
3752
3992
|
"div",
|
|
3753
3993
|
{
|
|
3754
3994
|
ref: containerRef,
|
|
3755
|
-
className,
|
|
3995
|
+
className: [ROOT_CLASS, className].filter(Boolean).join(" "),
|
|
3756
3996
|
role: "dialog",
|
|
3757
3997
|
"aria-modal": "true",
|
|
3758
3998
|
"aria-labelledby": titleId,
|
|
@@ -3821,7 +4061,8 @@ var styles13 = {
|
|
|
3821
4061
|
flexDirection: "column",
|
|
3822
4062
|
backgroundColor: "#ffffff",
|
|
3823
4063
|
border: "1px solid #e5e7eb",
|
|
3824
|
-
transition: "height 0.2s ease"
|
|
4064
|
+
transition: "height 0.2s ease",
|
|
4065
|
+
fontFamily: FONT_STACK
|
|
3825
4066
|
},
|
|
3826
4067
|
titleBar: {
|
|
3827
4068
|
display: "flex",
|
|
@@ -4093,6 +4334,7 @@ function useInlineCollab({
|
|
|
4093
4334
|
containerRef
|
|
4094
4335
|
};
|
|
4095
4336
|
}
|
|
4337
|
+
ensureGlobalStyles();
|
|
4096
4338
|
function CollabInline({
|
|
4097
4339
|
orderId,
|
|
4098
4340
|
patientData,
|
|
@@ -4115,9 +4357,9 @@ function CollabInline({
|
|
|
4115
4357
|
containerRef
|
|
4116
4358
|
} = useInlineCollab({ orderId, patientData, participantIds, messageLimit });
|
|
4117
4359
|
if (isLoading && !hasConversation) {
|
|
4118
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
4360
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
4119
4361
|
}
|
|
4120
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className, style: { ...styles14.container, ...style }, children: [
|
|
4362
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...styles14.container, ...style }, children: [
|
|
4121
4363
|
hasConversation && messages.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles14.preview, children: messages.slice(-messageLimit).map((message) => /* @__PURE__ */ jsxRuntime.jsx(InlineMessageRow, { message }, message.id)) }),
|
|
4122
4364
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles14.error, children: error }),
|
|
4123
4365
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4333,7 +4575,7 @@ var styles14 = {
|
|
|
4333
4575
|
backgroundColor: "#ffffff",
|
|
4334
4576
|
border: "1px solid #e5e7eb",
|
|
4335
4577
|
borderRadius: "8px",
|
|
4336
|
-
fontFamily:
|
|
4578
|
+
fontFamily: FONT_STACK
|
|
4337
4579
|
},
|
|
4338
4580
|
loadingState: {
|
|
4339
4581
|
padding: "8px",
|
|
@@ -4963,6 +5205,8 @@ var styles16 = {
|
|
|
4963
5205
|
textAlign: "center"
|
|
4964
5206
|
}
|
|
4965
5207
|
};
|
|
5208
|
+
ensureGlobalStyles();
|
|
5209
|
+
var COMPACT_BREAKPOINT = 720;
|
|
4966
5210
|
function CollabInbox({
|
|
4967
5211
|
initialConversationId,
|
|
4968
5212
|
onSelectConversation,
|
|
@@ -4972,37 +5216,70 @@ function CollabInbox({
|
|
|
4972
5216
|
}) {
|
|
4973
5217
|
const { conversations, isLoading, error } = useConversationList();
|
|
4974
5218
|
const [selectedId, setSelectedId] = React4.useState(initialConversationId ?? null);
|
|
5219
|
+
const [isCompact, setIsCompact] = React4.useState(
|
|
5220
|
+
() => typeof window === "undefined" ? false : window.innerWidth < COMPACT_BREAKPOINT
|
|
5221
|
+
);
|
|
5222
|
+
React4.useEffect(() => {
|
|
5223
|
+
if (typeof window === "undefined") return;
|
|
5224
|
+
const mq = window.matchMedia(`(max-width: ${COMPACT_BREAKPOINT - 1}px)`);
|
|
5225
|
+
const sync = () => setIsCompact(mq.matches);
|
|
5226
|
+
sync();
|
|
5227
|
+
mq.addEventListener("change", sync);
|
|
5228
|
+
return () => mq.removeEventListener("change", sync);
|
|
5229
|
+
}, []);
|
|
4975
5230
|
const selected = conversations.find((c) => c.id === selectedId) || null;
|
|
4976
5231
|
const handleSelect = (item) => {
|
|
4977
5232
|
setSelectedId(item.id);
|
|
4978
5233
|
onSelectConversation?.(item);
|
|
4979
5234
|
};
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5235
|
+
const showDetail = !isCompact || isCompact && !!selected;
|
|
5236
|
+
const showList = !isCompact || isCompact && !selected;
|
|
5237
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5238
|
+
"div",
|
|
5239
|
+
{
|
|
5240
|
+
className: [ROOT_CLASS, className].filter(Boolean).join(" "),
|
|
5241
|
+
style: { ...styles17.container, ...style },
|
|
5242
|
+
children: [
|
|
5243
|
+
showList && /* @__PURE__ */ jsxRuntime.jsx("div", { style: isCompact ? styles17.sidebarCompact : styles17.sidebar, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5244
|
+
ConversationList,
|
|
5245
|
+
{
|
|
5246
|
+
conversations,
|
|
5247
|
+
selectedId,
|
|
5248
|
+
isLoading,
|
|
5249
|
+
error,
|
|
5250
|
+
onSelect: handleSelect,
|
|
5251
|
+
title
|
|
5252
|
+
}
|
|
5253
|
+
) }),
|
|
5254
|
+
showDetail && /* @__PURE__ */ jsxRuntime.jsx("div", { style: isCompact ? styles17.mainCompact : styles17.main, children: selected ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5255
|
+
CollabPanel,
|
|
5256
|
+
{
|
|
5257
|
+
orderId: selected.orderId,
|
|
5258
|
+
patientData: buildPatientData(selected),
|
|
5259
|
+
showSeenBy: true,
|
|
5260
|
+
style: styles17.panel,
|
|
5261
|
+
onBack: isCompact ? () => setSelectedId(null) : void 0
|
|
5262
|
+
},
|
|
5263
|
+
selected.id
|
|
5264
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { hasAny: conversations.length > 0 }) })
|
|
5265
|
+
]
|
|
5266
|
+
}
|
|
5267
|
+
);
|
|
5003
5268
|
}
|
|
5004
5269
|
function buildPatientData(item) {
|
|
5005
5270
|
if (item.patientSnapshot) return item.patientSnapshot;
|
|
5271
|
+
const parts = item.name.split(" - ");
|
|
5272
|
+
if (parts.length >= 3) {
|
|
5273
|
+
const last4 = parts[parts.length - 1];
|
|
5274
|
+
const labName = parts[parts.length - 2];
|
|
5275
|
+
const patientName = parts.slice(0, parts.length - 2).join(" - ");
|
|
5276
|
+
return {
|
|
5277
|
+
patientName,
|
|
5278
|
+
labName: labName || void 0,
|
|
5279
|
+
orderId: item.orderId,
|
|
5280
|
+
displayOrderId: last4
|
|
5281
|
+
};
|
|
5282
|
+
}
|
|
5006
5283
|
return {
|
|
5007
5284
|
patientName: item.name,
|
|
5008
5285
|
orderId: item.orderId
|
|
@@ -5021,7 +5298,7 @@ var styles17 = {
|
|
|
5021
5298
|
height: "100%",
|
|
5022
5299
|
width: "100%",
|
|
5023
5300
|
backgroundColor: "#ffffff",
|
|
5024
|
-
fontFamily:
|
|
5301
|
+
fontFamily: FONT_STACK
|
|
5025
5302
|
},
|
|
5026
5303
|
sidebar: {
|
|
5027
5304
|
width: "320px",
|
|
@@ -5030,6 +5307,12 @@ var styles17 = {
|
|
|
5030
5307
|
display: "flex",
|
|
5031
5308
|
flexDirection: "column"
|
|
5032
5309
|
},
|
|
5310
|
+
sidebarCompact: {
|
|
5311
|
+
width: "100%",
|
|
5312
|
+
flex: 1,
|
|
5313
|
+
display: "flex",
|
|
5314
|
+
flexDirection: "column"
|
|
5315
|
+
},
|
|
5033
5316
|
main: {
|
|
5034
5317
|
flex: 1,
|
|
5035
5318
|
display: "flex",
|
|
@@ -5038,6 +5321,13 @@ var styles17 = {
|
|
|
5038
5321
|
padding: "12px",
|
|
5039
5322
|
backgroundColor: "#f3f4f6"
|
|
5040
5323
|
},
|
|
5324
|
+
mainCompact: {
|
|
5325
|
+
flex: 1,
|
|
5326
|
+
display: "flex",
|
|
5327
|
+
flexDirection: "column",
|
|
5328
|
+
minWidth: 0,
|
|
5329
|
+
backgroundColor: "#f3f4f6"
|
|
5330
|
+
},
|
|
5041
5331
|
panel: {
|
|
5042
5332
|
height: "100%",
|
|
5043
5333
|
width: "100%"
|