@robylon/web-react-sdk 1.1.28-staging.57 → 1.1.28-staging.59

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 CHANGED
@@ -13,7 +13,7 @@ npm install @robylon/web-react-sdk
13
13
  ### Vanilla JavaScript
14
14
 
15
15
  ```html
16
- <script src="https://staging-cdn.robylon.com/1.1.28-staging.56/robylon.min.js"></script>
16
+ <script src="https://staging-cdn.robylon.com/1.1.28-staging.58/robylon.min.js"></script>
17
17
  ```
18
18
 
19
19
  Or via npm:
package/dist/cjs/index.js CHANGED
@@ -235,6 +235,7 @@ var ChatbotEmbed = /** @class */ (function () {
235
235
  this.bubblePromptTimeouts = [];
236
236
  this.eventHandlers = new Map();
237
237
  this.isInitialized = false;
238
+ this._visibilityObserver = null;
238
239
  this.onMessageListener = function (event) {
239
240
  if (event.origin === _this.config.domain) {
240
241
  if (event.data === "closeChatbot") {
@@ -283,7 +284,7 @@ var ChatbotEmbed = /** @class */ (function () {
283
284
  }
284
285
  };
285
286
  this.config = config;
286
- // Use provided container or default to document.body
287
+ // Always maintain a reference to the container for visibility tracking
287
288
  this.containerElement = (options === null || options === void 0 ? void 0 : options.containerElement) || document.body;
288
289
  // Normalize the config
289
290
  if (typeof this.config.userId === "number") {
@@ -369,6 +370,15 @@ var ChatbotEmbed = /** @class */ (function () {
369
370
  var wildcardHandlers = this.eventHandlers.get("*") || [];
370
371
  wildcardHandlers.forEach(function (handler) { return handler(event); });
371
372
  };
373
+ // Add method to update container
374
+ ChatbotEmbed.prototype.setContainer = function (container) {
375
+ if (!container)
376
+ return;
377
+ // Only track the container for visibility
378
+ this.containerElement = container;
379
+ // Watch for container visibility changes
380
+ this.setupContainerVisibilityObserver();
381
+ };
372
382
  // Cleanup
373
383
  ChatbotEmbed.prototype.destroy = function () {
374
384
  // Remove DOM elements
@@ -385,6 +395,11 @@ var ChatbotEmbed = /** @class */ (function () {
385
395
  this.bubblePromptContainer.parentElement.removeChild(this.bubblePromptContainer);
386
396
  this.bubblePromptContainer = null;
387
397
  }
398
+ // Disconnect intersection observer
399
+ if (this._visibilityObserver) {
400
+ this._visibilityObserver.disconnect();
401
+ this._visibilityObserver = null;
402
+ }
388
403
  // Remove event listeners
389
404
  window === null || window === void 0 ? void 0 : window.removeEventListener("message", this.onMessageListener);
390
405
  // Clear event handlers
@@ -402,6 +417,35 @@ var ChatbotEmbed = /** @class */ (function () {
402
417
  ChatbotEmbed.prototype.setupEventListeners = function () {
403
418
  window === null || window === void 0 ? void 0 : window.addEventListener("message", this.onMessageListener);
404
419
  };
420
+ ChatbotEmbed.prototype.setupContainerVisibilityObserver = function () {
421
+ var _this = this;
422
+ // Watch for container visibility changes
423
+ if ("IntersectionObserver" in window &&
424
+ this.containerElement !== document.body) {
425
+ // Disconnect existing observer if any
426
+ if (this._visibilityObserver) {
427
+ this._visibilityObserver.disconnect();
428
+ }
429
+ this._visibilityObserver = new IntersectionObserver(function (entries) {
430
+ for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
431
+ var entry = entries_1[_i];
432
+ // If container is not visible, hide chatbot elements
433
+ if (!entry.isIntersecting) {
434
+ if (_this.iframe)
435
+ _this.iframe.style.display = "none";
436
+ if (_this.logoContainer)
437
+ _this.logoContainer.style.display = "none";
438
+ }
439
+ else {
440
+ // Restore button visibility when container becomes visible
441
+ if (_this.logoContainer)
442
+ _this.logoContainer.style.display = "flex";
443
+ }
444
+ }
445
+ });
446
+ this._visibilityObserver.observe(this.containerElement);
447
+ }
448
+ };
405
449
  ChatbotEmbed.prototype.init = function () {
406
450
  this.createIframe();
407
451
  this.createFloatingButton();
@@ -410,32 +454,41 @@ var ChatbotEmbed = /** @class */ (function () {
410
454
  var _this = this;
411
455
  var div = document.createElement("div");
412
456
  div.classList.add("message-bubble-container");
413
- Object.assign(div.style, {
414
- position: "absolute",
415
- bottom: "1.5rem",
416
- right: "1.5rem",
417
- zIndex: "1000",
418
- width: "48px",
419
- height: "48px",
420
- display: "flex",
421
- flexDirection: "column-reverse",
422
- backgroundColor: this.config.brand_colour,
423
- color: getBestFontColor(this.config.brand_colour),
424
- borderRadius: "50%",
425
- alignItems: "center",
426
- justifyContent: "center",
427
- cursor: "pointer",
428
- overflow: "hidden",
457
+ // Force styles with !important to override any potential conflicts
458
+ div.setAttribute("style", "\n position: fixed !important;\n bottom: 20px !important;\n right: 20px !important;\n z-index: 2147483647 !important;\n width: 60px !important;\n height: 60px !important;\n display: flex !important;\n flex-direction: column-reverse !important;\n background-color: ".concat(this.config.brand_colour, " !important;\n color: ").concat(getBestFontColor(this.config.brand_colour), " !important;\n border-radius: 50% !important;\n align-items: center !important;\n justify-content: center !important;\n cursor: pointer !important;\n overflow: hidden !important;\n box-shadow: 0 4px 8px rgba(0,0,0,0.2) !important;\n "));
459
+ // Explicitly log button creation
460
+ console.log("ROBYLON DEBUG: Creating button", {
461
+ time: new Date().toISOString(),
462
+ color: this.config.brand_colour,
429
463
  });
430
- this.containerElement.appendChild(div);
464
+ // Always append to body
465
+ document.body.appendChild(div);
431
466
  this.logoContainer = div;
432
467
  this.loadImage(this.logoContainer);
433
468
  this.createChatBubblContainer();
434
- this.logoContainer.addEventListener("click", this.toggleIframe.bind(this));
435
- // Emit button loaded event
469
+ // Ensure button is clickable
470
+ this.logoContainer.addEventListener("click", function () {
471
+ console.log("ROBYLON DEBUG: Button clicked");
472
+ _this.toggleIframe();
473
+ });
474
+ // Add a backup timeout to check button visibility
436
475
  setTimeout(function () {
437
- _this.emit("CHATBOT_BUTTON_LOADED");
438
- }, 0);
476
+ if (_this.logoContainer) {
477
+ console.log("ROBYLON DEBUG: Button visibility check", {
478
+ exists: !!_this.logoContainer,
479
+ isConnected: _this.logoContainer.isConnected,
480
+ offsetParent: !!_this.logoContainer.offsetParent,
481
+ computedDisplay: window === null || window === void 0 ? void 0 : window.getComputedStyle(_this.logoContainer).display,
482
+ rect: _this.logoContainer.getBoundingClientRect(),
483
+ });
484
+ // Force visibility again if needed
485
+ if ((window === null || window === void 0 ? void 0 : window.getComputedStyle(_this.logoContainer).display) === "none") {
486
+ _this.logoContainer.style.display = "flex !important";
487
+ }
488
+ }
489
+ }, 1000);
490
+ // Emit button loaded event
491
+ this.emit("CHATBOT_BUTTON_LOADED");
439
492
  };
440
493
  ChatbotEmbed.prototype.createChatBubblContainer = function () {
441
494
  var _this = this;
@@ -443,7 +496,7 @@ var ChatbotEmbed = /** @class */ (function () {
443
496
  var chatbaseContainer = document.createElement("div");
444
497
  chatbaseContainer.id = "chatbase-message-bubbles";
445
498
  Object.assign(chatbaseContainer.style, {
446
- position: "absolute",
499
+ position: "fixed", // Use fixed positioning
447
500
  bottom: "80px",
448
501
  borderRadius: "10px",
449
502
  fontFamily: "sans-serif",
@@ -543,7 +596,7 @@ var ChatbotEmbed = /** @class */ (function () {
543
596
  var _this = this;
544
597
  var iframe = document.createElement("iframe");
545
598
  Object.assign(iframe.style, {
546
- position: "absolute",
599
+ position: "fixed", // Use fixed positioning
547
600
  right: "32px",
548
601
  bottom: "86px",
549
602
  minWidth: "400px",
@@ -561,8 +614,8 @@ var ChatbotEmbed = /** @class */ (function () {
561
614
  display: "none",
562
615
  });
563
616
  iframe.src = "".concat(this.config.domain, "/chatbot-plugin?id=").concat(this.config.chatbotId);
564
- // CRITICAL CHANGE: Append to container instead of body
565
- this.containerElement.appendChild(iframe);
617
+ // Always append to document.body for consistent positioning
618
+ document.body.appendChild(iframe);
566
619
  this.iframe = iframe;
567
620
  // Media Query Handling
568
621
  var applyStylesBasedOnScreenWidth = function () {
@@ -622,19 +675,26 @@ var ChatbotEmbed = /** @class */ (function () {
622
675
  };
623
676
  ChatbotEmbed.prototype.loadImage = function (containerElement) {
624
677
  var image = document.createElement("img");
678
+ // Log image loading
679
+ console.log("ROBYLON DEBUG: Loading image", {
680
+ src: this.config.image_url || "".concat(this.config.domain, "/chatbubble.png"),
681
+ });
625
682
  image.src = this.config.image_url || "".concat(this.config.domain, "/chatbubble.png");
626
683
  image.alt = "Chat";
627
- Object.assign(image.style, {
628
- zIndex: "1000",
629
- cursor: "pointer",
630
- borderRadius: "50%",
631
- objectFit: "cover",
632
- width: "100%",
633
- height: "100%",
634
- });
684
+ // Force image visibility
685
+ image.setAttribute("style", "\n z-index: 2147483647 !important;\n cursor: pointer !important;\n border-radius: 50% !important;\n object-fit: cover !important;\n width: 100% !important;\n height: 100% !important;\n display: block !important;\n ");
635
686
  this.chatBtnImage = image;
636
687
  containerElement.innerHTML = ""; // Clear any existing content
637
688
  containerElement.appendChild(image);
689
+ // Add image load error handling
690
+ image.onerror = function (err) {
691
+ console.error("ROBYLON DEBUG: Image failed to load", {
692
+ src: image.src,
693
+ error: err,
694
+ });
695
+ // Add fallback content
696
+ containerElement.innerHTML = "Chat";
697
+ };
638
698
  };
639
699
  ChatbotEmbed.prototype.loadSvgInline = function (containerElement) {
640
700
  var svgChevronDown = "\n<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"Chevron_Down\">\n <path id=\"Vector\" d=\"M19 9L12 16L5 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n</svg>\n";
@@ -720,21 +780,6 @@ var ChatbotEmbed = /** @class */ (function () {
720
780
  };
721
781
  (_b = this.iframe.contentWindow) === null || _b === void 0 ? void 0 : _b.postMessage(data, this.config.domain || "*");
722
782
  };
723
- // Add method to update container
724
- ChatbotEmbed.prototype.setContainer = function (container) {
725
- if (!container)
726
- return;
727
- // Move existing elements to new container if they exist
728
- if (this.iframe && this.iframe.parentElement) {
729
- this.iframe.parentElement.removeChild(this.iframe);
730
- container.appendChild(this.iframe);
731
- }
732
- if (this.logoContainer && this.logoContainer.parentElement) {
733
- this.logoContainer.parentElement.removeChild(this.logoContainer);
734
- container.appendChild(this.logoContainer);
735
- }
736
- this.containerElement = container;
737
- };
738
783
  return ChatbotEmbed;
739
784
  }());
740
785
 
@@ -1175,80 +1220,109 @@ var RobylonChatbot = React.memo(function (_a) {
1175
1220
  }, [onEvent]);
1176
1221
  // Initialize the chatbot
1177
1222
  var initializeChatbot = React.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
1178
- var userId, isAnonymous, apiResponse, systemInfo, finalUserProfile, config, err_1, errorMessage;
1179
- var _a, _b, _c, _d, _e, _f, _g;
1180
- return __generator(this, function (_h) {
1181
- switch (_h.label) {
1223
+ var tryInitialize;
1224
+ return __generator(this, function (_a) {
1225
+ switch (_a.label) {
1182
1226
  case 0:
1183
1227
  if (!api_key) {
1184
1228
  setError("API key is required");
1229
+ console.error("ROBYLON DEBUG: API key is required");
1185
1230
  return [2 /*return*/];
1186
1231
  }
1187
- if (isInitializing || isInitialized)
1232
+ if (isInitializing || isInitialized) {
1233
+ console.log("ROBYLON DEBUG: Already initializing or initialized");
1188
1234
  return [2 /*return*/];
1189
- setIsInitializing(true);
1190
- _h.label = 1;
1191
- case 1:
1192
- _h.trys.push([1, 3, 4, 5]);
1193
- userId = user_id;
1194
- isAnonymous = false;
1195
- // Handle anonymous users
1196
- if (!userId) {
1197
- userId = getCookie("rblyn_anon") || generateUUID();
1198
- setCookie("rblyn_anon", String(userId), 365);
1199
- isAnonymous = true;
1200
1235
  }
1201
- return [4 /*yield*/, fetchChatbotConfig(api_key, userId, user_token)];
1202
- case 2:
1203
- apiResponse = _h.sent();
1204
- systemInfo = getSystemInfo();
1205
- finalUserProfile = __assign(__assign({}, systemInfo), user_profile);
1206
- config = {
1207
- chatbotId: api_key,
1208
- userId: userId ? String(userId) : null,
1209
- token: user_token,
1210
- isAnonymous: isAnonymous,
1211
- domain: getEnvironmentConfig().copilotUrl,
1212
- brand_colour: ((_b = (_a = apiResponse.user.org_info.brand_config) === null || _a === void 0 ? void 0 : _a.colors) === null || _b === void 0 ? void 0 : _b.brand_color) ||
1213
- "#6a26cd",
1214
- image_url: ((_d = (_c = apiResponse.user.org_info) === null || _c === void 0 ? void 0 : _c.brand_config) === null || _d === void 0 ? void 0 : _d.launcher_logo_url) || "",
1215
- userProfile: finalUserProfile,
1216
- chat_interface_config: {
1217
- chat_bubble_prompts: [],
1218
- display_name: ((_e = apiResponse.user.org_info.brand_config) === null || _e === void 0 ? void 0 : _e.display_name) || "",
1219
- welcome_message: ((_f = apiResponse.user.org_info.brand_config) === null || _f === void 0 ? void 0 : _f.welcome_message) ||
1220
- "Hey! What can we help you with today?",
1221
- redirect_url: ((_g = apiResponse.user.org_info.brand_config) === null || _g === void 0 ? void 0 : _g.redirect_url) || "",
1222
- },
1223
- };
1224
- // Store the config
1225
- setChatbotConfig(config);
1226
- // CRITICAL CHANGE: Pass container element to ChatbotEmbed
1227
- if (containerRef.current) {
1228
- chatbotRef.current = new ChatbotEmbed(config, {
1229
- containerElement: containerRef.current,
1236
+ setIsInitializing(true);
1237
+ console.log("ROBYLON DEBUG: Starting initialization");
1238
+ tryInitialize = function () {
1239
+ var args_1 = [];
1240
+ for (var _i = 0; _i < arguments.length; _i++) {
1241
+ args_1[_i] = arguments[_i];
1242
+ }
1243
+ return __awaiter(void 0, __spreadArray([], args_1, true), void 0, function (attempt) {
1244
+ var userId, isAnonymous, apiResponse, systemInfo, finalUserProfile, config, err_1, errorMessage;
1245
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1246
+ if (attempt === void 0) { attempt = 1; }
1247
+ return __generator(this, function (_j) {
1248
+ switch (_j.label) {
1249
+ case 0:
1250
+ _j.trys.push([0, 2, , 3]);
1251
+ userId = user_id;
1252
+ isAnonymous = false;
1253
+ // Handle anonymous users
1254
+ if (!userId) {
1255
+ userId = getCookie("rblyn_anon") || generateUUID();
1256
+ setCookie("rblyn_anon", String(userId), 365);
1257
+ isAnonymous = true;
1258
+ }
1259
+ console.log("ROBYLON DEBUG: Fetching chatbot config", {
1260
+ userId: userId,
1261
+ isAnonymous: isAnonymous,
1262
+ });
1263
+ return [4 /*yield*/, fetchChatbotConfig(api_key, userId, user_token)];
1264
+ case 1:
1265
+ apiResponse = _j.sent();
1266
+ console.log("ROBYLON DEBUG: API response received", {
1267
+ success: !!apiResponse,
1268
+ hasOrgInfo: !!((_a = apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.user) === null || _a === void 0 ? void 0 : _a.org_info),
1269
+ });
1270
+ systemInfo = getSystemInfo();
1271
+ finalUserProfile = __assign(__assign({}, systemInfo), user_profile);
1272
+ config = {
1273
+ chatbotId: api_key,
1274
+ userId: userId ? String(userId) : null,
1275
+ token: user_token,
1276
+ isAnonymous: isAnonymous,
1277
+ domain: getEnvironmentConfig().copilotUrl,
1278
+ brand_colour: ((_c = (_b = apiResponse.user.org_info.brand_config) === null || _b === void 0 ? void 0 : _b.colors) === null || _c === void 0 ? void 0 : _c.brand_color) ||
1279
+ "#6a26cd",
1280
+ image_url: ((_e = (_d = apiResponse.user.org_info) === null || _d === void 0 ? void 0 : _d.brand_config) === null || _e === void 0 ? void 0 : _e.launcher_logo_url) || "",
1281
+ userProfile: finalUserProfile,
1282
+ chat_interface_config: {
1283
+ chat_bubble_prompts: [],
1284
+ display_name: ((_f = apiResponse.user.org_info.brand_config) === null || _f === void 0 ? void 0 : _f.display_name) || "",
1285
+ welcome_message: ((_g = apiResponse.user.org_info.brand_config) === null || _g === void 0 ? void 0 : _g.welcome_message) ||
1286
+ "Hey! What can we help you with today?",
1287
+ redirect_url: ((_h = apiResponse.user.org_info.brand_config) === null || _h === void 0 ? void 0 : _h.redirect_url) || "",
1288
+ },
1289
+ };
1290
+ // Store the config
1291
+ setChatbotConfig(config);
1292
+ console.log("ROBYLON DEBUG: Creating ChatbotEmbed instance", config);
1293
+ // Create the chatbot instance and always use document.body first
1294
+ chatbotRef.current = new ChatbotEmbed(config);
1295
+ // Register event handler
1296
+ if (stableOnEvent) {
1297
+ chatbotRef.current.on("*", stableOnEvent);
1298
+ }
1299
+ setIsInitialized(true);
1300
+ console.log("ROBYLON DEBUG: Initialization complete");
1301
+ return [3 /*break*/, 3];
1302
+ case 2:
1303
+ err_1 = _j.sent();
1304
+ errorMessage = err_1 instanceof Error ? err_1.message : "Failed to initialize chatbot";
1305
+ console.error("ROBYLON DEBUG: Error during initialization (attempt ".concat(attempt, ")"), err_1);
1306
+ // Retry up to 3 times with increasing delay
1307
+ if (attempt < 3) {
1308
+ console.log("ROBYLON DEBUG: Retrying initialization (attempt ".concat(attempt + 1, ")"));
1309
+ setTimeout(function () { return tryInitialize(attempt + 1); }, attempt * 1000);
1310
+ }
1311
+ else {
1312
+ setError(errorMessage);
1313
+ logger.error("Chatbot initialization failed:", err_1);
1314
+ }
1315
+ return [3 /*break*/, 3];
1316
+ case 3: return [2 /*return*/];
1317
+ }
1318
+ });
1230
1319
  });
1231
- }
1232
- else {
1233
- // Fallback to body if container not available
1234
- chatbotRef.current = new ChatbotEmbed(config);
1235
- }
1236
- // Register event handler
1237
- if (stableOnEvent) {
1238
- chatbotRef.current.on("*", stableOnEvent);
1239
- }
1240
- setIsInitialized(true);
1241
- return [3 /*break*/, 5];
1242
- case 3:
1243
- err_1 = _h.sent();
1244
- errorMessage = err_1 instanceof Error ? err_1.message : "Failed to initialize chatbot";
1245
- setError(errorMessage);
1246
- logger.error("Chatbot initialization failed:", err_1);
1247
- return [3 /*break*/, 5];
1248
- case 4:
1320
+ };
1321
+ return [4 /*yield*/, tryInitialize()];
1322
+ case 1:
1323
+ _a.sent();
1249
1324
  setIsInitializing(false);
1250
- return [7 /*endfinally*/];
1251
- case 5: return [2 /*return*/];
1325
+ return [2 /*return*/];
1252
1326
  }
1253
1327
  });
1254
1328
  }); }, [
@@ -1258,14 +1332,27 @@ var RobylonChatbot = React.memo(function (_a) {
1258
1332
  stableOnEvent,
1259
1333
  isInitialized,
1260
1334
  isInitializing,
1335
+ user_profile,
1261
1336
  ]);
1262
1337
  // Initialize on component mount
1263
1338
  React.useEffect(function () {
1339
+ // Add explicit debugging
1340
+ console.log("ROBYLON DEBUG: Initializing React component", {
1341
+ apiKeyProvided: !!api_key,
1342
+ userIdProvided: !!user_id,
1343
+ });
1264
1344
  if (api_key) {
1265
- initializeChatbot();
1345
+ // Force immediate initialization
1346
+ try {
1347
+ initializeChatbot();
1348
+ }
1349
+ catch (err) {
1350
+ console.error("ROBYLON DEBUG: Initialization error", err);
1351
+ }
1266
1352
  }
1267
1353
  // Cleanup on unmount
1268
1354
  return function () {
1355
+ console.log("ROBYLON DEBUG: Cleaning up React component");
1269
1356
  if (chatbotRef.current) {
1270
1357
  chatbotRef.current.destroy();
1271
1358
  chatbotRef.current = null;
@@ -1275,6 +1362,15 @@ var RobylonChatbot = React.memo(function (_a) {
1275
1362
  // If container reference changes, update the ChatbotEmbed
1276
1363
  React.useEffect(function () {
1277
1364
  if (containerRef.current && chatbotRef.current && isInitialized) {
1365
+ // Log container dimensions to help debug positioning issues
1366
+ var rect = containerRef.current.getBoundingClientRect();
1367
+ logger.debug("Container dimensions:", {
1368
+ width: rect.width,
1369
+ height: rect.height,
1370
+ top: rect.top,
1371
+ left: rect.left,
1372
+ position: window.getComputedStyle(containerRef.current).position,
1373
+ });
1278
1374
  chatbotRef.current.setContainer(containerRef.current);
1279
1375
  }
1280
1376
  }, [containerRef.current, isInitialized]);
@@ -1287,13 +1383,16 @@ var RobylonChatbot = React.memo(function (_a) {
1287
1383
  });
1288
1384
  }
1289
1385
  }, [user_profile, isInitialized, chatbotConfig]);
1290
- // CRITICAL CHANGE: Return a container div
1386
+ // CRITICAL CHANGE: Return a minimal container div
1291
1387
  return (jsxRuntime.jsx("div", { ref: containerRef, className: "robylon-chatbot-container", style: {
1292
- position: "relative",
1293
- width: "100%",
1294
- height: "100%",
1295
- minHeight: "500px", // Add minimum height to ensure visibility
1296
- } }));
1388
+ display: "block",
1389
+ position: "fixed",
1390
+ bottom: 0,
1391
+ right: 0,
1392
+ width: "1px",
1393
+ height: "1px",
1394
+ pointerEvents: "none",
1395
+ }, "data-testid": "robylon-chatbot" }));
1297
1396
  }, function (prevProps, nextProps) {
1298
1397
  // Memoization comparison
1299
1398
  return (prevProps.api_key === nextProps.api_key &&