@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/README.md +18 -20
- package/dist/index.cjs +14 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +427 -14
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +427 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
package/dist/index.d.cts.map
CHANGED
|
@@ -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
|
|
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"}
|