@natoe/colab 0.1.5 → 0.1.7
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 +21 -13
- package/dist/index.d.ts +21 -13
- package/dist/index.js +452 -186
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +453 -187
- 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
|
|
|
@@ -370,7 +371,9 @@ function CollabProvider({ config, apiBaseUrl, children }) {
|
|
|
370
371
|
const data = snakeToCamel(await response.json());
|
|
371
372
|
orderIds.forEach((orderId) => {
|
|
372
373
|
const preview = data.previews[orderId] ?? null;
|
|
373
|
-
|
|
374
|
+
if (preview !== null) {
|
|
375
|
+
previewCache.current.set(orderId, preview);
|
|
376
|
+
}
|
|
374
377
|
resolvers.get(orderId)?.forEach((resolve) => resolve(preview));
|
|
375
378
|
});
|
|
376
379
|
} catch (error) {
|
|
@@ -417,7 +420,8 @@ function CollabProvider({ config, apiBaseUrl, children }) {
|
|
|
417
420
|
if (!response.ok) {
|
|
418
421
|
throw { code: "FETCH_ERROR", message: "Failed to fetch messages", status: response.status };
|
|
419
422
|
}
|
|
420
|
-
|
|
423
|
+
const msgs = snakeToCamel(await response.json());
|
|
424
|
+
return msgs.sort((a, b) => a.insertedAt.localeCompare(b.insertedAt));
|
|
421
425
|
},
|
|
422
426
|
[apiBaseUrl, authHeaders]
|
|
423
427
|
);
|
|
@@ -891,8 +895,8 @@ function useConversation({
|
|
|
891
895
|
const payload = {
|
|
892
896
|
body: "Voice message",
|
|
893
897
|
type: "audio",
|
|
894
|
-
|
|
895
|
-
|
|
898
|
+
media_url: url,
|
|
899
|
+
media_duration: duration
|
|
896
900
|
};
|
|
897
901
|
const { conv, persistedByCreate } = await ensureConversation(payload);
|
|
898
902
|
if (persistedByCreate) return;
|
|
@@ -908,8 +912,8 @@ function useConversation({
|
|
|
908
912
|
const payload = {
|
|
909
913
|
body: file.name,
|
|
910
914
|
type: isImage ? "image" : "file",
|
|
911
|
-
|
|
912
|
-
|
|
915
|
+
media_url: url,
|
|
916
|
+
file_name: file.name
|
|
913
917
|
};
|
|
914
918
|
const { conv, persistedByCreate } = await ensureConversation(payload);
|
|
915
919
|
if (persistedByCreate) return;
|
|
@@ -1141,71 +1145,190 @@ function useDeepLinks() {
|
|
|
1141
1145
|
function escapeRegex(string) {
|
|
1142
1146
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1143
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
|
+
}
|
|
1144
1199
|
function PatientHeader({
|
|
1145
1200
|
patientData,
|
|
1146
1201
|
onOpenDicom,
|
|
1147
1202
|
onOpenSettings,
|
|
1203
|
+
onBack,
|
|
1148
1204
|
className
|
|
1149
1205
|
}) {
|
|
1150
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
|
+
}
|
|
1151
1217
|
return /* @__PURE__ */ jsxs("div", { className, style: styles.container, children: [
|
|
1152
|
-
/* @__PURE__ */
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
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) })
|
|
1164
1231
|
] }),
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
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
|
|
1169
1268
|
] });
|
|
1170
1269
|
}
|
|
1171
1270
|
var styles = {
|
|
1172
1271
|
container: {
|
|
1173
|
-
padding: "
|
|
1272
|
+
padding: "14px 16px",
|
|
1174
1273
|
borderBottom: "1px solid #e5e7eb",
|
|
1175
1274
|
backgroundColor: "#f9fafb"
|
|
1176
1275
|
},
|
|
1177
|
-
|
|
1276
|
+
nameRow: {
|
|
1178
1277
|
display: "flex",
|
|
1179
|
-
|
|
1180
|
-
|
|
1278
|
+
alignItems: "center",
|
|
1279
|
+
gap: "6px"
|
|
1181
1280
|
},
|
|
1182
|
-
|
|
1281
|
+
backButton: {
|
|
1282
|
+
width: "36px",
|
|
1283
|
+
height: "36px",
|
|
1183
1284
|
display: "flex",
|
|
1184
1285
|
alignItems: "center",
|
|
1185
|
-
|
|
1186
|
-
|
|
1286
|
+
justifyContent: "center",
|
|
1287
|
+
marginLeft: "-8px",
|
|
1288
|
+
backgroundColor: "transparent",
|
|
1289
|
+
border: "none",
|
|
1290
|
+
borderRadius: "50%",
|
|
1291
|
+
cursor: "pointer",
|
|
1292
|
+
flexShrink: 0
|
|
1187
1293
|
},
|
|
1188
|
-
|
|
1294
|
+
nameText: {
|
|
1295
|
+
fontSize: "18px",
|
|
1189
1296
|
fontWeight: 600,
|
|
1190
|
-
|
|
1191
|
-
|
|
1297
|
+
color: "#111827",
|
|
1298
|
+
lineHeight: 1.3,
|
|
1299
|
+
minWidth: 0,
|
|
1300
|
+
overflow: "hidden",
|
|
1301
|
+
textOverflow: "ellipsis",
|
|
1302
|
+
whiteSpace: "nowrap"
|
|
1192
1303
|
},
|
|
1193
|
-
|
|
1304
|
+
metaRow: {
|
|
1194
1305
|
display: "flex",
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1306
|
+
flexWrap: "wrap",
|
|
1307
|
+
columnGap: "14px",
|
|
1308
|
+
rowGap: "4px",
|
|
1309
|
+
marginTop: "6px"
|
|
1198
1310
|
},
|
|
1199
|
-
|
|
1311
|
+
metaItem: {
|
|
1200
1312
|
fontSize: "13px",
|
|
1201
|
-
color: "#
|
|
1313
|
+
color: "#374151",
|
|
1314
|
+
whiteSpace: "nowrap"
|
|
1315
|
+
},
|
|
1316
|
+
metaLabel: {
|
|
1317
|
+
color: "#6b7280",
|
|
1318
|
+
fontWeight: 500
|
|
1319
|
+
},
|
|
1320
|
+
metaValue: {
|
|
1321
|
+
color: "#111827"
|
|
1202
1322
|
},
|
|
1203
1323
|
actions: {
|
|
1204
1324
|
display: "flex",
|
|
1205
1325
|
gap: "8px",
|
|
1206
|
-
marginTop: "
|
|
1326
|
+
marginTop: "10px"
|
|
1207
1327
|
},
|
|
1208
1328
|
dicomButton: {
|
|
1329
|
+
display: "inline-flex",
|
|
1330
|
+
alignItems: "center",
|
|
1331
|
+
gap: "8px",
|
|
1209
1332
|
minHeight: "40px",
|
|
1210
1333
|
padding: "8px 16px",
|
|
1211
1334
|
fontSize: "14px",
|
|
@@ -1217,6 +1340,9 @@ var styles = {
|
|
|
1217
1340
|
cursor: "pointer"
|
|
1218
1341
|
},
|
|
1219
1342
|
settingsButton: {
|
|
1343
|
+
display: "inline-flex",
|
|
1344
|
+
alignItems: "center",
|
|
1345
|
+
gap: "8px",
|
|
1220
1346
|
minHeight: "40px",
|
|
1221
1347
|
padding: "8px 16px",
|
|
1222
1348
|
fontSize: "14px",
|
|
@@ -1433,6 +1559,8 @@ function MoreIcon({ size = 18, color = "currentColor" }) {
|
|
|
1433
1559
|
}
|
|
1434
1560
|
);
|
|
1435
1561
|
}
|
|
1562
|
+
var VIEWPORT_MARGIN = 8;
|
|
1563
|
+
var TRIGGER_GAP = 4;
|
|
1436
1564
|
function MessageActionsMenu({
|
|
1437
1565
|
message,
|
|
1438
1566
|
onReply,
|
|
@@ -1444,16 +1572,43 @@ function MessageActionsMenu({
|
|
|
1444
1572
|
className
|
|
1445
1573
|
}) {
|
|
1446
1574
|
const [isOpen, setIsOpen] = useState(false);
|
|
1447
|
-
const
|
|
1575
|
+
const [coords, setCoords] = useState(null);
|
|
1448
1576
|
const triggerRef = useRef(null);
|
|
1577
|
+
const menuRef = useRef(null);
|
|
1449
1578
|
const isPinned = !!message.isPinned;
|
|
1450
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]);
|
|
1451
1607
|
useEffect(() => {
|
|
1452
1608
|
if (!isOpen) return;
|
|
1609
|
+
const isInside = (node) => !!node && (triggerRef.current?.contains(node) === true || menuRef.current?.contains(node) === true);
|
|
1453
1610
|
const handleClick = (e) => {
|
|
1454
|
-
if (!
|
|
1455
|
-
setIsOpen(false);
|
|
1456
|
-
}
|
|
1611
|
+
if (!isInside(e.target)) setIsOpen(false);
|
|
1457
1612
|
};
|
|
1458
1613
|
const handleKey = (e) => {
|
|
1459
1614
|
if (e.key === "Escape") {
|
|
@@ -1461,18 +1616,100 @@ function MessageActionsMenu({
|
|
|
1461
1616
|
triggerRef.current?.focus();
|
|
1462
1617
|
}
|
|
1463
1618
|
};
|
|
1619
|
+
const handleScroll = (e) => {
|
|
1620
|
+
if (!isInside(e.target)) setIsOpen(false);
|
|
1621
|
+
};
|
|
1622
|
+
const handleResize = () => setIsOpen(false);
|
|
1464
1623
|
document.addEventListener("mousedown", handleClick);
|
|
1465
1624
|
document.addEventListener("keydown", handleKey);
|
|
1625
|
+
window.addEventListener("resize", handleResize);
|
|
1626
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
1466
1627
|
return () => {
|
|
1467
1628
|
document.removeEventListener("mousedown", handleClick);
|
|
1468
1629
|
document.removeEventListener("keydown", handleKey);
|
|
1630
|
+
window.removeEventListener("resize", handleResize);
|
|
1631
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
1469
1632
|
};
|
|
1470
1633
|
}, [isOpen]);
|
|
1471
1634
|
const run = (fn) => {
|
|
1472
1635
|
setIsOpen(false);
|
|
1473
1636
|
fn();
|
|
1474
1637
|
};
|
|
1475
|
-
|
|
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: [
|
|
1476
1713
|
/* @__PURE__ */ jsx(
|
|
1477
1714
|
"button",
|
|
1478
1715
|
{
|
|
@@ -1490,75 +1727,7 @@ function MessageActionsMenu({
|
|
|
1490
1727
|
children: /* @__PURE__ */ jsx(MoreIcon, { size: 18, color: "#4b5563" })
|
|
1491
1728
|
}
|
|
1492
1729
|
),
|
|
1493
|
-
|
|
1494
|
-
"div",
|
|
1495
|
-
{
|
|
1496
|
-
role: "menu",
|
|
1497
|
-
"aria-label": "Message actions",
|
|
1498
|
-
style: {
|
|
1499
|
-
...styles4.menu,
|
|
1500
|
-
...anchorRight ? styles4.menuRight : styles4.menuLeft
|
|
1501
|
-
},
|
|
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
|
-
]
|
|
1560
|
-
}
|
|
1561
|
-
)
|
|
1730
|
+
menu && typeof document !== "undefined" ? createPortal(menu, document.body) : null
|
|
1562
1731
|
] });
|
|
1563
1732
|
}
|
|
1564
1733
|
var styles4 = {
|
|
@@ -1579,22 +1748,15 @@ var styles4 = {
|
|
|
1579
1748
|
color: "#4b5563"
|
|
1580
1749
|
},
|
|
1581
1750
|
menu: {
|
|
1582
|
-
position: "
|
|
1583
|
-
top: "100%",
|
|
1584
|
-
marginTop: "4px",
|
|
1751
|
+
position: "fixed",
|
|
1585
1752
|
minWidth: "160px",
|
|
1586
1753
|
backgroundColor: "#ffffff",
|
|
1587
1754
|
border: "1px solid #e5e7eb",
|
|
1588
1755
|
borderRadius: "10px",
|
|
1589
1756
|
boxShadow: "0 6px 18px rgba(0, 0, 0, 0.12)",
|
|
1590
1757
|
padding: "4px",
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
menuLeft: {
|
|
1594
|
-
left: 0
|
|
1595
|
-
},
|
|
1596
|
-
menuRight: {
|
|
1597
|
-
right: 0
|
|
1758
|
+
// Above the floating popup (z-index 9999) but below any future modal.
|
|
1759
|
+
zIndex: 1e4
|
|
1598
1760
|
},
|
|
1599
1761
|
item: {
|
|
1600
1762
|
display: "flex",
|
|
@@ -2247,31 +2409,34 @@ var MessageList = forwardRef(function MessageList2({
|
|
|
2247
2409
|
/* @__PURE__ */ jsx("p", { style: styles6.emptySubtitle, children: "Start the conversation \u2014 everyone on this case will see what you write." })
|
|
2248
2410
|
] }),
|
|
2249
2411
|
messages.length === 0 && isLoading && /* @__PURE__ */ jsx("div", { style: styles6.firstLoad, children: /* @__PURE__ */ jsx(Spinner, { size: 20 }) }),
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
/* @__PURE__ */
|
|
2257
|
-
|
|
2258
|
-
{
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
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
|
+
})(),
|
|
2275
2440
|
typingUsers.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles6.typingIndicator, children: [
|
|
2276
2441
|
typingUsers.map((t) => t.userName ?? "Someone").join(", "),
|
|
2277
2442
|
typingUsers.length === 1 ? " is " : " are ",
|
|
@@ -2351,7 +2516,11 @@ var styles6 = {
|
|
|
2351
2516
|
dayDivider: {
|
|
2352
2517
|
display: "flex",
|
|
2353
2518
|
justifyContent: "center",
|
|
2354
|
-
margin: "12px 0 8px"
|
|
2519
|
+
margin: "12px 0 8px",
|
|
2520
|
+
position: "sticky",
|
|
2521
|
+
top: "4px",
|
|
2522
|
+
zIndex: 1,
|
|
2523
|
+
pointerEvents: "none"
|
|
2355
2524
|
},
|
|
2356
2525
|
dayDividerPill: {
|
|
2357
2526
|
display: "inline-block",
|
|
@@ -2361,7 +2530,11 @@ var styles6 = {
|
|
|
2361
2530
|
color: "#334155",
|
|
2362
2531
|
backgroundColor: "#e2e8f0",
|
|
2363
2532
|
borderRadius: "12px",
|
|
2364
|
-
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"
|
|
2365
2538
|
}
|
|
2366
2539
|
};
|
|
2367
2540
|
function ReplyPreview({ message, onCancel, className }) {
|
|
@@ -3413,11 +3586,52 @@ var styles12 = {
|
|
|
3413
3586
|
letterSpacing: "0.4px"
|
|
3414
3587
|
}
|
|
3415
3588
|
};
|
|
3589
|
+
|
|
3590
|
+
// src/core/styles.ts
|
|
3591
|
+
var FONT_STACK = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
3592
|
+
var ROOT_CLASS = "natoe-colab-root";
|
|
3593
|
+
var GLOBAL_STYLE_ID = "natoe-colab-global-styles";
|
|
3594
|
+
var GLOBAL_CSS = `
|
|
3595
|
+
@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }
|
|
3596
|
+
|
|
3597
|
+
@keyframes natoe-colab-message-in {
|
|
3598
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
3599
|
+
to { opacity: 1; transform: translateY(0); }
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
/* High-contrast adjustments \u2014 older users on OS-level high-contrast mode
|
|
3603
|
+
get heavier borders and stronger text without losing the package look. */
|
|
3604
|
+
@media (prefers-contrast: more) {
|
|
3605
|
+
.${ROOT_CLASS} {
|
|
3606
|
+
color: #000000;
|
|
3607
|
+
}
|
|
3608
|
+
.${ROOT_CLASS} button {
|
|
3609
|
+
outline: 1px solid currentColor;
|
|
3610
|
+
}
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
/* Honour reduced-motion preferences by killing entry animations. */
|
|
3614
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3615
|
+
.${ROOT_CLASS} [data-natoe-message-bubble] {
|
|
3616
|
+
animation: none !important;
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
`;
|
|
3620
|
+
function ensureGlobalStyles() {
|
|
3621
|
+
if (typeof document === "undefined") return;
|
|
3622
|
+
if (document.getElementById(GLOBAL_STYLE_ID)) return;
|
|
3623
|
+
const style = document.createElement("style");
|
|
3624
|
+
style.id = GLOBAL_STYLE_ID;
|
|
3625
|
+
style.textContent = GLOBAL_CSS;
|
|
3626
|
+
document.head.appendChild(style);
|
|
3627
|
+
}
|
|
3628
|
+
ensureGlobalStyles();
|
|
3416
3629
|
function CollabPanel({
|
|
3417
3630
|
orderId,
|
|
3418
3631
|
patientData,
|
|
3419
3632
|
participantIds,
|
|
3420
3633
|
showSeenBy = true,
|
|
3634
|
+
onBack,
|
|
3421
3635
|
className,
|
|
3422
3636
|
style
|
|
3423
3637
|
}) {
|
|
@@ -3491,13 +3705,13 @@ function CollabPanel({
|
|
|
3491
3705
|
};
|
|
3492
3706
|
const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;
|
|
3493
3707
|
if (error) {
|
|
3494
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxs("div", { style: panelStyles.errorState, children: [
|
|
3708
|
+
return /* @__PURE__ */ jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsxs("div", { style: panelStyles.errorState, children: [
|
|
3495
3709
|
/* @__PURE__ */ jsx("p", { style: panelStyles.errorTitle, children: "Unable to load conversation" }),
|
|
3496
3710
|
/* @__PURE__ */ jsx("p", { style: panelStyles.errorMessage, children: error })
|
|
3497
3711
|
] }) });
|
|
3498
3712
|
}
|
|
3499
3713
|
if (isLoading && !conversation) {
|
|
3500
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...panelStyles.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: panelStyles.loadingState, children: "Loading conversation..." }) });
|
|
3714
|
+
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..." }) });
|
|
3501
3715
|
}
|
|
3502
3716
|
return /* @__PURE__ */ jsxs("div", { className, style: { ...panelStyles.container, ...style }, children: [
|
|
3503
3717
|
showSettings && conversation ? /* @__PURE__ */ jsx(
|
|
@@ -3525,7 +3739,8 @@ function CollabPanel({
|
|
|
3525
3739
|
patientData,
|
|
3526
3740
|
participants,
|
|
3527
3741
|
onOpenDicom: handleOpenDicom,
|
|
3528
|
-
onOpenSettings: () => setShowSettings(true)
|
|
3742
|
+
onOpenSettings: () => setShowSettings(true),
|
|
3743
|
+
onBack
|
|
3529
3744
|
}
|
|
3530
3745
|
),
|
|
3531
3746
|
pinnedMessages.length > 0 && /* @__PURE__ */ jsx(
|
|
@@ -3583,7 +3798,7 @@ var panelStyles = {
|
|
|
3583
3798
|
borderRadius: "8px",
|
|
3584
3799
|
overflow: "hidden",
|
|
3585
3800
|
border: "1px solid #e5e7eb",
|
|
3586
|
-
fontFamily:
|
|
3801
|
+
fontFamily: FONT_STACK
|
|
3587
3802
|
},
|
|
3588
3803
|
loadingState: {
|
|
3589
3804
|
display: "flex",
|
|
@@ -3642,6 +3857,7 @@ function ExpandIcon({ size = 18, color = "currentColor" }) {
|
|
|
3642
3857
|
}
|
|
3643
3858
|
);
|
|
3644
3859
|
}
|
|
3860
|
+
ensureGlobalStyles();
|
|
3645
3861
|
var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
3646
3862
|
function CollabPopup({
|
|
3647
3863
|
orderId,
|
|
@@ -3649,6 +3865,7 @@ function CollabPopup({
|
|
|
3649
3865
|
participantIds,
|
|
3650
3866
|
isOpen,
|
|
3651
3867
|
onClose,
|
|
3868
|
+
onBack,
|
|
3652
3869
|
initialPosition,
|
|
3653
3870
|
width = 380,
|
|
3654
3871
|
height = 520,
|
|
@@ -3742,7 +3959,7 @@ function CollabPopup({
|
|
|
3742
3959
|
"div",
|
|
3743
3960
|
{
|
|
3744
3961
|
ref: containerRef,
|
|
3745
|
-
className,
|
|
3962
|
+
className: [ROOT_CLASS, className].filter(Boolean).join(" "),
|
|
3746
3963
|
role: "dialog",
|
|
3747
3964
|
"aria-modal": "true",
|
|
3748
3965
|
"aria-labelledby": titleId,
|
|
@@ -3758,7 +3975,18 @@ function CollabPopup({
|
|
|
3758
3975
|
onMouseDown: handleMouseDown,
|
|
3759
3976
|
children: [
|
|
3760
3977
|
/* @__PURE__ */ jsxs("div", { "data-drag-handle": true, style: styles13.titleBar, children: [
|
|
3761
|
-
/* @__PURE__ */ jsx(
|
|
3978
|
+
onBack && /* @__PURE__ */ jsx(
|
|
3979
|
+
"button",
|
|
3980
|
+
{
|
|
3981
|
+
onClick: onBack,
|
|
3982
|
+
style: styles13.titleButton,
|
|
3983
|
+
"aria-label": "Go back",
|
|
3984
|
+
title: "Back",
|
|
3985
|
+
type: "button",
|
|
3986
|
+
children: "\u2190"
|
|
3987
|
+
}
|
|
3988
|
+
),
|
|
3989
|
+
/* @__PURE__ */ jsx("span", { id: titleId, style: { ...styles13.titleText, flex: 1 }, children: buildChannelName(patientData) }),
|
|
3762
3990
|
/* @__PURE__ */ jsxs("div", { style: styles13.titleActions, children: [
|
|
3763
3991
|
/* @__PURE__ */ jsx(
|
|
3764
3992
|
"button",
|
|
@@ -3800,7 +4028,8 @@ var styles13 = {
|
|
|
3800
4028
|
flexDirection: "column",
|
|
3801
4029
|
backgroundColor: "#ffffff",
|
|
3802
4030
|
border: "1px solid #e5e7eb",
|
|
3803
|
-
transition: "height 0.2s ease"
|
|
4031
|
+
transition: "height 0.2s ease",
|
|
4032
|
+
fontFamily: FONT_STACK
|
|
3804
4033
|
},
|
|
3805
4034
|
titleBar: {
|
|
3806
4035
|
display: "flex",
|
|
@@ -4045,8 +4274,8 @@ function useInlineCollab({
|
|
|
4045
4274
|
await dispatchSend({
|
|
4046
4275
|
body: "Voice message",
|
|
4047
4276
|
type: "audio",
|
|
4048
|
-
|
|
4049
|
-
|
|
4277
|
+
media_url: url,
|
|
4278
|
+
media_duration: duration
|
|
4050
4279
|
});
|
|
4051
4280
|
} catch (err) {
|
|
4052
4281
|
setError(err instanceof Error ? err.message : "Failed to send voice message");
|
|
@@ -4072,6 +4301,7 @@ function useInlineCollab({
|
|
|
4072
4301
|
containerRef
|
|
4073
4302
|
};
|
|
4074
4303
|
}
|
|
4304
|
+
ensureGlobalStyles();
|
|
4075
4305
|
function CollabInline({
|
|
4076
4306
|
orderId,
|
|
4077
4307
|
patientData,
|
|
@@ -4094,9 +4324,9 @@ function CollabInline({
|
|
|
4094
4324
|
containerRef
|
|
4095
4325
|
} = useInlineCollab({ orderId, patientData, participantIds, messageLimit });
|
|
4096
4326
|
if (isLoading && !hasConversation) {
|
|
4097
|
-
return /* @__PURE__ */ jsx("div", { className, style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
4327
|
+
return /* @__PURE__ */ jsx("div", { className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...styles14.container, ...style }, children: /* @__PURE__ */ jsx("div", { style: styles14.loadingState, children: "Loading..." }) });
|
|
4098
4328
|
}
|
|
4099
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, style: { ...styles14.container, ...style }, children: [
|
|
4329
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: [ROOT_CLASS, className].filter(Boolean).join(" "), style: { ...styles14.container, ...style }, children: [
|
|
4100
4330
|
hasConversation && messages.length > 0 && /* @__PURE__ */ jsx("div", { style: styles14.preview, children: messages.slice(-messageLimit).map((message) => /* @__PURE__ */ jsx(InlineMessageRow, { message }, message.id)) }),
|
|
4101
4331
|
error && /* @__PURE__ */ jsx("div", { style: styles14.error, children: error }),
|
|
4102
4332
|
/* @__PURE__ */ jsx(
|
|
@@ -4312,7 +4542,7 @@ var styles14 = {
|
|
|
4312
4542
|
backgroundColor: "#ffffff",
|
|
4313
4543
|
border: "1px solid #e5e7eb",
|
|
4314
4544
|
borderRadius: "8px",
|
|
4315
|
-
fontFamily:
|
|
4545
|
+
fontFamily: FONT_STACK
|
|
4316
4546
|
},
|
|
4317
4547
|
loadingState: {
|
|
4318
4548
|
padding: "8px",
|
|
@@ -4942,6 +5172,8 @@ var styles16 = {
|
|
|
4942
5172
|
textAlign: "center"
|
|
4943
5173
|
}
|
|
4944
5174
|
};
|
|
5175
|
+
ensureGlobalStyles();
|
|
5176
|
+
var COMPACT_BREAKPOINT = 720;
|
|
4945
5177
|
function CollabInbox({
|
|
4946
5178
|
initialConversationId,
|
|
4947
5179
|
onSelectConversation,
|
|
@@ -4951,34 +5183,55 @@ function CollabInbox({
|
|
|
4951
5183
|
}) {
|
|
4952
5184
|
const { conversations, isLoading, error } = useConversationList();
|
|
4953
5185
|
const [selectedId, setSelectedId] = useState(initialConversationId ?? null);
|
|
5186
|
+
const [isCompact, setIsCompact] = useState(
|
|
5187
|
+
() => typeof window === "undefined" ? false : window.innerWidth < COMPACT_BREAKPOINT
|
|
5188
|
+
);
|
|
5189
|
+
useEffect(() => {
|
|
5190
|
+
if (typeof window === "undefined") return;
|
|
5191
|
+
const mq = window.matchMedia(`(max-width: ${COMPACT_BREAKPOINT - 1}px)`);
|
|
5192
|
+
const sync = () => setIsCompact(mq.matches);
|
|
5193
|
+
sync();
|
|
5194
|
+
mq.addEventListener("change", sync);
|
|
5195
|
+
return () => mq.removeEventListener("change", sync);
|
|
5196
|
+
}, []);
|
|
4954
5197
|
const selected = conversations.find((c) => c.id === selectedId) || null;
|
|
4955
5198
|
const handleSelect = (item) => {
|
|
4956
5199
|
setSelectedId(item.id);
|
|
4957
5200
|
onSelectConversation?.(item);
|
|
4958
5201
|
};
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
5202
|
+
const showDetail = !isCompact || isCompact && !!selected;
|
|
5203
|
+
const showList = !isCompact || isCompact && !selected;
|
|
5204
|
+
return /* @__PURE__ */ jsxs(
|
|
5205
|
+
"div",
|
|
5206
|
+
{
|
|
5207
|
+
className: [ROOT_CLASS, className].filter(Boolean).join(" "),
|
|
5208
|
+
style: { ...styles17.container, ...style },
|
|
5209
|
+
children: [
|
|
5210
|
+
showList && /* @__PURE__ */ jsx("div", { style: isCompact ? styles17.sidebarCompact : styles17.sidebar, children: /* @__PURE__ */ jsx(
|
|
5211
|
+
ConversationList,
|
|
5212
|
+
{
|
|
5213
|
+
conversations,
|
|
5214
|
+
selectedId,
|
|
5215
|
+
isLoading,
|
|
5216
|
+
error,
|
|
5217
|
+
onSelect: handleSelect,
|
|
5218
|
+
title
|
|
5219
|
+
}
|
|
5220
|
+
) }),
|
|
5221
|
+
showDetail && /* @__PURE__ */ jsx("div", { style: isCompact ? styles17.mainCompact : styles17.main, children: selected ? /* @__PURE__ */ jsx(
|
|
5222
|
+
CollabPanel,
|
|
5223
|
+
{
|
|
5224
|
+
orderId: selected.orderId,
|
|
5225
|
+
patientData: buildPatientData(selected),
|
|
5226
|
+
showSeenBy: true,
|
|
5227
|
+
style: styles17.panel,
|
|
5228
|
+
onBack: isCompact ? () => setSelectedId(null) : void 0
|
|
5229
|
+
},
|
|
5230
|
+
selected.id
|
|
5231
|
+
) : /* @__PURE__ */ jsx(EmptyState, { hasAny: conversations.length > 0 }) })
|
|
5232
|
+
]
|
|
5233
|
+
}
|
|
5234
|
+
);
|
|
4982
5235
|
}
|
|
4983
5236
|
function buildPatientData(item) {
|
|
4984
5237
|
if (item.patientSnapshot) return item.patientSnapshot;
|
|
@@ -5000,7 +5253,7 @@ var styles17 = {
|
|
|
5000
5253
|
height: "100%",
|
|
5001
5254
|
width: "100%",
|
|
5002
5255
|
backgroundColor: "#ffffff",
|
|
5003
|
-
fontFamily:
|
|
5256
|
+
fontFamily: FONT_STACK
|
|
5004
5257
|
},
|
|
5005
5258
|
sidebar: {
|
|
5006
5259
|
width: "320px",
|
|
@@ -5009,6 +5262,12 @@ var styles17 = {
|
|
|
5009
5262
|
display: "flex",
|
|
5010
5263
|
flexDirection: "column"
|
|
5011
5264
|
},
|
|
5265
|
+
sidebarCompact: {
|
|
5266
|
+
width: "100%",
|
|
5267
|
+
flex: 1,
|
|
5268
|
+
display: "flex",
|
|
5269
|
+
flexDirection: "column"
|
|
5270
|
+
},
|
|
5012
5271
|
main: {
|
|
5013
5272
|
flex: 1,
|
|
5014
5273
|
display: "flex",
|
|
@@ -5017,6 +5276,13 @@ var styles17 = {
|
|
|
5017
5276
|
padding: "12px",
|
|
5018
5277
|
backgroundColor: "#f3f4f6"
|
|
5019
5278
|
},
|
|
5279
|
+
mainCompact: {
|
|
5280
|
+
flex: 1,
|
|
5281
|
+
display: "flex",
|
|
5282
|
+
flexDirection: "column",
|
|
5283
|
+
minWidth: 0,
|
|
5284
|
+
backgroundColor: "#f3f4f6"
|
|
5285
|
+
},
|
|
5020
5286
|
panel: {
|
|
5021
5287
|
height: "100%",
|
|
5022
5288
|
width: "100%"
|