@lorikeetai/react-native-sdk 2.0.0-alpha.3 → 2.1.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.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
2
- import { AppState, Linking, StyleSheet, Text, TouchableOpacity, View } from "react-native";
2
+ import { AppState, KeyboardAvoidingView, Linking, StyleSheet, Text, TouchableOpacity, View } from "react-native";
3
3
  import { SafeAreaView } from "react-native-safe-area-context";
4
4
  import { WebView } from "react-native-webview";
5
5
  import Svg, { Line, Path } from "react-native-svg";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
 
8
- //#region src/bridge.ts
8
+ // src/bridge.ts
9
9
  /**
10
10
  * The public key, base URL and token are one unit, and a conversation belongs to
11
11
  * the credentials that created it. Stamping an observation with them is what
@@ -25,8 +25,7 @@ const resumableConversation = (observed, identity, intendedTicketId) => {
25
25
  };
26
26
  };
27
27
 
28
- //#endregion
29
- //#region src/encode.ts
28
+ // src/encode.ts
30
29
  const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
31
30
  /**
32
31
  * Base64 of a string's UTF-8 bytes.
@@ -53,8 +52,7 @@ function base64EncodeUtf8(value) {
53
52
  return encoded;
54
53
  }
55
54
 
56
- //#endregion
57
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/typeof.js
55
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/typeof.js
58
56
  function _typeof(o) {
59
57
  "@babel/helpers - typeof";
60
58
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -64,8 +62,7 @@ function _typeof(o) {
64
62
  }, _typeof(o);
65
63
  }
66
64
 
67
- //#endregion
68
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPrimitive.js
65
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/toPrimitive.js
69
66
  function toPrimitive(t, r) {
70
67
  if ("object" != _typeof(t) || !t) return t;
71
68
  var e = t[Symbol.toPrimitive];
@@ -77,15 +74,13 @@ function toPrimitive(t, r) {
77
74
  return ("string" === r ? String : Number)(t);
78
75
  }
79
76
 
80
- //#endregion
81
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPropertyKey.js
77
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/toPropertyKey.js
82
78
  function toPropertyKey(t) {
83
79
  var i = toPrimitive(t, "string");
84
80
  return "symbol" == _typeof(i) ? i : i + "";
85
81
  }
86
82
 
87
- //#endregion
88
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/defineProperty.js
83
+ // \0@oxc-project+runtime@0.156.0/helpers/esm/defineProperty.js
89
84
  function _defineProperty(e, r, t) {
90
85
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
91
86
  value: t,
@@ -95,8 +90,7 @@ function _defineProperty(e, r, t) {
95
90
  }) : e[r] = t, e;
96
91
  }
97
92
 
98
- //#endregion
99
- //#region src/client.ts
93
+ // src/client.ts
100
94
  var LorikeetClient = class {
101
95
  constructor({ customisations, api_base, metadata, public_key }) {
102
96
  _defineProperty(this, "baseUrl", "https://chat.lorikeetcx.ai");
@@ -142,12 +136,16 @@ var LorikeetClient = class {
142
136
  }
143
137
  };
144
138
 
145
- //#endregion
146
- //#region src/errors.ts
139
+ // src/errors.ts
147
140
  /**
148
- * Codes the chat page posts to the host as `{ type: 'error', error: CODE }`.
149
- * Mirrored here because the page publishes them nowhere else, so a host would
150
- * otherwise be matching on strings it discovered by observation.
141
+ * The chat page's error vocabulary, as it reaches a host in
142
+ * `{ type: 'error', error: CODE }`. Mirrored here because the page publishes it
143
+ * nowhere else, so a host would otherwise be matching on strings it discovered
144
+ * by observation.
145
+ *
146
+ * The page's own list rather than a list of codes seen in the wild:
147
+ * `MISSING_PUBLIC_KEY` has no producer today, and is kept because narrowing this
148
+ * would be a breaking change.
151
149
  */
152
150
  const LORIKEET_ERROR_CODES = [
153
151
  "MISSING_TOKEN",
@@ -185,8 +183,7 @@ function isUnusableConversation(message) {
185
183
  return type === "error" && typeof error === "string" ? isUnusableConversationCode(error) : false;
186
184
  }
187
185
 
188
- //#endregion
189
- //#region src/events.ts
186
+ // src/events.ts
190
187
  const asRecord = (message) => typeof message === "object" && message !== null && !Array.isArray(message) ? message : null;
191
188
  const asNonEmptyString = (value) => typeof value === "string" && value !== "" ? value : null;
192
189
  /**
@@ -264,8 +261,7 @@ const resumedTicketIdFromUri = (uri) => {
264
261
  return (_segments$ = segments[2]) !== null && _segments$ !== void 0 ? _segments$ : null;
265
262
  };
266
263
 
267
- //#endregion
268
- //#region src/lifecycle.ts
264
+ // src/lifecycle.ts
269
265
  /**
270
266
  * The page gives its message stream ten attempts with exponential backoff
271
267
  * capped at 30s (`message-stream-utils.tsx`), so the budget runs out roughly
@@ -302,8 +298,7 @@ const shouldReloadAfterBackground = (backgroundedAt, now, thresholdMs = BACKGROU
302
298
  return elapsed >= thresholdMs;
303
299
  };
304
300
 
305
- //#endregion
306
- //#region src/links.ts
301
+ // src/links.ts
307
302
  /**
308
303
  * Schemes the WebView resolves for itself. None of them is a page the customer
309
304
  * asked to leave the app for, and the OS cannot open them anyway.
@@ -348,8 +343,7 @@ const isInternalNavigation = (url, baseUrl) => {
348
343
  return target.origin === base.origin;
349
344
  };
350
345
 
351
- //#endregion
352
- //#region src/message-circle-plus-icon.tsx
346
+ // src/message-circle-plus-icon.tsx
353
347
  const MessageCirclePlusIcon = ({ size = 24, color = "currentColor", strokeWidth = 2 }) => {
354
348
  return /* @__PURE__ */ jsxs(Svg, {
355
349
  fill: "none",
@@ -386,13 +380,13 @@ const MessageCirclePlusIcon = ({ size = 24, color = "currentColor", strokeWidth
386
380
  });
387
381
  };
388
382
 
389
- //#endregion
390
- //#region src/widget.tsx
383
+ // src/widget.tsx
391
384
  const stylesheet = StyleSheet.create({
392
385
  root: {
393
386
  flex: 1,
394
387
  backgroundColor: "#fff"
395
388
  },
389
+ keyboardAvoiding: { flex: 1 },
396
390
  container: {
397
391
  flex: 1,
398
392
  borderRadius: 8,
@@ -496,7 +490,7 @@ const LorikeetWidgetHeader = ({ title, style, icon = /* @__PURE__ */ jsx(Message
496
490
  ]
497
491
  });
498
492
  };
499
- const LorikeetWidgetView = forwardRef(function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, styles, onEvent, onWebViewMessage, ticketId, session, metadata, webviewProps }, ref) {
493
+ const LorikeetWidgetView = forwardRef(function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, styles, onEvent, onWebViewMessage, ticketId, session, metadata, webviewProps, avoidKeyboard = true }, ref) {
500
494
  var _customisations$hideH, _customisations$title;
501
495
  const [lorikeetClient, setLorikeetClient] = useState(null);
502
496
  const [loaded, setLoaded] = useState(null);
@@ -507,6 +501,15 @@ const LorikeetWidgetView = forwardRef(function LorikeetWidgetView({ publicKey, b
507
501
  setGeneration((previous) => previous + 1);
508
502
  }, []);
509
503
  const webViewRef = useRef(null);
504
+ const containerRef = useRef(null);
505
+ const [keyboardOffset, setKeyboardOffset] = useState(0);
506
+ const measureKeyboardOffset = useCallback((event) => {
507
+ var _containerRef$current;
508
+ const { y } = event.nativeEvent.layout;
509
+ (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 || _containerRef$current.measureInWindow((_x, windowY) => {
510
+ setKeyboardOffset(windowY - y);
511
+ });
512
+ }, []);
510
513
  const [refusedTicketId, setRefusedTicketId] = useState(null);
511
514
  const observedRef = useRef(null);
512
515
  const backgroundedAtRef = useRef(null);
@@ -794,67 +797,74 @@ const LorikeetWidgetView = forwardRef(function LorikeetWidgetView({ publicKey, b
794
797
  "right"
795
798
  ],
796
799
  style: stylesheet.root,
797
- children: /* @__PURE__ */ jsxs(View, {
798
- style: stylesheet.container,
799
- children: [
800
- hideHeader && closed !== "minimised" ? /* @__PURE__ */ jsx(LorikeetWidgetHeader, {
801
- onIconPress: startNewChat,
802
- style: styles === null || styles === void 0 ? void 0 : styles.header,
803
- title: (_customisations$title = customisations === null || customisations === void 0 ? void 0 : customisations.title) !== null && _customisations$title !== void 0 ? _customisations$title : "Lorikeet AI Agent"
804
- }) : null,
805
- closed === "minimised" ? /* @__PURE__ */ jsx(TouchableOpacity, {
806
- onPress: reopen,
807
- style: stylesheet.closedControl,
808
- children: /* @__PURE__ */ jsx(Text, {
809
- style: stylesheet.headerText,
810
- children: "Reopen chat"
811
- })
812
- }) : null,
813
- !hideHeader && closed === "ended" ? /* @__PURE__ */ jsx(TouchableOpacity, {
814
- onPress: startNewChat,
815
- style: stylesheet.closedControl,
816
- children: /* @__PURE__ */ jsx(Text, {
817
- style: stylesheet.headerText,
818
- children: "Start new chat"
819
- })
820
- }) : null,
821
- /* @__PURE__ */ jsx(View, {
822
- accessibilityElementsHidden: isClosed,
823
- importantForAccessibility: isClosed ? "no-hide-descendants" : "auto",
824
- pointerEvents: isClosed ? "none" : "auto",
825
- style: isClosed ? stylesheet.closed : stylesheet.webView,
826
- children: /* @__PURE__ */ jsx(LorikeetWidgetWebView, {
827
- baseUrl: lorikeetClient.baseUrl,
828
- onEvent: handleEvent,
829
- ref: webViewRef,
830
- uri: loaded.uri,
831
- webviewProps: {
832
- allowsInlineMediaPlayback: true,
833
- mediaPlaybackRequiresUserAction: false,
834
- scalesPageToFit: true,
835
- startInLoadingState: true,
836
- style: stylesheet.webView,
837
- ...webviewProps,
838
- onMessage: handleMessage,
839
- onRenderProcessGone: (event) => {
840
- var _webviewProps$onRende;
841
- if (generation === generationRef.current) reload();
842
- webviewProps === null || webviewProps === void 0 || (_webviewProps$onRende = webviewProps.onRenderProcessGone) === null || _webviewProps$onRende === void 0 || _webviewProps$onRende.call(webviewProps, event);
843
- },
844
- onContentProcessDidTerminate: (event) => {
845
- var _webviewProps$onConte;
846
- if (generation === generationRef.current) reload();
847
- webviewProps === null || webviewProps === void 0 || (_webviewProps$onConte = webviewProps.onContentProcessDidTerminate) === null || _webviewProps$onConte === void 0 || _webviewProps$onConte.call(webviewProps, event);
800
+ children: /* @__PURE__ */ jsx(KeyboardAvoidingView, {
801
+ behavior: "padding",
802
+ enabled: avoidKeyboard,
803
+ keyboardVerticalOffset: keyboardOffset,
804
+ onLayout: measureKeyboardOffset,
805
+ style: stylesheet.keyboardAvoiding,
806
+ children: /* @__PURE__ */ jsxs(View, {
807
+ ref: containerRef,
808
+ style: stylesheet.container,
809
+ children: [
810
+ hideHeader && closed !== "minimised" ? /* @__PURE__ */ jsx(LorikeetWidgetHeader, {
811
+ onIconPress: startNewChat,
812
+ style: styles === null || styles === void 0 ? void 0 : styles.header,
813
+ title: (_customisations$title = customisations === null || customisations === void 0 ? void 0 : customisations.title) !== null && _customisations$title !== void 0 ? _customisations$title : "Lorikeet AI Agent"
814
+ }) : null,
815
+ closed === "minimised" ? /* @__PURE__ */ jsx(TouchableOpacity, {
816
+ onPress: reopen,
817
+ style: stylesheet.closedControl,
818
+ children: /* @__PURE__ */ jsx(Text, {
819
+ style: stylesheet.headerText,
820
+ children: "Reopen chat"
821
+ })
822
+ }) : null,
823
+ !hideHeader && closed === "ended" ? /* @__PURE__ */ jsx(TouchableOpacity, {
824
+ onPress: startNewChat,
825
+ style: stylesheet.closedControl,
826
+ children: /* @__PURE__ */ jsx(Text, {
827
+ style: stylesheet.headerText,
828
+ children: "Start new chat"
829
+ })
830
+ }) : null,
831
+ /* @__PURE__ */ jsx(View, {
832
+ accessibilityElementsHidden: isClosed,
833
+ importantForAccessibility: isClosed ? "no-hide-descendants" : "auto",
834
+ pointerEvents: isClosed ? "none" : "auto",
835
+ style: isClosed ? stylesheet.closed : stylesheet.webView,
836
+ children: /* @__PURE__ */ jsx(LorikeetWidgetWebView, {
837
+ baseUrl: lorikeetClient.baseUrl,
838
+ onEvent: handleEvent,
839
+ ref: webViewRef,
840
+ uri: loaded.uri,
841
+ webviewProps: {
842
+ allowsInlineMediaPlayback: true,
843
+ mediaPlaybackRequiresUserAction: false,
844
+ scalesPageToFit: true,
845
+ startInLoadingState: true,
846
+ style: stylesheet.webView,
847
+ ...webviewProps,
848
+ onMessage: handleMessage,
849
+ onRenderProcessGone: (event) => {
850
+ var _webviewProps$onRende;
851
+ if (generation === generationRef.current) reload();
852
+ webviewProps === null || webviewProps === void 0 || (_webviewProps$onRende = webviewProps.onRenderProcessGone) === null || _webviewProps$onRende === void 0 || _webviewProps$onRende.call(webviewProps, event);
853
+ },
854
+ onContentProcessDidTerminate: (event) => {
855
+ var _webviewProps$onConte;
856
+ if (generation === generationRef.current) reload();
857
+ webviewProps === null || webviewProps === void 0 || (_webviewProps$onConte = webviewProps.onContentProcessDidTerminate) === null || _webviewProps$onConte === void 0 || _webviewProps$onConte.call(webviewProps, event);
858
+ }
848
859
  }
849
- }
850
- }, `${identity}|${resumingTicketId !== null && resumingTicketId !== void 0 ? resumingTicketId : ""}|${generation}`)
851
- })
852
- ]
860
+ }, `${identity}|${resumingTicketId !== null && resumingTicketId !== void 0 ? resumingTicketId : ""}|${generation}`)
861
+ })
862
+ ]
863
+ })
853
864
  })
854
865
  });
855
866
  });
856
867
  LorikeetWidgetView.displayName = "LorikeetWidgetView";
857
868
 
858
- //#endregion
859
869
  export { LOGOUT_CONFIRMATION_TIMEOUT_MS, LORIKEET_ERROR_CODES, LorikeetClient, LorikeetWidgetHeader, LorikeetWidgetView, LorikeetWidgetWebView, isUnusableConversation, isUnusableConversationCode };
860
870
  //# sourceMappingURL=index.js.map