@natoe/colab 0.1.11 → 0.1.13
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 +140 -14
- package/dist/index.d.ts +140 -14
- package/dist/index.js +1086 -616
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1085 -618
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -321,6 +321,173 @@ var CollabSocket = class {
|
|
|
321
321
|
this.config = null;
|
|
322
322
|
}
|
|
323
323
|
};
|
|
324
|
+
|
|
325
|
+
// src/core/theme.ts
|
|
326
|
+
var FONT_SIZE = {
|
|
327
|
+
xs: "12px",
|
|
328
|
+
sm: "13px",
|
|
329
|
+
md: "15px",
|
|
330
|
+
lg: "17px",
|
|
331
|
+
xxl: "28px"
|
|
332
|
+
};
|
|
333
|
+
var FONT_WEIGHT = {
|
|
334
|
+
regular: 400,
|
|
335
|
+
medium: 500,
|
|
336
|
+
semibold: 600,
|
|
337
|
+
bold: 700
|
|
338
|
+
};
|
|
339
|
+
var LINE_HEIGHT = {
|
|
340
|
+
tight: 1.3,
|
|
341
|
+
normal: 1.45};
|
|
342
|
+
var SPACE = {
|
|
343
|
+
S1: "4px",
|
|
344
|
+
S2: "8px",
|
|
345
|
+
S3: "12px",
|
|
346
|
+
S4: "16px",
|
|
347
|
+
S5: "20px",
|
|
348
|
+
S6: "24px",
|
|
349
|
+
S12: "48px"
|
|
350
|
+
};
|
|
351
|
+
var RADIUS = {
|
|
352
|
+
sm: "4px",
|
|
353
|
+
md: "8px",
|
|
354
|
+
lg: "12px",
|
|
355
|
+
xl: "16px",
|
|
356
|
+
pill: "9999px",
|
|
357
|
+
full: "50%"
|
|
358
|
+
};
|
|
359
|
+
var THEME_VAR = {
|
|
360
|
+
primary: "--natoe-colab-primary",
|
|
361
|
+
primaryHover: "--natoe-colab-primary-hover",
|
|
362
|
+
primaryBg: "--natoe-colab-primary-bg",
|
|
363
|
+
primaryFg: "--natoe-colab-primary-fg",
|
|
364
|
+
success: "--natoe-colab-success",
|
|
365
|
+
warning: "--natoe-colab-warning",
|
|
366
|
+
danger: "--natoe-colab-danger",
|
|
367
|
+
dangerBg: "--natoe-colab-danger-bg",
|
|
368
|
+
dangerBorder: "--natoe-colab-danger-border",
|
|
369
|
+
dangerFg: "--natoe-colab-danger-fg",
|
|
370
|
+
fontStack: "--natoe-colab-font-stack"
|
|
371
|
+
};
|
|
372
|
+
var THEME_DEFAULTS = {
|
|
373
|
+
primary: "#2563eb",
|
|
374
|
+
primaryHover: "#1d4ed8",
|
|
375
|
+
primaryBg: "#dbeafe",
|
|
376
|
+
primaryFg: "#1d4ed8",
|
|
377
|
+
success: "#059669",
|
|
378
|
+
warning: "#d97706",
|
|
379
|
+
danger: "#dc2626",
|
|
380
|
+
dangerBg: "#fef2f2",
|
|
381
|
+
dangerBorder: "#fecaca",
|
|
382
|
+
dangerFg: "#b91c1c",
|
|
383
|
+
fontStack: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
|
|
384
|
+
};
|
|
385
|
+
var cssVar = (name, fallback) => `var(${name}, ${fallback})`;
|
|
386
|
+
var COLOR = {
|
|
387
|
+
// Brand — themeable
|
|
388
|
+
primary: cssVar(THEME_VAR.primary, THEME_DEFAULTS.primary),
|
|
389
|
+
primaryHover: cssVar(THEME_VAR.primaryHover, THEME_DEFAULTS.primaryHover),
|
|
390
|
+
/** Tinted surface for chips/cards on brand-coloured states. */
|
|
391
|
+
primaryBg: cssVar(THEME_VAR.primaryBg, THEME_DEFAULTS.primaryBg),
|
|
392
|
+
primaryFg: cssVar(THEME_VAR.primaryFg, THEME_DEFAULTS.primaryFg),
|
|
393
|
+
// Neutral grayscale — not themeable, taken from Tailwind's zinc-leaning
|
|
394
|
+
// slate to match the package's existing tonal balance.
|
|
395
|
+
white: "#ffffff",
|
|
396
|
+
neutral50: "#f9fafb",
|
|
397
|
+
neutral100: "#f3f4f6",
|
|
398
|
+
neutral200: "#e5e7eb",
|
|
399
|
+
neutral300: "#d1d5db",
|
|
400
|
+
neutral400: "#9ca3af",
|
|
401
|
+
neutral500: "#6b7280",
|
|
402
|
+
neutral600: "#4b5563",
|
|
403
|
+
neutral700: "#374151",
|
|
404
|
+
neutral800: "#1f2937",
|
|
405
|
+
neutral900: "#111827",
|
|
406
|
+
slate800: "#1e293b",
|
|
407
|
+
// Semantic — themeable
|
|
408
|
+
success: cssVar(THEME_VAR.success, THEME_DEFAULTS.success),
|
|
409
|
+
warning: cssVar(THEME_VAR.warning, THEME_DEFAULTS.warning),
|
|
410
|
+
danger: cssVar(THEME_VAR.danger, THEME_DEFAULTS.danger),
|
|
411
|
+
dangerBg: cssVar(THEME_VAR.dangerBg, THEME_DEFAULTS.dangerBg),
|
|
412
|
+
dangerBorder: cssVar(THEME_VAR.dangerBorder, THEME_DEFAULTS.dangerBorder),
|
|
413
|
+
dangerFg: cssVar(THEME_VAR.dangerFg, THEME_DEFAULTS.dangerFg)
|
|
414
|
+
};
|
|
415
|
+
var SIZE = {
|
|
416
|
+
/** Default interactive height (text buttons, list rows). */
|
|
417
|
+
control: "40px",
|
|
418
|
+
/** Square icon-only buttons inside chrome (popup title, menu trigger). */
|
|
419
|
+
controlIcon: "36px"};
|
|
420
|
+
var SHADOW = {
|
|
421
|
+
/** Cards / floating popovers (message-actions menu). */
|
|
422
|
+
popover: "0 6px 18px rgba(0, 0, 0, 0.12)",
|
|
423
|
+
toast: "0 4px 12px rgba(0, 0, 0, 0.18)"
|
|
424
|
+
};
|
|
425
|
+
var Z_INDEX = {
|
|
426
|
+
/** Sticky day divider — above bubbles, below interactive popovers. */
|
|
427
|
+
sticky: 1,
|
|
428
|
+
/** Toasts inside a panel. */
|
|
429
|
+
toast: 20,
|
|
430
|
+
/** Floating CollabPopup dialog. */
|
|
431
|
+
dialog: 9999,
|
|
432
|
+
/** Portaled message-actions menu — must sit above the dialog. */
|
|
433
|
+
menu: 1e4
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// src/core/styles.ts
|
|
437
|
+
var FONT_STACK = `var(${THEME_VAR.fontStack}, ${THEME_DEFAULTS.fontStack})`;
|
|
438
|
+
var ROOT_CLASS = "natoe-colab-root";
|
|
439
|
+
var GLOBAL_STYLE_ID = "natoe-colab-global-styles";
|
|
440
|
+
var ROOT_DEFAULTS_BLOCK = Object.keys(THEME_DEFAULTS).map((key) => ` ${THEME_VAR[key]}: ${THEME_DEFAULTS[key]};`).join("\n");
|
|
441
|
+
var GLOBAL_CSS = `
|
|
442
|
+
:root {
|
|
443
|
+
${ROOT_DEFAULTS_BLOCK}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }
|
|
447
|
+
|
|
448
|
+
@keyframes natoe-colab-message-in {
|
|
449
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
450
|
+
to { opacity: 1; transform: translateY(0); }
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* High-contrast adjustments \u2014 older users on OS-level high-contrast mode
|
|
454
|
+
get heavier borders and stronger text without losing the package look. */
|
|
455
|
+
@media (prefers-contrast: more) {
|
|
456
|
+
.${ROOT_CLASS} {
|
|
457
|
+
color: #000000;
|
|
458
|
+
}
|
|
459
|
+
.${ROOT_CLASS} button {
|
|
460
|
+
outline: 1px solid currentColor;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/* Honour reduced-motion preferences by killing entry animations. */
|
|
465
|
+
@media (prefers-reduced-motion: reduce) {
|
|
466
|
+
.${ROOT_CLASS} [data-natoe-message-bubble] {
|
|
467
|
+
animation: none !important;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
`;
|
|
471
|
+
function ensureGlobalStyles() {
|
|
472
|
+
if (typeof document === "undefined") return;
|
|
473
|
+
if (document.getElementById(GLOBAL_STYLE_ID)) return;
|
|
474
|
+
const style = document.createElement("style");
|
|
475
|
+
style.id = GLOBAL_STYLE_ID;
|
|
476
|
+
style.textContent = GLOBAL_CSS;
|
|
477
|
+
document.head.appendChild(style);
|
|
478
|
+
}
|
|
479
|
+
function applyThemeOverrides(theme) {
|
|
480
|
+
if (typeof document === "undefined") return;
|
|
481
|
+
const root = document.documentElement;
|
|
482
|
+
Object.keys(THEME_VAR).forEach((key) => {
|
|
483
|
+
const value = theme?.[key];
|
|
484
|
+
if (value) {
|
|
485
|
+
root.style.setProperty(THEME_VAR[key], value);
|
|
486
|
+
} else {
|
|
487
|
+
root.style.removeProperty(THEME_VAR[key]);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
324
491
|
var CollabContext = React4.createContext(null);
|
|
325
492
|
function useCollab() {
|
|
326
493
|
const context = React4.useContext(CollabContext);
|
|
@@ -339,6 +506,9 @@ function CollabProvider({ config, apiBaseUrl, children }) {
|
|
|
339
506
|
const pendingResolvers = React4.useRef(/* @__PURE__ */ new Map());
|
|
340
507
|
const previewCache = React4.useRef(/* @__PURE__ */ new Map());
|
|
341
508
|
const batchScheduled = React4.useRef(false);
|
|
509
|
+
React4.useEffect(() => {
|
|
510
|
+
applyThemeOverrides(config.theme);
|
|
511
|
+
}, [config.theme]);
|
|
342
512
|
React4.useEffect(() => {
|
|
343
513
|
if (typeof window === "undefined") return;
|
|
344
514
|
let s = socket;
|
|
@@ -554,6 +724,7 @@ function CollabProvider({ config, apiBaseUrl, children }) {
|
|
|
554
724
|
config,
|
|
555
725
|
apiBaseUrl,
|
|
556
726
|
totalUnread,
|
|
727
|
+
unreadCounts,
|
|
557
728
|
requestPreview,
|
|
558
729
|
invalidatePreview,
|
|
559
730
|
fetchMessages,
|
|
@@ -575,7 +746,11 @@ function buildChannelName(patientData) {
|
|
|
575
746
|
const patientPart = patientData.patientName?.trim() || "Unknown";
|
|
576
747
|
const labPart = patientData.labName?.trim()?.slice(0, 24) || "";
|
|
577
748
|
const last4 = (patientData.displayOrderId ?? "").trim().slice(-4) || "0000";
|
|
578
|
-
return `${patientPart} - ${labPart} - ${last4}`;
|
|
749
|
+
return labPart ? `${patientPart} - ${labPart} - ${last4}` : `${patientPart} - ${last4}`;
|
|
750
|
+
}
|
|
751
|
+
function cleanChannelName(name) {
|
|
752
|
+
if (!name) return "";
|
|
753
|
+
return name.replace(/\s+-\s+-\s+/g, " - ").trim();
|
|
579
754
|
}
|
|
580
755
|
|
|
581
756
|
// src/hooks/useConversation.ts
|
|
@@ -610,8 +785,11 @@ function useConversation({
|
|
|
610
785
|
const ensureConversationInFlight = React4.useRef(null);
|
|
611
786
|
const markedReadIdsRef = React4.useRef(/* @__PURE__ */ new Set());
|
|
612
787
|
const buildName = React4.useCallback(
|
|
613
|
-
() =>
|
|
614
|
-
|
|
788
|
+
() => {
|
|
789
|
+
const labName = patientData.labName ?? (config.userRole === "lab" ? config.userName : void 0);
|
|
790
|
+
return buildChannelName({ ...patientData, labName });
|
|
791
|
+
},
|
|
792
|
+
[patientData, config.userRole, config.userName]
|
|
615
793
|
);
|
|
616
794
|
const joinChannel = React4.useCallback(
|
|
617
795
|
(conv) => {
|
|
@@ -724,26 +902,22 @@ function useConversation({
|
|
|
724
902
|
setConversation(existingConv);
|
|
725
903
|
setParticipants(preview.participants);
|
|
726
904
|
joinChannel(existingConv);
|
|
727
|
-
setMessages(preview.lastMessages);
|
|
728
|
-
setHasMore(preview.messageCount > preview.lastMessages.length);
|
|
729
|
-
setPinnedMessages(preview.lastMessages.filter((m) => m.isPinned));
|
|
730
|
-
setIsLoading(false);
|
|
731
905
|
if (loadHistory) {
|
|
732
906
|
fetchMessages(preview.conversationId).then((history) => {
|
|
733
907
|
if (cancelled) return;
|
|
734
|
-
setMessages(
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
});
|
|
739
|
-
setHasMore(history.length > 0);
|
|
740
|
-
setPinnedMessages((prev) => {
|
|
741
|
-
const fromHistory = history.filter((m) => m.isPinned);
|
|
742
|
-
const seen = new Set(prev.map((m) => m.id));
|
|
743
|
-
return [...fromHistory.filter((m) => !seen.has(m.id)), ...prev];
|
|
744
|
-
});
|
|
908
|
+
setMessages(history);
|
|
909
|
+
setHasMore(history.length >= MESSAGES_PAGE_SIZE);
|
|
910
|
+
setPinnedMessages(history.filter((m) => m.isPinned));
|
|
911
|
+
setIsLoading(false);
|
|
745
912
|
}).catch(() => {
|
|
913
|
+
if (cancelled) return;
|
|
914
|
+
setIsLoading(false);
|
|
746
915
|
});
|
|
916
|
+
} else {
|
|
917
|
+
setMessages([]);
|
|
918
|
+
setHasMore(false);
|
|
919
|
+
setPinnedMessages([]);
|
|
920
|
+
setIsLoading(false);
|
|
747
921
|
}
|
|
748
922
|
} catch (err) {
|
|
749
923
|
if (cancelled) return;
|
|
@@ -824,7 +998,7 @@ function useConversation({
|
|
|
824
998
|
const payload = {
|
|
825
999
|
body,
|
|
826
1000
|
type: "text",
|
|
827
|
-
...replyTo ? {
|
|
1001
|
+
...replyTo ? { reply_to_id: replyTo.id } : {}
|
|
828
1002
|
};
|
|
829
1003
|
const { conv, persistedByCreate } = await ensureConversation(payload);
|
|
830
1004
|
setReplyTo(null);
|
|
@@ -877,7 +1051,7 @@ function useConversation({
|
|
|
877
1051
|
const payload = {
|
|
878
1052
|
body: target.body,
|
|
879
1053
|
type: "text",
|
|
880
|
-
...target.replyToId ? {
|
|
1054
|
+
...target.replyToId ? { reply_to_id: target.replyToId } : {}
|
|
881
1055
|
};
|
|
882
1056
|
try {
|
|
883
1057
|
await socket.sendMessage(conversation.id, payload);
|
|
@@ -1202,106 +1376,10 @@ function BackIcon({ size = 22, color = "currentColor" }) {
|
|
|
1202
1376
|
}
|
|
1203
1377
|
);
|
|
1204
1378
|
}
|
|
1205
|
-
|
|
1206
|
-
// src/core/theme.ts
|
|
1207
|
-
var FONT_SIZE = {
|
|
1208
|
-
xs: "12px",
|
|
1209
|
-
sm: "13px",
|
|
1210
|
-
md: "15px",
|
|
1211
|
-
lg: "17px",
|
|
1212
|
-
xxl: "28px"
|
|
1213
|
-
};
|
|
1214
|
-
var FONT_WEIGHT = {
|
|
1215
|
-
regular: 400,
|
|
1216
|
-
medium: 500,
|
|
1217
|
-
semibold: 600,
|
|
1218
|
-
bold: 700
|
|
1219
|
-
};
|
|
1220
|
-
var LINE_HEIGHT = {
|
|
1221
|
-
tight: 1.3,
|
|
1222
|
-
normal: 1.45};
|
|
1223
|
-
var SPACE = {
|
|
1224
|
-
S1: "4px",
|
|
1225
|
-
S2: "8px",
|
|
1226
|
-
S3: "12px",
|
|
1227
|
-
S4: "16px",
|
|
1228
|
-
S5: "20px",
|
|
1229
|
-
S6: "24px",
|
|
1230
|
-
S12: "48px"
|
|
1231
|
-
};
|
|
1232
|
-
var RADIUS = {
|
|
1233
|
-
sm: "4px",
|
|
1234
|
-
md: "8px",
|
|
1235
|
-
lg: "12px",
|
|
1236
|
-
pill: "9999px",
|
|
1237
|
-
full: "50%"
|
|
1238
|
-
};
|
|
1239
|
-
var COLOR = {
|
|
1240
|
-
// Brand
|
|
1241
|
-
primary: "#2563eb",
|
|
1242
|
-
/** Tinted surface for chips/cards on brand-coloured states. */
|
|
1243
|
-
primaryBg: "#dbeafe",
|
|
1244
|
-
primaryFg: "#1d4ed8",
|
|
1245
|
-
// Neutral grayscale — taken from Tailwind's zinc-leaning slate, the
|
|
1246
|
-
// existing dominant family in the package.
|
|
1247
|
-
white: "#ffffff",
|
|
1248
|
-
neutral50: "#f9fafb",
|
|
1249
|
-
neutral100: "#f3f4f6",
|
|
1250
|
-
neutral200: "#e5e7eb",
|
|
1251
|
-
neutral300: "#d1d5db",
|
|
1252
|
-
neutral400: "#9ca3af",
|
|
1253
|
-
neutral500: "#6b7280",
|
|
1254
|
-
neutral600: "#4b5563",
|
|
1255
|
-
neutral700: "#374151",
|
|
1256
|
-
neutral800: "#1f2937",
|
|
1257
|
-
neutral900: "#111827",
|
|
1258
|
-
// Slate (used by day dividers + dialog title bar)
|
|
1259
|
-
slate200: "#e2e8f0",
|
|
1260
|
-
slate700: "#334155",
|
|
1261
|
-
slate800: "#1e293b",
|
|
1262
|
-
// Semantic
|
|
1263
|
-
success: "#059669",
|
|
1264
|
-
warning: "#d97706",
|
|
1265
|
-
danger: "#dc2626",
|
|
1266
|
-
dangerBg: "#fef2f2",
|
|
1267
|
-
dangerBorder: "#fecaca",
|
|
1268
|
-
dangerFg: "#b91c1c"
|
|
1269
|
-
};
|
|
1270
|
-
var SIZE = {
|
|
1271
|
-
/** Default interactive height (text buttons, list rows). */
|
|
1272
|
-
control: "40px",
|
|
1273
|
-
/** Square icon-only buttons inside chrome (popup title, menu trigger). */
|
|
1274
|
-
controlIcon: "36px",
|
|
1275
|
-
/** Primary input controls (textarea send/attach). 44px = WCAG min. */
|
|
1276
|
-
controlPrimary: "44px",
|
|
1277
|
-
/** Avatar in the inbox row. */
|
|
1278
|
-
avatar: "40px",
|
|
1279
|
-
/** Unread dot. */
|
|
1280
|
-
dot: "10px"
|
|
1281
|
-
};
|
|
1282
|
-
var SHADOW = {
|
|
1283
|
-
/** Cards / floating popovers (message-actions menu). */
|
|
1284
|
-
popover: "0 6px 18px rgba(0, 0, 0, 0.12)",
|
|
1285
|
-
/** Dialog (CollabPopup). */
|
|
1286
|
-
dialog: "0 8px 30px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08)",
|
|
1287
|
-
/** Subtle separator shadow (sticky day divider, toast). */
|
|
1288
|
-
subtle: "0 1px 2px rgba(0, 0, 0, 0.04)",
|
|
1289
|
-
toast: "0 4px 12px rgba(0, 0, 0, 0.18)"
|
|
1290
|
-
};
|
|
1291
|
-
var Z_INDEX = {
|
|
1292
|
-
/** Sticky day divider — above bubbles, below interactive popovers. */
|
|
1293
|
-
sticky: 1,
|
|
1294
|
-
/** Toasts inside a panel. */
|
|
1295
|
-
toast: 20,
|
|
1296
|
-
/** Floating CollabPopup dialog. */
|
|
1297
|
-
dialog: 9999,
|
|
1298
|
-
/** Portaled message-actions menu — must sit above the dialog. */
|
|
1299
|
-
menu: 1e4
|
|
1300
|
-
};
|
|
1301
1379
|
function resolveDisplayName(patientData, displayName) {
|
|
1302
1380
|
const localComplete = !!patientData.labName && !!patientData.displayOrderId;
|
|
1303
1381
|
if (localComplete) return buildChannelName(patientData);
|
|
1304
|
-
return displayName
|
|
1382
|
+
return cleanChannelName(displayName) || buildChannelName(patientData);
|
|
1305
1383
|
}
|
|
1306
1384
|
function PatientHeader({
|
|
1307
1385
|
patientData,
|
|
@@ -1314,15 +1392,28 @@ function PatientHeader({
|
|
|
1314
1392
|
}) {
|
|
1315
1393
|
const hasDicom = !!(patientData.studyId && patientData.storageId);
|
|
1316
1394
|
const meta = [];
|
|
1317
|
-
if (patientData.patientAge
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1395
|
+
if (patientData.patientAge && patientData.patientSex) {
|
|
1396
|
+
meta.push({
|
|
1397
|
+
key: "ageSex",
|
|
1398
|
+
label: "Age / Sex",
|
|
1399
|
+
value: `${patientData.patientAge} \xB7 ${patientData.patientSex}`
|
|
1400
|
+
});
|
|
1401
|
+
} else if (patientData.patientAge) {
|
|
1402
|
+
meta.push({ key: "age", label: "Age", value: String(patientData.patientAge) });
|
|
1403
|
+
} else if (patientData.patientSex) {
|
|
1404
|
+
meta.push({ key: "sex", label: "Sex", value: String(patientData.patientSex) });
|
|
1405
|
+
}
|
|
1406
|
+
if (patientData.studyType) {
|
|
1407
|
+
meta.push({ key: "modality", label: "Modality", value: patientData.studyType });
|
|
1322
1408
|
}
|
|
1323
|
-
if (patientData.
|
|
1324
|
-
meta.push({
|
|
1409
|
+
if (patientData.bodyParts && patientData.bodyParts.length > 0) {
|
|
1410
|
+
meta.push({
|
|
1411
|
+
key: "body",
|
|
1412
|
+
label: "Body part",
|
|
1413
|
+
value: patientData.bodyParts.join(", ")
|
|
1414
|
+
});
|
|
1325
1415
|
}
|
|
1416
|
+
const hasActions = hasDicom && onOpenDicom || onOpenSettings;
|
|
1326
1417
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles.container, children: [
|
|
1327
1418
|
!hideName && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.nameRow, children: [
|
|
1328
1419
|
onBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1338,54 +1429,55 @@ function PatientHeader({
|
|
|
1338
1429
|
),
|
|
1339
1430
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.nameText, children: resolveDisplayName(patientData, displayName) })
|
|
1340
1431
|
] }),
|
|
1341
|
-
|
|
1342
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
1343
|
-
item.label,
|
|
1344
|
-
":
|
|
1345
|
-
] }),
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
]
|
|
1374
|
-
}
|
|
1375
|
-
)
|
|
1376
|
-
] }) : null
|
|
1432
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.caseCard, children: [
|
|
1433
|
+
meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.metaRow, children: meta.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.metaCol, children: [
|
|
1434
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.metaLabel, children: item.label }),
|
|
1435
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.metaValue, children: item.value })
|
|
1436
|
+
] }, item.key)) }),
|
|
1437
|
+
hasActions && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.actions, children: [
|
|
1438
|
+
hasDicom && onOpenDicom && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1439
|
+
"button",
|
|
1440
|
+
{
|
|
1441
|
+
onClick: onOpenDicom,
|
|
1442
|
+
style: styles.dicomButton,
|
|
1443
|
+
type: "button",
|
|
1444
|
+
"aria-label": "View DICOM study",
|
|
1445
|
+
children: [
|
|
1446
|
+
/* @__PURE__ */ jsxRuntime.jsx(DicomIcon, { size: 18, color: COLOR.primary }),
|
|
1447
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "View DICOM" })
|
|
1448
|
+
]
|
|
1449
|
+
}
|
|
1450
|
+
),
|
|
1451
|
+
onOpenSettings && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1452
|
+
"button",
|
|
1453
|
+
{
|
|
1454
|
+
onClick: onOpenSettings,
|
|
1455
|
+
style: styles.settingsIconButton,
|
|
1456
|
+
type: "button",
|
|
1457
|
+
"aria-label": "Open channel settings",
|
|
1458
|
+
title: "Settings",
|
|
1459
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SettingsIcon, { size: 18, color: COLOR.neutral600 })
|
|
1460
|
+
}
|
|
1461
|
+
)
|
|
1462
|
+
] })
|
|
1463
|
+
] })
|
|
1377
1464
|
] });
|
|
1378
1465
|
}
|
|
1379
1466
|
var styles = {
|
|
1380
1467
|
container: {
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
backgroundColor: COLOR.
|
|
1468
|
+
display: "flex",
|
|
1469
|
+
flexDirection: "column",
|
|
1470
|
+
backgroundColor: COLOR.primaryBg,
|
|
1471
|
+
borderBottom: `1px solid ${COLOR.neutral200}`
|
|
1384
1472
|
},
|
|
1473
|
+
// Optional name row, only when `hideName` is false (compact-inbox path)
|
|
1385
1474
|
nameRow: {
|
|
1386
1475
|
display: "flex",
|
|
1387
1476
|
alignItems: "center",
|
|
1388
|
-
gap: SPACE.S2
|
|
1477
|
+
gap: SPACE.S2,
|
|
1478
|
+
padding: `${SPACE.S3} ${SPACE.S4} ${SPACE.S2}`,
|
|
1479
|
+
borderBottom: `1px solid ${COLOR.neutral200}`,
|
|
1480
|
+
backgroundColor: COLOR.white
|
|
1389
1481
|
},
|
|
1390
1482
|
backButton: {
|
|
1391
1483
|
width: SIZE.controlIcon,
|
|
@@ -1402,65 +1494,90 @@ var styles = {
|
|
|
1402
1494
|
},
|
|
1403
1495
|
nameText: {
|
|
1404
1496
|
fontSize: FONT_SIZE.lg,
|
|
1405
|
-
fontWeight: FONT_WEIGHT.
|
|
1497
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
1406
1498
|
color: COLOR.neutral900,
|
|
1407
1499
|
lineHeight: LINE_HEIGHT.tight,
|
|
1500
|
+
letterSpacing: "-0.01em",
|
|
1408
1501
|
minWidth: 0,
|
|
1409
1502
|
overflow: "hidden",
|
|
1410
1503
|
textOverflow: "ellipsis",
|
|
1411
1504
|
whiteSpace: "nowrap"
|
|
1412
1505
|
},
|
|
1506
|
+
// Case card: meta columns flowing in a wrap-row, actions stacked
|
|
1507
|
+
// below. Each meta column is a small label-above-value pair so the
|
|
1508
|
+
// user can scan field names quickly without a legend.
|
|
1509
|
+
caseCard: {
|
|
1510
|
+
display: "flex",
|
|
1511
|
+
flexDirection: "column",
|
|
1512
|
+
gap: SPACE.S3,
|
|
1513
|
+
padding: `${SPACE.S3} ${SPACE.S5}`
|
|
1514
|
+
},
|
|
1515
|
+
// Wrap-row of stacked label/value columns. Compact column gap keeps
|
|
1516
|
+
// the row dense without crowding; row gap kicks in when columns
|
|
1517
|
+
// wrap to a second line on narrow popups.
|
|
1413
1518
|
metaRow: {
|
|
1414
1519
|
display: "flex",
|
|
1415
1520
|
flexWrap: "wrap",
|
|
1416
|
-
columnGap: SPACE.
|
|
1417
|
-
rowGap: SPACE.
|
|
1418
|
-
|
|
1521
|
+
columnGap: SPACE.S5,
|
|
1522
|
+
rowGap: SPACE.S2,
|
|
1523
|
+
minWidth: 0
|
|
1419
1524
|
},
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1525
|
+
metaCol: {
|
|
1526
|
+
display: "flex",
|
|
1527
|
+
flexDirection: "column",
|
|
1528
|
+
gap: "2px",
|
|
1529
|
+
minWidth: 0
|
|
1424
1530
|
},
|
|
1425
1531
|
metaLabel: {
|
|
1532
|
+
fontSize: "11px",
|
|
1533
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
1534
|
+
letterSpacing: "0.06em",
|
|
1535
|
+
textTransform: "uppercase",
|
|
1426
1536
|
color: COLOR.neutral500,
|
|
1427
|
-
|
|
1537
|
+
whiteSpace: "nowrap"
|
|
1428
1538
|
},
|
|
1429
1539
|
metaValue: {
|
|
1430
|
-
|
|
1540
|
+
fontSize: FONT_SIZE.sm,
|
|
1541
|
+
fontWeight: FONT_WEIGHT.semibold,
|
|
1542
|
+
color: COLOR.neutral900,
|
|
1543
|
+
whiteSpace: "nowrap",
|
|
1544
|
+
overflow: "hidden",
|
|
1545
|
+
textOverflow: "ellipsis",
|
|
1546
|
+
maxWidth: "180px"
|
|
1431
1547
|
},
|
|
1432
1548
|
actions: {
|
|
1433
1549
|
display: "flex",
|
|
1434
1550
|
gap: SPACE.S2,
|
|
1435
|
-
|
|
1551
|
+
flexShrink: 0
|
|
1436
1552
|
},
|
|
1437
1553
|
dicomButton: {
|
|
1438
1554
|
display: "inline-flex",
|
|
1439
1555
|
alignItems: "center",
|
|
1440
1556
|
gap: SPACE.S2,
|
|
1441
1557
|
minHeight: SIZE.control,
|
|
1442
|
-
padding: `${SPACE.S2}
|
|
1558
|
+
padding: `${SPACE.S2} 14px`,
|
|
1443
1559
|
fontSize: FONT_SIZE.sm,
|
|
1444
|
-
fontWeight: FONT_WEIGHT.
|
|
1445
|
-
color: COLOR.
|
|
1446
|
-
backgroundColor: COLOR.
|
|
1447
|
-
border:
|
|
1448
|
-
borderRadius: RADIUS.
|
|
1560
|
+
fontWeight: FONT_WEIGHT.semibold,
|
|
1561
|
+
color: COLOR.primary,
|
|
1562
|
+
backgroundColor: COLOR.white,
|
|
1563
|
+
border: `1.5px solid ${COLOR.primary}`,
|
|
1564
|
+
borderRadius: RADIUS.lg,
|
|
1449
1565
|
cursor: "pointer"
|
|
1450
1566
|
},
|
|
1451
|
-
|
|
1567
|
+
// Settings is icon-only (40x40 tile) since it's a secondary action
|
|
1568
|
+
// and View DICOM already carries a label.
|
|
1569
|
+
settingsIconButton: {
|
|
1570
|
+
width: SIZE.control,
|
|
1571
|
+
height: SIZE.control,
|
|
1452
1572
|
display: "inline-flex",
|
|
1453
1573
|
alignItems: "center",
|
|
1454
|
-
|
|
1455
|
-
minHeight: SIZE.control,
|
|
1456
|
-
padding: `${SPACE.S2} ${SPACE.S4}`,
|
|
1457
|
-
fontSize: FONT_SIZE.sm,
|
|
1458
|
-
fontWeight: FONT_WEIGHT.medium,
|
|
1459
|
-
color: COLOR.neutral700,
|
|
1574
|
+
justifyContent: "center",
|
|
1460
1575
|
backgroundColor: COLOR.white,
|
|
1461
|
-
border: `1px solid ${COLOR.
|
|
1462
|
-
borderRadius: RADIUS.
|
|
1463
|
-
|
|
1576
|
+
border: `1px solid ${COLOR.neutral200}`,
|
|
1577
|
+
borderRadius: RADIUS.lg,
|
|
1578
|
+
color: COLOR.neutral600,
|
|
1579
|
+
cursor: "pointer",
|
|
1580
|
+
flexShrink: 0
|
|
1464
1581
|
}
|
|
1465
1582
|
};
|
|
1466
1583
|
function ReplyQuoteBlock({
|
|
@@ -1469,10 +1586,10 @@ function ReplyQuoteBlock({
|
|
|
1469
1586
|
onClick,
|
|
1470
1587
|
className
|
|
1471
1588
|
}) {
|
|
1472
|
-
const baseBg = inOwnBubble ? "rgba(255,255,255,0.
|
|
1589
|
+
const baseBg = inOwnBubble ? "rgba(255,255,255,0.22)" : COLOR.white;
|
|
1473
1590
|
const barColor = inOwnBubble ? COLOR.white : COLOR.primary;
|
|
1474
1591
|
const nameColor = inOwnBubble ? COLOR.white : COLOR.primary;
|
|
1475
|
-
const bodyColor = inOwnBubble ? "rgba(255,255,255,0.
|
|
1592
|
+
const bodyColor = inOwnBubble ? "rgba(255,255,255,0.9)" : COLOR.neutral700;
|
|
1476
1593
|
const preview = renderSnapshotPreview(snapshot);
|
|
1477
1594
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1478
1595
|
"div",
|
|
@@ -1844,43 +1961,50 @@ var styles4 = {
|
|
|
1844
1961
|
position: "relative",
|
|
1845
1962
|
display: "inline-block"
|
|
1846
1963
|
},
|
|
1964
|
+
// Pill-shaped trigger matching the prototype's `.nc-msg-act` style —
|
|
1965
|
+
// always visible (touch-friendly) rather than hover-only.
|
|
1847
1966
|
trigger: {
|
|
1848
|
-
|
|
1849
|
-
height: SIZE.controlIcon,
|
|
1850
|
-
display: "flex",
|
|
1967
|
+
display: "inline-flex",
|
|
1851
1968
|
alignItems: "center",
|
|
1852
1969
|
justifyContent: "center",
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1970
|
+
width: "32px",
|
|
1971
|
+
height: "32px",
|
|
1972
|
+
backgroundColor: COLOR.white,
|
|
1973
|
+
border: `1px solid ${COLOR.neutral200}`,
|
|
1974
|
+
borderRadius: "999px",
|
|
1856
1975
|
cursor: "pointer",
|
|
1857
|
-
color: COLOR.neutral600
|
|
1976
|
+
color: COLOR.neutral600,
|
|
1977
|
+
transition: "background-color 120ms ease, color 120ms ease, border-color 120ms ease"
|
|
1858
1978
|
},
|
|
1859
1979
|
menu: {
|
|
1860
1980
|
position: "fixed",
|
|
1861
|
-
minWidth: "
|
|
1981
|
+
minWidth: "200px",
|
|
1862
1982
|
backgroundColor: COLOR.white,
|
|
1863
|
-
border: `1px solid ${COLOR.
|
|
1864
|
-
borderRadius: RADIUS.
|
|
1983
|
+
border: `1px solid ${COLOR.neutral300}`,
|
|
1984
|
+
borderRadius: RADIUS.lg,
|
|
1865
1985
|
boxShadow: SHADOW.popover,
|
|
1866
|
-
padding:
|
|
1986
|
+
padding: "6px",
|
|
1987
|
+
display: "flex",
|
|
1988
|
+
flexDirection: "column",
|
|
1989
|
+
gap: "2px",
|
|
1867
1990
|
// Above the floating popup (z-index dialog) but below any future modal.
|
|
1868
1991
|
zIndex: Z_INDEX.menu
|
|
1869
1992
|
},
|
|
1870
1993
|
item: {
|
|
1871
1994
|
display: "flex",
|
|
1872
1995
|
alignItems: "center",
|
|
1873
|
-
gap: SPACE.
|
|
1996
|
+
gap: SPACE.S2,
|
|
1874
1997
|
width: "100%",
|
|
1875
1998
|
minHeight: SIZE.control,
|
|
1876
|
-
padding:
|
|
1999
|
+
padding: `10px ${SPACE.S3}`,
|
|
1877
2000
|
fontSize: FONT_SIZE.sm,
|
|
1878
|
-
color: COLOR.
|
|
2001
|
+
color: COLOR.neutral700,
|
|
1879
2002
|
backgroundColor: "transparent",
|
|
1880
2003
|
border: "none",
|
|
1881
|
-
borderRadius: RADIUS.
|
|
2004
|
+
borderRadius: RADIUS.md,
|
|
1882
2005
|
cursor: "pointer",
|
|
1883
|
-
textAlign: "left"
|
|
2006
|
+
textAlign: "left",
|
|
2007
|
+
fontFamily: "inherit"
|
|
1884
2008
|
},
|
|
1885
2009
|
itemDisabled: {
|
|
1886
2010
|
color: COLOR.neutral400,
|
|
@@ -1994,71 +2118,116 @@ function MessageBubble({
|
|
|
1994
2118
|
},
|
|
1995
2119
|
children: [
|
|
1996
2120
|
isOwn && actionsSlot,
|
|
1997
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1998
|
-
"div",
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
message.type === "image" && /* @__PURE__ */ jsxRuntime.jsx(ImageContent, { mediaUrl: message.mediaUrl, fileName: message.fileName }),
|
|
2024
|
-
message.type === "file" && /* @__PURE__ */ jsxRuntime.jsx(FileContent, { mediaUrl: message.mediaUrl, fileName: message.fileName }),
|
|
2025
|
-
message.type === "deep_link" && /* @__PURE__ */ jsxRuntime.jsx(DeepLinkContent, { body: message.body, metadata: message.metadata, onDeepLinkClick }),
|
|
2026
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles5.timestamp, children: formatTime(message.insertedAt) }),
|
|
2027
|
-
isOwn && message.status === "sending" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles5.statusRow, children: [
|
|
2028
|
-
/* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 12, color: "rgba(255,255,255,0.85)" }),
|
|
2029
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles5.statusText, children: "Sending\u2026" })
|
|
2030
|
-
] }),
|
|
2031
|
-
isOwn && message.status === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles5.statusRow, children: [
|
|
2032
|
-
/* @__PURE__ */ jsxRuntime.jsx(AlertIcon, { size: 12, color: "#fecaca" }),
|
|
2033
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles5.statusText, children: "Not sent" }),
|
|
2034
|
-
onRetry && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2035
|
-
"button",
|
|
2121
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles5.bubbleWrapper, children: [
|
|
2122
|
+
!isOwn && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles5.authorRow, children: [
|
|
2123
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2124
|
+
"span",
|
|
2125
|
+
{
|
|
2126
|
+
style: {
|
|
2127
|
+
...styles5.authorAvatar,
|
|
2128
|
+
backgroundColor: roleColor(message.senderRole)
|
|
2129
|
+
},
|
|
2130
|
+
"aria-hidden": "true",
|
|
2131
|
+
children: computeInitials(message.senderName)
|
|
2132
|
+
}
|
|
2133
|
+
),
|
|
2134
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles5.authorName, children: message.senderName }),
|
|
2135
|
+
/* @__PURE__ */ jsxRuntime.jsx(RoleBadge, { role: message.senderRole })
|
|
2136
|
+
] }),
|
|
2137
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2138
|
+
"div",
|
|
2139
|
+
{
|
|
2140
|
+
style: {
|
|
2141
|
+
...styles5.bubble,
|
|
2142
|
+
...isOwn ? styles5.ownBubble : styles5.otherBubble
|
|
2143
|
+
},
|
|
2144
|
+
children: [
|
|
2145
|
+
message.isPinned && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2146
|
+
"div",
|
|
2036
2147
|
{
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
children:
|
|
2148
|
+
style: {
|
|
2149
|
+
...styles5.pinnedBadge,
|
|
2150
|
+
...isOwn ? styles5.pinnedBadgeOwn : styles5.pinnedBadgeOther
|
|
2151
|
+
},
|
|
2152
|
+
children: [
|
|
2153
|
+
/* @__PURE__ */ jsxRuntime.jsx(PinIcon, { size: 12 }),
|
|
2154
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Pinned" })
|
|
2155
|
+
]
|
|
2042
2156
|
}
|
|
2043
|
-
)
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
}
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2157
|
+
),
|
|
2158
|
+
message.replyToSnapshot && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2159
|
+
ReplyQuoteBlock,
|
|
2160
|
+
{
|
|
2161
|
+
snapshot: message.replyToSnapshot,
|
|
2162
|
+
inOwnBubble: isOwn,
|
|
2163
|
+
onClick: onReplyJumpTo
|
|
2164
|
+
}
|
|
2165
|
+
),
|
|
2166
|
+
message.type === "text" && /* @__PURE__ */ jsxRuntime.jsx(TextContent, { body: message.body, onDeepLinkClick }),
|
|
2167
|
+
message.type === "audio" && /* @__PURE__ */ jsxRuntime.jsx(AudioContent, { mediaUrl: message.mediaUrl, duration: message.mediaDuration }),
|
|
2168
|
+
message.type === "image" && /* @__PURE__ */ jsxRuntime.jsx(ImageContent, { mediaUrl: message.mediaUrl, fileName: message.fileName }),
|
|
2169
|
+
message.type === "file" && /* @__PURE__ */ jsxRuntime.jsx(FileContent, { mediaUrl: message.mediaUrl, fileName: message.fileName }),
|
|
2170
|
+
message.type === "deep_link" && /* @__PURE__ */ jsxRuntime.jsx(DeepLinkContent, { body: message.body, metadata: message.metadata, onDeepLinkClick }),
|
|
2171
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles5.bubbleFoot, children: [
|
|
2172
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles5.timestamp, children: formatTime(message.insertedAt) }),
|
|
2173
|
+
isOwn && message.status === "sending" && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles5.footStatus, children: [
|
|
2174
|
+
/* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 11, color: "rgba(255,255,255,0.85)" }),
|
|
2175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Sending\u2026" })
|
|
2176
|
+
] }),
|
|
2177
|
+
isOwn && message.status === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles5.footStatusFailed, children: [
|
|
2178
|
+
/* @__PURE__ */ jsxRuntime.jsx(AlertIcon, { size: 11, color: "#fecaca" }),
|
|
2179
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Not sent" }),
|
|
2180
|
+
onRetry && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2181
|
+
"button",
|
|
2182
|
+
{
|
|
2183
|
+
type: "button",
|
|
2184
|
+
onClick: () => onRetry(message.id),
|
|
2185
|
+
style: styles5.retryButton,
|
|
2186
|
+
"aria-label": "Retry sending message",
|
|
2187
|
+
children: "Retry"
|
|
2188
|
+
}
|
|
2189
|
+
)
|
|
2190
|
+
] }),
|
|
2191
|
+
showSeenBy && isOwn && !message.status && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2192
|
+
SeenByIndicator,
|
|
2193
|
+
{
|
|
2194
|
+
readBy: message.readBy ?? [],
|
|
2195
|
+
participants,
|
|
2196
|
+
currentUserId,
|
|
2197
|
+
senderId: message.senderId
|
|
2198
|
+
}
|
|
2199
|
+
)
|
|
2200
|
+
] })
|
|
2201
|
+
]
|
|
2202
|
+
}
|
|
2203
|
+
)
|
|
2204
|
+
] }),
|
|
2057
2205
|
!isOwn && actionsSlot
|
|
2058
2206
|
]
|
|
2059
2207
|
}
|
|
2060
2208
|
);
|
|
2061
2209
|
}
|
|
2210
|
+
function computeInitials(name) {
|
|
2211
|
+
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("") || "?";
|
|
2212
|
+
}
|
|
2213
|
+
function roleColor(role) {
|
|
2214
|
+
switch (role) {
|
|
2215
|
+
case "radiologist":
|
|
2216
|
+
return "#4f46e5";
|
|
2217
|
+
// indigo (blue-leaning)
|
|
2218
|
+
case "lab":
|
|
2219
|
+
return "#2563eb";
|
|
2220
|
+
// brand blue
|
|
2221
|
+
case "physician":
|
|
2222
|
+
return "#0284c7";
|
|
2223
|
+
// sky
|
|
2224
|
+
case "admin":
|
|
2225
|
+
return "#64748b";
|
|
2226
|
+
// slate (muted)
|
|
2227
|
+
default:
|
|
2228
|
+
return "#6b7280";
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2062
2231
|
function TextContent({ body, onDeepLinkClick }) {
|
|
2063
2232
|
if (body.includes(DEEP_LINK_PREFIX)) {
|
|
2064
2233
|
const parts = body.split(new RegExp(`(${escapeRegex2(DEEP_LINK_PREFIX)}[\\w/.-]+)`, "g"));
|
|
@@ -2120,19 +2289,13 @@ function DeepLinkContent({
|
|
|
2120
2289
|
);
|
|
2121
2290
|
}
|
|
2122
2291
|
function SystemBubble({ message }) {
|
|
2123
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2292
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles5.systemWrapper, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles5.systemPill, children: [
|
|
2124
2293
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: message.body }),
|
|
2125
2294
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles5.systemTime, children: formatTime(message.insertedAt) })
|
|
2126
|
-
] });
|
|
2295
|
+
] }) });
|
|
2127
2296
|
}
|
|
2128
2297
|
function RoleBadge({ role }) {
|
|
2129
|
-
|
|
2130
|
-
radiologist: "#7c3aed",
|
|
2131
|
-
lab: "#2563eb",
|
|
2132
|
-
physician: "#059669",
|
|
2133
|
-
admin: "#dc2626"
|
|
2134
|
-
};
|
|
2135
|
-
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...styles5.roleBadge, backgroundColor: `${colors[role]}15`, color: colors[role] }, children: ROLE_LABELS[role] ?? role });
|
|
2298
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...styles5.roleBadge, backgroundColor: roleColor(role) }, children: ROLE_LABELS[role] ?? role });
|
|
2136
2299
|
}
|
|
2137
2300
|
function formatTime(iso) {
|
|
2138
2301
|
try {
|
|
@@ -2154,89 +2317,134 @@ var styles5 = {
|
|
|
2154
2317
|
display: "flex",
|
|
2155
2318
|
alignItems: "flex-end",
|
|
2156
2319
|
gap: SPACE.S1,
|
|
2157
|
-
marginBottom: SPACE.
|
|
2320
|
+
marginBottom: SPACE.S3,
|
|
2158
2321
|
paddingLeft: SPACE.S4,
|
|
2159
2322
|
paddingRight: SPACE.S4
|
|
2160
2323
|
},
|
|
2161
2324
|
bubbleWrapper: {
|
|
2162
2325
|
position: "relative",
|
|
2163
|
-
maxWidth: "
|
|
2326
|
+
maxWidth: "78%",
|
|
2327
|
+
display: "flex",
|
|
2328
|
+
flexDirection: "column",
|
|
2329
|
+
gap: "4px"
|
|
2164
2330
|
},
|
|
2165
2331
|
actionsSlot: {
|
|
2166
2332
|
flexShrink: 0,
|
|
2167
2333
|
alignSelf: "flex-end"
|
|
2168
2334
|
},
|
|
2335
|
+
// Author row above the bubble — only rendered for others' messages.
|
|
2336
|
+
authorRow: {
|
|
2337
|
+
display: "flex",
|
|
2338
|
+
alignItems: "center",
|
|
2339
|
+
gap: SPACE.S2
|
|
2340
|
+
},
|
|
2341
|
+
authorAvatar: {
|
|
2342
|
+
width: "36px",
|
|
2343
|
+
height: "36px",
|
|
2344
|
+
borderRadius: "50%",
|
|
2345
|
+
color: COLOR.white,
|
|
2346
|
+
fontSize: FONT_SIZE.sm,
|
|
2347
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
2348
|
+
display: "flex",
|
|
2349
|
+
alignItems: "center",
|
|
2350
|
+
justifyContent: "center",
|
|
2351
|
+
flexShrink: 0,
|
|
2352
|
+
letterSpacing: "0.02em"
|
|
2353
|
+
},
|
|
2354
|
+
authorName: {
|
|
2355
|
+
fontSize: FONT_SIZE.sm,
|
|
2356
|
+
fontWeight: FONT_WEIGHT.semibold,
|
|
2357
|
+
color: COLOR.neutral700,
|
|
2358
|
+
overflow: "hidden",
|
|
2359
|
+
textOverflow: "ellipsis",
|
|
2360
|
+
whiteSpace: "nowrap",
|
|
2361
|
+
minWidth: 0
|
|
2362
|
+
},
|
|
2169
2363
|
bubble: {
|
|
2170
2364
|
padding: `${SPACE.S3} ${SPACE.S4}`,
|
|
2171
|
-
borderRadius:
|
|
2172
|
-
wordBreak: "break-word"
|
|
2365
|
+
borderRadius: "18px",
|
|
2366
|
+
wordBreak: "break-word",
|
|
2367
|
+
border: "1px solid transparent"
|
|
2173
2368
|
},
|
|
2174
2369
|
ownBubble: {
|
|
2175
2370
|
backgroundColor: COLOR.primary,
|
|
2176
2371
|
color: COLOR.white,
|
|
2177
|
-
|
|
2372
|
+
borderColor: COLOR.primary,
|
|
2373
|
+
borderBottomRightRadius: "6px"
|
|
2178
2374
|
},
|
|
2179
2375
|
otherBubble: {
|
|
2180
2376
|
backgroundColor: COLOR.neutral100,
|
|
2181
2377
|
color: COLOR.neutral900,
|
|
2182
|
-
|
|
2378
|
+
borderColor: COLOR.neutral200,
|
|
2379
|
+
borderBottomLeftRadius: "6px"
|
|
2183
2380
|
},
|
|
2184
2381
|
pinnedBadge: {
|
|
2185
2382
|
display: "inline-flex",
|
|
2186
2383
|
alignItems: "center",
|
|
2187
|
-
gap:
|
|
2188
|
-
fontSize:
|
|
2189
|
-
fontWeight: FONT_WEIGHT.
|
|
2190
|
-
marginBottom: SPACE.
|
|
2191
|
-
|
|
2384
|
+
gap: "4px",
|
|
2385
|
+
fontSize: "11px",
|
|
2386
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
2387
|
+
marginBottom: SPACE.S2,
|
|
2388
|
+
padding: `2px ${SPACE.S2}`,
|
|
2389
|
+
borderRadius: "999px",
|
|
2390
|
+
textTransform: "uppercase",
|
|
2391
|
+
letterSpacing: "0.05em"
|
|
2192
2392
|
},
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
gap: SPACE.S2,
|
|
2197
|
-
marginBottom: SPACE.S1
|
|
2393
|
+
pinnedBadgeOther: {
|
|
2394
|
+
color: "#b8680f",
|
|
2395
|
+
backgroundColor: "#fff7e0"
|
|
2198
2396
|
},
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
color: COLOR.neutral700
|
|
2397
|
+
pinnedBadgeOwn: {
|
|
2398
|
+
color: "#fff4d6",
|
|
2399
|
+
backgroundColor: "rgba(255, 255, 255, 0.2)"
|
|
2203
2400
|
},
|
|
2204
2401
|
roleBadge: {
|
|
2205
|
-
fontSize:
|
|
2206
|
-
fontWeight: FONT_WEIGHT.
|
|
2207
|
-
padding:
|
|
2208
|
-
borderRadius: RADIUS.sm
|
|
2402
|
+
fontSize: "10px",
|
|
2403
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
2404
|
+
padding: "2px 7px",
|
|
2405
|
+
borderRadius: RADIUS.sm,
|
|
2406
|
+
textTransform: "uppercase",
|
|
2407
|
+
letterSpacing: "0.06em",
|
|
2408
|
+
color: COLOR.white,
|
|
2409
|
+
flexShrink: 0
|
|
2209
2410
|
},
|
|
2210
2411
|
textBody: {
|
|
2211
2412
|
margin: 0,
|
|
2212
2413
|
fontSize: FONT_SIZE.md,
|
|
2213
|
-
lineHeight:
|
|
2414
|
+
lineHeight: 1.5
|
|
2415
|
+
},
|
|
2416
|
+
bubbleFoot: {
|
|
2417
|
+
display: "flex",
|
|
2418
|
+
alignItems: "center",
|
|
2419
|
+
justifyContent: "flex-end",
|
|
2420
|
+
gap: SPACE.S2,
|
|
2421
|
+
marginTop: SPACE.S2,
|
|
2422
|
+
fontSize: "11px",
|
|
2423
|
+
opacity: 0.85
|
|
2214
2424
|
},
|
|
2215
2425
|
timestamp: {
|
|
2216
|
-
fontSize:
|
|
2426
|
+
fontSize: "11px",
|
|
2217
2427
|
color: "inherit",
|
|
2218
|
-
|
|
2219
|
-
marginTop: SPACE.S1,
|
|
2220
|
-
textAlign: "right"
|
|
2428
|
+
fontVariantNumeric: "tabular-nums"
|
|
2221
2429
|
},
|
|
2222
|
-
|
|
2223
|
-
display: "flex",
|
|
2430
|
+
footStatus: {
|
|
2431
|
+
display: "inline-flex",
|
|
2224
2432
|
alignItems: "center",
|
|
2225
|
-
gap:
|
|
2226
|
-
|
|
2227
|
-
fontSize: FONT_SIZE.xs,
|
|
2228
|
-
justifyContent: "flex-end",
|
|
2229
|
-
color: "rgba(255, 255, 255, 0.9)"
|
|
2433
|
+
gap: "4px",
|
|
2434
|
+
fontSize: "11px"
|
|
2230
2435
|
},
|
|
2231
|
-
|
|
2232
|
-
|
|
2436
|
+
footStatusFailed: {
|
|
2437
|
+
display: "inline-flex",
|
|
2438
|
+
alignItems: "center",
|
|
2439
|
+
gap: "4px",
|
|
2440
|
+
fontSize: "11px"
|
|
2233
2441
|
},
|
|
2234
2442
|
retryButton: {
|
|
2235
2443
|
background: "transparent",
|
|
2236
2444
|
border: "none",
|
|
2237
2445
|
color: COLOR.white,
|
|
2238
2446
|
fontWeight: FONT_WEIGHT.semibold,
|
|
2239
|
-
fontSize:
|
|
2447
|
+
fontSize: "11px",
|
|
2240
2448
|
textDecoration: "underline",
|
|
2241
2449
|
cursor: "pointer",
|
|
2242
2450
|
padding: `0 ${SPACE.S1}`
|
|
@@ -2299,18 +2507,25 @@ var styles5 = {
|
|
|
2299
2507
|
color: COLOR.neutral500,
|
|
2300
2508
|
fontFamily: "monospace"
|
|
2301
2509
|
},
|
|
2302
|
-
|
|
2510
|
+
systemWrapper: {
|
|
2303
2511
|
display: "flex",
|
|
2304
2512
|
justifyContent: "center",
|
|
2513
|
+
margin: `${SPACE.S2} 0`
|
|
2514
|
+
},
|
|
2515
|
+
systemPill: {
|
|
2516
|
+
display: "inline-flex",
|
|
2305
2517
|
alignItems: "center",
|
|
2306
2518
|
gap: SPACE.S2,
|
|
2307
|
-
padding:
|
|
2308
|
-
|
|
2519
|
+
padding: `5px ${SPACE.S3}`,
|
|
2520
|
+
backgroundColor: COLOR.neutral100,
|
|
2521
|
+
borderRadius: "999px",
|
|
2522
|
+
fontSize: FONT_SIZE.xs,
|
|
2309
2523
|
color: COLOR.neutral500
|
|
2310
2524
|
},
|
|
2311
2525
|
systemTime: {
|
|
2312
|
-
fontSize:
|
|
2313
|
-
color: COLOR.neutral400
|
|
2526
|
+
fontSize: "11px",
|
|
2527
|
+
color: COLOR.neutral400,
|
|
2528
|
+
fontVariantNumeric: "tabular-nums"
|
|
2314
2529
|
}
|
|
2315
2530
|
};
|
|
2316
2531
|
function ChatIllustration({ size = 96 }) {
|
|
@@ -2449,6 +2664,7 @@ var MessageList = React4.forwardRef(function MessageList2({
|
|
|
2449
2664
|
const containerRef = React4.useRef(null);
|
|
2450
2665
|
const bottomRef = React4.useRef(null);
|
|
2451
2666
|
const prevMessageCount = React4.useRef(messages.length);
|
|
2667
|
+
const hasInitiallyScrolledRef = React4.useRef(false);
|
|
2452
2668
|
React4.useImperativeHandle(
|
|
2453
2669
|
ref,
|
|
2454
2670
|
() => ({
|
|
@@ -2466,7 +2682,31 @@ var MessageList = React4.forwardRef(function MessageList2({
|
|
|
2466
2682
|
}),
|
|
2467
2683
|
[]
|
|
2468
2684
|
);
|
|
2685
|
+
React4.useLayoutEffect(() => {
|
|
2686
|
+
const container = containerRef.current;
|
|
2687
|
+
if (!container || messages.length === 0) return;
|
|
2688
|
+
if (hasInitiallyScrolledRef.current) return;
|
|
2689
|
+
hasInitiallyScrolledRef.current = true;
|
|
2690
|
+
prevMessageCount.current = messages.length;
|
|
2691
|
+
const firstUnread = messages.find(
|
|
2692
|
+
(m) => m.type !== "system" && m.senderId !== currentUserId && !(m.readBy ?? []).includes(currentUserId)
|
|
2693
|
+
);
|
|
2694
|
+
if (firstUnread) {
|
|
2695
|
+
const el = container.querySelector(
|
|
2696
|
+
`[data-message-id="${firstUnread.id}"]`
|
|
2697
|
+
);
|
|
2698
|
+
if (el) {
|
|
2699
|
+
const containerRect = container.getBoundingClientRect();
|
|
2700
|
+
const elRect = el.getBoundingClientRect();
|
|
2701
|
+
const offset = elRect.top - containerRect.top + container.scrollTop;
|
|
2702
|
+
container.scrollTop = Math.max(0, offset - 16);
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
container.scrollTop = container.scrollHeight;
|
|
2707
|
+
}, [messages, currentUserId]);
|
|
2469
2708
|
React4.useEffect(() => {
|
|
2709
|
+
if (!hasInitiallyScrolledRef.current) return;
|
|
2470
2710
|
if (messages.length > prevMessageCount.current) {
|
|
2471
2711
|
const lastMessage = messages[messages.length - 1];
|
|
2472
2712
|
const isOwnMessage = lastMessage?.senderId === currentUserId;
|
|
@@ -2525,7 +2765,11 @@ var MessageList = React4.forwardRef(function MessageList2({
|
|
|
2525
2765
|
const showDivider = !!currentBucket && currentBucket !== lastValidBucket;
|
|
2526
2766
|
if (currentBucket) lastValidBucket = currentBucket;
|
|
2527
2767
|
return /* @__PURE__ */ jsxRuntime.jsxs(React4__default.default.Fragment, { children: [
|
|
2528
|
-
showDivider && /* @__PURE__ */ jsxRuntime.
|
|
2768
|
+
showDivider && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles6.dayDivider, role: "separator", "aria-label": "Date", children: [
|
|
2769
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles6.dayHr, "aria-hidden": "true" }),
|
|
2770
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles6.dayLabel, children: formatDayDivider(message.insertedAt) }),
|
|
2771
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles6.dayHr, "aria-hidden": "true" })
|
|
2772
|
+
] }),
|
|
2529
2773
|
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-message-id": message.id, "data-natoe-message-bubble": true, style: styles6.bubbleSlot, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2530
2774
|
MessageBubble,
|
|
2531
2775
|
{
|
|
@@ -2624,23 +2868,32 @@ var styles6 = {
|
|
|
2624
2868
|
},
|
|
2625
2869
|
dayDivider: {
|
|
2626
2870
|
display: "flex",
|
|
2627
|
-
|
|
2628
|
-
|
|
2871
|
+
alignItems: "center",
|
|
2872
|
+
gap: SPACE.S3,
|
|
2873
|
+
margin: `${SPACE.S4} 0 ${SPACE.S3}`,
|
|
2629
2874
|
position: "sticky",
|
|
2630
2875
|
top: SPACE.S1,
|
|
2631
2876
|
zIndex: Z_INDEX.sticky,
|
|
2632
2877
|
pointerEvents: "none"
|
|
2633
2878
|
},
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2879
|
+
dayHr: {
|
|
2880
|
+
flex: 1,
|
|
2881
|
+
height: "1px",
|
|
2882
|
+
backgroundColor: COLOR.neutral200
|
|
2883
|
+
},
|
|
2884
|
+
dayLabel: {
|
|
2885
|
+
flexShrink: 0,
|
|
2886
|
+
fontSize: FONT_SIZE.xs,
|
|
2887
|
+
fontWeight: FONT_WEIGHT.semibold,
|
|
2888
|
+
color: COLOR.neutral500,
|
|
2889
|
+
textTransform: "uppercase",
|
|
2890
|
+
letterSpacing: "0.06em",
|
|
2891
|
+
// Subtle pill background so the label is readable when it overlays
|
|
2892
|
+
// bubbles passing under it during sticky scroll. Without this the
|
|
2893
|
+
// hairlines visually run through the text on tinted backgrounds.
|
|
2894
|
+
padding: `2px ${SPACE.S2}`,
|
|
2895
|
+
backgroundColor: COLOR.white,
|
|
2896
|
+
borderRadius: RADIUS.sm
|
|
2644
2897
|
},
|
|
2645
2898
|
bubbleSlot: {
|
|
2646
2899
|
animation: "natoe-colab-message-in 180ms ease-out"
|
|
@@ -2894,11 +3147,11 @@ function MessageInput({
|
|
|
2894
3147
|
{
|
|
2895
3148
|
onClick: () => fileInputRef.current?.click(),
|
|
2896
3149
|
disabled: disabled || isSending,
|
|
2897
|
-
style: styles8.
|
|
3150
|
+
style: styles8.attachButton,
|
|
2898
3151
|
"aria-label": "Attach file",
|
|
2899
3152
|
title: "Attach file",
|
|
2900
3153
|
type: "button",
|
|
2901
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(AttachIcon, { size: 22, color:
|
|
3154
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AttachIcon, { size: 22, color: COLOR.neutral700 })
|
|
2902
3155
|
}
|
|
2903
3156
|
),
|
|
2904
3157
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2937,7 +3190,7 @@ function MessageInput({
|
|
|
2937
3190
|
style: styles8.textarea
|
|
2938
3191
|
}
|
|
2939
3192
|
),
|
|
2940
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3193
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2941
3194
|
"button",
|
|
2942
3195
|
{
|
|
2943
3196
|
onClick: handleSendText,
|
|
@@ -2946,10 +3199,13 @@ function MessageInput({
|
|
|
2946
3199
|
title: "Send message",
|
|
2947
3200
|
style: {
|
|
2948
3201
|
...styles8.sendButton,
|
|
2949
|
-
opacity: text.trim() ? 1 : 0.
|
|
3202
|
+
opacity: text.trim() ? 1 : 0.5
|
|
2950
3203
|
},
|
|
2951
3204
|
type: "button",
|
|
2952
|
-
children:
|
|
3205
|
+
children: [
|
|
3206
|
+
/* @__PURE__ */ jsxRuntime.jsx(SendIcon, { size: 20, color: COLOR.white }),
|
|
3207
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles8.sendLabel, children: "Send" })
|
|
3208
|
+
]
|
|
2953
3209
|
}
|
|
2954
3210
|
)
|
|
2955
3211
|
] })
|
|
@@ -3011,49 +3267,67 @@ var styles8 = {
|
|
|
3011
3267
|
inputBar: {
|
|
3012
3268
|
display: "flex",
|
|
3013
3269
|
alignItems: "flex-end",
|
|
3014
|
-
gap:
|
|
3015
|
-
padding: `${SPACE.S3} ${SPACE.
|
|
3016
|
-
},
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3270
|
+
gap: "10px",
|
|
3271
|
+
padding: `${SPACE.S3} ${SPACE.S4} 14px`
|
|
3272
|
+
},
|
|
3273
|
+
// 48px square tile with a 14px corner radius — visually grounds the
|
|
3274
|
+
// attach affordance as part of the composer chrome rather than a stray
|
|
3275
|
+
// round icon button.
|
|
3276
|
+
attachButton: {
|
|
3277
|
+
width: "48px",
|
|
3278
|
+
height: "48px",
|
|
3020
3279
|
display: "flex",
|
|
3021
3280
|
alignItems: "center",
|
|
3022
3281
|
justifyContent: "center",
|
|
3023
|
-
backgroundColor:
|
|
3024
|
-
border:
|
|
3025
|
-
borderRadius:
|
|
3282
|
+
backgroundColor: COLOR.neutral100,
|
|
3283
|
+
border: `1.5px solid ${COLOR.neutral200}`,
|
|
3284
|
+
borderRadius: "14px",
|
|
3026
3285
|
cursor: "pointer",
|
|
3027
|
-
flexShrink: 0
|
|
3286
|
+
flexShrink: 0,
|
|
3287
|
+
color: COLOR.neutral700,
|
|
3288
|
+
transition: "background-color 120ms ease, color 120ms ease, border-color 120ms ease"
|
|
3028
3289
|
},
|
|
3029
3290
|
textarea: {
|
|
3030
3291
|
flex: 1,
|
|
3031
|
-
|
|
3292
|
+
minHeight: "48px",
|
|
3293
|
+
maxHeight: "140px",
|
|
3294
|
+
padding: "13px 16px",
|
|
3032
3295
|
fontSize: FONT_SIZE.md,
|
|
3033
3296
|
lineHeight: LINE_HEIGHT.normal,
|
|
3034
|
-
|
|
3035
|
-
|
|
3297
|
+
color: COLOR.neutral900,
|
|
3298
|
+
backgroundColor: COLOR.neutral100,
|
|
3299
|
+
border: `1.5px solid ${COLOR.neutral200}`,
|
|
3300
|
+
borderRadius: "14px",
|
|
3036
3301
|
resize: "none",
|
|
3037
3302
|
outline: "none",
|
|
3038
3303
|
fontFamily: "inherit",
|
|
3039
|
-
|
|
3040
|
-
minHeight: SIZE.controlPrimary
|
|
3304
|
+
transition: "background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease"
|
|
3041
3305
|
},
|
|
3306
|
+
// Pill-shaped send: icon + "Send" label. Always labelled (never icon-
|
|
3307
|
+
// only) so the affordance is obvious to first-time users.
|
|
3042
3308
|
sendButton: {
|
|
3043
|
-
|
|
3044
|
-
height: SIZE.controlPrimary,
|
|
3045
|
-
display: "flex",
|
|
3309
|
+
display: "inline-flex",
|
|
3046
3310
|
alignItems: "center",
|
|
3047
|
-
|
|
3311
|
+
gap: "6px",
|
|
3312
|
+
minWidth: "48px",
|
|
3313
|
+
height: "48px",
|
|
3314
|
+
padding: `0 ${SPACE.S4}`,
|
|
3048
3315
|
backgroundColor: COLOR.primary,
|
|
3049
3316
|
color: COLOR.white,
|
|
3050
3317
|
border: "none",
|
|
3051
|
-
borderRadius:
|
|
3318
|
+
borderRadius: "14px",
|
|
3052
3319
|
cursor: "pointer",
|
|
3053
|
-
flexShrink: 0
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3320
|
+
flexShrink: 0,
|
|
3321
|
+
fontFamily: "inherit",
|
|
3322
|
+
fontSize: "15px",
|
|
3323
|
+
fontWeight: FONT_WEIGHT.semibold,
|
|
3324
|
+
transition: "opacity 120ms ease, background-color 120ms ease"
|
|
3325
|
+
},
|
|
3326
|
+
sendLabel: {
|
|
3327
|
+
lineHeight: 1
|
|
3328
|
+
}};
|
|
3329
|
+
function ParticipantsList({
|
|
3330
|
+
participants,
|
|
3057
3331
|
currentUserId,
|
|
3058
3332
|
isAdmin,
|
|
3059
3333
|
onRemoveUser,
|
|
@@ -3107,10 +3381,14 @@ function fallbackName(role) {
|
|
|
3107
3381
|
}
|
|
3108
3382
|
function RoleBadge2({ role }) {
|
|
3109
3383
|
const colors = {
|
|
3110
|
-
radiologist: { bg: "#
|
|
3384
|
+
radiologist: { bg: "#eef2ff", text: "#4f46e5" },
|
|
3385
|
+
// indigo
|
|
3111
3386
|
lab: { bg: "#eff6ff", text: "#2563eb" },
|
|
3112
|
-
|
|
3113
|
-
|
|
3387
|
+
// brand blue
|
|
3388
|
+
physician: { bg: "#e0f2fe", text: "#0284c7" },
|
|
3389
|
+
// sky
|
|
3390
|
+
admin: { bg: "#f1f5f9", text: "#64748b" }
|
|
3391
|
+
// slate
|
|
3114
3392
|
};
|
|
3115
3393
|
const color = colors[role];
|
|
3116
3394
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...styles9.roleBadge, backgroundColor: color.bg, color: color.text }, children: role });
|
|
@@ -3719,45 +3997,6 @@ var styles12 = {
|
|
|
3719
3997
|
letterSpacing: "0.4px"
|
|
3720
3998
|
}
|
|
3721
3999
|
};
|
|
3722
|
-
|
|
3723
|
-
// src/core/styles.ts
|
|
3724
|
-
var FONT_STACK = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
3725
|
-
var ROOT_CLASS = "natoe-colab-root";
|
|
3726
|
-
var GLOBAL_STYLE_ID = "natoe-colab-global-styles";
|
|
3727
|
-
var GLOBAL_CSS = `
|
|
3728
|
-
@keyframes natoe-colab-spin { to { transform: rotate(360deg); } }
|
|
3729
|
-
|
|
3730
|
-
@keyframes natoe-colab-message-in {
|
|
3731
|
-
from { opacity: 0; transform: translateY(4px); }
|
|
3732
|
-
to { opacity: 1; transform: translateY(0); }
|
|
3733
|
-
}
|
|
3734
|
-
|
|
3735
|
-
/* High-contrast adjustments \u2014 older users on OS-level high-contrast mode
|
|
3736
|
-
get heavier borders and stronger text without losing the package look. */
|
|
3737
|
-
@media (prefers-contrast: more) {
|
|
3738
|
-
.${ROOT_CLASS} {
|
|
3739
|
-
color: #000000;
|
|
3740
|
-
}
|
|
3741
|
-
.${ROOT_CLASS} button {
|
|
3742
|
-
outline: 1px solid currentColor;
|
|
3743
|
-
}
|
|
3744
|
-
}
|
|
3745
|
-
|
|
3746
|
-
/* Honour reduced-motion preferences by killing entry animations. */
|
|
3747
|
-
@media (prefers-reduced-motion: reduce) {
|
|
3748
|
-
.${ROOT_CLASS} [data-natoe-message-bubble] {
|
|
3749
|
-
animation: none !important;
|
|
3750
|
-
}
|
|
3751
|
-
}
|
|
3752
|
-
`;
|
|
3753
|
-
function ensureGlobalStyles() {
|
|
3754
|
-
if (typeof document === "undefined") return;
|
|
3755
|
-
if (document.getElementById(GLOBAL_STYLE_ID)) return;
|
|
3756
|
-
const style = document.createElement("style");
|
|
3757
|
-
style.id = GLOBAL_STYLE_ID;
|
|
3758
|
-
style.textContent = GLOBAL_CSS;
|
|
3759
|
-
document.head.appendChild(style);
|
|
3760
|
-
}
|
|
3761
4000
|
ensureGlobalStyles();
|
|
3762
4001
|
function CollabPanel({
|
|
3763
4002
|
orderId,
|
|
@@ -3766,6 +4005,7 @@ function CollabPanel({
|
|
|
3766
4005
|
showSeenBy = true,
|
|
3767
4006
|
onBack,
|
|
3768
4007
|
hidePatientName = false,
|
|
4008
|
+
onConversationChange,
|
|
3769
4009
|
className,
|
|
3770
4010
|
style
|
|
3771
4011
|
}) {
|
|
@@ -3794,6 +4034,9 @@ function CollabPanel({
|
|
|
3794
4034
|
pinMessage,
|
|
3795
4035
|
unpinMessage
|
|
3796
4036
|
} = useConversation({ orderId, patientData, participantIds });
|
|
4037
|
+
React4.useEffect(() => {
|
|
4038
|
+
onConversationChange?.(conversation);
|
|
4039
|
+
}, [conversation, onConversationChange]);
|
|
3797
4040
|
const channelSettings = useChannelSettings({
|
|
3798
4041
|
conversationId: conversation?.id ?? null
|
|
3799
4042
|
});
|
|
@@ -4002,6 +4245,7 @@ function CollabPopup({
|
|
|
4002
4245
|
isOpen,
|
|
4003
4246
|
onClose,
|
|
4004
4247
|
onBack,
|
|
4248
|
+
onMinimize,
|
|
4005
4249
|
initialPosition,
|
|
4006
4250
|
width = 380,
|
|
4007
4251
|
height = 520,
|
|
@@ -4015,10 +4259,12 @@ function CollabPopup({
|
|
|
4015
4259
|
);
|
|
4016
4260
|
const [isDragging, setIsDragging] = React4.useState(false);
|
|
4017
4261
|
const [isMinimized, setIsMinimized] = React4.useState(false);
|
|
4262
|
+
const [loadedConversation, setLoadedConversation] = React4.useState(null);
|
|
4018
4263
|
const dragOffset = React4.useRef({ x: 0, y: 0 });
|
|
4019
4264
|
const containerRef = React4.useRef(null);
|
|
4020
4265
|
const previouslyFocused = React4.useRef(null);
|
|
4021
4266
|
const titleId = React4.useId();
|
|
4267
|
+
const titleText = cleanChannelName(loadedConversation?.name) || buildChannelName(patientData);
|
|
4022
4268
|
const handleMouseDown = React4.useCallback(
|
|
4023
4269
|
(e) => {
|
|
4024
4270
|
if (!e.target.closest("[data-drag-handle]")) return;
|
|
@@ -4115,40 +4361,62 @@ function CollabPopup({
|
|
|
4115
4361
|
"button",
|
|
4116
4362
|
{
|
|
4117
4363
|
onClick: onBack,
|
|
4118
|
-
style: styles13.
|
|
4119
|
-
"aria-label": "
|
|
4364
|
+
style: styles13.titleSquare,
|
|
4365
|
+
"aria-label": "Back to messages",
|
|
4120
4366
|
title: "Back",
|
|
4121
4367
|
type: "button",
|
|
4122
|
-
children:
|
|
4368
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(BackIcon, { size: 18, color: COLOR.neutral700 })
|
|
4123
4369
|
}
|
|
4124
4370
|
),
|
|
4125
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4371
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles13.titleCenter, children: [
|
|
4372
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, style: styles13.patientName, children: patientData.patientName || titleText }),
|
|
4373
|
+
(patientData.labName || patientData.displayOrderId) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles13.subRow, children: [
|
|
4374
|
+
patientData.labName && /* @__PURE__ */ jsxRuntime.jsx("span", { children: patientData.labName }),
|
|
4375
|
+
patientData.labName && patientData.displayOrderId && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles13.subDot, "aria-hidden": "true", children: "\xB7" }),
|
|
4376
|
+
patientData.displayOrderId && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles13.mono, children: [
|
|
4377
|
+
"#",
|
|
4378
|
+
patientData.displayOrderId.slice(-4)
|
|
4379
|
+
] })
|
|
4380
|
+
] })
|
|
4381
|
+
] }),
|
|
4126
4382
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles13.titleActions, children: [
|
|
4127
4383
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4128
4384
|
"button",
|
|
4129
4385
|
{
|
|
4130
|
-
onClick: () =>
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4386
|
+
onClick: () => {
|
|
4387
|
+
if (onMinimize) onMinimize();
|
|
4388
|
+
else setIsMinimized(!isMinimized);
|
|
4389
|
+
},
|
|
4390
|
+
style: styles13.titleSquare,
|
|
4391
|
+
"aria-label": onMinimize ? "Minimize chat" : isMinimized ? "Expand chat" : "Minimize chat",
|
|
4392
|
+
title: onMinimize ? "Minimize" : isMinimized ? "Expand" : "Minimize",
|
|
4134
4393
|
type: "button",
|
|
4135
|
-
children: isMinimized ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4394
|
+
children: onMinimize || !isMinimized ? /* @__PURE__ */ jsxRuntime.jsx(MinimizeIcon, { size: 18, color: COLOR.neutral700 }) : /* @__PURE__ */ jsxRuntime.jsx(ExpandIcon, { size: 18, color: COLOR.neutral700 })
|
|
4136
4395
|
}
|
|
4137
4396
|
),
|
|
4138
4397
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4139
4398
|
"button",
|
|
4140
4399
|
{
|
|
4141
4400
|
onClick: onClose,
|
|
4142
|
-
style: styles13.
|
|
4401
|
+
style: styles13.titleSquare,
|
|
4143
4402
|
"aria-label": "Close chat",
|
|
4144
4403
|
title: "Close",
|
|
4145
4404
|
type: "button",
|
|
4146
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { size:
|
|
4405
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { size: 18, color: COLOR.neutral700 })
|
|
4147
4406
|
}
|
|
4148
4407
|
)
|
|
4149
4408
|
] })
|
|
4150
4409
|
] }),
|
|
4151
|
-
!isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles13.panelWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4410
|
+
!isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles13.panelWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4411
|
+
CollabPanel,
|
|
4412
|
+
{
|
|
4413
|
+
orderId,
|
|
4414
|
+
patientData,
|
|
4415
|
+
participantIds,
|
|
4416
|
+
hidePatientName: true,
|
|
4417
|
+
onConversationChange: setLoadedConversation
|
|
4418
|
+
}
|
|
4419
|
+
) })
|
|
4152
4420
|
]
|
|
4153
4421
|
}
|
|
4154
4422
|
);
|
|
@@ -4157,51 +4425,78 @@ var styles13 = {
|
|
|
4157
4425
|
container: {
|
|
4158
4426
|
position: "fixed",
|
|
4159
4427
|
zIndex: Z_INDEX.dialog,
|
|
4160
|
-
borderRadius:
|
|
4161
|
-
boxShadow:
|
|
4428
|
+
borderRadius: "20px",
|
|
4429
|
+
boxShadow: "0 20px 48px rgba(20, 21, 28, 0.16), 0 6px 16px rgba(20, 21, 28, 0.08)",
|
|
4162
4430
|
overflow: "hidden",
|
|
4163
4431
|
display: "flex",
|
|
4164
4432
|
flexDirection: "column",
|
|
4165
4433
|
backgroundColor: COLOR.white,
|
|
4166
|
-
border: `1px solid ${COLOR.
|
|
4434
|
+
border: `1px solid ${COLOR.neutral300}`,
|
|
4167
4435
|
transition: "height 0.2s ease",
|
|
4168
4436
|
fontFamily: FONT_STACK
|
|
4169
4437
|
},
|
|
4170
4438
|
titleBar: {
|
|
4171
4439
|
display: "flex",
|
|
4172
|
-
justifyContent: "space-between",
|
|
4173
4440
|
alignItems: "center",
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
backgroundColor: COLOR.
|
|
4441
|
+
gap: SPACE.S2,
|
|
4442
|
+
padding: `10px ${SPACE.S3}`,
|
|
4443
|
+
backgroundColor: COLOR.white,
|
|
4444
|
+
borderBottom: `1px solid ${COLOR.neutral200}`,
|
|
4177
4445
|
cursor: "grab",
|
|
4178
4446
|
userSelect: "none",
|
|
4179
4447
|
flexShrink: 0
|
|
4180
4448
|
},
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4449
|
+
titleCenter: {
|
|
4450
|
+
flex: 1,
|
|
4451
|
+
minWidth: 0,
|
|
4452
|
+
display: "flex",
|
|
4453
|
+
flexDirection: "column",
|
|
4454
|
+
gap: "2px"
|
|
4455
|
+
},
|
|
4456
|
+
patientName: {
|
|
4457
|
+
margin: 0,
|
|
4458
|
+
fontSize: FONT_SIZE.lg,
|
|
4459
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
4460
|
+
letterSpacing: "-0.01em",
|
|
4461
|
+
color: COLOR.neutral900,
|
|
4462
|
+
overflow: "hidden",
|
|
4463
|
+
textOverflow: "ellipsis",
|
|
4464
|
+
whiteSpace: "nowrap"
|
|
4465
|
+
},
|
|
4466
|
+
subRow: {
|
|
4467
|
+
display: "flex",
|
|
4468
|
+
alignItems: "center",
|
|
4469
|
+
gap: SPACE.S2,
|
|
4470
|
+
fontSize: FONT_SIZE.sm,
|
|
4471
|
+
color: COLOR.neutral500,
|
|
4185
4472
|
overflow: "hidden",
|
|
4186
4473
|
textOverflow: "ellipsis",
|
|
4187
4474
|
whiteSpace: "nowrap"
|
|
4188
4475
|
},
|
|
4476
|
+
subDot: {
|
|
4477
|
+
color: COLOR.neutral400
|
|
4478
|
+
},
|
|
4479
|
+
mono: {
|
|
4480
|
+
fontFamily: "'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
4481
|
+
fontVariantNumeric: "tabular-nums"
|
|
4482
|
+
},
|
|
4189
4483
|
titleActions: {
|
|
4190
4484
|
display: "flex",
|
|
4191
4485
|
gap: SPACE.S1,
|
|
4192
4486
|
flexShrink: 0
|
|
4193
4487
|
},
|
|
4194
|
-
|
|
4195
|
-
width:
|
|
4196
|
-
height:
|
|
4488
|
+
titleSquare: {
|
|
4489
|
+
width: "36px",
|
|
4490
|
+
height: "36px",
|
|
4197
4491
|
display: "flex",
|
|
4198
4492
|
alignItems: "center",
|
|
4199
4493
|
justifyContent: "center",
|
|
4200
|
-
backgroundColor:
|
|
4201
|
-
border:
|
|
4494
|
+
backgroundColor: COLOR.neutral100,
|
|
4495
|
+
border: `1px solid ${COLOR.neutral200}`,
|
|
4202
4496
|
borderRadius: RADIUS.md,
|
|
4203
4497
|
cursor: "pointer",
|
|
4204
|
-
color: COLOR.
|
|
4498
|
+
color: COLOR.neutral700,
|
|
4499
|
+
flexShrink: 0
|
|
4205
4500
|
},
|
|
4206
4501
|
panelWrapper: {
|
|
4207
4502
|
flex: 1,
|
|
@@ -4505,10 +4800,14 @@ function InlineMessageRow({ message }) {
|
|
|
4505
4800
|
}
|
|
4506
4801
|
function RoleDot({ role }) {
|
|
4507
4802
|
const colors = {
|
|
4508
|
-
radiologist: "#
|
|
4803
|
+
radiologist: "#4f46e5",
|
|
4804
|
+
// indigo
|
|
4509
4805
|
lab: "#2563eb",
|
|
4510
|
-
|
|
4511
|
-
|
|
4806
|
+
// brand blue
|
|
4807
|
+
physician: "#0284c7",
|
|
4808
|
+
// sky
|
|
4809
|
+
admin: "#64748b"
|
|
4810
|
+
// slate
|
|
4512
4811
|
};
|
|
4513
4812
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...styles14.roleDot, backgroundColor: colors[role] } });
|
|
4514
4813
|
}
|
|
@@ -4930,6 +5229,10 @@ function ConversationListItem({
|
|
|
4930
5229
|
}) {
|
|
4931
5230
|
const hasUnread = item.unreadCount > 0;
|
|
4932
5231
|
const displayName = item.name || item.patientSnapshot?.patientName || "Unknown";
|
|
5232
|
+
const studyType = item.patientSnapshot?.studyType;
|
|
5233
|
+
const patientId = item.patientSnapshot?.patientId;
|
|
5234
|
+
const showStudyRow = !!(studyType || patientId);
|
|
5235
|
+
const initials = computeInitials2(item.patientSnapshot?.patientName || displayName);
|
|
4933
5236
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4934
5237
|
"button",
|
|
4935
5238
|
{
|
|
@@ -4937,15 +5240,11 @@ function ConversationListItem({
|
|
|
4937
5240
|
onClick,
|
|
4938
5241
|
style: {
|
|
4939
5242
|
...styles15.container,
|
|
4940
|
-
...isSelected ? styles15.selected : {}
|
|
4941
|
-
...hasUnread ? styles15.unread : {}
|
|
5243
|
+
...isSelected ? styles15.selected : {}
|
|
4942
5244
|
},
|
|
4943
5245
|
type: "button",
|
|
4944
5246
|
children: [
|
|
4945
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4946
|
-
item.picture ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: item.picture, alt: "", style: styles15.avatar }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles15.avatarFallback, children: (displayName).charAt(0).toUpperCase() }),
|
|
4947
|
-
hasUnread && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.unreadDot })
|
|
4948
|
-
] }),
|
|
5247
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles15.avatarWrapper, children: item.picture ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: item.picture, alt: "", style: styles15.avatarImg }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles15.avatarTile, "aria-hidden": "true", children: initials }) }),
|
|
4949
5248
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles15.content, children: [
|
|
4950
5249
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles15.topRow, children: [
|
|
4951
5250
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4969,101 +5268,120 @@ function ConversationListItem({
|
|
|
4969
5268
|
}
|
|
4970
5269
|
)
|
|
4971
5270
|
] }),
|
|
5271
|
+
showStudyRow && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles15.studyRow, children: [
|
|
5272
|
+
studyType && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.studyType, children: studyType }),
|
|
5273
|
+
studyType && patientId && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.studyDivider, children: "\xB7" }),
|
|
5274
|
+
patientId && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles15.studyId, children: [
|
|
5275
|
+
"MRN ",
|
|
5276
|
+
patientId
|
|
5277
|
+
] })
|
|
5278
|
+
] }),
|
|
4972
5279
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles15.bottomRow, children: [
|
|
4973
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4974
|
-
|
|
4975
|
-
{
|
|
4976
|
-
style: {
|
|
4977
|
-
...styles15.preview,
|
|
4978
|
-
...hasUnread ? styles15.previewUnread : {}
|
|
4979
|
-
},
|
|
4980
|
-
children: renderLastMessagePreview(item.lastMessage)
|
|
4981
|
-
}
|
|
4982
|
-
),
|
|
4983
|
-
hasUnread && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.badge, children: item.unreadCount > 99 ? "99+" : item.unreadCount })
|
|
5280
|
+
/* @__PURE__ */ jsxRuntime.jsx(PreviewLine, { message: item.lastMessage, hasUnread }),
|
|
5281
|
+
hasUnread && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.badge, "aria-label": `${item.unreadCount} unread`, children: item.unreadCount > 99 ? "99+" : item.unreadCount })
|
|
4984
5282
|
] })
|
|
4985
5283
|
] })
|
|
4986
5284
|
]
|
|
4987
5285
|
}
|
|
4988
5286
|
);
|
|
4989
5287
|
}
|
|
4990
|
-
function
|
|
4991
|
-
if (!message)
|
|
4992
|
-
|
|
5288
|
+
function PreviewLine({ message, hasUnread }) {
|
|
5289
|
+
if (!message) {
|
|
5290
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.preview, children: "No messages yet" });
|
|
5291
|
+
}
|
|
5292
|
+
if (message.type === "system") {
|
|
5293
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles15.preview, children: message.body });
|
|
5294
|
+
}
|
|
5295
|
+
const text = previewText(message);
|
|
5296
|
+
const sender = message.senderName ? `${message.senderName.split(" ")[0]}:` : "";
|
|
5297
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5298
|
+
"span",
|
|
5299
|
+
{
|
|
5300
|
+
style: {
|
|
5301
|
+
...styles15.preview,
|
|
5302
|
+
...hasUnread ? styles15.previewUnread : {}
|
|
5303
|
+
},
|
|
5304
|
+
children: [
|
|
5305
|
+
sender && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles15.previewSender, children: [
|
|
5306
|
+
sender,
|
|
5307
|
+
" "
|
|
5308
|
+
] }),
|
|
5309
|
+
text
|
|
5310
|
+
]
|
|
5311
|
+
}
|
|
5312
|
+
);
|
|
5313
|
+
}
|
|
5314
|
+
function previewText(message) {
|
|
4993
5315
|
switch (message.type) {
|
|
4994
5316
|
case "audio":
|
|
4995
|
-
return
|
|
5317
|
+
return "Voice message";
|
|
4996
5318
|
case "image":
|
|
4997
|
-
return
|
|
5319
|
+
return message.fileName || "Image";
|
|
4998
5320
|
case "file":
|
|
4999
|
-
return
|
|
5321
|
+
return message.fileName || "File";
|
|
5000
5322
|
case "deep_link":
|
|
5001
|
-
return
|
|
5002
|
-
case "system":
|
|
5003
|
-
return message.body;
|
|
5323
|
+
return message.body || "Shared link";
|
|
5004
5324
|
default: {
|
|
5005
5325
|
const body = message.body || "";
|
|
5006
|
-
|
|
5007
|
-
return `${prefix}${preview}`;
|
|
5326
|
+
return body.length > 60 ? `${body.slice(0, 60)}\u2026` : body;
|
|
5008
5327
|
}
|
|
5009
5328
|
}
|
|
5010
5329
|
}
|
|
5330
|
+
function computeInitials2(name) {
|
|
5331
|
+
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase() ?? "").join("") || "?";
|
|
5332
|
+
}
|
|
5011
5333
|
var styles15 = {
|
|
5012
5334
|
container: {
|
|
5013
5335
|
display: "flex",
|
|
5014
|
-
alignItems: "
|
|
5015
|
-
gap:
|
|
5016
|
-
padding: `${SPACE.S3} ${SPACE.S3}`,
|
|
5336
|
+
alignItems: "flex-start",
|
|
5337
|
+
gap: "14px",
|
|
5017
5338
|
width: "100%",
|
|
5339
|
+
padding: `14px ${SPACE.S5}`,
|
|
5340
|
+
minHeight: "84px",
|
|
5018
5341
|
backgroundColor: "transparent",
|
|
5019
5342
|
border: "none",
|
|
5020
|
-
|
|
5343
|
+
borderLeft: "4px solid transparent",
|
|
5021
5344
|
cursor: "pointer",
|
|
5022
|
-
textAlign: "left"
|
|
5345
|
+
textAlign: "left",
|
|
5346
|
+
color: "inherit",
|
|
5347
|
+
fontFamily: "inherit",
|
|
5348
|
+
transition: "background-color 120ms ease"
|
|
5023
5349
|
},
|
|
5024
5350
|
selected: {
|
|
5025
|
-
backgroundColor: COLOR.primaryBg
|
|
5351
|
+
backgroundColor: COLOR.primaryBg,
|
|
5352
|
+
borderLeftColor: COLOR.primary
|
|
5026
5353
|
},
|
|
5027
|
-
unread: {},
|
|
5028
5354
|
avatarWrapper: {
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
height: SIZE.avatar,
|
|
5355
|
+
width: "52px",
|
|
5356
|
+
height: "52px",
|
|
5032
5357
|
flexShrink: 0
|
|
5033
5358
|
},
|
|
5034
|
-
|
|
5035
|
-
width:
|
|
5036
|
-
height:
|
|
5037
|
-
borderRadius: RADIUS.
|
|
5038
|
-
objectFit: "cover"
|
|
5359
|
+
avatarImg: {
|
|
5360
|
+
width: "52px",
|
|
5361
|
+
height: "52px",
|
|
5362
|
+
borderRadius: RADIUS.xl,
|
|
5363
|
+
objectFit: "cover",
|
|
5364
|
+
boxShadow: "inset 0 -2px 0 rgba(0, 0, 0, 0.08)"
|
|
5039
5365
|
},
|
|
5040
|
-
|
|
5041
|
-
width:
|
|
5042
|
-
height:
|
|
5043
|
-
borderRadius: RADIUS.
|
|
5044
|
-
backgroundColor: COLOR.
|
|
5366
|
+
avatarTile: {
|
|
5367
|
+
width: "52px",
|
|
5368
|
+
height: "52px",
|
|
5369
|
+
borderRadius: RADIUS.xl,
|
|
5370
|
+
backgroundColor: COLOR.primary,
|
|
5371
|
+
color: COLOR.white,
|
|
5045
5372
|
display: "flex",
|
|
5046
5373
|
alignItems: "center",
|
|
5047
5374
|
justifyContent: "center",
|
|
5048
|
-
fontSize: FONT_SIZE.
|
|
5049
|
-
fontWeight: FONT_WEIGHT.
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
unreadDot: {
|
|
5053
|
-
position: "absolute",
|
|
5054
|
-
top: "0",
|
|
5055
|
-
left: "0",
|
|
5056
|
-
width: SIZE.dot,
|
|
5057
|
-
height: SIZE.dot,
|
|
5058
|
-
borderRadius: RADIUS.full,
|
|
5059
|
-
backgroundColor: COLOR.primary,
|
|
5060
|
-
border: `2px solid ${COLOR.white}`
|
|
5375
|
+
fontSize: FONT_SIZE.lg,
|
|
5376
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
5377
|
+
letterSpacing: "0.02em",
|
|
5378
|
+
boxShadow: "inset 0 -2px 0 rgba(0, 0, 0, 0.08)"
|
|
5061
5379
|
},
|
|
5062
5380
|
content: {
|
|
5063
5381
|
flex: 1,
|
|
5064
5382
|
display: "flex",
|
|
5065
5383
|
flexDirection: "column",
|
|
5066
|
-
gap: "
|
|
5384
|
+
gap: "3px",
|
|
5067
5385
|
minWidth: 0
|
|
5068
5386
|
},
|
|
5069
5387
|
topRow: {
|
|
@@ -5088,123 +5406,191 @@ var styles15 = {
|
|
|
5088
5406
|
time: {
|
|
5089
5407
|
fontSize: FONT_SIZE.xs,
|
|
5090
5408
|
color: COLOR.neutral500,
|
|
5409
|
+
fontVariantNumeric: "tabular-nums",
|
|
5091
5410
|
flexShrink: 0
|
|
5092
5411
|
},
|
|
5093
5412
|
timeUnread: {
|
|
5094
5413
|
color: COLOR.primary,
|
|
5095
5414
|
fontWeight: FONT_WEIGHT.semibold
|
|
5096
5415
|
},
|
|
5416
|
+
studyRow: {
|
|
5417
|
+
display: "flex",
|
|
5418
|
+
alignItems: "center",
|
|
5419
|
+
gap: SPACE.S2,
|
|
5420
|
+
minWidth: 0
|
|
5421
|
+
},
|
|
5422
|
+
studyType: {
|
|
5423
|
+
fontSize: FONT_SIZE.sm,
|
|
5424
|
+
color: COLOR.neutral500,
|
|
5425
|
+
overflow: "hidden",
|
|
5426
|
+
textOverflow: "ellipsis",
|
|
5427
|
+
whiteSpace: "nowrap"
|
|
5428
|
+
},
|
|
5429
|
+
studyDivider: {
|
|
5430
|
+
fontSize: FONT_SIZE.sm,
|
|
5431
|
+
color: COLOR.neutral400,
|
|
5432
|
+
flexShrink: 0
|
|
5433
|
+
},
|
|
5434
|
+
studyId: {
|
|
5435
|
+
fontSize: FONT_SIZE.sm,
|
|
5436
|
+
color: COLOR.neutral500,
|
|
5437
|
+
fontFamily: "'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
5438
|
+
fontVariantNumeric: "tabular-nums",
|
|
5439
|
+
flexShrink: 0
|
|
5440
|
+
},
|
|
5097
5441
|
bottomRow: {
|
|
5098
5442
|
display: "flex",
|
|
5099
5443
|
justifyContent: "space-between",
|
|
5100
5444
|
alignItems: "center",
|
|
5101
|
-
gap: SPACE.S2
|
|
5445
|
+
gap: SPACE.S2,
|
|
5446
|
+
marginTop: "2px"
|
|
5102
5447
|
},
|
|
5103
5448
|
preview: {
|
|
5104
5449
|
fontSize: FONT_SIZE.sm,
|
|
5105
|
-
color: COLOR.
|
|
5450
|
+
color: COLOR.neutral500,
|
|
5106
5451
|
overflow: "hidden",
|
|
5107
5452
|
textOverflow: "ellipsis",
|
|
5108
5453
|
whiteSpace: "nowrap",
|
|
5109
5454
|
flex: 1,
|
|
5110
5455
|
minWidth: 0
|
|
5111
5456
|
},
|
|
5457
|
+
previewSender: {
|
|
5458
|
+
color: COLOR.neutral700,
|
|
5459
|
+
fontWeight: FONT_WEIGHT.semibold
|
|
5460
|
+
},
|
|
5112
5461
|
previewUnread: {
|
|
5113
5462
|
color: COLOR.neutral900,
|
|
5114
5463
|
fontWeight: FONT_WEIGHT.medium
|
|
5115
5464
|
},
|
|
5116
5465
|
badge: {
|
|
5117
|
-
minWidth: "
|
|
5118
|
-
height: "
|
|
5119
|
-
padding:
|
|
5466
|
+
minWidth: "22px",
|
|
5467
|
+
height: "22px",
|
|
5468
|
+
padding: "0 9px",
|
|
5120
5469
|
fontSize: FONT_SIZE.xs,
|
|
5121
|
-
fontWeight: FONT_WEIGHT.
|
|
5470
|
+
fontWeight: FONT_WEIGHT.bold,
|
|
5122
5471
|
color: COLOR.white,
|
|
5123
|
-
backgroundColor: COLOR.
|
|
5472
|
+
backgroundColor: COLOR.danger,
|
|
5124
5473
|
borderRadius: RADIUS.pill,
|
|
5125
5474
|
display: "flex",
|
|
5126
5475
|
alignItems: "center",
|
|
5127
5476
|
justifyContent: "center",
|
|
5477
|
+
fontVariantNumeric: "tabular-nums",
|
|
5128
5478
|
flexShrink: 0
|
|
5129
5479
|
}
|
|
5130
5480
|
};
|
|
5481
|
+
function SearchIcon({ size = 20, color = "currentColor" }) {
|
|
5482
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5483
|
+
"svg",
|
|
5484
|
+
{
|
|
5485
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
5486
|
+
width: size,
|
|
5487
|
+
height: size,
|
|
5488
|
+
viewBox: "0 0 24 24",
|
|
5489
|
+
fill: "none",
|
|
5490
|
+
stroke: color,
|
|
5491
|
+
strokeWidth: "2",
|
|
5492
|
+
strokeLinecap: "round",
|
|
5493
|
+
strokeLinejoin: "round",
|
|
5494
|
+
"aria-hidden": "true",
|
|
5495
|
+
children: [
|
|
5496
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "7" }),
|
|
5497
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 20l-4-4" })
|
|
5498
|
+
]
|
|
5499
|
+
}
|
|
5500
|
+
);
|
|
5501
|
+
}
|
|
5131
5502
|
function ConversationList({
|
|
5132
5503
|
conversations,
|
|
5133
5504
|
selectedId,
|
|
5134
5505
|
isLoading,
|
|
5135
5506
|
error,
|
|
5136
5507
|
onSelect,
|
|
5137
|
-
title = "Conversations",
|
|
5138
5508
|
className
|
|
5139
5509
|
}) {
|
|
5140
5510
|
const [query, setQuery] = React4.useState("");
|
|
5141
|
-
const [
|
|
5511
|
+
const [filter, setFilter] = React4.useState("all");
|
|
5512
|
+
const [searchFocused, setSearchFocused] = React4.useState(false);
|
|
5513
|
+
const unreadCount = React4.useMemo(
|
|
5514
|
+
() => conversations.filter((c) => c.unreadCount > 0).length,
|
|
5515
|
+
[conversations]
|
|
5516
|
+
);
|
|
5517
|
+
const autoDefaultedRef = React4.useRef(false);
|
|
5518
|
+
React4.useEffect(() => {
|
|
5519
|
+
if (autoDefaultedRef.current) return;
|
|
5520
|
+
if (conversations.length === 0) return;
|
|
5521
|
+
autoDefaultedRef.current = true;
|
|
5522
|
+
if (unreadCount > 0) setFilter("unread");
|
|
5523
|
+
}, [conversations.length, unreadCount]);
|
|
5142
5524
|
const filtered = React4.useMemo(() => {
|
|
5143
5525
|
let result = conversations;
|
|
5144
|
-
if (
|
|
5526
|
+
if (filter === "unread") {
|
|
5145
5527
|
result = result.filter((c) => c.unreadCount > 0);
|
|
5146
5528
|
}
|
|
5147
5529
|
const q = query.trim().toLowerCase();
|
|
5148
5530
|
if (q) {
|
|
5149
5531
|
result = result.filter((c) => {
|
|
5150
|
-
const patient = c.patientSnapshot?.patientName?.toLowerCase() || "";
|
|
5151
5532
|
const name = c.name.toLowerCase();
|
|
5152
|
-
|
|
5533
|
+
const patient = c.patientSnapshot?.patientName?.toLowerCase() || "";
|
|
5534
|
+
const studyType = c.patientSnapshot?.studyType?.toLowerCase() || "";
|
|
5535
|
+
const patientId = c.patientSnapshot?.patientId?.toLowerCase() || "";
|
|
5536
|
+
return name.includes(q) || patient.includes(q) || studyType.includes(q) || patientId.includes(q);
|
|
5153
5537
|
});
|
|
5154
5538
|
}
|
|
5155
5539
|
return result;
|
|
5156
|
-
}, [conversations, query,
|
|
5157
|
-
const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);
|
|
5540
|
+
}, [conversations, query, filter]);
|
|
5158
5541
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles16.container, children: [
|
|
5159
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles16.
|
|
5160
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5161
|
-
|
|
5162
|
-
totalUnread > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles16.totalBadge, children: totalUnread })
|
|
5163
|
-
] }),
|
|
5164
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles16.searchRow, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5165
|
-
"input",
|
|
5542
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles16.tabs, children: [
|
|
5543
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5544
|
+
TabButton,
|
|
5166
5545
|
{
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
style: styles16.searchInput
|
|
5546
|
+
label: "Unread",
|
|
5547
|
+
count: unreadCount,
|
|
5548
|
+
isActive: filter === "unread",
|
|
5549
|
+
onClick: () => setFilter("unread")
|
|
5172
5550
|
}
|
|
5173
|
-
)
|
|
5174
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
type: "button",
|
|
5184
|
-
children: "All"
|
|
5185
|
-
}
|
|
5186
|
-
),
|
|
5187
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5188
|
-
"button",
|
|
5189
|
-
{
|
|
5190
|
-
onClick: () => setShowUnreadOnly(true),
|
|
5191
|
-
style: {
|
|
5192
|
-
...styles16.filterButton,
|
|
5193
|
-
...showUnreadOnly ? styles16.filterButtonActive : {}
|
|
5194
|
-
},
|
|
5195
|
-
type: "button",
|
|
5196
|
-
children: [
|
|
5197
|
-
"Unread ",
|
|
5198
|
-
totalUnread > 0 && `(${totalUnread})`
|
|
5199
|
-
]
|
|
5200
|
-
}
|
|
5201
|
-
)
|
|
5202
|
-
] })
|
|
5551
|
+
),
|
|
5552
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5553
|
+
TabButton,
|
|
5554
|
+
{
|
|
5555
|
+
label: "All",
|
|
5556
|
+
count: conversations.length,
|
|
5557
|
+
isActive: filter === "all",
|
|
5558
|
+
onClick: () => setFilter("all")
|
|
5559
|
+
}
|
|
5560
|
+
)
|
|
5203
5561
|
] }),
|
|
5562
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5563
|
+
"div",
|
|
5564
|
+
{
|
|
5565
|
+
style: {
|
|
5566
|
+
...styles16.search,
|
|
5567
|
+
...searchFocused ? styles16.searchFocused : {}
|
|
5568
|
+
},
|
|
5569
|
+
children: [
|
|
5570
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: styles16.searchIcon, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { size: 20, color: COLOR.neutral500 }) }),
|
|
5571
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5572
|
+
"input",
|
|
5573
|
+
{
|
|
5574
|
+
type: "text",
|
|
5575
|
+
value: query,
|
|
5576
|
+
onChange: (e) => setQuery(e.target.value),
|
|
5577
|
+
onFocus: () => setSearchFocused(true),
|
|
5578
|
+
onBlur: () => setSearchFocused(false),
|
|
5579
|
+
placeholder: "Search by patient name or MRN",
|
|
5580
|
+
"aria-label": "Search conversations",
|
|
5581
|
+
style: styles16.searchInput
|
|
5582
|
+
}
|
|
5583
|
+
)
|
|
5584
|
+
]
|
|
5585
|
+
}
|
|
5586
|
+
),
|
|
5204
5587
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles16.list, children: [
|
|
5205
|
-
isLoading && /* @__PURE__ */ jsxRuntime.
|
|
5206
|
-
|
|
5207
|
-
|
|
5588
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles16.loading, children: [
|
|
5589
|
+
/* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 16 }),
|
|
5590
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading conversations\u2026" })
|
|
5591
|
+
] }),
|
|
5592
|
+
error && !isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles16.errorState, children: error }),
|
|
5593
|
+
!isLoading && !error && filtered.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { filter, hasQuery: query.trim().length > 0 }),
|
|
5208
5594
|
filtered.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5209
5595
|
ConversationListItem,
|
|
5210
5596
|
{
|
|
@@ -5217,95 +5603,178 @@ function ConversationList({
|
|
|
5217
5603
|
] })
|
|
5218
5604
|
] });
|
|
5219
5605
|
}
|
|
5606
|
+
function TabButton({
|
|
5607
|
+
label,
|
|
5608
|
+
count,
|
|
5609
|
+
isActive,
|
|
5610
|
+
onClick
|
|
5611
|
+
}) {
|
|
5612
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5613
|
+
"button",
|
|
5614
|
+
{
|
|
5615
|
+
type: "button",
|
|
5616
|
+
onClick,
|
|
5617
|
+
style: {
|
|
5618
|
+
...styles16.tab,
|
|
5619
|
+
...isActive ? styles16.tabActive : {}
|
|
5620
|
+
},
|
|
5621
|
+
children: [
|
|
5622
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
|
|
5623
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5624
|
+
"span",
|
|
5625
|
+
{
|
|
5626
|
+
style: {
|
|
5627
|
+
...styles16.tabCount,
|
|
5628
|
+
...isActive ? styles16.tabCountActive : {}
|
|
5629
|
+
},
|
|
5630
|
+
children: count
|
|
5631
|
+
}
|
|
5632
|
+
)
|
|
5633
|
+
]
|
|
5634
|
+
}
|
|
5635
|
+
);
|
|
5636
|
+
}
|
|
5637
|
+
function EmptyState({ filter, hasQuery }) {
|
|
5638
|
+
let title = "No conversations yet";
|
|
5639
|
+
let subtitle = "New chats will show up here as cases come in.";
|
|
5640
|
+
if (filter === "unread") {
|
|
5641
|
+
title = "No unread messages";
|
|
5642
|
+
subtitle = "You're all caught up.";
|
|
5643
|
+
} else if (hasQuery) {
|
|
5644
|
+
title = "No conversations match";
|
|
5645
|
+
subtitle = "Try a different search.";
|
|
5646
|
+
}
|
|
5647
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles16.empty, children: [
|
|
5648
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChatIllustration, { size: 88 }),
|
|
5649
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: styles16.emptyTitle, children: title }),
|
|
5650
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: styles16.emptySubtitle, children: subtitle })
|
|
5651
|
+
] });
|
|
5652
|
+
}
|
|
5220
5653
|
var styles16 = {
|
|
5221
5654
|
container: {
|
|
5222
5655
|
display: "flex",
|
|
5223
5656
|
flexDirection: "column",
|
|
5224
5657
|
height: "100%",
|
|
5225
|
-
backgroundColor: COLOR.white
|
|
5226
|
-
borderRight: `1px solid ${COLOR.neutral200}`
|
|
5658
|
+
backgroundColor: COLOR.white
|
|
5227
5659
|
},
|
|
5228
|
-
header
|
|
5229
|
-
|
|
5660
|
+
// Tabs sit at the top of the panel now (header section removed).
|
|
5661
|
+
// A bit more top padding so they don't crowd the top edge.
|
|
5662
|
+
tabs: {
|
|
5663
|
+
display: "flex",
|
|
5664
|
+
gap: SPACE.S2,
|
|
5665
|
+
padding: `${SPACE.S5} ${SPACE.S5} ${SPACE.S2}`,
|
|
5230
5666
|
borderBottom: `1px solid ${COLOR.neutral200}`,
|
|
5231
|
-
backgroundColor: COLOR.neutral50,
|
|
5232
5667
|
flexShrink: 0
|
|
5233
5668
|
},
|
|
5234
|
-
|
|
5235
|
-
display: "flex",
|
|
5669
|
+
tab: {
|
|
5670
|
+
display: "inline-flex",
|
|
5236
5671
|
alignItems: "center",
|
|
5237
5672
|
gap: SPACE.S2,
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5673
|
+
padding: `${SPACE.S2} ${SPACE.S4}`,
|
|
5674
|
+
backgroundColor: "transparent",
|
|
5675
|
+
border: "none",
|
|
5676
|
+
borderRadius: RADIUS.lg,
|
|
5677
|
+
cursor: "pointer",
|
|
5678
|
+
color: COLOR.neutral500,
|
|
5679
|
+
fontFamily: "inherit",
|
|
5680
|
+
fontSize: FONT_SIZE.sm,
|
|
5243
5681
|
fontWeight: FONT_WEIGHT.semibold,
|
|
5244
|
-
|
|
5682
|
+
transition: "background-color 120ms ease, color 120ms ease"
|
|
5245
5683
|
},
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5684
|
+
tabActive: {
|
|
5685
|
+
backgroundColor: COLOR.primaryBg,
|
|
5686
|
+
color: COLOR.primary
|
|
5687
|
+
},
|
|
5688
|
+
tabCount: {
|
|
5250
5689
|
fontSize: FONT_SIZE.xs,
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
backgroundColor: COLOR.primary,
|
|
5690
|
+
fontVariantNumeric: "tabular-nums",
|
|
5691
|
+
padding: "1px 8px",
|
|
5254
5692
|
borderRadius: RADIUS.pill,
|
|
5693
|
+
backgroundColor: COLOR.neutral200,
|
|
5694
|
+
color: COLOR.neutral500,
|
|
5695
|
+
fontWeight: FONT_WEIGHT.semibold
|
|
5696
|
+
},
|
|
5697
|
+
tabCountActive: {
|
|
5698
|
+
backgroundColor: COLOR.primary,
|
|
5699
|
+
color: COLOR.white
|
|
5700
|
+
},
|
|
5701
|
+
search: {
|
|
5255
5702
|
display: "flex",
|
|
5256
5703
|
alignItems: "center",
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5704
|
+
gap: SPACE.S2,
|
|
5705
|
+
margin: `14px ${SPACE.S5} ${SPACE.S3}`,
|
|
5706
|
+
padding: `${SPACE.S3} 14px`,
|
|
5707
|
+
backgroundColor: COLOR.neutral100,
|
|
5708
|
+
border: `1.5px solid ${COLOR.neutral200}`,
|
|
5709
|
+
borderRadius: "14px",
|
|
5710
|
+
transition: "background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease"
|
|
5261
5711
|
},
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
border: `1px solid ${COLOR.neutral200}`,
|
|
5267
|
-
borderRadius: RADIUS.md,
|
|
5268
|
-
outline: "none",
|
|
5269
|
-
fontFamily: "inherit"
|
|
5712
|
+
searchFocused: {
|
|
5713
|
+
backgroundColor: COLOR.white,
|
|
5714
|
+
borderColor: COLOR.primary,
|
|
5715
|
+
boxShadow: `0 0 0 3px ${COLOR.primaryBg}`
|
|
5270
5716
|
},
|
|
5271
|
-
|
|
5717
|
+
searchIcon: {
|
|
5272
5718
|
display: "flex",
|
|
5273
|
-
|
|
5719
|
+
alignItems: "center",
|
|
5720
|
+
justifyContent: "center",
|
|
5721
|
+
flexShrink: 0
|
|
5274
5722
|
},
|
|
5275
|
-
|
|
5723
|
+
searchInput: {
|
|
5276
5724
|
flex: 1,
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
},
|
|
5285
|
-
filterButtonActive: {
|
|
5286
|
-
color: COLOR.white,
|
|
5287
|
-
backgroundColor: COLOR.primary,
|
|
5288
|
-
borderColor: COLOR.primary,
|
|
5289
|
-
fontWeight: FONT_WEIGHT.medium
|
|
5725
|
+
minWidth: 0,
|
|
5726
|
+
border: "none",
|
|
5727
|
+
background: "transparent",
|
|
5728
|
+
outline: "none",
|
|
5729
|
+
fontFamily: "inherit",
|
|
5730
|
+
fontSize: FONT_SIZE.md,
|
|
5731
|
+
color: COLOR.neutral900
|
|
5290
5732
|
},
|
|
5291
5733
|
list: {
|
|
5292
5734
|
flex: 1,
|
|
5293
|
-
overflowY: "auto"
|
|
5735
|
+
overflowY: "auto",
|
|
5736
|
+
padding: "4px 0 12px"
|
|
5294
5737
|
},
|
|
5295
|
-
|
|
5296
|
-
|
|
5738
|
+
loading: {
|
|
5739
|
+
display: "flex",
|
|
5740
|
+
alignItems: "center",
|
|
5741
|
+
justifyContent: "center",
|
|
5742
|
+
gap: SPACE.S2,
|
|
5743
|
+
padding: `44px ${SPACE.S5}`,
|
|
5297
5744
|
fontSize: FONT_SIZE.sm,
|
|
5298
|
-
color: COLOR.neutral500
|
|
5299
|
-
textAlign: "center"
|
|
5745
|
+
color: COLOR.neutral500
|
|
5300
5746
|
},
|
|
5301
5747
|
errorState: {
|
|
5302
5748
|
padding: SPACE.S4,
|
|
5749
|
+
margin: SPACE.S3,
|
|
5303
5750
|
fontSize: FONT_SIZE.sm,
|
|
5304
5751
|
color: COLOR.danger,
|
|
5305
5752
|
backgroundColor: COLOR.dangerBg,
|
|
5306
|
-
|
|
5753
|
+
border: `1px solid ${COLOR.dangerBorder}`,
|
|
5307
5754
|
borderRadius: RADIUS.md,
|
|
5308
5755
|
textAlign: "center"
|
|
5756
|
+
},
|
|
5757
|
+
empty: {
|
|
5758
|
+
display: "flex",
|
|
5759
|
+
flexDirection: "column",
|
|
5760
|
+
alignItems: "center",
|
|
5761
|
+
justifyContent: "center",
|
|
5762
|
+
padding: "44px 24px",
|
|
5763
|
+
textAlign: "center",
|
|
5764
|
+
color: COLOR.neutral500
|
|
5765
|
+
},
|
|
5766
|
+
emptyTitle: {
|
|
5767
|
+
margin: "12px 0 4px",
|
|
5768
|
+
fontSize: FONT_SIZE.md,
|
|
5769
|
+
fontWeight: FONT_WEIGHT.semibold,
|
|
5770
|
+
color: COLOR.neutral700
|
|
5771
|
+
},
|
|
5772
|
+
emptySubtitle: {
|
|
5773
|
+
margin: 0,
|
|
5774
|
+
fontSize: FONT_SIZE.sm,
|
|
5775
|
+
color: COLOR.neutral500,
|
|
5776
|
+
maxWidth: "280px",
|
|
5777
|
+
lineHeight: LINE_HEIGHT.normal
|
|
5309
5778
|
}
|
|
5310
5779
|
};
|
|
5311
5780
|
ensureGlobalStyles();
|
|
@@ -5313,7 +5782,6 @@ var COMPACT_BREAKPOINT = 720;
|
|
|
5313
5782
|
function CollabInbox({
|
|
5314
5783
|
initialConversationId,
|
|
5315
5784
|
onSelectConversation,
|
|
5316
|
-
title,
|
|
5317
5785
|
className,
|
|
5318
5786
|
style
|
|
5319
5787
|
}) {
|
|
@@ -5350,8 +5818,7 @@ function CollabInbox({
|
|
|
5350
5818
|
selectedId,
|
|
5351
5819
|
isLoading,
|
|
5352
5820
|
error,
|
|
5353
|
-
onSelect: handleSelect
|
|
5354
|
-
title
|
|
5821
|
+
onSelect: handleSelect
|
|
5355
5822
|
}
|
|
5356
5823
|
) }),
|
|
5357
5824
|
showDetail && /* @__PURE__ */ jsxRuntime.jsx("div", { style: isCompact ? styles17.mainCompact : styles17.main, children: selected ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5364,7 +5831,7 @@ function CollabInbox({
|
|
|
5364
5831
|
onBack: isCompact ? () => setSelectedId(null) : void 0
|
|
5365
5832
|
},
|
|
5366
5833
|
selected.id
|
|
5367
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5834
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(EmptyState2, { hasAny: conversations.length > 0 }) })
|
|
5368
5835
|
]
|
|
5369
5836
|
}
|
|
5370
5837
|
);
|
|
@@ -5398,7 +5865,7 @@ function parseChannelName(name, orderId) {
|
|
|
5398
5865
|
orderId
|
|
5399
5866
|
};
|
|
5400
5867
|
}
|
|
5401
|
-
function
|
|
5868
|
+
function EmptyState2({ hasAny }) {
|
|
5402
5869
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles17.empty, children: [
|
|
5403
5870
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: styles17.emptyIcon, children: "\u{1F4AC}" }),
|
|
5404
5871
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { style: styles17.emptyTitle, children: hasAny ? "Select a conversation" : "No conversations yet" }),
|
|
@@ -5804,7 +6271,10 @@ exports.ReplyPreview = ReplyPreview;
|
|
|
5804
6271
|
exports.ReplyQuoteBlock = ReplyQuoteBlock;
|
|
5805
6272
|
exports.SUPPORTED_IMAGE_TYPES = SUPPORTED_IMAGE_TYPES;
|
|
5806
6273
|
exports.SeenByIndicator = SeenByIndicator;
|
|
6274
|
+
exports.THEME_DEFAULTS = THEME_DEFAULTS;
|
|
6275
|
+
exports.THEME_VAR = THEME_VAR;
|
|
5807
6276
|
exports.TYPING_DEBOUNCE_MS = TYPING_DEBOUNCE_MS;
|
|
6277
|
+
exports.applyThemeOverrides = applyThemeOverrides;
|
|
5808
6278
|
exports.useAudioRecorder = useAudioRecorder;
|
|
5809
6279
|
exports.useChannelSettings = useChannelSettings;
|
|
5810
6280
|
exports.useCollab = useCollab;
|