File size: 1,729 Bytes
f76c374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import type { ReactNode } from 'react'

/**
 * CHAT EMPTY STATE — the blank transcript as a contribution area.
 *
 * Core owns exactly one empty state: the intro splash, which belongs to a
 * fresh draft with no session selected. A session that exists but has nothing
 * in it yet falls outside that — and whoever opened it is the only one who
 * knows what should stand in the gap. A bot's chat wants the bot's face and
 * name; core has neither, and should not learn them.
 *
 * So the slot is contributed. A plugin claims the sessions it owns by
 * returning an element for them and `null` for everything else, which is also
 * how it stands down while the transcript is still hydrating.
 *
 * Ownership is per session, so EVERY registration is mounted and each answers
 * for itself. Declining is free; two plugins claiming one session render both,
 * which is the visible cost of never letting registration order silently
 * suppress the plugin that actually owns the chat.
 */

export const CHAT_EMPTY_AREA = 'chat.empty'

/** Props handed to a chat-empty contribution's `render`. */
export interface ChatEmptyProps {
  /** The live session whose transcript is empty. */
  sessionId: string
}

/** Payload of a `chat.empty` contribution's `data`. */
export interface ChatEmptyContribution {
  /** Renders the empty state, or returns `null` to decline the session and
   *  leave the transcript blank. Mounted as a component inside the
   *  contribution error boundary, so it can subscribe to its own stores and
   *  appear once they load — the roster a bot chat needs arrives after the
   *  transcript does. A throw degrades to an inline error, not a dead chat. */
  render: (props: ChatEmptyProps) => ReactNode
}