@robylon/react-native-sdk 1.10.1-staging.0 → 1.10.1-staging.1

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.
@@ -0,0 +1,7 @@
1
+ # .npmignore.production
2
+ src/
3
+ __tests__/
4
+ __fixtures__/
5
+ __mocks__/
6
+ .env*
7
+ *.log
@@ -0,0 +1,6 @@
1
+ # .npmignore.staging
2
+ __tests__/
3
+ __fixtures__/
4
+ __mocks__/
5
+ .env*
6
+ *.log
@@ -0,0 +1,17 @@
1
+ {
2
+ "git": {
3
+ "commitMessage": "chore: release ",
4
+ "tagName": "v"
5
+ },
6
+ "npm": {
7
+ "publish": true
8
+ },
9
+ "github": {
10
+ "release": true
11
+ },
12
+ "plugins": {
13
+ "@release-it/conventional-changelog": {
14
+ "preset": "angular"
15
+ }
16
+ }
17
+ }
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
2
+ //# sourceMappingURL=openChatbot.js.mapdule", {
4
3
  value: true
5
4
  });
6
5
  exports.openChatbot = void 0;
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_constants","openChatbot","chatbotId","additionalParams","params","URLSearchParams","id","url","BASE_CHATBOT_URL","toString","Linking","openURL","exports"],"sourceRoot":"../../src","sources":["openChatbot.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AAEO,MAAME,WAAW,GAAGA,CACzBC,SAAiB,EACjBC,gBAAwC,GAAG,CAAC,CAAC,KACpC;EACT,MAAMC,MAAM,GAAG,IAAIC,eAAe,CAAC;IAAEC,EAAE,EAAEJ,SAAS;IAAE,GAAGC;EAAiB,CAAC,CAAC;EAC1E,MAAMI,GAAG,GAAG,GAAGC,2BAAgB,IAAIJ,MAAM,CAACK,QAAQ,CAAC,CAAC,EAAE;EACtDC,oBAAO,CAACC,OAAO,CAACJ,GAAG,CAAC;AACtB,CAAC;AAACK,OAAA,CAAAX,WAAA,GAAAA,WAAA","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["openChatbot.tsx"],"mappings":"","ignoreList":[]}
package/package.json CHANGED
@@ -1,18 +1,12 @@
1
1
  {
2
2
  "name": "@robylon/react-native-sdk",
3
- "version": "1.10.1-staging.0",
3
+ "version": "1.10.1-staging.1",
4
4
  "description": "React Native SDK for Robylon",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
7
7
  "types": "lib/typescript/index.d.ts",
8
8
  "react-native": "src/index.tsx",
9
9
  "source": "src/index.tsx",
10
- "files": [
11
- "lib",
12
- "!**/__tests__",
13
- "!**/__fixtures__",
14
- "!**/__mocks__"
15
- ],
16
10
  "scripts": {
17
11
  "prepare": "bob build",
18
12
  "build": "bob build",
@@ -0,0 +1,407 @@
1
+ {
2
+ "name": "@robylon/robylon-react-native-sdk",
3
+ "version": "1.6.0",
4
+ "description": "React Native SDK for Robylon",
5
+ "main": "lib/commonjs/index.js",
6
+ "module": "lib/module/index.js",
7
+ "types": "lib/typescript/index.d.ts",
8
+ "react-native": "src/index.tsx",
9
+ "source": "src/index.tsx",
10
+ "files": [
11
+ "src",
12
+ "lib",
13
+ "!**/__tests__",
14
+ "!**/__fixtures__",
15
+ "!**/__mocks__"
16
+ ],
17
+ "scripts": {
18
+ "prepare": "bob build",
19
+ "build": "bob build",
20
+ "clean": "del lib"
21
+ },
22
+ "peerDependencies": {
23
+ "react": "*",
24
+ "react-native": "*",
25
+ "react-native-webview": "^13.12.2"
26
+ },
27
+ "devDependencies": {
28
+ "@types/react": "^18.0.0",
29
+ "@types/react-native": "^0.70.0",
30
+ "react": "^18.0.0",
31
+ "react-native": "^0.70.0",
32
+ "react-native-builder-bob": "^0.20.0",
33
+ "typescript": "^4.5.2"
34
+ },
35
+ "react-native-builder-bob": {
36
+ "source": "src",
37
+ "output": "lib",
38
+ "targets": [
39
+ "commonjs",
40
+ "module",
41
+ [
42
+ "typescript",
43
+ {
44
+ "project": "tsconfig.build.json",
45
+ "tsc": "./node_modules/.bin/tsc"
46
+ }
47
+ ]
48
+ ]
49
+ },
50
+ "directories": {
51
+ "lib": "lib"
52
+ },
53
+ "dependencies": {
54
+ "accepts": "^1.3.8",
55
+ "anser": "^1.4.10",
56
+ "abort-controller": "^3.0.0",
57
+ "aggregate-error": "^3.1.0",
58
+ "ansi-regex": "^5.0.1",
59
+ "anymatch": "^3.1.3",
60
+ "ansi-fragments": "^0.2.1",
61
+ "absolute-path": "^0.0.0",
62
+ "array-union": "^2.1.0",
63
+ "ansi-styles": "^4.3.0",
64
+ "asap": "^2.0.6",
65
+ "ast-types": "^0.15.2",
66
+ "astral-regex": "^1.0.0",
67
+ "async-limiter": "^1.0.1",
68
+ "babel-plugin-polyfill-corejs3": "^0.10.6",
69
+ "babel-plugin-polyfill-regenerator": "^0.6.2",
70
+ "appdirsjs": "^1.2.7",
71
+ "babel-plugin-polyfill-corejs2": "^0.4.11",
72
+ "async": "^3.2.6",
73
+ "babel-core": "^7.0.0-bridge.0",
74
+ "babel-preset-fbjs": "^3.4.0",
75
+ "balanced-match": "^1.0.2",
76
+ "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0",
77
+ "base64-js": "^1.5.1",
78
+ "braces": "^3.0.3",
79
+ "brace-expansion": "^1.1.11",
80
+ "buffer-from": "^1.1.2",
81
+ "browserslist": "^4.24.0",
82
+ "buffer": "^5.7.1",
83
+ "bser": "^2.1.1",
84
+ "callsites": "^3.1.0",
85
+ "bytes": "^3.0.0",
86
+ "caller-path": "^2.0.0",
87
+ "chalk": "^4.1.2",
88
+ "bl": "^4.1.0",
89
+ "caniuse-lite": "^1.0.30001666",
90
+ "camelcase": "^6.3.0",
91
+ "cli-spinners": "^2.9.2",
92
+ "clone": "^1.0.4",
93
+ "cli-cursor": "^3.1.0",
94
+ "clone-deep": "^4.0.1",
95
+ "caller-callsite": "^2.0.0",
96
+ "color-convert": "^2.0.1",
97
+ "cliui": "^6.0.0",
98
+ "color-name": "^1.1.4",
99
+ "command-exists": "^1.2.9",
100
+ "colorette": "^1.4.0",
101
+ "compressible": "^2.0.18",
102
+ "commondir": "^1.0.1",
103
+ "commander": "^9.5.0",
104
+ "connect": "^3.7.0",
105
+ "concat-map": "^0.0.1",
106
+ "compression": "^1.7.4",
107
+ "core-util-is": "^1.0.3",
108
+ "core-js-compat": "^3.38.1",
109
+ "convert-source-map": "^2.0.0",
110
+ "cross-spawn": "^7.0.3",
111
+ "csstype": "^3.1.3",
112
+ "dayjs": "^1.11.13",
113
+ "dedent": "^0.7.0",
114
+ "deepmerge": "^3.3.0",
115
+ "decamelize": "^1.2.0",
116
+ "defaults": "^1.0.4",
117
+ "denodeify": "^1.2.1",
118
+ "del": "^6.1.1",
119
+ "dir-glob": "^3.0.1",
120
+ "depd": "^2.0.0",
121
+ "electron-to-chromium": "^1.5.31",
122
+ "destroy": "^1.2.0",
123
+ "ee-first": "^1.1.1",
124
+ "encodeurl": "^1.0.2",
125
+ "emoji-regex": "^8.0.0",
126
+ "end-of-stream": "^1.4.4",
127
+ "error-stack-parser": "^2.1.4",
128
+ "escalade": "^3.2.0",
129
+ "error-ex": "^1.3.2",
130
+ "errorhandler": "^1.5.1",
131
+ "escape-html": "^1.0.3",
132
+ "escape-string-regexp": "^4.0.0",
133
+ "envinfo": "^7.14.0",
134
+ "esutils": "^2.0.3",
135
+ "etag": "^1.8.1",
136
+ "event-target-shim": "^5.0.1",
137
+ "esprima": "^4.0.1",
138
+ "fast-glob": "^3.3.2",
139
+ "finalhandler": "^1.1.2",
140
+ "ci-info": "^3.9.0",
141
+ "fb-watchman": "^2.0.2",
142
+ "fastq": "^1.17.1",
143
+ "fill-range": "^7.1.1",
144
+ "flow-parser": "^0.121.0",
145
+ "fresh": "^0.5.2",
146
+ "find-up": "^4.1.0",
147
+ "fs.realpath": "^1.0.0",
148
+ "fsevents": "^2.3.3",
149
+ "gensync": "^1.0.0-beta.2",
150
+ "function-bind": "^1.1.2",
151
+ "fs-extra": "^8.1.0",
152
+ "glob-parent": "^5.1.2",
153
+ "glob": "^7.2.3",
154
+ "get-caller-file": "^2.0.5",
155
+ "graceful-fs": "^4.2.11",
156
+ "globby": "^11.1.0",
157
+ "find-cache-dir": "^2.1.0",
158
+ "has-flag": "^4.0.0",
159
+ "hasown": "^2.0.2",
160
+ "hermes-parser": "^0.8.0",
161
+ "globals": "^11.12.0",
162
+ "http-errors": "^2.0.0",
163
+ "ignore": "^5.3.2",
164
+ "hermes-estree": "^0.8.0",
165
+ "hermes-profile-transformer": "^0.0.6",
166
+ "image-size": "^0.6.3",
167
+ "imurmurhash": "^0.1.4",
168
+ "ieee754": "^1.2.1",
169
+ "import-fresh": "^3.3.0",
170
+ "inherits": "^2.0.4",
171
+ "indent-string": "^4.0.0",
172
+ "inflight": "^1.0.6",
173
+ "is-absolute": "^1.0.0",
174
+ "ip": "^1.1.9",
175
+ "is-arrayish": "^0.2.1",
176
+ "is-directory": "^0.3.1",
177
+ "invariant": "^2.2.4",
178
+ "is-core-module": "^2.15.1",
179
+ "is-git-dirty": "^2.0.2",
180
+ "is-extglob": "^2.1.1",
181
+ "is-glob": "^4.0.3",
182
+ "is-interactive": "^1.0.0",
183
+ "is-git-repository": "^2.0.0",
184
+ "is-fullwidth-code-point": "^2.0.0",
185
+ "is-path-cwd": "^2.2.0",
186
+ "is-number": "^7.0.0",
187
+ "is-plain-object": "^2.0.4",
188
+ "is-relative": "^1.0.0",
189
+ "is-path-inside": "^3.0.3",
190
+ "is-unicode-supported": "^0.1.0",
191
+ "is-unc-path": "^1.0.0",
192
+ "is-stream": "^2.0.1",
193
+ "is-windows": "^1.0.2",
194
+ "is-wsl": "^1.1.0",
195
+ "isarray": "^1.0.0",
196
+ "isexe": "^2.0.0",
197
+ "isobject": "^3.0.1",
198
+ "jest-regex-util": "^27.5.1",
199
+ "jest-serializer": "^27.5.1",
200
+ "jest-get-type": "^26.3.0",
201
+ "jest-worker": "^27.5.1",
202
+ "jetifier": "^2.0.0",
203
+ "joi": "^17.13.3",
204
+ "jest-validate": "^26.6.2",
205
+ "jscodeshift": "^0.14.0",
206
+ "jsesc": "^3.0.2",
207
+ "js-tokens": "^4.0.0",
208
+ "json-parse-better-errors": "^1.0.2",
209
+ "json-parse-even-better-errors": "^2.3.1",
210
+ "jsc-safe-url": "^0.2.4",
211
+ "kind-of": "^6.0.3",
212
+ "klaw": "^1.3.1",
213
+ "lines-and-columns": "^1.2.4",
214
+ "kleur": "^3.0.3",
215
+ "leven": "^3.1.0",
216
+ "locate-path": "^5.0.0",
217
+ "lodash.debounce": "^4.0.8",
218
+ "jsc-android": "^250230.2.1",
219
+ "lodash.throttle": "^4.1.1",
220
+ "log-symbols": "^4.1.0",
221
+ "json5": "^2.2.3",
222
+ "loose-envify": "^1.4.0",
223
+ "logkitty": "^0.7.1",
224
+ "lru-cache": "^5.1.1",
225
+ "makeerror": "^1.0.12",
226
+ "merge-stream": "^2.0.0",
227
+ "memoize-one": "^5.2.1",
228
+ "make-dir": "^2.1.0",
229
+ "merge2": "^1.4.1",
230
+ "metro": "^0.72.4",
231
+ "metro-babel-transformer": "^0.72.4",
232
+ "metro-cache-key": "^0.72.4",
233
+ "metro-config": "^0.72.4",
234
+ "metro-core": "^0.72.4",
235
+ "metro-file-map": "^0.72.4",
236
+ "jsonfile": "^4.0.0",
237
+ "metro-hermes-compiler": "^0.72.4",
238
+ "metro-inspector-proxy": "^0.72.4",
239
+ "metro-cache": "^0.72.4",
240
+ "metro-resolver": "^0.72.4",
241
+ "metro-runtime": "^0.72.4",
242
+ "metro-react-native-babel-transformer": "^0.72.4",
243
+ "metro-react-native-babel-preset": "^0.72.4",
244
+ "metro-minify-uglify": "^0.72.4",
245
+ "metro-source-map": "^0.72.4",
246
+ "metro-symbolicate": "^0.72.4",
247
+ "metro-transform-plugins": "^0.72.4",
248
+ "mime-types": "^2.1.35",
249
+ "mimic-fn": "^2.1.0",
250
+ "metro-transform-worker": "^0.72.4",
251
+ "minimatch": "^3.1.2",
252
+ "mkdirp": "^0.5.6",
253
+ "ms": "^2.1.3",
254
+ "mime": "^2.6.0",
255
+ "negotiator": "^0.6.3",
256
+ "neo-async": "^2.6.2",
257
+ "minimist": "^1.2.8",
258
+ "nice-try": "^1.0.5",
259
+ "jest-util": "^27.5.1",
260
+ "nocache": "^3.0.4",
261
+ "node-fetch": "^2.7.0",
262
+ "node-int64": "^0.4.0",
263
+ "node-dir": "^0.1.17",
264
+ "node-stream-zip": "^1.15.0",
265
+ "normalize-path": "^3.0.0",
266
+ "node-releases": "^2.0.18",
267
+ "ob1": "^0.72.4",
268
+ "nullthrows": "^1.1.1",
269
+ "npm-run-path": "^4.0.1",
270
+ "object-assign": "^4.1.1",
271
+ "on-finished": "^2.3.0",
272
+ "on-headers": "^1.0.2",
273
+ "once": "^1.4.0",
274
+ "onetime": "^5.1.2",
275
+ "os-tmpdir": "^1.0.2",
276
+ "open": "^6.4.0",
277
+ "p-limit": "^2.3.0",
278
+ "ora": "^5.4.1",
279
+ "p-finally": "^1.0.0",
280
+ "parent-module": "^1.0.1",
281
+ "p-try": "^2.2.0",
282
+ "p-map": "^4.0.0",
283
+ "p-locate": "^4.1.0",
284
+ "parse-json": "^5.2.0",
285
+ "parseurl": "^1.3.3",
286
+ "path-exists": "^4.0.0",
287
+ "path-parse": "^1.0.7",
288
+ "path-key": "^3.1.1",
289
+ "path-type": "^4.0.0",
290
+ "path-is-absolute": "^1.0.1",
291
+ "picomatch": "^2.3.1",
292
+ "pirates": "^4.0.6",
293
+ "picocolors": "^1.1.0",
294
+ "pkg-dir": "^3.0.0",
295
+ "micromatch": "^4.0.8",
296
+ "pretty-format": "^26.6.2",
297
+ "process-nextick-args": "^2.0.1",
298
+ "promise": "^8.3.0",
299
+ "pify": "^4.0.1",
300
+ "queue-microtask": "^1.2.3",
301
+ "pump": "^3.0.2",
302
+ "prompts": "^2.4.2",
303
+ "range-parser": "^1.2.1",
304
+ "react-devtools-core": "^4.27.7",
305
+ "react-is": "^17.0.2",
306
+ "react-native-gradle-plugin": "^0.70.3",
307
+ "react-native-codegen": "^0.70.7",
308
+ "react-refresh": "^0.4.3",
309
+ "react-shallow-renderer": "^16.15.0",
310
+ "react-native-webview": "^13.12.2",
311
+ "recast": "^0.21.5",
312
+ "regenerate-unicode-properties": "^10.2.0",
313
+ "readable-stream": "^3.6.2",
314
+ "regenerate": "^1.4.2",
315
+ "regenerator-runtime": "^0.13.11",
316
+ "regjsgen": "^0.8.0",
317
+ "regenerator-transform": "^0.15.2",
318
+ "readline": "^1.3.0",
319
+ "regjsparser": "^0.11.0",
320
+ "regexpu-core": "^6.1.1",
321
+ "require-main-filename": "^2.0.0",
322
+ "require-directory": "^2.1.1",
323
+ "restore-cursor": "^3.1.0",
324
+ "resolve": "^1.22.8",
325
+ "reusify": "^1.0.4",
326
+ "resolve-from": "^4.0.0",
327
+ "rimraf": "^3.0.2",
328
+ "safe-buffer": "^5.1.2",
329
+ "send": "^0.19.0",
330
+ "run-parallel": "^1.2.0",
331
+ "clean-stack": "^2.2.0",
332
+ "serialize-error": "^2.1.0",
333
+ "set-blocking": "^2.0.0",
334
+ "serve-static": "^1.16.2",
335
+ "debug": "^4.3.7",
336
+ "setprototypeof": "^1.2.0",
337
+ "shebang-regex": "^3.0.0",
338
+ "shebang-command": "^2.0.0",
339
+ "shallow-clone": "^3.0.1",
340
+ "slice-ansi": "^2.1.0",
341
+ "shell-quote": "^1.8.1",
342
+ "sisteransi": "^1.0.5",
343
+ "signal-exit": "^3.0.7",
344
+ "source-map-support": "^0.5.21",
345
+ "stackframe": "^1.3.4",
346
+ "stacktrace-parser": "^0.1.10",
347
+ "string-width": "^4.2.3",
348
+ "source-map": "^0.7.4",
349
+ "string_decoder": "^1.3.0",
350
+ "sprintf-js": "^1.0.3",
351
+ "strip-ansi": "^5.2.0",
352
+ "statuses": "^1.5.0",
353
+ "sudo-prompt": "^9.2.1",
354
+ "supports-preserve-symlinks-flag": "^1.0.0",
355
+ "strip-final-newline": "^2.0.0",
356
+ "temp": "^0.8.3",
357
+ "strip-eof": "^1.0.0",
358
+ "through2": "^2.0.5",
359
+ "mime-db": "^1.53.0",
360
+ "tmpl": "^1.0.5",
361
+ "throat": "^5.0.0",
362
+ "to-regex-range": "^5.0.1",
363
+ "tr46": "^0.0.3",
364
+ "supports-color": "^7.2.0",
365
+ "to-fast-properties": "^2.0.0",
366
+ "toidentifier": "^1.0.1",
367
+ "tslib": "^2.7.0",
368
+ "type-fest": "^0.7.1",
369
+ "undici-types": "^6.19.8",
370
+ "unicode-match-property-ecmascript": "^2.0.0",
371
+ "unicode-canonical-property-names-ecmascript": "^2.0.1",
372
+ "unicode-property-aliases-ecmascript": "^2.1.0",
373
+ "unicode-match-property-value-ecmascript": "^2.2.0",
374
+ "universalify": "^0.1.2",
375
+ "uglify-es": "^3.3.9",
376
+ "unc-path-regex": "^0.1.2",
377
+ "update-browserslist-db": "^1.1.1",
378
+ "vary": "^1.1.2",
379
+ "unpipe": "^1.0.0",
380
+ "utils-merge": "^1.0.1",
381
+ "util-deprecate": "^1.0.2",
382
+ "vlq": "^1.0.1",
383
+ "use-sync-external-store": "^1.2.2",
384
+ "walker": "^1.0.8",
385
+ "wcwidth": "^1.0.1",
386
+ "webidl-conversions": "^3.0.1",
387
+ "which": "^2.0.2",
388
+ "whatwg-fetch": "^3.6.20",
389
+ "wrappy": "^1.0.2",
390
+ "whatwg-url": "^5.0.0",
391
+ "wrap-ansi": "^6.2.0",
392
+ "write-file-atomic": "^2.4.3",
393
+ "which-module": "^2.0.1",
394
+ "xtend": "^4.0.2",
395
+ "ws": "^6.2.3",
396
+ "yallist": "^3.1.1",
397
+ "y18n": "^4.0.3",
398
+ "yargs": "^15.4.1",
399
+ "scheduler": "^0.22.0",
400
+ "yaml": "^1.10.2",
401
+ "slash": "^3.0.0",
402
+ "yargs-parser": "^21.1.1",
403
+ "yocto-queue": "^0.1.0"
404
+ },
405
+ "author": "",
406
+ "license": "ISC"
407
+ }
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ dependencies: {
3
+ "react-native": {
4
+ platforms: {
5
+ android: null, // disable Android platform, other platforms will still autolink if provided
6
+ ios: null, // disable iOS platform, other platforms will still autolink if provided
7
+ },
8
+ },
9
+ },
10
+ };
@@ -0,0 +1,44 @@
1
+ // File: src/ChatbotWebview.tsx
2
+ import React, { useEffect, useState } from "react";
3
+ import { View } from "react-native";
4
+ import { WebView } from "react-native-webview";
5
+ import { BASE_CHATBOT_URL } from "./constants";
6
+ import LoadingIndicator from "./LoadingIndicator";
7
+
8
+ interface ChatbotWebviewProps {
9
+ chatbotId: string;
10
+ additionalParams?: Record<string, string>;
11
+ }
12
+
13
+ const constructUrl = (
14
+ chatbotId: string,
15
+ additionalParams: Record<string, string> = {}
16
+ ): string => {
17
+ const params = new URLSearchParams({ id: chatbotId, ...additionalParams });
18
+ return `${BASE_CHATBOT_URL}?${params.toString()}`;
19
+ };
20
+
21
+ export const ChatbotWebview: React.FC<ChatbotWebviewProps> = ({
22
+ chatbotId,
23
+ additionalParams,
24
+ }) => {
25
+ const [url, setUrl] = useState<string>("");
26
+
27
+ useEffect(() => {
28
+ setUrl(constructUrl(chatbotId, additionalParams));
29
+ }, [chatbotId, additionalParams]);
30
+
31
+ return (
32
+ <View style={{ flex: 1 }}>
33
+ {url ? (
34
+ <WebView
35
+ source={{ uri: url }}
36
+ startInLoadingState={true}
37
+ renderLoading={() => <LoadingIndicator />}
38
+ />
39
+ ) : (
40
+ <LoadingIndicator />
41
+ )}
42
+ </View>
43
+ );
44
+ };
@@ -0,0 +1,379 @@
1
+ import React, { useState, useEffect, useRef, useMemo } from "react";
2
+ import {
3
+ View,
4
+ StyleSheet,
5
+ Animated,
6
+ Dimensions,
7
+ Platform,
8
+ StatusBar,
9
+ } from "react-native";
10
+ import { WebView, WebViewMessageEvent } from "react-native-webview";
11
+ import FloatingButton from "./FloatingButton";
12
+ import { BASE_CHATBOT_URL } from "./constants";
13
+
14
+ interface ChatbotSDKProps {
15
+ api_key: string;
16
+ user_id?: string;
17
+ user_token?: string;
18
+ additional_params?: Record<string, string>;
19
+ show_floating_button?: boolean;
20
+ onMessage?: (message: any) => void;
21
+ isFullScreen?: boolean;
22
+ enableAnimation?: boolean;
23
+ onOpen?: () => void;
24
+ onClose?: () => void;
25
+ }
26
+
27
+ interface ChatbotMessage {
28
+ type: string;
29
+ data?: any;
30
+ }
31
+
32
+ interface ChatbotConfig {
33
+ brand_color: string;
34
+ image_url: string;
35
+ welcome_message: string;
36
+ }
37
+
38
+ const ChatbotSDK: React.FC<ChatbotSDKProps> = ({
39
+ api_key,
40
+ user_id,
41
+ user_token,
42
+ additional_params = {},
43
+ show_floating_button = true,
44
+ onMessage,
45
+ isFullScreen = true,
46
+ enableAnimation = true,
47
+ onOpen,
48
+ onClose,
49
+ }) => {
50
+ const [isWebViewVisible, setIsWebViewVisible] = useState(false);
51
+ const [chatbotConfig, setChatbotConfig] = useState<ChatbotConfig | null>(
52
+ null
53
+ );
54
+ const [loading, setLoading] = useState(true);
55
+ const webViewRef = useRef<WebView>(null);
56
+ const fadeAnim = useRef(new Animated.Value(0)).current;
57
+ const isFirstLoadRef = useRef(true);
58
+ const webViewUrl = useMemo(
59
+ () => constructUrl(),
60
+ [api_key, user_id, additional_params]
61
+ );
62
+
63
+ const stableAdditionalParams = useMemo(
64
+ () => additional_params,
65
+ [JSON.stringify(additional_params)]
66
+ );
67
+
68
+ const triggerAppInit = () => {
69
+ if (webViewRef.current) {
70
+ webViewRef.current.injectJavaScript(`
71
+ // Trigger APP_READY equivalent
72
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'APP_READY' }));
73
+ true;
74
+ `);
75
+ }
76
+ };
77
+
78
+ useEffect(() => {
79
+ const fetchChatbotConfig = async () => {
80
+ try {
81
+ const endpointUrl = `https://stage-api.robylon.ai/users/auth/copilot/`;
82
+ const payload = {
83
+ client_user_id: user_id,
84
+ org_id: api_key,
85
+ token: user_token,
86
+ extra_info: stableAdditionalParams,
87
+ };
88
+
89
+ const response = await fetch(endpointUrl, {
90
+ method: "POST",
91
+ headers: {
92
+ "Content-Type": "application/json",
93
+ },
94
+ body: JSON.stringify(payload),
95
+ });
96
+
97
+ if (!response.ok) {
98
+ throw new Error("Failed to fetch chatbot configuration");
99
+ }
100
+
101
+ const data = await response.json();
102
+ const orgInfo = data?.user?.org_info;
103
+
104
+ if (orgInfo) {
105
+ setChatbotConfig({
106
+ brand_color: orgInfo?.config?.brand_colour || "#007AFF",
107
+ image_url: orgInfo?.brand_config?.launcher_logo_url || "",
108
+ welcome_message: orgInfo?.config?.welcome_message || "",
109
+ });
110
+ }
111
+ } catch (error) {
112
+ console.error("Error fetching chatbot configuration:", error);
113
+ } finally {
114
+ setLoading(false);
115
+ }
116
+ };
117
+
118
+ if (api_key && user_id) {
119
+ fetchChatbotConfig();
120
+ }
121
+ }, [api_key, user_id, user_token, stableAdditionalParams]);
122
+
123
+ function constructUrl(): string {
124
+ if (!user_id) return "";
125
+ const params = new URLSearchParams({
126
+ id: api_key,
127
+ user_id,
128
+ ...additional_params,
129
+ });
130
+ return `${BASE_CHATBOT_URL}?${params.toString()}`;
131
+ }
132
+
133
+ const openWebView = () => {
134
+ setIsWebViewVisible(true);
135
+ if (enableAnimation) {
136
+ Animated.timing(fadeAnim, {
137
+ toValue: 1,
138
+ duration: 250,
139
+ useNativeDriver: true,
140
+ }).start(() => {
141
+ onOpen?.();
142
+ if (!isFirstLoadRef.current) {
143
+ // If not first load, manually trigger initialization
144
+ setTimeout(triggerAppInit, 100);
145
+ }
146
+ });
147
+ } else {
148
+ fadeAnim.setValue(1);
149
+ requestAnimationFrame(() => {
150
+ onOpen?.();
151
+ if (!isFirstLoadRef.current) {
152
+ setTimeout(triggerAppInit, 100);
153
+ }
154
+ });
155
+ }
156
+ };
157
+
158
+ const closeWebView = () => {
159
+ if (webViewRef.current) {
160
+ console.log("closeWebView");
161
+ webViewRef.current.postMessage(
162
+ JSON.stringify({
163
+ name: "closeFrame",
164
+ domain: "app-domain.com",
165
+ })
166
+ );
167
+ }
168
+
169
+ const complete = () => {
170
+ setIsWebViewVisible(false);
171
+ onClose?.();
172
+ };
173
+
174
+ if (enableAnimation) {
175
+ Animated.timing(fadeAnim, {
176
+ toValue: 0,
177
+ duration: 200,
178
+ useNativeDriver: true,
179
+ }).start(complete);
180
+ } else {
181
+ fadeAnim.setValue(0);
182
+ requestAnimationFrame(complete);
183
+ }
184
+ };
185
+
186
+ const handleMessage = (event: WebViewMessageEvent) => {
187
+ const { data } = event.nativeEvent;
188
+
189
+ try {
190
+ const parsedData: ChatbotMessage = JSON.parse(data);
191
+
192
+ if (parsedData.type === "APP_READY") {
193
+ console.log("APP_READY", webViewRef.current && isWebViewVisible);
194
+ if (webViewRef.current && isWebViewVisible) {
195
+ webViewRef.current.injectJavaScript(`
196
+ window.postMessage(${JSON.stringify({
197
+ name: "openFrame",
198
+ domain: "app-domain.com",
199
+ })}, '*');
200
+ window.postMessage(${JSON.stringify({
201
+ name: "registerUserId",
202
+ action: "registerUserId",
203
+ domain: "app-domain.com",
204
+ data: {
205
+ userId: `${user_id}`,
206
+ token: `${user_token}`,
207
+ },
208
+ })}, '*');
209
+ `);
210
+ }
211
+ }
212
+
213
+ if (typeof parsedData !== "object" || !parsedData.type) {
214
+ console.warn("Invalid message structure");
215
+ return;
216
+ }
217
+
218
+ switch (parsedData.type) {
219
+ case "close_chatbot":
220
+ closeWebView();
221
+ break;
222
+ default:
223
+ if (onMessage) onMessage(parsedData);
224
+ }
225
+ } catch (error) {
226
+ console.error("Failed to parse or process WebView message:", error);
227
+ }
228
+ };
229
+
230
+ const getScreenDimensions = () => {
231
+ const windowHeight = Dimensions.get("window").height;
232
+ const windowWidth = Dimensions.get("window").width;
233
+ const statusBarHeight =
234
+ Platform.OS === "ios" ? 0 : StatusBar.currentHeight || 0;
235
+
236
+ return {
237
+ height: windowHeight - statusBarHeight,
238
+ width: windowWidth,
239
+ };
240
+ };
241
+
242
+ const screenDimensions = getScreenDimensions();
243
+
244
+ return (
245
+ <View style={styles.mainContainer}>
246
+ {!loading && (
247
+ <>
248
+ {show_floating_button && api_key && chatbotConfig && (
249
+ <FloatingButton
250
+ onPress={openWebView}
251
+ brandColor={chatbotConfig.brand_color}
252
+ imageUrl={chatbotConfig.image_url}
253
+ />
254
+ )}
255
+ <View
256
+ style={[
257
+ styles.webViewWrapper,
258
+ { height: isWebViewVisible ? "100%" : 0 },
259
+ ]}
260
+ pointerEvents={isWebViewVisible ? "auto" : "none"}
261
+ >
262
+ <Animated.View
263
+ style={[
264
+ isFullScreen
265
+ ? styles.fullScreenContainer
266
+ : styles.inlineContainer,
267
+ { opacity: fadeAnim },
268
+ ]}
269
+ >
270
+ <WebView
271
+ ref={webViewRef}
272
+ source={{ uri: webViewUrl }}
273
+ onMessage={handleMessage}
274
+ style={styles.webview}
275
+ containerStyle={
276
+ isFullScreen
277
+ ? {
278
+ width: screenDimensions.width,
279
+ height: screenDimensions.height,
280
+ }
281
+ : undefined
282
+ }
283
+ allowsInlineMediaPlayback={true}
284
+ mediaPlaybackRequiresUserAction={false}
285
+ allowFileAccess={false}
286
+ geolocationEnabled={false}
287
+ javaScriptEnabled={true}
288
+ domStorageEnabled={true}
289
+ cacheEnabled={true}
290
+ scrollEnabled={true}
291
+ bounces={false}
292
+ onShouldStartLoadWithRequest={(request) => {
293
+ return request.url.startsWith(BASE_CHATBOT_URL);
294
+ }}
295
+ startInLoadingState={isFirstLoadRef.current}
296
+ onLoadEnd={() => {
297
+ webViewRef.current?.injectJavaScript(`
298
+ if (!document.querySelector('meta[name="viewport"]')) {
299
+ var meta = document.createElement('meta');
300
+ meta.name = 'viewport';
301
+ meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';
302
+ document.getElementsByTagName('head')[0].appendChild(meta);
303
+ }
304
+
305
+ if (!document.querySelector('#injectedStyle')) {
306
+ const style = document.createElement('style');
307
+ style.id = 'injectedStyle';
308
+ style.textContent = \`
309
+ html, body, #root, #__next {
310
+ height: 100% !important;
311
+ min-height: 100% !important;
312
+ overflow: hidden !important;
313
+ }
314
+ \`;
315
+ document.head.appendChild(style);
316
+ }
317
+
318
+ window.sendToChatbot = function(message) {
319
+ window.ReactNativeWebView.postMessage(JSON.stringify(message));
320
+ };
321
+
322
+ var closeButton = document.querySelector('.chatbot-close-button');
323
+ if (closeButton) {
324
+ closeButton.addEventListener('click', () => {
325
+ window.sendToChatbot({ type: 'close_chatbot' });
326
+ });
327
+ }
328
+
329
+ true;
330
+ `);
331
+ isFirstLoadRef.current = false;
332
+ }}
333
+ onError={(syntheticEvent) => {
334
+ const { nativeEvent } = syntheticEvent;
335
+ console.warn("WebView error:", nativeEvent);
336
+ }}
337
+ />
338
+ </Animated.View>
339
+ </View>
340
+ </>
341
+ )}
342
+ </View>
343
+ );
344
+ };
345
+
346
+ const styles = StyleSheet.create({
347
+ mainContainer: {
348
+ flex: 1,
349
+ position: "relative",
350
+ },
351
+ webViewWrapper: {
352
+ position: "absolute",
353
+ top: 0,
354
+ left: 0,
355
+ right: 0,
356
+ bottom: 0,
357
+ overflow: "hidden",
358
+ zIndex: 1000,
359
+ },
360
+ fullScreenContainer: {
361
+ position: "absolute",
362
+ top: 0,
363
+ left: 0,
364
+ right: 0,
365
+ bottom: 0,
366
+ backgroundColor: "white",
367
+ zIndex: 1000,
368
+ },
369
+ inlineContainer: {
370
+ flex: 1,
371
+ backgroundColor: "white",
372
+ },
373
+ webview: {
374
+ flex: 1,
375
+ backgroundColor: "white",
376
+ },
377
+ });
378
+
379
+ export default ChatbotSDK;
@@ -0,0 +1,57 @@
1
+ import React from "react";
2
+ import { TouchableOpacity, StyleSheet, Text, Image } from "react-native";
3
+
4
+ interface FloatingButtonProps {
5
+ onPress: () => void;
6
+ brandColor?: string; // For dynamic branding
7
+ imageUrl?: string; // For brand logo or icon
8
+ }
9
+
10
+ const FloatingButton: React.FC<FloatingButtonProps> = ({
11
+ onPress,
12
+ brandColor = "#007AFF", // Default color
13
+ imageUrl,
14
+ }) => {
15
+ return (
16
+ <TouchableOpacity
17
+ style={[styles.button, { backgroundColor: brandColor }]}
18
+ onPress={onPress}
19
+ >
20
+ {imageUrl ? (
21
+ <Image source={{ uri: imageUrl }} style={styles.buttonImage} />
22
+ ) : (
23
+ <Text style={styles.buttonText}>Chat</Text>
24
+ )}
25
+ </TouchableOpacity>
26
+ );
27
+ };
28
+
29
+ const styles = StyleSheet.create({
30
+ button: {
31
+ position: "absolute",
32
+ bottom: 20,
33
+ right: 20,
34
+ borderRadius: 30,
35
+ width: 60,
36
+ height: 60,
37
+ justifyContent: "center",
38
+ alignItems: "center",
39
+ elevation: 5,
40
+ shadowColor: "#000",
41
+ shadowOffset: { width: 0, height: 2 },
42
+ shadowOpacity: 0.25,
43
+ shadowRadius: 3.84,
44
+ },
45
+ buttonText: {
46
+ color: "white",
47
+ fontSize: 16,
48
+ fontWeight: "bold",
49
+ },
50
+ buttonImage: {
51
+ width: 40,
52
+ height: 40,
53
+ borderRadius: 20,
54
+ },
55
+ });
56
+
57
+ export default FloatingButton;
@@ -0,0 +1,11 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { View, ActivityIndicator } from "react-native";
3
+ import { WebView } from "react-native-webview";
4
+
5
+ const LoadingIndicator: React.FC = () => (
6
+ <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
7
+ <ActivityIndicator size="large" color="#0000ff" />
8
+ </View>
9
+ );
10
+
11
+ export default LoadingIndicator;
package/src/config.ts ADDED
@@ -0,0 +1,4 @@
1
+ export const config = {
2
+ API_URL: process.env.API_URL || 'https://api.robylon.com',
3
+ DEBUG: process.env.DEBUG === 'true'
4
+ };
@@ -0,0 +1,3 @@
1
+ const BASE_CHATBOT_DOMAIN = process.env.CHATBOT_DOMAIN || "";
2
+ const CHATBOT_PATH = process.env.CHATBOT_PATH || "";
3
+ export const BASE_CHATBOT_URL = `${BASE_CHATBOT_DOMAIN}/${CHATBOT_PATH}`;
@@ -0,0 +1,6 @@
1
+ // declare module "react-native" {
2
+ // export const View: any;
3
+ // export const ActivityIndicator: any;
4
+ // export const Linking: any;
5
+ // // Add other React Native exports as needed
6
+ // }
package/src/index.tsx ADDED
@@ -0,0 +1,2 @@
1
+ export { default as ChatbotSDK } from "./Chatbotsdk";
2
+ export { openChatbot } from "./openChatbot";
@@ -0,0 +1,11 @@
1
+ import { Linking } from "react-native";
2
+ import { BASE_CHATBOT_URL } from "./constants";
3
+
4
+ export const openChatbot = (
5
+ chatbotId: string,
6
+ additionalParams: Record<string, string> = {}
7
+ ): void => {
8
+ const params = new URLSearchParams({ id: chatbotId, ...additionalParams });
9
+ const url = `${BASE_CHATBOT_URL}?${params.toString()}`;
10
+ Linking.openURL(url);
11
+ };
File without changes
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "outDir": "./lib/typescript"
6
+ },
7
+ "exclude": [
8
+ "**/__tests__",
9
+ "**/__mocks__",
10
+ "**/__fixtures__",
11
+ "node_modules",
12
+ "babel.config.js",
13
+ "metro.config.js",
14
+ "jest.config.js"
15
+ ]
16
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "module": "esnext",
5
+ "lib": ["esnext"],
6
+ "jsx": "react-native",
7
+ "strict": true,
8
+ "moduleResolution": "node",
9
+ "allowSyntheticDefaultImports": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "noEmit": false,
16
+ "emitDeclarationOnly": true,
17
+ "declaration": true,
18
+ "types": ["react-native", "node"]
19
+ },
20
+ "exclude": [
21
+ "node_modules",
22
+ "babel.config.js",
23
+ "metro.config.js",
24
+ "jest.config.js"
25
+ ]
26
+ }