@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 +132 -13
- package/dist/index.d.ts +132 -13
- package/dist/index.js +1056 -608
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1055 -610
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
/**
|
|
149
|
-
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
669
|
-
*
|
|
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
|
-
/**
|
|
149
|
-
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
669
|
-
*
|
|
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 };
|