@lorikeetai/react-native-sdk 2.0.0-alpha.2 → 2.0.0

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.cts CHANGED
@@ -4,50 +4,135 @@ import { StyleProp, TextStyle } from "react-native";
4
4
  type ConversationMetadata = Record<string, unknown>;
5
5
  //#endregion
6
6
  //#region src/customisations.d.ts
7
+ /**
8
+ * What the chat page accepts as `customisations`, as the SDK's own types.
9
+ *
10
+ * A copy of the web SDK's shape rather than an import of it. The web SDK is a
11
+ * browser bundle an app has no reason to install, and importing a type from it
12
+ * left the published `dist/index.d.ts` referencing a module consumers do not
13
+ * have: `Customisations` then degraded to `any` and typed nothing.
14
+ * `ConversationMetadata` is duplicated here for the same reason.
15
+ *
16
+ * `src/customisations.web-sdk-parity.ts` fails `typecheck` if the two drift. Not
17
+ * the build: that file is unreachable from `index.ts`, so the declaration build
18
+ * never sees it.
19
+ *
20
+ * Fields that only mean something on a web page are kept so the page's behaviour
21
+ * is unchanged and so a host sharing one configuration object with its web
22
+ * widget still type-checks. The viewport sizes, the launcher button and `mode`
23
+ * are all read by the web SDK rather than by the page, so none of them reaches
24
+ * anything this SDK renders.
25
+ */
26
+ /**
27
+ * Sizing for one viewport. Mostly desktop: the page is full-screen on mobile, so
28
+ * `height`, `width` and `borderRadius` are read for `desktop` alone, while
29
+ * `topClearance` and `default_open` are read for whichever viewport applies.
30
+ */
7
31
  interface ViewportCustomisations {
32
+ /** Clamped to a 2rem maximum. */
8
33
  borderRadius?: string;
9
34
  default_open?: boolean;
35
+ /** Clamped to the viewport minus `topClearance`, and to a 20rem minimum. */
10
36
  height?: string;
37
+ /** Reserved space above the widget. Desktop default 6.5rem. */
11
38
  topClearance?: string;
12
39
  width?: string;
13
40
  }
14
41
  interface Customisations {
42
+ /** Falls back to the logo image. */
15
43
  avatarUrl?: string;
16
44
  botName?: string;
17
45
  desktop?: ViewportCustomisations;
46
+ /**
47
+ * Which header the customer gets, not whether there is one. `true` hides the
48
+ * page's own; `false` keeps it, and with it the page's way out of a
49
+ * conversation. Ending and minimising are what that header is for, and which
50
+ * controls it offers depends on the subscriber's configuration, so hiding it
51
+ * leaves the customer no way to end or minimise unless the host supplies one.
52
+ *
53
+ * What replaces a hidden one is the host's business, so there is no one
54
+ * default to quote. `LorikeetWidgetView` substitutes its own header, a title
55
+ * and new chat, and does so when this is omitted. `LorikeetClient` only
56
+ * serialises the flag and renders nothing, so a composed host keeps the page's
57
+ * header unless it asks for it to go, and must render `LorikeetWidgetHeader`
58
+ * itself when it does.
59
+ */
18
60
  hideHeader?: boolean;
61
+ /** @default '_blank' */
19
62
  linkTarget?: '_blank' | '_parent';
20
63
  logoUrl?: string;
21
64
  messages?: {
65
+ /** Shown when the widget is in an unexpectedly failed state. */
22
66
  failOver?: string;
67
+ /**
68
+ * Shown when live chat has been switched off deliberately. Reachable only
69
+ * where the live agent bridge is on for the subscriber; without it the widget
70
+ * has no unavailable state for this to label.
71
+ */
23
72
  unavailable?: string;
73
+ /**
74
+ * Replaces the line under "Someone is taking a look", for a conversation
75
+ * handed to a person. Say where the reply will come from when the default
76
+ * should not promise it. Shown only where the live chat experience is on,
77
+ * which is what puts the notice on screen in the first place.
78
+ */
24
79
  escalated?: string;
25
80
  };
26
81
  mobile?: ViewportCustomisations;
27
82
  mode?: 'controlled' | 'uncontrolled';
83
+ /**
84
+ * Styling for the launcher button the web widget renders. The React Native
85
+ * SDK renders no launcher, so this reaches the page and does nothing.
86
+ *
87
+ * @danger Experimental and may change.
88
+ */
28
89
  rootElement?: {
29
90
  border?: string;
30
91
  borderRadius?: string;
31
92
  zIndex?: number;
32
93
  bottom?: string;
33
94
  right?: string;
95
+ /** Any CSS size value. Defaults to 3rem. */
34
96
  size?: string;
35
97
  };
98
+ /** Show dates as well as times, on every message. */
36
99
  showVerboseTimestamps?: boolean;
37
100
  theme?: CustomisationTheme;
38
101
  title?: string;
102
+ /** @default false */
39
103
  useSubtleBranding?: boolean;
40
104
  }
41
105
  interface CustomisationTheme {
106
+ /**
107
+ * Colour or gradient for the main area. Any colour value, and any gradient
108
+ * function including multiple layers. Image-based backgrounds are not
109
+ * supported. Takes precedence over `backgroundColor`.
110
+ */
42
111
  background?: string;
43
112
  backgroundColor?: string;
113
+ /** Accent fill, currently the header. Resolves to a neutral when unset. */
44
114
  brandAccentColor?: string;
45
115
  brandColor?: string;
116
+ /** @default 'light' */
46
117
  colorMode?: 'light' | 'dark';
47
118
  fontFamily?: string;
119
+ /**
120
+ * Google Fonts CSS URL declaring the `@font-face` rules for `fontFamily`.
121
+ * The page ships Inter only, so a brand font the device lacks falls back
122
+ * unless its files are loaded. Must be https, host `fonts.googleapis.com`,
123
+ * path `/css` or `/css2`, and carry `family` plus at most a standard
124
+ * `display`. A URL failing any of that is dropped whole rather than trimmed,
125
+ * so one stray query param means no font loads at all.
126
+ */
48
127
  fontUrl?: string;
128
+ /**
129
+ * Colour or gradient for the header, on the same terms as `background`.
130
+ * Takes precedence over `brandAccentColor`.
131
+ */
49
132
  headerBackground?: string;
133
+ /** For text on a dark background. */
50
134
  inverseTextColor?: string;
135
+ /** Falls back to the brand colour. */
51
136
  linkColor?: string;
52
137
  linkHoverColor?: string;
53
138
  secondaryBrandColor?: string;
@@ -56,84 +141,377 @@ interface CustomisationTheme {
56
141
  }
57
142
  //#endregion
58
143
  //#region src/events.d.ts
59
- type LorikeetWidgetEvent = {
144
+ /**
145
+ * What the page reports, as events rather than as raw bridge messages.
146
+ *
147
+ * Names follow the web SDK's (`LorikeetEvent` in `@lorikeetai/web-sdk/types`)
148
+ * wherever it has one, because a host that integrates both should not have to
149
+ * learn two vocabularies. The rest cover what the page tells a host that owns
150
+ * its own layout and storage, which the web SDK largely handles for itself: it
151
+ * surfaces a close without its reason, a created ticket without the stored pair
152
+ * behind it, and `EXPIRED_TOKEN` alone of the error codes. `logout_failed` is
153
+ * the one the SDK reports itself, for a page that said nothing when it had to.
154
+ *
155
+ * `token_expiry` is deliberately absent, and the anonymous session token with
156
+ * it. The credential model they belong to is being rewritten, and an event is
157
+ * the hardest thing to take back. `persist_session` is translated despite
158
+ * carrying a credential, because a resume cannot be rebuilt without it.
159
+ */
160
+ type LorikeetWidgetEvent =
161
+ /** The page is up and the conversation is usable. */
162
+ {
60
163
  type: 'ready';
61
- } | {
164
+ } |
165
+ /**
166
+ * A ticket that did not exist before this page loaded. Once per ticket, and
167
+ * never for a resume. The web SDK suppresses a resume too, but counts once
168
+ * per session rather than per ticket, so this is the stricter of the two.
169
+ */
170
+ {
62
171
  type: 'ticket_created';
63
172
  ticketId: string;
64
- } | {
173
+ } |
174
+ /** The customer sent something. */
175
+ {
65
176
  type: 'customer_message';
66
- } | {
177
+ } |
178
+ /**
179
+ * The agent sent something. `markUnread` is the page asking for an unread
180
+ * indicator, which it only does where its live chat experience is on; the web
181
+ * SDK's launcher dot is driven by it, and it badges only while the widget is
182
+ * out of sight.
183
+ *
184
+ * Absent from a page older than the release that added it, which is not the
185
+ * same as `false`.
186
+ */
187
+ {
67
188
  type: 'agent_message';
68
189
  markUnread?: boolean;
69
- } | {
190
+ } |
191
+ /**
192
+ * The page closed itself, and why. `ended_by_customer` is usually followed by
193
+ * a `new_chat`, once the end and any CSAT have settled, so a host that tears
194
+ * down here never sees the rest of the handshake. Usually rather than always:
195
+ * a CSAT rating that fails holds the replacement back, and nothing but another
196
+ * close releases it. `minimised` has nothing behind it: the conversation is
197
+ * intact and hiding it is enough.
198
+ *
199
+ * `reason` is absent from a page older than the release that added it, from one
200
+ * whose host lifecycle events are switched off, and from the closes the page
201
+ * makes on its own behalf, its error boundary among them. An absent reason
202
+ * reads as an end, so a minimise is only distinguishable when the page names
203
+ * it.
204
+ */
205
+ {
70
206
  type: 'close';
71
207
  reason?: 'ended_by_customer' | 'minimised';
72
- } | {
208
+ } |
209
+ /**
210
+ * The conversation ended without the customer ending it: an agent closed it,
211
+ * or it timed out. Nothing follows, and nothing is asking the host to hide
212
+ * anything. Left unhandled, this is the customer stranded on a conversation
213
+ * that can no longer be used.
214
+ *
215
+ * Reported only by a page whose host lifecycle events are on, so it is not
216
+ * the only way an ended conversation can reach a host.
217
+ */
218
+ {
73
219
  type: 'conversation_ended';
74
- } | {
220
+ } |
221
+ /**
222
+ * The page asking for a replacement conversation. It cannot navigate itself,
223
+ * so acting on this is the host's half of End chat.
224
+ */
225
+ {
75
226
  type: 'new_chat';
76
- } | {
227
+ } |
228
+ /**
229
+ * Store this against the customer, alongside the session. A resume needs both:
230
+ * the ticket alone is refused, usually as `CUSTOMER_ID_MISSING`.
231
+ */
232
+ {
77
233
  type: 'persist_ticket_id';
78
234
  ticketId: string;
79
- } | {
235
+ } |
236
+ /**
237
+ * The other half of the stored pair, as its own message. The SDK does not rely
238
+ * on which half arrives first, and neither should a host.
239
+ */
240
+ {
80
241
  type: 'persist_session';
81
242
  session: string;
82
- } | {
243
+ } |
244
+ /**
245
+ * `/logout` cleared the frame: the chat's cookies for this key, server-side,
246
+ * and the storage the page kept. Reached by navigating the WebView to
247
+ * `LorikeetClient.getLogoutUrl()`, and the only confirmation that the
248
+ * clearing happened. The page's load event is not: an error page fires that
249
+ * too.
250
+ *
251
+ * `persistAnonymousSessionToken` is deliberately not translated. It carries a
252
+ * 365-day identity credential, this SDK offers no way to use one, and the web
253
+ * SDK keeps the same message inside the frame rather than handing it to its
254
+ * host. A typed event would be a published commitment to storing it, days
255
+ * before the hand-off protocol is meant to stop putting it in a URL at all.
256
+ */
257
+ {
83
258
  type: 'logged_out';
84
- } | {
259
+ } |
260
+ /**
261
+ * The SDK's own report, not the page's: `/logout` did not confirm inside
262
+ * `LOGOUT_CONFIRMATION_TIMEOUT_MS`, so the previous customer may still be
263
+ * signed in on this device.
264
+ *
265
+ * The widget stays unavailable rather than starting the next customer's chat,
266
+ * because the alternative is handing them a device the last one's credentials
267
+ * still open. Call `logout()` again to retry.
268
+ */
269
+ {
85
270
  type: 'logout_failed';
86
- } | {
271
+ } |
272
+ /** A page-level failure. `LORIKEET_ERROR_CODES` lists the codes. */
273
+ {
87
274
  type: 'error';
88
275
  error: string;
89
- } | {
276
+ } |
277
+ /**
278
+ * The preload page finished warming, and what the server said about it.
279
+ *
280
+ * Unreachable from React Native, and published in error. The preload page
281
+ * posts straight to `window.parent` behind a `window.parent !== window`
282
+ * guard, which is false in a WebView, so it never takes the native bridge the
283
+ * page's other messages go through. Kept because removing a published union
284
+ * member is a breaking change; retire it when 2.x leaves alpha, or when the
285
+ * page learns to post it natively.
286
+ */
287
+ {
90
288
  type: 'preload_complete';
91
289
  clientStart: boolean;
92
290
  lazyTicketCreationEnabled: boolean;
93
291
  };
292
+ /** The names, spelled out rather than derived, so callers import a real type. */
94
293
  type LorikeetWidgetEventType = 'agent_message' | 'close' | 'conversation_ended' | 'customer_message' | 'error' | 'logged_out' | 'logout_failed' | 'new_chat' | 'persist_session' | 'persist_ticket_id' | 'preload_complete' | 'ready' | 'ticket_created';
95
294
  //#endregion
96
295
  //#region src/types.d.ts
97
296
  interface LorikeetInitOptions {
297
+ /**
298
+ * The base URL of the Lorikeet API for the widget to interact with.
299
+ */
98
300
  api_base?: string;
301
+ /**
302
+ * The options available to customise the widget.
303
+ */
99
304
  customisations?: Customisations;
305
+ /**
306
+ * Arbitrary context to attach to the conversation. Sent as JSON, not base64,
307
+ * which is what both the widget route and the resume route expect.
308
+ */
100
309
  metadata?: ConversationMetadata;
310
+ /**
311
+ * The public key to use.
312
+ */
101
313
  public_key: string;
102
314
  }
103
315
  type LorikeetWidgetWebViewProps = {
316
+ /**
317
+ * The URI of the widget.
318
+ */
104
319
  uri: string;
320
+ /**
321
+ * The base URL of the Lorikeet API for the widget to interact with.
322
+ */
105
323
  baseUrl?: string;
324
+ /**
325
+ * The props for the react-native-webview component
326
+ */
106
327
  webviewProps?: WebViewProps;
328
+ /**
329
+ * What the page reported, as typed events rather than raw bridge messages.
330
+ *
331
+ * This component acts on navigation alone; about the conversation it does
332
+ * nothing. A top-level navigation leaving the widget's origin goes to the OS,
333
+ * unless your own `webviewProps.onShouldStartLoadWithRequest` returns `false`
334
+ * for it, which is taken as a decision and not second-guessed. A navigation
335
+ * the WebView reports as a subframe stays in the page, since a frame the page
336
+ * embedded is not a link the customer followed. A host
337
+ * composing it owns its own URL, layout and storage, so hiding on a close,
338
+ * rebuilding a resume URL or recovering from process loss are all theirs to
339
+ * do. `LorikeetWidgetView` consumes this same path and acts on top of it,
340
+ * because it owns the URL.
341
+ */
107
342
  onEvent?: (event: LorikeetWidgetEvent) => void;
108
343
  };
109
344
  type LorikeetWidgetHeaderProps = {
345
+ /**
346
+ * The title of the widget.
347
+ */
110
348
  title: string;
349
+ /**
350
+ * The style of the header text.
351
+ */
111
352
  style?: StyleProp<TextStyle>;
353
+ /**
354
+ * The icon to display in the header.
355
+ */
112
356
  icon?: React.ReactNode;
357
+ /**
358
+ * The function to call when the icon is pressed.
359
+ */
113
360
  onIconPress?: () => void;
114
361
  };
362
+ /**
363
+ * What a host can ask `LorikeetWidgetView` to do, through a ref. Imperative
364
+ * because logging out and reopening are events on the host's side rather than
365
+ * states the widget can read off its props.
366
+ */
115
367
  type LorikeetWidgetHandle = {
368
+ /**
369
+ * The conversation the widget would resume right now, or `null` when it has
370
+ * none to resume.
371
+ *
372
+ * The pull half of `persist_ticket_id` and `persist_session`. Those report a
373
+ * conversation as the page names it; this answers what the widget is on after
374
+ * it has acted, which is not always the same thing. A resume the server
375
+ * refuses is replaced, and a new chat replaces whatever came before it, so a
376
+ * host holding what it passed at mount can be holding a conversation that no
377
+ * longer exists.
378
+ *
379
+ * The ticket is the half that decides. `null` means no ticket has been
380
+ * reported for these credentials: none yet, a session on its own, the
381
+ * credentials have moved on, or the customer has been logged out. It does not
382
+ * mean the conversation is over. A conversation the customer ended is still
383
+ * reported, because that is still what the widget is on and what its own
384
+ * recovery would resume; `close` and its `reason` are how you hear that it
385
+ * ended.
386
+ *
387
+ * A reported ticket with no `session` yet is not `null`, and is also not
388
+ * resumable on its own: the ticket route needs both. Treat `session` as
389
+ * outstanding rather than absent until it arrives.
390
+ *
391
+ * Reads live, so inside an `onEvent` handler for `persist_ticket_id` or
392
+ * `persist_session` it has already taken that event into account. What it will
393
+ * not do is answer before a ticket exists, and the page normally sends the
394
+ * session first, so the `persist_session` handler sees `null`. Store each half
395
+ * from its own event rather than asking here.
396
+ *
397
+ * `minimised` moves with a render instead, so inside a `close` handler it
398
+ * describes what was on screen before: read `reason` on the `close` rather
399
+ * than this. Read it again after a change rather than caching what it said.
400
+ */
116
401
  getConversation: () => {
117
402
  minimised: boolean;
118
403
  session?: string;
119
404
  ticketId?: string;
120
405
  } | null;
406
+ /**
407
+ * Clear this customer's chat from the device, for the credentials currently in
408
+ * props. Navigates the WebView to the page's own `/logout`, which drops the
409
+ * chat's cookies and the storage the page keeps; neither is reachable from
410
+ * native code, so clearing your stored `ticketId` and `session` alone leaves
411
+ * the conversation reopenable by the next person on the device.
412
+ *
413
+ * The widget renders nothing but that page until it confirms, and changing
414
+ * `publicKey`, `baseUrl` or `authToken` does not cut it short: signing the
415
+ * next customer in mid-clear would leave the previous one's cookies on the
416
+ * device. Wait for `logged_out` on `onEvent`, then pass the next credentials.
417
+ *
418
+ * A page that does not confirm within ten seconds reports `logout_failed` and
419
+ * leaves the widget unavailable rather than opening a chat on a device the
420
+ * previous customer's credentials still unlock. Call this again to retry; a
421
+ * retry while one is pending retries that customer, not whoever is in props
422
+ * by then.
423
+ *
424
+ * `logout_failed` outlives this component, and the obligation with it. The
425
+ * SDK stores nothing, so a widget unmounted before the clear confirmed, by a
426
+ * screen change or an app restart, comes back with no memory of it and will
427
+ * open a chat normally. Record the failure where you record the conversation,
428
+ * and call `logout()` again before you mount a chat for anyone else.
429
+ *
430
+ * Clear your own stored `ticketId` and `session` as well.
431
+ */
121
432
  logout: () => void;
433
+ /**
434
+ * Show a minimised conversation again, exactly as the customer left it.
435
+ * Nothing reloads and nothing is reported, so the conversation keeps its
436
+ * place, its draft and its stream.
437
+ *
438
+ * For a host with its own launcher. The widget already offers a control of
439
+ * its own while minimised, and it does the same thing.
440
+ *
441
+ * A no-op unless the widget is minimised. A conversation the customer ended
442
+ * is left alone, because it only reopens read-only, and so is one the
443
+ * credentials have moved on from.
444
+ */
122
445
  reopen: () => void;
123
446
  };
124
447
  type LorikeetWidgetViewProps = {
448
+ /**
449
+ * The public key to use.
450
+ */
125
451
  publicKey: string;
452
+ /**
453
+ * The base URL of the Lorikeet API for the widget to interact with.
454
+ */
126
455
  baseUrl?: string;
456
+ /**
457
+ * The auth token to use when retrieving the widget URL.
458
+ */
127
459
  authToken: string;
460
+ /**
461
+ * The function to call when a message is received from the webview.
462
+ *
463
+ * @deprecated Prefer `onEvent`, which reports the page's messages as typed
464
+ * events rather than raw JSON a host has to match on by string. Still called,
465
+ * and still additive with `webviewProps.onMessage`.
466
+ *
467
+ * `onEvent` is not a superset. Messages the SDK deliberately leaves
468
+ * untranslated, `persistAnonymousSessionToken` among them, arrive on the raw
469
+ * bridge only. Read those through `webviewProps.onMessage`, which carries the
470
+ * same stream and is not deprecated, rather than taking this prop for them.
471
+ */
128
472
  onWebViewMessage?: (event: WebViewMessageEvent) => void;
473
+ /**
474
+ * What the page reported, as typed events. The same stream
475
+ * `LorikeetWidgetWebView` emits, after the widget has acted on it.
476
+ */
129
477
  onEvent?: (event: LorikeetWidgetEvent) => void;
478
+ /**
479
+ * The options available to customise the widget.
480
+ */
130
481
  customisations?: Customisations;
482
+ /**
483
+ * The style of the components - limited to header text
484
+ */
131
485
  styles?: {
132
486
  header?: StyleProp<TextStyle>;
133
487
  };
488
+ /**
489
+ * Resume this conversation instead of starting a new one. Without it the
490
+ * widget boots `/widget`, which mints a fresh ticket on every mount.
491
+ *
492
+ * Take it from the `persist_ticket_id` event, or from `getConversation()`, and
493
+ * store it yourself; the SDK has no storage of its own.
494
+ */
134
495
  ticketId?: string;
496
+ /**
497
+ * The session token last reported by `persist_session`, stored alongside
498
+ * `ticketId`. The ticket route needs it to authorise a WebView that has no
499
+ * cookie yet, so a resume without it is refused, usually as
500
+ * CUSTOMER_ID_MISSING.
501
+ */
135
502
  session?: string;
503
+ /**
504
+ * Arbitrary context to attach to the conversation, for routing or for the
505
+ * agent to read. Survives a resume: the ticket route forwards it into the
506
+ * re-init URL.
507
+ */
136
508
  metadata?: ConversationMetadata;
509
+ /**
510
+ * Props forwarded to the underlying react-native-webview. The SDK supplies
511
+ * defaults for media playback, scaling and the loading state, and any of them
512
+ * can be overridden here. `onMessage` is additive rather than an override:
513
+ * the SDK reads the bridge first and then calls yours.
514
+ */
137
515
  webviewProps?: WebViewProps;
138
516
  };
139
517
  //#endregion
@@ -156,14 +534,49 @@ declare class LorikeetClient {
156
534
  ticket_id?: string;
157
535
  token: string;
158
536
  }) => string;
537
+ /**
538
+ * The page that clears this key's credentials from the WebView: its cookies,
539
+ * server-side, and the storage the frame keeps. Navigating a WebView here is
540
+ * the only way to reach either, so a host that only drops its own copy of
541
+ * `ticketId` and `session` leaves the next person on the device able to
542
+ * reopen the conversation.
543
+ *
544
+ * The page confirms with a `loggedOut` message, which the SDK reports as
545
+ * `logged_out`. The load event does not: an error page fires that too.
546
+ */
159
547
  getLogoutUrl: () => string;
160
548
  }
161
549
  //#endregion
162
550
  //#region src/errors.d.ts
551
+ /**
552
+ * The chat page's error vocabulary, as it reaches a host in
553
+ * `{ type: 'error', error: CODE }`. Mirrored here because the page publishes it
554
+ * nowhere else, so a host would otherwise be matching on strings it discovered
555
+ * by observation.
556
+ *
557
+ * The page's own list rather than a list of codes seen in the wild:
558
+ * `MISSING_PUBLIC_KEY` has no producer today, and is kept because narrowing this
559
+ * would be a breaking change.
560
+ */
163
561
  declare const LORIKEET_ERROR_CODES: readonly ["MISSING_TOKEN", "CORRUPT_TOKEN_DATA", "DECRYPT_FAILED", "EXPIRED_TOKEN", "MALFORMED_TOKEN", "MISSING_PUBLIC_KEY", "UNKNOWN_PUBLIC_KEY", "CUSTOMER_ID_CONFLICT", "CUSTOMER_ID_MISSING", "FATAL_ERROR", "INVALID_SESSION", "DOMAIN_NOT_ALLOWED", "TICKET_NOT_FOUND"];
164
562
  type LorikeetErrorCode = (typeof LORIKEET_ERROR_CODES)[number];
563
+ /** Whether an error code means the stored conversation cannot be reopened. */
165
564
  declare function isUnusableConversationCode(code: string): boolean;
166
565
  declare function isUnusableConversation(message: unknown): boolean;
167
566
  //#endregion
168
- export { type CustomisationTheme, type Customisations, LORIKEET_ERROR_CODES, LorikeetClient, type LorikeetErrorCode, type LorikeetInitOptions, type LorikeetWidgetEvent, type LorikeetWidgetEventType, type LorikeetWidgetHandle, LorikeetWidgetHeader, type LorikeetWidgetHeaderProps, LorikeetWidgetView, type LorikeetWidgetViewProps, LorikeetWidgetWebView, type LorikeetWidgetWebViewProps, isUnusableConversation, isUnusableConversationCode };
567
+ //#region src/lifecycle.d.ts
568
+ /**
569
+ * How long `/logout` gets to confirm it cleared the frame before the host is
570
+ * told it did not. Matches the web SDK's own budget, and like it, a logout that
571
+ * misses the deadline leaves the widget unavailable rather than letting the next
572
+ * customer start a chat on a device the previous one's credentials still open.
573
+ *
574
+ * `LorikeetWidgetView` applies this to its own `logout()`. Exported because a
575
+ * composed host has to run the timer itself and nothing else will report
576
+ * `logout_failed` for it, and two hosts choosing their own budgets is how one
577
+ * app calls a clear failed that the other never does.
578
+ */
579
+ declare const LOGOUT_CONFIRMATION_TIMEOUT_MS = 10000;
580
+ //#endregion
581
+ export { type CustomisationTheme, type Customisations, LOGOUT_CONFIRMATION_TIMEOUT_MS, LORIKEET_ERROR_CODES, LorikeetClient, type LorikeetErrorCode, type LorikeetInitOptions, type LorikeetWidgetEvent, type LorikeetWidgetEventType, type LorikeetWidgetHandle, LorikeetWidgetHeader, type LorikeetWidgetHeaderProps, LorikeetWidgetView, type LorikeetWidgetViewProps, LorikeetWidgetWebView, type LorikeetWidgetWebViewProps, isUnusableConversation, isUnusableConversationCode };
169
582
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/conversation-metadata.ts","../src/customisations.ts","../src/events.ts","../src/types.ts","../src/widget.tsx","../src/client.ts","../src/errors.ts"],"mappings":";;;KAEY,uBAAuB;;;UCezB;EAER;EACA;EAEA;EAEA;EACA;;UAGe;EAEf;EACA;EACA,UAAU;EAEV;EAEA;EACA;EACA;IAEE;IAEA;IAMA;;EAEF,SAAS;EACT;EAOA;IACE;IACA;IACA;IACA;IACA;IAEA;;EAGF;EACA,QAAQ;EACR;EAEA;;UAGe;EAMf;EACA;EAEA;EACA;EAEA;EACA;EAQA;EAKA;EAEA;EAEA;EACA;EACA;EACA;EACA;;;;KC9FU;EAEN;;EAKA;EAAwB;;EAExB;;EAUA;EAAuB;;EASvB;EAAe;;EAOf;;EAKA;;EAKA;EAA2B;;EAE3B;EAAyB;;EAczB;;EAUA;;EAEA;EAAe;;EAYf;EACA;EACA;;KAIM;;;UCnGK;EAIf;EAIA,iBAAiB;EAKjB,WAAW;EAIX;;KAGU;EAIV;EAIA;EAIA,eAAe;EASf,WAAW,OAAO;;KAGR;EAIV;EAIA,QAAQ,UAAU;EAIlB,OAAO,MAAM;EAIb;;KAQU;EAwBV;IACE;IACA;IACA;;EA4BF;EAaA;;KAGU;EAIV;EAIA;EAIA;EAQA,oBAAoB,OAAO;EAK3B,WAAW,OAAO;EAIlB,iBAAiB;EAIjB;IACE,SAAS,UAAU;;EASrB;EAMA;EAMA,WAAW;EAOX,eAAe;;;;cCtHJ,uCAAqB,0BAAA,6CAAA,cAAA;cA2HrB,yBAAwB,OAAA,OAAA,MAAA,eAKlC,8CAAyB,IAAA;cAYf,oCAAkB,0BAAA,0CAAA,cAAA;;;cCjOlB;EACX;EACA,gBAAgB;EAChB,UAAU;EACV;EAEY,cACV,gBACA,UACA,UACA,cACC;EAeH,kBAAiB,gBAAA,eAAA,OAAA,WAAA;IAOf;IACA;IACA;IACA;IACA;;EAmDF;;;;cCxFW;KAgBD,4BAA4B;iBAexB,2BAA2B;iBAK3B,uBAAuB"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/conversation-metadata.ts","../src/customisations.ts","../src/events.ts","../src/types.ts","../src/widget.tsx","../src/client.ts","../src/errors.ts","../src/lifecycle.ts"],"mappings":";;;KAEY,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;UCuBzB;;EAER;EACA;;EAEA;;EAEA;EACA;;UAGe;;EAEf;EACA;EACA,UAAU;;;;;;;;;;;;;;;EAeV;;EAEA;EACA;EACA;;IAEE;;;;;;IAMA;;;;;;;IAOA;;EAEF,SAAS;EACT;;;;;;;EAOA;IACE;IACA;IACA;IACA;IACA;;IAEA;;;EAGF;EACA,QAAQ;EACR;;EAEA;;UAGe;;;;;;EAMf;EACA;;EAEA;EACA;;EAEA;EACA;;;;;;;;;EASA;;;;;EAKA;;EAEA;;EAEA;EACA;EACA;EACA;EACA;;;;;;;;;;;;;;;;;;;;KCxHU;;;EAEN;;;;;;;;EAMA;EAAwB;;;;EAExB;;;;;;;;;;;;EAUA;EAAuB;;;;;;;;;;;;;;;;;EAevB;EAAe;;;;;;;;;;;;EAUf;;;;;;;EAKA;;;;;;;EAKA;EAA2B;;;;;;;EAK3B;EAAyB;;;;;;;;;;;;;;;;EAczB;;;;;;;;;;;;EAUA;;;;EAEA;EAAe;;;;;;;;;;;;;EAYf;EACA;EACA;;;KAIM;;;UCjHK;;;;EAIf;;;;EAIA,iBAAiB;;;;;EAKjB,WAAW;;;;EAIX;;KAGU;;;;EAIV;;;;EAIA;;;;EAIA,eAAe;;;;;;;;;;;;;;;EAef,WAAW,OAAO;;KAGR;;;;EAIV;;;;EAIA,QAAQ,UAAU;;;;EAIlB,OAAO,MAAM;;;;EAIb;;;;;;;KAQU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkCV;IACE;IACA;IACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BF;;;;;;;;;;;;;EAaA;;KAGU;;;;EAIV;;;;EAIA;;;;EAIA;;;;;;;;;;;;;EAaA,oBAAoB,OAAO;;;;;EAK3B,WAAW,OAAO;;;;EAIlB,iBAAiB;;;;EAIjB;IACE,SAAS,UAAU;;;;;;;;;EASrB;;;;;;;EAOA;;;;;;EAMA,WAAW;;;;;;;EAOX,eAAe;;;;cC5IJ,uCAAqB,0BAAA,6CAAA,cAAA;cA2HrB,yBAAwB,OAAA,OAAA,MAAA,eAKlC,8CAAyB,IAAA;cAYf,oCAAkB,0BAAA,0CAAA,cAAA;;;cCjOlB;EACX;EACA,gBAAgB;EAChB,UAAU;EACV;EAEY,cACV,gBACA,UACA,UACA,cACC;EAeH,kBAAiB,gBAAA,eAAA,OAAA,WAAA;IAOf;IACA;IACA;IACA;IACA;;;;;;;;;;;;EAmDF;;;;;;;;;;;;;;cCnFW;KAgBD,4BAA4B;;iBAexB,2BAA2B;iBAK3B,uBAAuB;;;;;;;;;;;;;;cCtB1B"}