@natoe/colab 0.1.12 → 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 CHANGED
@@ -2,6 +2,39 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import { Channel } from 'phoenix';
4
4
 
5
+ /** CSS variable names for the themeable color tokens. */
6
+ declare const THEME_VAR: {
7
+ readonly primary: "--natoe-colab-primary";
8
+ readonly primaryHover: "--natoe-colab-primary-hover";
9
+ readonly primaryBg: "--natoe-colab-primary-bg";
10
+ readonly primaryFg: "--natoe-colab-primary-fg";
11
+ readonly success: "--natoe-colab-success";
12
+ readonly warning: "--natoe-colab-warning";
13
+ readonly danger: "--natoe-colab-danger";
14
+ readonly dangerBg: "--natoe-colab-danger-bg";
15
+ readonly dangerBorder: "--natoe-colab-danger-border";
16
+ readonly dangerFg: "--natoe-colab-danger-fg";
17
+ readonly fontStack: "--natoe-colab-font-stack";
18
+ };
19
+ /** Default values for the themeable tokens (used by both CSS emission and
20
+ * the inline-style fallback inside `var(..., fallback)`). */
21
+ declare const THEME_DEFAULTS: {
22
+ readonly primary: "#2563eb";
23
+ readonly primaryHover: "#1d4ed8";
24
+ readonly primaryBg: "#dbeafe";
25
+ readonly primaryFg: "#1d4ed8";
26
+ readonly success: "#059669";
27
+ readonly warning: "#d97706";
28
+ readonly danger: "#dc2626";
29
+ readonly dangerBg: "#fef2f2";
30
+ readonly dangerBorder: "#fecaca";
31
+ readonly dangerFg: "#b91c1c";
32
+ readonly fontStack: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
33
+ };
34
+ /** Public override shape — passed via CollabConfig.theme. Every key is
35
+ * optional; unspecified keys fall back to {@link THEME_DEFAULTS}. */
36
+ type Theme = Partial<Record<keyof typeof THEME_DEFAULTS, string>>;
37
+
5
38
  interface CollabConfig {
6
39
  /** Phoenix WebSocket URL (e.g. wss://backend.natoe.ai/socket) */
7
40
  socketUrl: string;
@@ -12,6 +45,15 @@ interface CollabConfig {
12
45
  userRole: UserRole;
13
46
  userName: string;
14
47
  userAvatar?: string;
48
+ /**
49
+ * Optional theme overrides. Any key set here is applied as a CSS custom
50
+ * property on `:root`, replacing the package's default for that token.
51
+ * Keys not provided keep their default. See {@link Theme} for the
52
+ * complete list of overridable tokens (brand + semantic colors + font
53
+ * stack). Spacing, type scale, radii are deliberately not themeable —
54
+ * changing those wholesale breaks the package's visual rhythm.
55
+ */
56
+ theme?: Theme;
15
57
  /** Host app callbacks — colab calls these, never implements them */
16
58
  onOpenDicom?: (studyId: string, storageId: string) => void;
17
59
  onUploadFile?: (file: File | Blob, fileName?: string) => Promise<string>;
@@ -23,6 +65,8 @@ interface PatientData {
23
65
  patientName: string;
24
66
  patientAge?: string;
25
67
  patientSex?: string;
68
+ /** Patient MRN — shown on inbox rows and searchable in the inbox filter. */
69
+ patientId?: string;
26
70
  studyType?: string;
27
71
  studyId?: string;
28
72
  storageId?: string;
@@ -145,8 +189,13 @@ interface SendMessagePayload {
145
189
  media_duration?: number;
146
190
  file_name?: string;
147
191
  metadata?: Record<string, unknown>;
148
- /** ID of message being replied to (snapshot is built server-side) */
149
- replyToId?: string;
192
+ /**
193
+ * ID of message being replied to (snapshot is built server-side).
194
+ * Wire-level key is snake_case to match the channel handler — the
195
+ * other optional fields here (media_url, file_name, …) follow the
196
+ * same convention.
197
+ */
198
+ reply_to_id?: string;
150
199
  }
151
200
  type ChannelEvent = 'message:new' | 'message:read' | 'message:pinned' | 'message:unpinned' | 'user:typing' | 'user:joined' | 'user:left' | 'channel:updated' | 'channel:deleted';
152
201
  interface TypingEvent {
@@ -216,6 +265,14 @@ interface CollabPopupProps {
216
265
  onClose: () => void;
217
266
  /** Optional back navigation — renders a ← button in the title bar when provided */
218
267
  onBack?: () => void;
268
+ /**
269
+ * When provided, the minimize button calls this callback instead of
270
+ * toggling the popup's own shrink-to-titlebar state. Hosts use this
271
+ * to minimize the popup to an external chip / dock. With this set the
272
+ * minimize button always shows the minimize glyph (no expand state),
273
+ * since the host owns the open/minimized lifecycle.
274
+ */
275
+ onMinimize?: () => void;
219
276
  /** Initial position (defaults to bottom-right) */
220
277
  initialPosition?: {
221
278
  x: number;
@@ -231,7 +288,7 @@ interface CollabPopupProps {
231
288
  * Draggable floating chat popup — drop-in replacement for DraggableChatPopup.
232
289
  * Renders a CollabPanel inside a movable, resizable container.
233
290
  */
234
- declare function CollabPopup({ orderId, patientData, participantIds, isOpen, onClose, onBack, initialPosition, width, height, className, }: CollabPopupProps): react_jsx_runtime.JSX.Element | null;
291
+ declare function CollabPopup({ orderId, patientData, participantIds, isOpen, onClose, onBack, onMinimize, initialPosition, width, height, className, }: CollabPopupProps): react_jsx_runtime.JSX.Element | null;
235
292
 
236
293
  interface CollabInlineProps {
237
294
  orderId: string;
@@ -264,8 +321,6 @@ interface CollabInboxProps {
264
321
  initialConversationId?: string;
265
322
  /** Optional callback when the user selects a conversation */
266
323
  onSelectConversation?: (item: ConversationListItem$1) => void;
267
- /** Title for the sidebar */
268
- title?: string;
269
324
  className?: string;
270
325
  style?: React.CSSProperties;
271
326
  }
@@ -276,7 +331,7 @@ interface CollabInboxProps {
276
331
  * Uses the same CollabPanel as the floating popup, so all features
277
332
  * (reply, pin, seen-by, DICOM, voice, attachments) are available.
278
333
  */
279
- declare function CollabInbox({ initialConversationId, onSelectConversation, title, className, style, }: CollabInboxProps): react_jsx_runtime.JSX.Element;
334
+ declare function CollabInbox({ initialConversationId, onSelectConversation, className, style, }: CollabInboxProps): react_jsx_runtime.JSX.Element;
280
335
 
281
336
  type MessageCallback = (message: Message) => void;
282
337
  type TypingCallback = (event: TypingEvent) => void;
@@ -372,6 +427,13 @@ interface CollabContextValue {
372
427
  config: CollabConfig;
373
428
  apiBaseUrl: string;
374
429
  totalUnread: number;
430
+ /**
431
+ * Per-conversation unread counts, keyed by conversation ID. Updated
432
+ * live via the user_notifications channel's unread_update push, so
433
+ * surfaces like a minimized-chat chip can reflect changes without
434
+ * mounting their own useConversation.
435
+ */
436
+ unreadCounts: Record<string, number>;
375
437
  /** Batched preview lookup — coalesces calls within a microtask */
376
438
  requestPreview: (orderId: string) => Promise<ConversationPreview | null>;
377
439
  /** Invalidate a cached preview (e.g. when a new message arrives) */
@@ -649,14 +711,16 @@ interface ConversationListProps {
649
711
  isLoading: boolean;
650
712
  error: string | null;
651
713
  onSelect: (item: ConversationListItem$1) => void;
652
- /** Optional title shown above the list */
653
- title?: string;
654
714
  className?: string;
655
715
  }
656
716
  /**
657
- * Scrollable sidebar list of conversations with search and unread filter.
717
+ * Scrollable inbox of conversations. Unread/All tabs (with count pills)
718
+ * sit at the top, followed by a search field with a focus-within ring.
719
+ * On first data load with any unread items the inbox auto-defaults to
720
+ * the Unread tab so triage starts on what matters. Empty/loading/error
721
+ * states are illustrated and descriptive rather than terse one-liners.
658
722
  */
659
- declare function ConversationList({ conversations, selectedId, isLoading, error, onSelect, title, className, }: ConversationListProps): react_jsx_runtime.JSX.Element;
723
+ declare function ConversationList({ conversations, selectedId, isLoading, error, onSelect, className, }: ConversationListProps): react_jsx_runtime.JSX.Element;
660
724
 
661
725
  interface ConversationListItemProps {
662
726
  item: ConversationListItem$1;
@@ -665,8 +729,21 @@ interface ConversationListItemProps {
665
729
  className?: string;
666
730
  }
667
731
  /**
668
- * Single row in the inbox sidebar — shows patient/channel name, last message
669
- * preview, timestamp, and unread badge.
732
+ * Single row in the inbox sidebar.
733
+ *
734
+ * Three-row layout (top-to-bottom):
735
+ * 1. Patient/channel name + relative time
736
+ * 2. Study type + monospace `MRN <patientId>` (surfaced from the
737
+ * snapshot; either field is optional and the row collapses if both
738
+ * are missing)
739
+ * 3. Last message preview (sender prefix in stronger weight) + unread
740
+ * count badge on the right
741
+ *
742
+ * Active row gets a 4px brand-color left-border accent + tinted background.
743
+ * The avatar is a 52px **square** tile (16px rounded corners) with brand-
744
+ * coloured fill and white initials — easier to scan than a circle at this
745
+ * size and consistent across the inbox without depending on any case
746
+ * status field we don't model.
670
747
  */
671
748
  declare function ConversationListItem({ item, isSelected, onClick, className, }: ConversationListItemProps): react_jsx_runtime.JSX.Element;
672
749
 
@@ -683,6 +760,20 @@ interface PatientHeaderProps {
683
760
  displayName?: string;
684
761
  className?: string;
685
762
  }
763
+ /**
764
+ * "Case card" header that sits below the window title bar. Tinted blue-50
765
+ * background to set it apart from the conversation body. Renders a row
766
+ * of labelled key-value columns (label uppercase on top, value below) for
767
+ * the clinical context the host passed in, with the action buttons
768
+ * (View DICOM + Settings) right-aligned.
769
+ *
770
+ * Used in two layouts:
771
+ * - Popup path (`hideName=true`): the surrounding title bar already
772
+ * shows the patient name, so we render the case card only.
773
+ * - Compact-inbox path (`hideName=false`): the panel is a full-page
774
+ * experience and there's no outer title, so we still show the name +
775
+ * back button stacked above the case card.
776
+ */
686
777
  declare function PatientHeader({ patientData, onOpenDicom, onOpenSettings, onBack, hideName, displayName, className, }: PatientHeaderProps): react_jsx_runtime.JSX.Element;
687
778
 
688
779
  interface MessageListHandle {
@@ -864,6 +955,34 @@ interface ParticipantsListProps {
864
955
  }
865
956
  declare function ParticipantsList({ participants, currentUserId, isAdmin, onRemoveUser, className, }: ParticipantsListProps): react_jsx_runtime.JSX.Element;
866
957
 
958
+ /**
959
+ * Shared style tokens + the global stylesheet the package injects once per
960
+ * page.
961
+ *
962
+ * Top-level wrappers (CollabPopup, CollabPanel, CollabInline, CollabInbox)
963
+ * import {@link FONT_STACK} so every surface renders with the same font
964
+ * stack, even when the package is mounted inside an iframe whose
965
+ * surrounding document doesn't set one.
966
+ *
967
+ * Themeable tokens (brand + semantic colors + the font stack) are emitted
968
+ * as CSS custom properties on `:root` so host apps can override them via
969
+ * `CollabConfig.theme` (see {@link applyThemeOverrides}). Non-themeable
970
+ * tokens (neutrals, slate, spacing, radius, sizes) live as inline values
971
+ * in core/theme.ts and stay constant.
972
+ *
973
+ * The prefers-contrast / prefers-reduced-motion adjustments are emitted
974
+ * inside the same stylesheet so they apply wherever a `natoe-colab-root`
975
+ * wrapper is mounted.
976
+ */
977
+
978
+ /**
979
+ * Apply a host-supplied theme by setting CSS custom properties on the
980
+ * document root. Keys missing from `theme` have their previously-set
981
+ * override cleared so toggling overrides back to undefined returns the
982
+ * default — never leaves stale values behind.
983
+ */
984
+ declare function applyThemeOverrides(theme: Theme | undefined): void;
985
+
867
986
  /** Phoenix channel event names — must match backend channel implementation */
868
987
  declare const EVENTS: {
869
988
  readonly MESSAGE_NEW: "message:new";
@@ -902,4 +1021,4 @@ declare const SUPPORTED_IMAGE_TYPES: string[];
902
1021
  /** Max file size in bytes (20MB) */
903
1022
  declare const MAX_FILE_SIZE: number;
904
1023
 
905
- export { AUDIO_MIME_TYPE, type ChannelEvent, ChannelSettings, type ChannelUpdatePayload, type CollabConfig, type CollabError, CollabInbox, CollabInline, CollabPanel, CollabPopup, CollabProvider, CollabSocket, type Conversation, ConversationList, ConversationListItem, type ConversationListItem$1 as ConversationListItemData, type ConversationPreview, type CreateConversationResponse, DEEP_LINK_PREFIX, EVENTS, type InviteUserPayload, MAX_FILE_SIZE, MAX_PINNED_MESSAGES, MESSAGES_PAGE_SIZE, MESSAGE_TYPES, type Message, MessageActionsMenu, MessageBubble, MessageInput, MessageList, type MessageListHandle, type MessageSnapshot, type MessageType, type Participant, ParticipantsList, type PatientData, PatientHeader, PinnedMessagesBar, type PreviewBatchResponse, ReplyPreview, ReplyQuoteBlock, SUPPORTED_IMAGE_TYPES, SeenByIndicator, type SendMessagePayload, TYPING_DEBOUNCE_MS, type TypingEvent, type UserRole, useAudioRecorder, useChannelSettings, useCollab, useConversation, useConversationList, useDeepLinks, useInlineCollab, useMessages, usePinnedMessages, useUnreadCount };
1024
+ export { AUDIO_MIME_TYPE, type ChannelEvent, ChannelSettings, type ChannelUpdatePayload, type CollabConfig, type CollabError, CollabInbox, CollabInline, CollabPanel, CollabPopup, CollabProvider, CollabSocket, type Conversation, ConversationList, ConversationListItem, type ConversationListItem$1 as ConversationListItemData, type ConversationPreview, type CreateConversationResponse, DEEP_LINK_PREFIX, EVENTS, type InviteUserPayload, MAX_FILE_SIZE, MAX_PINNED_MESSAGES, MESSAGES_PAGE_SIZE, MESSAGE_TYPES, type Message, MessageActionsMenu, MessageBubble, MessageInput, MessageList, type MessageListHandle, type MessageSnapshot, type MessageType, type Participant, ParticipantsList, type PatientData, PatientHeader, PinnedMessagesBar, type PreviewBatchResponse, ReplyPreview, ReplyQuoteBlock, SUPPORTED_IMAGE_TYPES, SeenByIndicator, type SendMessagePayload, THEME_DEFAULTS, THEME_VAR, TYPING_DEBOUNCE_MS, type Theme, type TypingEvent, type UserRole, applyThemeOverrides, useAudioRecorder, useChannelSettings, useCollab, useConversation, useConversationList, useDeepLinks, useInlineCollab, useMessages, usePinnedMessages, useUnreadCount };
package/dist/index.d.ts CHANGED
@@ -2,6 +2,39 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import { Channel } from 'phoenix';
4
4
 
5
+ /** CSS variable names for the themeable color tokens. */
6
+ declare const THEME_VAR: {
7
+ readonly primary: "--natoe-colab-primary";
8
+ readonly primaryHover: "--natoe-colab-primary-hover";
9
+ readonly primaryBg: "--natoe-colab-primary-bg";
10
+ readonly primaryFg: "--natoe-colab-primary-fg";
11
+ readonly success: "--natoe-colab-success";
12
+ readonly warning: "--natoe-colab-warning";
13
+ readonly danger: "--natoe-colab-danger";
14
+ readonly dangerBg: "--natoe-colab-danger-bg";
15
+ readonly dangerBorder: "--natoe-colab-danger-border";
16
+ readonly dangerFg: "--natoe-colab-danger-fg";
17
+ readonly fontStack: "--natoe-colab-font-stack";
18
+ };
19
+ /** Default values for the themeable tokens (used by both CSS emission and
20
+ * the inline-style fallback inside `var(..., fallback)`). */
21
+ declare const THEME_DEFAULTS: {
22
+ readonly primary: "#2563eb";
23
+ readonly primaryHover: "#1d4ed8";
24
+ readonly primaryBg: "#dbeafe";
25
+ readonly primaryFg: "#1d4ed8";
26
+ readonly success: "#059669";
27
+ readonly warning: "#d97706";
28
+ readonly danger: "#dc2626";
29
+ readonly dangerBg: "#fef2f2";
30
+ readonly dangerBorder: "#fecaca";
31
+ readonly dangerFg: "#b91c1c";
32
+ readonly fontStack: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
33
+ };
34
+ /** Public override shape — passed via CollabConfig.theme. Every key is
35
+ * optional; unspecified keys fall back to {@link THEME_DEFAULTS}. */
36
+ type Theme = Partial<Record<keyof typeof THEME_DEFAULTS, string>>;
37
+
5
38
  interface CollabConfig {
6
39
  /** Phoenix WebSocket URL (e.g. wss://backend.natoe.ai/socket) */
7
40
  socketUrl: string;
@@ -12,6 +45,15 @@ interface CollabConfig {
12
45
  userRole: UserRole;
13
46
  userName: string;
14
47
  userAvatar?: string;
48
+ /**
49
+ * Optional theme overrides. Any key set here is applied as a CSS custom
50
+ * property on `:root`, replacing the package's default for that token.
51
+ * Keys not provided keep their default. See {@link Theme} for the
52
+ * complete list of overridable tokens (brand + semantic colors + font
53
+ * stack). Spacing, type scale, radii are deliberately not themeable —
54
+ * changing those wholesale breaks the package's visual rhythm.
55
+ */
56
+ theme?: Theme;
15
57
  /** Host app callbacks — colab calls these, never implements them */
16
58
  onOpenDicom?: (studyId: string, storageId: string) => void;
17
59
  onUploadFile?: (file: File | Blob, fileName?: string) => Promise<string>;
@@ -23,6 +65,8 @@ interface PatientData {
23
65
  patientName: string;
24
66
  patientAge?: string;
25
67
  patientSex?: string;
68
+ /** Patient MRN — shown on inbox rows and searchable in the inbox filter. */
69
+ patientId?: string;
26
70
  studyType?: string;
27
71
  studyId?: string;
28
72
  storageId?: string;
@@ -145,8 +189,13 @@ interface SendMessagePayload {
145
189
  media_duration?: number;
146
190
  file_name?: string;
147
191
  metadata?: Record<string, unknown>;
148
- /** ID of message being replied to (snapshot is built server-side) */
149
- replyToId?: string;
192
+ /**
193
+ * ID of message being replied to (snapshot is built server-side).
194
+ * Wire-level key is snake_case to match the channel handler — the
195
+ * other optional fields here (media_url, file_name, …) follow the
196
+ * same convention.
197
+ */
198
+ reply_to_id?: string;
150
199
  }
151
200
  type ChannelEvent = 'message:new' | 'message:read' | 'message:pinned' | 'message:unpinned' | 'user:typing' | 'user:joined' | 'user:left' | 'channel:updated' | 'channel:deleted';
152
201
  interface TypingEvent {
@@ -216,6 +265,14 @@ interface CollabPopupProps {
216
265
  onClose: () => void;
217
266
  /** Optional back navigation — renders a ← button in the title bar when provided */
218
267
  onBack?: () => void;
268
+ /**
269
+ * When provided, the minimize button calls this callback instead of
270
+ * toggling the popup's own shrink-to-titlebar state. Hosts use this
271
+ * to minimize the popup to an external chip / dock. With this set the
272
+ * minimize button always shows the minimize glyph (no expand state),
273
+ * since the host owns the open/minimized lifecycle.
274
+ */
275
+ onMinimize?: () => void;
219
276
  /** Initial position (defaults to bottom-right) */
220
277
  initialPosition?: {
221
278
  x: number;
@@ -231,7 +288,7 @@ interface CollabPopupProps {
231
288
  * Draggable floating chat popup — drop-in replacement for DraggableChatPopup.
232
289
  * Renders a CollabPanel inside a movable, resizable container.
233
290
  */
234
- declare function CollabPopup({ orderId, patientData, participantIds, isOpen, onClose, onBack, initialPosition, width, height, className, }: CollabPopupProps): react_jsx_runtime.JSX.Element | null;
291
+ declare function CollabPopup({ orderId, patientData, participantIds, isOpen, onClose, onBack, onMinimize, initialPosition, width, height, className, }: CollabPopupProps): react_jsx_runtime.JSX.Element | null;
235
292
 
236
293
  interface CollabInlineProps {
237
294
  orderId: string;
@@ -264,8 +321,6 @@ interface CollabInboxProps {
264
321
  initialConversationId?: string;
265
322
  /** Optional callback when the user selects a conversation */
266
323
  onSelectConversation?: (item: ConversationListItem$1) => void;
267
- /** Title for the sidebar */
268
- title?: string;
269
324
  className?: string;
270
325
  style?: React.CSSProperties;
271
326
  }
@@ -276,7 +331,7 @@ interface CollabInboxProps {
276
331
  * Uses the same CollabPanel as the floating popup, so all features
277
332
  * (reply, pin, seen-by, DICOM, voice, attachments) are available.
278
333
  */
279
- declare function CollabInbox({ initialConversationId, onSelectConversation, title, className, style, }: CollabInboxProps): react_jsx_runtime.JSX.Element;
334
+ declare function CollabInbox({ initialConversationId, onSelectConversation, className, style, }: CollabInboxProps): react_jsx_runtime.JSX.Element;
280
335
 
281
336
  type MessageCallback = (message: Message) => void;
282
337
  type TypingCallback = (event: TypingEvent) => void;
@@ -372,6 +427,13 @@ interface CollabContextValue {
372
427
  config: CollabConfig;
373
428
  apiBaseUrl: string;
374
429
  totalUnread: number;
430
+ /**
431
+ * Per-conversation unread counts, keyed by conversation ID. Updated
432
+ * live via the user_notifications channel's unread_update push, so
433
+ * surfaces like a minimized-chat chip can reflect changes without
434
+ * mounting their own useConversation.
435
+ */
436
+ unreadCounts: Record<string, number>;
375
437
  /** Batched preview lookup — coalesces calls within a microtask */
376
438
  requestPreview: (orderId: string) => Promise<ConversationPreview | null>;
377
439
  /** Invalidate a cached preview (e.g. when a new message arrives) */
@@ -649,14 +711,16 @@ interface ConversationListProps {
649
711
  isLoading: boolean;
650
712
  error: string | null;
651
713
  onSelect: (item: ConversationListItem$1) => void;
652
- /** Optional title shown above the list */
653
- title?: string;
654
714
  className?: string;
655
715
  }
656
716
  /**
657
- * Scrollable sidebar list of conversations with search and unread filter.
717
+ * Scrollable inbox of conversations. Unread/All tabs (with count pills)
718
+ * sit at the top, followed by a search field with a focus-within ring.
719
+ * On first data load with any unread items the inbox auto-defaults to
720
+ * the Unread tab so triage starts on what matters. Empty/loading/error
721
+ * states are illustrated and descriptive rather than terse one-liners.
658
722
  */
659
- declare function ConversationList({ conversations, selectedId, isLoading, error, onSelect, title, className, }: ConversationListProps): react_jsx_runtime.JSX.Element;
723
+ declare function ConversationList({ conversations, selectedId, isLoading, error, onSelect, className, }: ConversationListProps): react_jsx_runtime.JSX.Element;
660
724
 
661
725
  interface ConversationListItemProps {
662
726
  item: ConversationListItem$1;
@@ -665,8 +729,21 @@ interface ConversationListItemProps {
665
729
  className?: string;
666
730
  }
667
731
  /**
668
- * Single row in the inbox sidebar — shows patient/channel name, last message
669
- * preview, timestamp, and unread badge.
732
+ * Single row in the inbox sidebar.
733
+ *
734
+ * Three-row layout (top-to-bottom):
735
+ * 1. Patient/channel name + relative time
736
+ * 2. Study type + monospace `MRN <patientId>` (surfaced from the
737
+ * snapshot; either field is optional and the row collapses if both
738
+ * are missing)
739
+ * 3. Last message preview (sender prefix in stronger weight) + unread
740
+ * count badge on the right
741
+ *
742
+ * Active row gets a 4px brand-color left-border accent + tinted background.
743
+ * The avatar is a 52px **square** tile (16px rounded corners) with brand-
744
+ * coloured fill and white initials — easier to scan than a circle at this
745
+ * size and consistent across the inbox without depending on any case
746
+ * status field we don't model.
670
747
  */
671
748
  declare function ConversationListItem({ item, isSelected, onClick, className, }: ConversationListItemProps): react_jsx_runtime.JSX.Element;
672
749
 
@@ -683,6 +760,20 @@ interface PatientHeaderProps {
683
760
  displayName?: string;
684
761
  className?: string;
685
762
  }
763
+ /**
764
+ * "Case card" header that sits below the window title bar. Tinted blue-50
765
+ * background to set it apart from the conversation body. Renders a row
766
+ * of labelled key-value columns (label uppercase on top, value below) for
767
+ * the clinical context the host passed in, with the action buttons
768
+ * (View DICOM + Settings) right-aligned.
769
+ *
770
+ * Used in two layouts:
771
+ * - Popup path (`hideName=true`): the surrounding title bar already
772
+ * shows the patient name, so we render the case card only.
773
+ * - Compact-inbox path (`hideName=false`): the panel is a full-page
774
+ * experience and there's no outer title, so we still show the name +
775
+ * back button stacked above the case card.
776
+ */
686
777
  declare function PatientHeader({ patientData, onOpenDicom, onOpenSettings, onBack, hideName, displayName, className, }: PatientHeaderProps): react_jsx_runtime.JSX.Element;
687
778
 
688
779
  interface MessageListHandle {
@@ -864,6 +955,34 @@ interface ParticipantsListProps {
864
955
  }
865
956
  declare function ParticipantsList({ participants, currentUserId, isAdmin, onRemoveUser, className, }: ParticipantsListProps): react_jsx_runtime.JSX.Element;
866
957
 
958
+ /**
959
+ * Shared style tokens + the global stylesheet the package injects once per
960
+ * page.
961
+ *
962
+ * Top-level wrappers (CollabPopup, CollabPanel, CollabInline, CollabInbox)
963
+ * import {@link FONT_STACK} so every surface renders with the same font
964
+ * stack, even when the package is mounted inside an iframe whose
965
+ * surrounding document doesn't set one.
966
+ *
967
+ * Themeable tokens (brand + semantic colors + the font stack) are emitted
968
+ * as CSS custom properties on `:root` so host apps can override them via
969
+ * `CollabConfig.theme` (see {@link applyThemeOverrides}). Non-themeable
970
+ * tokens (neutrals, slate, spacing, radius, sizes) live as inline values
971
+ * in core/theme.ts and stay constant.
972
+ *
973
+ * The prefers-contrast / prefers-reduced-motion adjustments are emitted
974
+ * inside the same stylesheet so they apply wherever a `natoe-colab-root`
975
+ * wrapper is mounted.
976
+ */
977
+
978
+ /**
979
+ * Apply a host-supplied theme by setting CSS custom properties on the
980
+ * document root. Keys missing from `theme` have their previously-set
981
+ * override cleared so toggling overrides back to undefined returns the
982
+ * default — never leaves stale values behind.
983
+ */
984
+ declare function applyThemeOverrides(theme: Theme | undefined): void;
985
+
867
986
  /** Phoenix channel event names — must match backend channel implementation */
868
987
  declare const EVENTS: {
869
988
  readonly MESSAGE_NEW: "message:new";
@@ -902,4 +1021,4 @@ declare const SUPPORTED_IMAGE_TYPES: string[];
902
1021
  /** Max file size in bytes (20MB) */
903
1022
  declare const MAX_FILE_SIZE: number;
904
1023
 
905
- export { AUDIO_MIME_TYPE, type ChannelEvent, ChannelSettings, type ChannelUpdatePayload, type CollabConfig, type CollabError, CollabInbox, CollabInline, CollabPanel, CollabPopup, CollabProvider, CollabSocket, type Conversation, ConversationList, ConversationListItem, type ConversationListItem$1 as ConversationListItemData, type ConversationPreview, type CreateConversationResponse, DEEP_LINK_PREFIX, EVENTS, type InviteUserPayload, MAX_FILE_SIZE, MAX_PINNED_MESSAGES, MESSAGES_PAGE_SIZE, MESSAGE_TYPES, type Message, MessageActionsMenu, MessageBubble, MessageInput, MessageList, type MessageListHandle, type MessageSnapshot, type MessageType, type Participant, ParticipantsList, type PatientData, PatientHeader, PinnedMessagesBar, type PreviewBatchResponse, ReplyPreview, ReplyQuoteBlock, SUPPORTED_IMAGE_TYPES, SeenByIndicator, type SendMessagePayload, TYPING_DEBOUNCE_MS, type TypingEvent, type UserRole, useAudioRecorder, useChannelSettings, useCollab, useConversation, useConversationList, useDeepLinks, useInlineCollab, useMessages, usePinnedMessages, useUnreadCount };
1024
+ export { AUDIO_MIME_TYPE, type ChannelEvent, ChannelSettings, type ChannelUpdatePayload, type CollabConfig, type CollabError, CollabInbox, CollabInline, CollabPanel, CollabPopup, CollabProvider, CollabSocket, type Conversation, ConversationList, ConversationListItem, type ConversationListItem$1 as ConversationListItemData, type ConversationPreview, type CreateConversationResponse, DEEP_LINK_PREFIX, EVENTS, type InviteUserPayload, MAX_FILE_SIZE, MAX_PINNED_MESSAGES, MESSAGES_PAGE_SIZE, MESSAGE_TYPES, type Message, MessageActionsMenu, MessageBubble, MessageInput, MessageList, type MessageListHandle, type MessageSnapshot, type MessageType, type Participant, ParticipantsList, type PatientData, PatientHeader, PinnedMessagesBar, type PreviewBatchResponse, ReplyPreview, ReplyQuoteBlock, SUPPORTED_IMAGE_TYPES, SeenByIndicator, type SendMessagePayload, THEME_DEFAULTS, THEME_VAR, TYPING_DEBOUNCE_MS, type Theme, type TypingEvent, type UserRole, applyThemeOverrides, useAudioRecorder, useChannelSettings, useCollab, useConversation, useConversationList, useDeepLinks, useInlineCollab, useMessages, usePinnedMessages, useUnreadCount };