@brainfish-ai/widgets-initiator 1.13.5 → 1.15.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/types/actions/clientAction.d.ts +13 -0
- package/dist/types/initIframeTrigger/components/IframeContainer.d.ts +5 -1
- package/dist/types/initIframeTrigger/constants/breakpoints.d.ts +1 -0
- package/dist/types/initIframeTrigger/constants/classes.d.ts +2 -0
- package/dist/types/initIframeTrigger/constants/searchbar.d.ts +1 -0
- package/dist/types/initIframeTrigger/index.d.ts +1 -1
- package/dist/types/initIframeTrigger/initSearchBar.d.ts +10 -0
- package/dist/types/initIframeTrigger/initWidgetButton.d.ts +10 -0
- package/dist/types/initIframeTrigger/listeners/initBodyResizeObserver.d.ts +2 -1
- package/dist/types/initIframeTrigger/listeners/initMessageListener.d.ts +5 -1
- package/dist/types/initIframeTrigger/managers/AnalyticsTracker.d.ts +15 -0
- package/dist/types/initIframeTrigger/managers/IframeStateManager.d.ts +30 -12
- package/dist/types/initIframeTrigger/managers/WidgetDOMController.d.ts +23 -0
- package/dist/types/initIframeTrigger/managers/WidgetGlobalAPI.d.ts +12 -0
- package/dist/types/initIframeTrigger/managers/WidgetRegistry.d.ts +25 -0
- package/dist/types/initIframeTrigger/managers/WidgetState.d.ts +15 -0
- package/dist/types/initIframeTrigger/utils/createSearchTrigger.d.ts +13 -0
- package/dist/types/routeChangeDetector.d.ts +2 -0
- package/dist/types/types/brainfish.d.ts +2 -0
- package/dist/types/utils/brainfishQueue.d.ts +2 -0
- package/dist/web.cjs.js +1 -1
- package/dist/web.js +743 -336
- package/package.json +1 -1
package/dist/web.js
CHANGED
|
@@ -42,7 +42,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
42
42
|
!function() {
|
|
43
43
|
try {
|
|
44
44
|
var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}, n = new e.Error().stack;
|
|
45
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "
|
|
45
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "8cbdac46-7b15-4d3d-b1ea-fcaf3113cd88", e._sentryDebugIdIdentifier = "sentry-dbid-8cbdac46-7b15-4d3d-b1ea-fcaf3113cd88");
|
|
46
46
|
} catch (e2) {
|
|
47
47
|
}
|
|
48
48
|
}();
|
|
@@ -113,7 +113,7 @@ function decodeProtectedHeader(token) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
var _global = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : {};
|
|
116
|
-
_global.SENTRY_RELEASE = { id: "
|
|
116
|
+
_global.SENTRY_RELEASE = { id: "a78428dd0393f7306b3a5d99b998727c646efbb9" };
|
|
117
117
|
var WidgetType;
|
|
118
118
|
(function(WidgetType2) {
|
|
119
119
|
WidgetType2["Sidebar"] = "sidebar";
|
|
@@ -171,7 +171,7 @@ const sendErrors = (apiHost, error, widgetKey) => {
|
|
|
171
171
|
"api-key": widgetKey
|
|
172
172
|
},
|
|
173
173
|
body: JSON.stringify({
|
|
174
|
-
error: `WebWidgetVersion: ${"1.
|
|
174
|
+
error: `WebWidgetVersion: ${"1.15.0"}. ${error.message}`,
|
|
175
175
|
stack: error.stack,
|
|
176
176
|
cause: {
|
|
177
177
|
message: errorData.message,
|
|
@@ -342,11 +342,11 @@ function initializeWidget(widget, config) {
|
|
|
342
342
|
widget.HelpWidget.initPopup(config);
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
|
-
const initializedWidgets$
|
|
345
|
+
const initializedWidgets$2 = /* @__PURE__ */ new Set();
|
|
346
346
|
const initSearchWidget = (options, config) => __async(null, null, function* () {
|
|
347
347
|
const apiHost = getApiHost(options.overrides);
|
|
348
348
|
try {
|
|
349
|
-
if (initializedWidgets$
|
|
349
|
+
if (initializedWidgets$2.has(options.widgetKey)) {
|
|
350
350
|
return void 0;
|
|
351
351
|
}
|
|
352
352
|
const result = yield init({
|
|
@@ -372,7 +372,7 @@ const initSearchWidget = (options, config) => __async(null, null, function* () {
|
|
|
372
372
|
});
|
|
373
373
|
}
|
|
374
374
|
initializeWidget(widget, transformedConfig);
|
|
375
|
-
initializedWidgets$
|
|
375
|
+
initializedWidgets$2.add(options.widgetKey);
|
|
376
376
|
return widget;
|
|
377
377
|
}
|
|
378
378
|
} catch (error) {
|
|
@@ -481,6 +481,7 @@ function createBrainfishQueue() {
|
|
|
481
481
|
setSecretAttributes: (...args) => queueOrExecute("Widgets.setSecretAttributes", args),
|
|
482
482
|
open: () => queueOrExecute("Widgets.open", []),
|
|
483
483
|
close: () => queueOrExecute("Widgets.close", []),
|
|
484
|
+
registerClientActionHandler: (...args) => queueOrExecute("Widgets.registerClientActionHandler", args),
|
|
484
485
|
isReady: false
|
|
485
486
|
},
|
|
486
487
|
SearchWidget: {
|
|
@@ -511,230 +512,38 @@ const createQueues = () => {
|
|
|
511
512
|
};
|
|
512
513
|
}
|
|
513
514
|
};
|
|
514
|
-
function
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const TRIGGER_BUTTON_CLASS = "bf-trigger-button";
|
|
524
|
-
function createTriggerButton(widgetKey, triggerButtonIcon) {
|
|
525
|
-
const button = createElementWithClass("button", TRIGGER_BUTTON_CLASS, {
|
|
526
|
-
id: `trigger-button-${widgetKey}`,
|
|
527
|
-
"aria-controls": IFRAME_CONTAINER_CLASS,
|
|
528
|
-
"aria-expanded": "false",
|
|
529
|
-
"data-name": TRIGGER_BUTTON_CLASS
|
|
530
|
-
});
|
|
531
|
-
const icon = createElementWithClass("div", "trigger-button-icon", {
|
|
532
|
-
"aria-hidden": "true"
|
|
533
|
-
});
|
|
534
|
-
if (!triggerButtonIcon) {
|
|
535
|
-
icon.innerHTML = `
|
|
536
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
537
|
-
<path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path>
|
|
538
|
-
</svg>
|
|
539
|
-
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="fish-icon visible">
|
|
540
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.71844 10.3882L4.60606 6.98384L1.71844 3.58375C1.4014 3.21362 1.44424 2.65841 1.81269 2.33993C1.97978 2.1979 2.65242 1.98701 3.04657 2.43461L5.78425 5.65824C6.14281 5.29523 6.51693 4.95924 6.90479 4.65114C8.88976 3.07437 11.2345 2.22803 13.6931 2.22803C16.9492 2.22803 20.0039 3.71718 22.2917 6.41142C22.5702 6.74282 22.5702 7.22916 22.2917 7.56056C20.0039 10.2591 16.9492 11.744 13.6931 11.744C11.2348 11.744 8.89035 10.8948 6.90554 9.31995C6.51741 9.01199 6.14304 8.67628 5.78425 8.31374L3.04657 11.5374C2.72953 11.9075 2.18114 11.9505 1.81269 11.632C1.44852 11.3179 1.40568 10.7584 1.71844 10.3882ZM5.93026 10.4683C8.17161 12.2599 10.8546 13.25 13.6931 13.25C17.4881 13.25 21.019 11.4034 23.4447 8.52942C24.1873 7.64571 24.1843 6.31801 23.4397 5.43663C20.8944 2.43919 17.4337 0.722025 13.6931 0.722025C10.8555 0.722025 8.17194 1.70845 5.92952 3.50276L4.17682 1.43933C3.57943 0.760929 2.79325 0.630009 2.25286 0.662947C1.98116 0.679506 1.73125 0.736852 1.51895 0.811846C1.26839 0.900352 1.03017 1.02718 0.827835 1.20058C-0.165283 2.05903 -0.283916 3.561 0.574656 4.56345L2.63075 6.98445L0.568104 9.41623C-0.272133 10.4106 -0.166523 11.9125 0.827835 12.7714C1.81372 13.6243 3.34308 13.5062 4.19036 12.5171L5.93026 10.4683Z" fill="currentColor"/>
|
|
541
|
-
</svg>
|
|
542
|
-
`;
|
|
543
|
-
} else {
|
|
544
|
-
icon.innerHTML = `
|
|
545
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
546
|
-
<path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path>
|
|
547
|
-
</svg>
|
|
548
|
-
<img src="${triggerButtonIcon}" class="fish-icon visible" alt="Trigger button icon" height="32" width="32" aria-hidden="true" aria-label="help button icon" />
|
|
549
|
-
`;
|
|
515
|
+
function base64Encode(text) {
|
|
516
|
+
const encoder = new TextEncoder();
|
|
517
|
+
const uint8Array = encoder.encode(text);
|
|
518
|
+
if (typeof window !== "undefined" && typeof window.btoa === "function") {
|
|
519
|
+
const binaryString = Array.from(
|
|
520
|
+
uint8Array,
|
|
521
|
+
(byte) => String.fromCharCode(byte)
|
|
522
|
+
).join("");
|
|
523
|
+
return btoa(binaryString);
|
|
550
524
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
return { button, icon };
|
|
554
|
-
}
|
|
555
|
-
function createIframeContainer(widgetUrl) {
|
|
556
|
-
const iframeContainer = createElementWithClass(
|
|
557
|
-
"div",
|
|
558
|
-
IFRAME_CONTAINER_CLASS,
|
|
559
|
-
{
|
|
560
|
-
id: IFRAME_CONTAINER_CLASS,
|
|
561
|
-
"aria-live": "polite",
|
|
562
|
-
"aria-hidden": "true"
|
|
563
|
-
}
|
|
564
|
-
);
|
|
565
|
-
const loadingIndicator = createElementWithClass("div", "iframe-loading-indicator");
|
|
566
|
-
const spinner = createElementWithClass("div", "spinner");
|
|
567
|
-
loadingIndicator.setAttribute("aria-label", "Loading content");
|
|
568
|
-
loadingIndicator.setAttribute("role", "status");
|
|
569
|
-
loadingIndicator.appendChild(spinner);
|
|
570
|
-
iframeContainer.appendChild(loadingIndicator);
|
|
571
|
-
const iframe = createElementWithClass("iframe", "trigger-iframe", {
|
|
572
|
-
src: widgetUrl,
|
|
573
|
-
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms",
|
|
574
|
-
allow: "clipboard-write",
|
|
575
|
-
role: "dialog"
|
|
576
|
-
});
|
|
577
|
-
iframe.style.opacity = "0";
|
|
578
|
-
iframe.addEventListener("load", () => {
|
|
579
|
-
loadingIndicator.style.display = "none";
|
|
580
|
-
iframe.style.opacity = "1";
|
|
581
|
-
});
|
|
582
|
-
iframe.addEventListener("error", (error) => {
|
|
583
|
-
console.error("Error loading iframe:", error);
|
|
584
|
-
loadingIndicator.innerHTML = "";
|
|
585
|
-
const errorIcon = createElementWithClass("div", "loading-error");
|
|
586
|
-
loadingIndicator.appendChild(errorIcon);
|
|
587
|
-
loadingIndicator.setAttribute("aria-label", "Failed to load content");
|
|
588
|
-
});
|
|
589
|
-
iframeContainer.appendChild(iframe);
|
|
590
|
-
return { iframeContainer, iframe };
|
|
591
|
-
}
|
|
592
|
-
function toggleIframeSize() {
|
|
593
|
-
const iframeContainer = document.querySelector(
|
|
594
|
-
`.${IFRAME_CONTAINER_CLASS}`
|
|
595
|
-
);
|
|
596
|
-
if (iframeContainer.classList.contains("expanded")) {
|
|
597
|
-
iframeContainer.classList.remove("expanded");
|
|
598
|
-
} else {
|
|
599
|
-
iframeContainer.classList.add("expanded");
|
|
525
|
+
if (typeof Buffer !== "undefined") {
|
|
526
|
+
return Buffer.from(uint8Array).toString("base64");
|
|
600
527
|
}
|
|
528
|
+
throw new Error("[utils.base64Encode]: Unsupported environment");
|
|
601
529
|
}
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
icon,
|
|
610
|
-
isButtonHidden
|
|
611
|
-
}) {
|
|
612
|
-
var _a, _b;
|
|
613
|
-
this.button = button || null;
|
|
614
|
-
this.icon = icon || null;
|
|
615
|
-
this.isButtonHidden = isButtonHidden || false;
|
|
616
|
-
if (button) {
|
|
617
|
-
button.addEventListener("click", () => this.toggleIframeVisibility());
|
|
618
|
-
}
|
|
619
|
-
if ((_a = window.Brainfish) == null ? void 0 : _a.HelpWidget) {
|
|
620
|
-
window.Brainfish.HelpWidget.close = () => this.closeWidget();
|
|
621
|
-
window.Brainfish.HelpWidget.open = () => this.openWidget();
|
|
622
|
-
}
|
|
623
|
-
if ((_b = window.Brainfish) == null ? void 0 : _b.Widgets) {
|
|
624
|
-
window.Brainfish.Widgets.open = () => this.openWidget();
|
|
625
|
-
window.Brainfish.Widgets.close = () => this.closeWidget();
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
static toggleIframeVisibility() {
|
|
629
|
-
this.isOpen = !this.isOpen;
|
|
630
|
-
if (this.isOpen) {
|
|
631
|
-
this.openWidget();
|
|
632
|
-
} else {
|
|
633
|
-
this.closeWidget();
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
// Open the widget programmatically
|
|
637
|
-
static openWidget() {
|
|
638
|
-
var _a;
|
|
639
|
-
this.isOpen = true;
|
|
640
|
-
const iframeContainer = document.querySelector(".bf-iframe-container");
|
|
641
|
-
const iframe = iframeContainer == null ? void 0 : iframeContainer.querySelector("iframe");
|
|
642
|
-
iframeContainer == null ? void 0 : iframeContainer.classList.add("open");
|
|
643
|
-
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "false");
|
|
644
|
-
(_a = iframe == null ? void 0 : iframe.contentWindow) == null ? void 0 : _a.postMessage({ type: "FOCUS_SEARCH_FIELD" }, "*");
|
|
645
|
-
if (this.button && this.icon) {
|
|
646
|
-
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
647
|
-
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
648
|
-
this.button.setAttribute("aria-expanded", "true");
|
|
649
|
-
fishIconSVG.classList.remove("visible");
|
|
650
|
-
closeIconSVG.classList.add("visible");
|
|
651
|
-
if (document.body.clientWidth <= MOBILE_BREAKPOINT) {
|
|
652
|
-
this.hideTriggerButton();
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
window.dispatchEvent(new Event("onBrainfishWidgetOpen"));
|
|
656
|
-
window.BrainfishAnalytics("track", "Open Widget");
|
|
657
|
-
}
|
|
658
|
-
// Close the widget programmatically
|
|
659
|
-
static closeWidget() {
|
|
660
|
-
this.isOpen = false;
|
|
661
|
-
const iframeContainer = document.querySelector(".bf-iframe-container");
|
|
662
|
-
iframeContainer == null ? void 0 : iframeContainer.classList.remove("open");
|
|
663
|
-
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "true");
|
|
664
|
-
if (this.button && this.icon) {
|
|
665
|
-
this.button.setAttribute("aria-expanded", "false");
|
|
666
|
-
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
667
|
-
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
668
|
-
fishIconSVG.classList.add("visible");
|
|
669
|
-
closeIconSVG.classList.remove("visible");
|
|
670
|
-
if (document.body.clientWidth <= MOBILE_BREAKPOINT) {
|
|
671
|
-
this.showTriggerButton();
|
|
672
|
-
}
|
|
530
|
+
const base64Decode = (text) => {
|
|
531
|
+
if (typeof window !== "undefined" && typeof window.atob === "function") {
|
|
532
|
+
const binaryString = atob(text);
|
|
533
|
+
const len = binaryString.length;
|
|
534
|
+
const bytes = new Uint8Array(len);
|
|
535
|
+
for (let i = 0; i < len; i++) {
|
|
536
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
673
537
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
static showTriggerButton() {
|
|
678
|
-
var _a;
|
|
679
|
-
(_a = this.button) == null ? void 0 : _a.classList.remove("hidden");
|
|
538
|
+
const decoder2 = new TextDecoder();
|
|
539
|
+
return decoder2.decode(bytes);
|
|
680
540
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
(_a = this.button) == null ? void 0 : _a.classList.add("hidden");
|
|
541
|
+
if (typeof Buffer !== "undefined") {
|
|
542
|
+
return Buffer.from(text, "base64").toString("utf-8");
|
|
684
543
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
__publicField(IframeStateManager, "icon", null);
|
|
689
|
-
__publicField(IframeStateManager, "isButtonHidden", false);
|
|
690
|
-
function initMessageListener({
|
|
691
|
-
widgetHost,
|
|
692
|
-
apiHost,
|
|
693
|
-
widgetKey,
|
|
694
|
-
signal
|
|
695
|
-
}) {
|
|
696
|
-
const messageHandler = (event) => {
|
|
697
|
-
if (event.origin !== widgetHost) return;
|
|
698
|
-
const { type } = event.data;
|
|
699
|
-
if (type === "TOGGLE_WIDGET_SIZE") {
|
|
700
|
-
toggleIframeSize();
|
|
701
|
-
}
|
|
702
|
-
if (type === "TRACK_EVENT") {
|
|
703
|
-
if (!window.BrainfishAnalytics) return;
|
|
704
|
-
const { eventName, data } = event.data;
|
|
705
|
-
window.BrainfishAnalytics("track", eventName, data);
|
|
706
|
-
}
|
|
707
|
-
if (type === "CLOSE_WIDGET") {
|
|
708
|
-
window.BrainfishAnalytics("track", "Close Widget");
|
|
709
|
-
IframeStateManager.toggleIframeVisibility();
|
|
710
|
-
}
|
|
711
|
-
if (type === "NEXT_BEST_ACTION_CLICKED") {
|
|
712
|
-
const { action, searchQueryId, query, answer } = event.data;
|
|
713
|
-
const context = { action, searchQueryId };
|
|
714
|
-
if (!["function", "callback"].includes(action.type)) {
|
|
715
|
-
console.error("Invalid action type", action);
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
window.__bfCallbacks = window.__bfCallbacks || {};
|
|
719
|
-
if (window.__bfCallbacks[action.id]) {
|
|
720
|
-
window.__bfCallbacks[action.id](query, answer, context);
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
const scriptUrl = `${apiHost}/api/searchWidgets.callback.codeblocks?apiKey=${widgetKey}&codeblockId=${action.id}`;
|
|
724
|
-
const script = document.createElement("script");
|
|
725
|
-
script.src = scriptUrl;
|
|
726
|
-
document.head.appendChild(script);
|
|
727
|
-
script.onload = () => {
|
|
728
|
-
window.__bfCallbacks[action.id](query, answer, context);
|
|
729
|
-
setTimeout(() => {
|
|
730
|
-
document.head.removeChild(script);
|
|
731
|
-
}, 300);
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
};
|
|
735
|
-
window.addEventListener("message", messageHandler, { signal });
|
|
736
|
-
}
|
|
737
|
-
const styles = '.bf-trigger-button{position:fixed;bottom:16px;right:16px;width:36px;height:36px;border-radius:50%;border:none;box-shadow:0 1px 6px #0000000f,0 2px 32px #00000029;transition:transform 167ms cubic-bezier(.33,0,0,1);box-sizing:content-box;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:1000;padding:12px;gap:10px;overflow:hidden}.bf-trigger-button.hidden{display:none}.trigger-button-icon{display:flex;align-items:center;justify-content:center;width:36px;height:36px;position:relative}.trigger-button-icon svg{width:100%;height:100%;position:absolute;inset:0}.trigger-button-icon>svg>path{transition:transform .3s ease,opacity .3s ease;transform:scale(.5);transform-origin:center;opacity:0}.trigger-button-icon .fish-icon{display:none}.trigger-button-icon .fish-icon.visible{display:block}.trigger-button-icon svg.visible{display:block}.trigger-button-icon>svg.visible>path{opacity:1;transform:scale(1)}.trigger-iframe{position:relative;width:100%;height:100%;border:none;outline:none;transform:translateZ(0)}.bf-iframe-container{display:none;position:fixed;z-index:2147483000000;background-color:#fff;bottom:0;right:0;width:100vw;height:100vh;border:none;overflow:hidden;opacity:0;pointer-events:none;transform:translateY(20px);transition:opacity .3s ease,transform .3s ease,width .2s ease-in-out,height .2s ease-in-out}.bf-iframe-container.open{display:block;opacity:1;transform:translateY(0);pointer-events:auto;top:0;left:0}@media (min-width: 576px){.bf-iframe-container{bottom:80px;right:24px;width:448px;height:min(750px,calc(100vh - 80px));border-radius:8px;border:1px solid var(--Dark-300, #D4D4D4);box-shadow:0 20px 25px -5px #1212171a,0 10px 10px -5px #1212170a}.bf-iframe-container.open{top:unset;left:unset}.bf-iframe-container.expanded{width:min(calc(448px * 1.35),calc(100vw - 16px));height:min(calc(750px * 1.35),calc(100vh - 80px))}}.iframe-loading-indicator{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;align-items:center;justify-content:center;z-index:10}.spinner{width:24px;height:24px;border:2px solid rgba(0,0,0,.1);border-radius:50%;border-top-color:#3498db;animation:spin 1s ease-in-out infinite}@keyframes spin{to{transform:rotate(360deg)}}.loading-error{width:24px;height:24px;position:relative;display:flex;align-items:center;justify-content:center}.loading-error:before,.loading-error:after{content:"";position:absolute;width:16px;height:2px;background-color:#e74c3c;border-radius:2px}.loading-error:before{transform:rotate(45deg)}.loading-error:after{transform:rotate(-45deg)}';
|
|
544
|
+
throw new Error("[utils.base64Decode]: Unsupported environment");
|
|
545
|
+
};
|
|
546
|
+
const styles = `.bf-trigger-button{position:fixed;bottom:16px;right:16px;width:36px;height:36px;border-radius:50%;border:none;box-shadow:0 1px 6px #0000000f,0 2px 32px #00000029;transition:transform 167ms cubic-bezier(.33,0,0,1);box-sizing:content-box;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:1000;padding:12px;gap:10px;overflow:hidden}.bf-trigger-button.hidden{display:none}.trigger-button-icon{display:flex;align-items:center;justify-content:center;width:36px;height:36px;position:relative}.trigger-button-icon svg{width:100%;height:100%;position:absolute;inset:0}.trigger-button-icon>svg>path{transition:transform .3s ease,opacity .3s ease;transform:scale(.5);transform-origin:center;opacity:0}.trigger-button-icon .fish-icon{display:none}.trigger-button-icon .fish-icon.visible{display:block}.trigger-button-icon svg.visible{display:block}.trigger-button-icon>svg.visible>path{opacity:1;transform:scale(1)}.trigger-iframe{position:relative;width:100%;height:100%;border:none;outline:none;transform:translateZ(0)}.bf-iframe-container,.bf-search-bar-iframe-container{display:none;position:fixed;z-index:2147483000000;background-color:#fff;bottom:0;right:0;width:100vw;height:calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom));border:none;overflow:hidden;opacity:0;pointer-events:none;transform:translateY(20px);transition:opacity .3s ease,transform .3s ease,width .2s ease-in-out,height .2s ease-in-out}.bf-iframe-container.open,.bf-search-bar-iframe-container.open{display:block;opacity:1;transform:translateY(0);pointer-events:auto;top:env(safe-area-inset-top);left:0}@media (min-width: 576px){.bf-iframe-container,.bf-search-bar-iframe-container{bottom:80px;right:24px;width:448px;height:min(750px,calc(100vh - 80px));border-radius:8px;border:1px solid var(--Dark-300, #D4D4D4);box-shadow:0 20px 25px -5px #1212171a,0 10px 10px -5px #1212170a}.bf-iframe-container.open{top:unset;left:unset}.bf-search-bar-iframe-container.open{width:100vw;height:calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom));position:fixed;top:0;left:0}.bf-iframe-container.expanded,.bf-search-bar-iframe-container.expanded{width:min(calc(448px * 1.35),calc(100vw - 16px));height:min(calc(750px * 1.35),calc(100vh - 80px))}}@media (min-width: 962px){.bf-search-bar-iframe-container.open{width:80vw;height:auto;top:50%;left:50%;transform:translateY(-50%) translate(-50%)}}@media (min-width: 1200px){.bf-search-bar-iframe-container.open{width:60vw;min-width:770px}}@media (min-width: 1400px){.bf-search-bar-iframe-container.open{width:50vw;min-width:770px}}brainfish-search-widget{display:flex;align-items:center;height:46px;width:100%;background-color:#fff;border-radius:8px;border:1px solid #ccc;box-shadow:0 2px 4px #0000001a;font-size:16px;color:#171717;padding-left:46px;cursor:text;&:after{content:attr(data-placeholder)}&:before{content:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><circle cx="112" cy="112" r="80" fill="none" stroke="%23737373" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="168.57" y1="168.57" x2="224" y2="224" fill="none" stroke="%23737373" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>');display:block;width:24px;height:24px;position:absolute;left:12px;top:50%;transform:translateY(-50%)}}.bf-search-bar-iframe-backdrop{display:block;position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999;background-color:#d9d9d905;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.iframe-loading-indicator{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;align-items:center;justify-content:center;z-index:10}.spinner{width:24px;height:24px;border:2px solid rgba(0,0,0,.1);border-radius:50%;border-top-color:#3498db;animation:spin 1s ease-in-out infinite}@keyframes spin{to{transform:rotate(360deg)}}.loading-error{width:24px;height:24px;position:relative;display:flex;align-items:center;justify-content:center}.loading-error:before,.loading-error:after{content:"";position:absolute;width:16px;height:2px;background-color:#e74c3c;border-radius:2px}.loading-error:before{transform:rotate(45deg)}.loading-error:after{transform:rotate(-45deg)}`;
|
|
738
547
|
function getDefaultExportFromCjs(x) {
|
|
739
548
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
740
549
|
}
|
|
@@ -1715,6 +1524,10 @@ function requireLighten() {
|
|
|
1715
1524
|
}
|
|
1716
1525
|
var lightenExports = /* @__PURE__ */ requireLighten();
|
|
1717
1526
|
const lighten = /* @__PURE__ */ getDefaultExportFromCjs(lightenExports);
|
|
1527
|
+
const IFRAME_CONTAINER_CLASS = "bf-iframe-container";
|
|
1528
|
+
const TRIGGER_BUTTON_CLASS = "bf-trigger-button";
|
|
1529
|
+
const SEARCH_BAR_IFRAME_CONTAINER_CLASS = "bf-search-bar-iframe-container";
|
|
1530
|
+
const SEARCH_BAR_IFRAME_BACKDROP_CLASS = "bf-search-bar-iframe-backdrop";
|
|
1718
1531
|
function insertStyles(primaryColor = "#000", foreground = "FFF") {
|
|
1719
1532
|
const style = document.createElement("style");
|
|
1720
1533
|
style.attributes.setNamedItem(document.createAttribute("data-widget-styles"));
|
|
@@ -1737,95 +1550,514 @@ function insertStylesIfNeeded(config) {
|
|
|
1737
1550
|
insertStyles(buttonColor, iconColor);
|
|
1738
1551
|
}
|
|
1739
1552
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
};
|
|
1760
|
-
checkAndUpdateDarkMode();
|
|
1761
|
-
observeBodyClassChanges();
|
|
1553
|
+
class WidgetState {
|
|
1554
|
+
constructor(widgetKey, widgetType) {
|
|
1555
|
+
__publicField(this, "isOpen", false);
|
|
1556
|
+
this.widgetKey = widgetKey;
|
|
1557
|
+
this.widgetType = widgetType;
|
|
1558
|
+
}
|
|
1559
|
+
get isWidgetOpen() {
|
|
1560
|
+
return this.isOpen;
|
|
1561
|
+
}
|
|
1562
|
+
openWidget() {
|
|
1563
|
+
this.isOpen = true;
|
|
1564
|
+
}
|
|
1565
|
+
closeWidget() {
|
|
1566
|
+
this.isOpen = false;
|
|
1567
|
+
}
|
|
1568
|
+
toggleWidget() {
|
|
1569
|
+
this.isOpen = !this.isOpen;
|
|
1570
|
+
return this.isOpen;
|
|
1571
|
+
}
|
|
1762
1572
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
(
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1573
|
+
const MOBILE_BREAKPOINT = 576;
|
|
1574
|
+
const DESKTOP_BREAKPOINT = 962;
|
|
1575
|
+
class WidgetDOMController {
|
|
1576
|
+
constructor(widgetType) {
|
|
1577
|
+
__publicField(this, "button", null);
|
|
1578
|
+
__publicField(this, "icon", null);
|
|
1579
|
+
this.widgetType = widgetType;
|
|
1580
|
+
}
|
|
1581
|
+
get containerClass() {
|
|
1582
|
+
return this.widgetType === WidgetType.Searchbar ? SEARCH_BAR_IFRAME_CONTAINER_CLASS : IFRAME_CONTAINER_CLASS;
|
|
1583
|
+
}
|
|
1584
|
+
setElements(button, icon) {
|
|
1585
|
+
this.button = button || null;
|
|
1586
|
+
this.icon = icon || null;
|
|
1587
|
+
}
|
|
1588
|
+
openWidget(options = {}) {
|
|
1589
|
+
var _a, _b;
|
|
1590
|
+
const iframeContainer = document.querySelector(`.${this.containerClass}`);
|
|
1591
|
+
const iframe = iframeContainer == null ? void 0 : iframeContainer.querySelector("iframe");
|
|
1592
|
+
if (options.newConversation) {
|
|
1593
|
+
(_a = iframe == null ? void 0 : iframe.contentWindow) == null ? void 0 : _a.postMessage({ type: "NEW_CONVERSATION" }, "*");
|
|
1774
1594
|
}
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1595
|
+
(_b = iframe == null ? void 0 : iframe.contentWindow) == null ? void 0 : _b.postMessage({ type: "FOCUS_SEARCH_FIELD" }, "*");
|
|
1596
|
+
iframeContainer == null ? void 0 : iframeContainer.classList.add("open");
|
|
1597
|
+
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "false");
|
|
1598
|
+
this.updateButtonForOpen();
|
|
1599
|
+
}
|
|
1600
|
+
closeWidget() {
|
|
1601
|
+
const iframeContainer = document.querySelector(`.${this.containerClass}`);
|
|
1602
|
+
iframeContainer == null ? void 0 : iframeContainer.classList.remove("open");
|
|
1603
|
+
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "true");
|
|
1604
|
+
this.updateButtonForClose();
|
|
1605
|
+
}
|
|
1606
|
+
updateButtonForOpen() {
|
|
1607
|
+
if (!this.button || !this.icon) return;
|
|
1608
|
+
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
1609
|
+
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
1610
|
+
this.button.setAttribute("aria-expanded", "true");
|
|
1611
|
+
fishIconSVG == null ? void 0 : fishIconSVG.classList.remove("visible");
|
|
1612
|
+
closeIconSVG == null ? void 0 : closeIconSVG.classList.add("visible");
|
|
1613
|
+
if (this.isMobile()) {
|
|
1614
|
+
this.hideTriggerButton();
|
|
1784
1615
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
const
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1616
|
+
}
|
|
1617
|
+
updateButtonForClose() {
|
|
1618
|
+
if (!this.button || !this.icon) return;
|
|
1619
|
+
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
1620
|
+
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
1621
|
+
this.button.setAttribute("aria-expanded", "false");
|
|
1622
|
+
fishIconSVG == null ? void 0 : fishIconSVG.classList.add("visible");
|
|
1623
|
+
closeIconSVG == null ? void 0 : closeIconSVG.classList.remove("visible");
|
|
1624
|
+
if (this.isMobile()) {
|
|
1625
|
+
this.showTriggerButton();
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
showTriggerButton() {
|
|
1629
|
+
var _a;
|
|
1630
|
+
(_a = this.button) == null ? void 0 : _a.classList.remove("hidden");
|
|
1631
|
+
}
|
|
1632
|
+
hideTriggerButton() {
|
|
1633
|
+
var _a;
|
|
1634
|
+
(_a = this.button) == null ? void 0 : _a.classList.add("hidden");
|
|
1635
|
+
}
|
|
1636
|
+
isMobile() {
|
|
1637
|
+
return document.body.clientWidth <= MOBILE_BREAKPOINT;
|
|
1638
|
+
}
|
|
1639
|
+
setupButtonClickListener(callback) {
|
|
1640
|
+
if (this.button) {
|
|
1641
|
+
this.button.addEventListener("click", callback);
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1794
1644
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
if (typeof window !== "undefined" && typeof window.btoa === "function") {
|
|
1799
|
-
const binaryString = Array.from(
|
|
1800
|
-
uint8Array,
|
|
1801
|
-
(byte) => String.fromCharCode(byte)
|
|
1802
|
-
).join("");
|
|
1803
|
-
return btoa(binaryString);
|
|
1645
|
+
class WidgetRegistry {
|
|
1646
|
+
static register(widgetKey, instance) {
|
|
1647
|
+
this.instances.set(widgetKey, instance);
|
|
1804
1648
|
}
|
|
1805
|
-
|
|
1806
|
-
return
|
|
1649
|
+
static getInstance(widgetKey) {
|
|
1650
|
+
return this.instances.get(widgetKey);
|
|
1651
|
+
}
|
|
1652
|
+
static unregister(widgetKey) {
|
|
1653
|
+
this.instances.delete(widgetKey);
|
|
1654
|
+
}
|
|
1655
|
+
static getAllInstances() {
|
|
1656
|
+
return Array.from(this.instances.values());
|
|
1657
|
+
}
|
|
1658
|
+
static getOpenInstance() {
|
|
1659
|
+
return this.getAllInstances().find((instance) => instance.isWidgetOpen);
|
|
1660
|
+
}
|
|
1661
|
+
static getClosedPopupInstance() {
|
|
1662
|
+
return this.getAllInstances().find(
|
|
1663
|
+
(instance) => !instance.isWidgetOpen && instance.widgetType === WidgetType.Popup
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
static clear() {
|
|
1667
|
+
this.instances.clear();
|
|
1807
1668
|
}
|
|
1808
|
-
throw new Error("[utils.base64Encode]: Unsupported environment");
|
|
1809
1669
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1670
|
+
__publicField(WidgetRegistry, "instances", /* @__PURE__ */ new Map());
|
|
1671
|
+
class WidgetGlobalAPI {
|
|
1672
|
+
static initialize() {
|
|
1673
|
+
if (this.isInitialized) return;
|
|
1674
|
+
this.setupDeprecatedAPI();
|
|
1675
|
+
this.setupNewAPI();
|
|
1676
|
+
this.isInitialized = true;
|
|
1677
|
+
}
|
|
1678
|
+
static setupDeprecatedAPI() {
|
|
1679
|
+
var _a;
|
|
1680
|
+
if ((_a = window.Brainfish) == null ? void 0 : _a.HelpWidget) {
|
|
1681
|
+
window.Brainfish.HelpWidget.close = (trigger) => this.closeCurrentlyOpenWidget();
|
|
1682
|
+
window.Brainfish.HelpWidget.open = (trigger) => this.openCurrentlyClosedPopupWidget(trigger);
|
|
1817
1683
|
}
|
|
1818
|
-
const decoder2 = new TextDecoder();
|
|
1819
|
-
return decoder2.decode(bytes);
|
|
1820
1684
|
}
|
|
1821
|
-
|
|
1822
|
-
|
|
1685
|
+
static setupNewAPI() {
|
|
1686
|
+
var _a;
|
|
1687
|
+
if ((_a = window.Brainfish) == null ? void 0 : _a.Widgets) {
|
|
1688
|
+
window.Brainfish.Widgets.open = () => this.openCurrentlyClosedPopupWidget();
|
|
1689
|
+
window.Brainfish.Widgets.close = () => this.closeCurrentlyOpenWidget();
|
|
1690
|
+
}
|
|
1823
1691
|
}
|
|
1824
|
-
|
|
1692
|
+
static closeCurrentlyOpenWidget() {
|
|
1693
|
+
const openInstance = WidgetRegistry.getOpenInstance();
|
|
1694
|
+
if (openInstance) {
|
|
1695
|
+
openInstance.closeWidget();
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
static openCurrentlyClosedPopupWidget(trigger) {
|
|
1699
|
+
const closedPopupInstance = WidgetRegistry.getClosedPopupInstance();
|
|
1700
|
+
if (closedPopupInstance) {
|
|
1701
|
+
const options = trigger ? { newConversation: true, trigger } : {};
|
|
1702
|
+
closedPopupInstance.openWidget(options);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
__publicField(WidgetGlobalAPI, "isInitialized", false);
|
|
1707
|
+
class AnalyticsTracker {
|
|
1708
|
+
constructor(widgetType, widgetKey) {
|
|
1709
|
+
this.widgetType = widgetType;
|
|
1710
|
+
this.widgetKey = widgetKey;
|
|
1711
|
+
}
|
|
1712
|
+
trackOpenWidget(trigger) {
|
|
1713
|
+
this.dispatchEvent("onBrainfishWidgetOpen");
|
|
1714
|
+
if (trigger) {
|
|
1715
|
+
this.trackAnalytics("Open Widget - Custom Trigger", { trigger });
|
|
1716
|
+
} else {
|
|
1717
|
+
this.trackAnalytics("Open Widget");
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
trackCloseWidget() {
|
|
1721
|
+
this.dispatchEvent("onBrainfishWidgetClose");
|
|
1722
|
+
this.trackAnalytics("Close Widget");
|
|
1723
|
+
}
|
|
1724
|
+
trackCustomEvent(eventName, data = {}) {
|
|
1725
|
+
this.trackAnalytics(eventName, data);
|
|
1726
|
+
}
|
|
1727
|
+
dispatchEvent(eventName) {
|
|
1728
|
+
window.dispatchEvent(new Event(eventName));
|
|
1729
|
+
}
|
|
1730
|
+
trackAnalytics(eventName, data = {}) {
|
|
1731
|
+
if (window.BrainfishAnalytics) {
|
|
1732
|
+
window.BrainfishAnalytics("track", eventName, __spreadProps(__spreadValues({}, data), {
|
|
1733
|
+
widgetKey: this.widgetKey
|
|
1734
|
+
}), {
|
|
1735
|
+
source: this.widgetType,
|
|
1736
|
+
widgetKey: this.widgetKey
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
class IframeStateManager {
|
|
1742
|
+
constructor(widgetKey, widgetType) {
|
|
1743
|
+
__publicField(this, "state");
|
|
1744
|
+
__publicField(this, "domController");
|
|
1745
|
+
__publicField(this, "analyticsTracker");
|
|
1746
|
+
this.state = new WidgetState(widgetKey, widgetType);
|
|
1747
|
+
this.domController = new WidgetDOMController(widgetType);
|
|
1748
|
+
this.analyticsTracker = new AnalyticsTracker(widgetType, widgetKey);
|
|
1749
|
+
}
|
|
1750
|
+
static getInstance(widgetKey) {
|
|
1751
|
+
return WidgetRegistry.getInstance(widgetKey);
|
|
1752
|
+
}
|
|
1753
|
+
get widgetKey() {
|
|
1754
|
+
return this.state.widgetKey;
|
|
1755
|
+
}
|
|
1756
|
+
get widgetType() {
|
|
1757
|
+
return this.state.widgetType;
|
|
1758
|
+
}
|
|
1759
|
+
get isWidgetOpen() {
|
|
1760
|
+
return this.state.isWidgetOpen;
|
|
1761
|
+
}
|
|
1762
|
+
get containerClass() {
|
|
1763
|
+
return this.domController.containerClass;
|
|
1764
|
+
}
|
|
1765
|
+
initialize({
|
|
1766
|
+
button,
|
|
1767
|
+
icon,
|
|
1768
|
+
isButtonHidden
|
|
1769
|
+
}) {
|
|
1770
|
+
this.domController.setElements(button, icon);
|
|
1771
|
+
this.domController.setupButtonClickListener(() => this.toggleIframeVisibility());
|
|
1772
|
+
WidgetRegistry.register(this.widgetKey, this);
|
|
1773
|
+
WidgetGlobalAPI.initialize();
|
|
1774
|
+
}
|
|
1775
|
+
toggleIframeVisibility() {
|
|
1776
|
+
const wasOpen = this.state.toggleWidget();
|
|
1777
|
+
if (wasOpen) {
|
|
1778
|
+
this.openWidget();
|
|
1779
|
+
} else {
|
|
1780
|
+
this.closeWidget();
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
// Open the widget programmatically
|
|
1784
|
+
openWidget(options = {}) {
|
|
1785
|
+
this.state.openWidget();
|
|
1786
|
+
this.domController.openWidget(options);
|
|
1787
|
+
this.analyticsTracker.trackOpenWidget(options.trigger);
|
|
1788
|
+
}
|
|
1789
|
+
// Close the widget programmatically
|
|
1790
|
+
closeWidget() {
|
|
1791
|
+
this.state.closeWidget();
|
|
1792
|
+
this.domController.closeWidget();
|
|
1793
|
+
this.analyticsTracker.trackCloseWidget();
|
|
1794
|
+
}
|
|
1795
|
+
showTriggerButton() {
|
|
1796
|
+
this.domController.showTriggerButton();
|
|
1797
|
+
}
|
|
1798
|
+
hideTriggerButton() {
|
|
1799
|
+
this.domController.hideTriggerButton();
|
|
1800
|
+
}
|
|
1801
|
+
trackCustomEvent(eventName, data = {}) {
|
|
1802
|
+
this.analyticsTracker.trackCustomEvent(eventName, data);
|
|
1803
|
+
}
|
|
1804
|
+
// Cleanup method to remove this instance
|
|
1805
|
+
destroy() {
|
|
1806
|
+
WidgetRegistry.unregister(this.widgetKey);
|
|
1807
|
+
}
|
|
1808
|
+
static initialize(options) {
|
|
1809
|
+
const instance = new IframeStateManager(options.widgetKey, options.widgetType);
|
|
1810
|
+
instance.initialize(options);
|
|
1811
|
+
return instance;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
function createElementWithClass(tagName, className, attributes = {}) {
|
|
1815
|
+
const element = document.createElement(tagName);
|
|
1816
|
+
element.className = className;
|
|
1817
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
1818
|
+
element.setAttribute(key, value);
|
|
1819
|
+
});
|
|
1820
|
+
return element;
|
|
1821
|
+
}
|
|
1822
|
+
function createTriggerButton(widgetKey, triggerButtonIcon) {
|
|
1823
|
+
const button = createElementWithClass("button", TRIGGER_BUTTON_CLASS, {
|
|
1824
|
+
id: `trigger-button-${widgetKey}`,
|
|
1825
|
+
"aria-controls": IFRAME_CONTAINER_CLASS,
|
|
1826
|
+
"aria-expanded": "false",
|
|
1827
|
+
"data-name": TRIGGER_BUTTON_CLASS
|
|
1828
|
+
});
|
|
1829
|
+
const icon = createElementWithClass("div", "trigger-button-icon", {
|
|
1830
|
+
"aria-hidden": "true"
|
|
1831
|
+
});
|
|
1832
|
+
if (!triggerButtonIcon) {
|
|
1833
|
+
icon.innerHTML = `
|
|
1834
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
1835
|
+
<path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path>
|
|
1836
|
+
</svg>
|
|
1837
|
+
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="fish-icon visible">
|
|
1838
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.71844 10.3882L4.60606 6.98384L1.71844 3.58375C1.4014 3.21362 1.44424 2.65841 1.81269 2.33993C1.97978 2.1979 2.65242 1.98701 3.04657 2.43461L5.78425 5.65824C6.14281 5.29523 6.51693 4.95924 6.90479 4.65114C8.88976 3.07437 11.2345 2.22803 13.6931 2.22803C16.9492 2.22803 20.0039 3.71718 22.2917 6.41142C22.5702 6.74282 22.5702 7.22916 22.2917 7.56056C20.0039 10.2591 16.9492 11.744 13.6931 11.744C11.2348 11.744 8.89035 10.8948 6.90554 9.31995C6.51741 9.01199 6.14304 8.67628 5.78425 8.31374L3.04657 11.5374C2.72953 11.9075 2.18114 11.9505 1.81269 11.632C1.44852 11.3179 1.40568 10.7584 1.71844 10.3882ZM5.93026 10.4683C8.17161 12.2599 10.8546 13.25 13.6931 13.25C17.4881 13.25 21.019 11.4034 23.4447 8.52942C24.1873 7.64571 24.1843 6.31801 23.4397 5.43663C20.8944 2.43919 17.4337 0.722025 13.6931 0.722025C10.8555 0.722025 8.17194 1.70845 5.92952 3.50276L4.17682 1.43933C3.57943 0.760929 2.79325 0.630009 2.25286 0.662947C1.98116 0.679506 1.73125 0.736852 1.51895 0.811846C1.26839 0.900352 1.03017 1.02718 0.827835 1.20058C-0.165283 2.05903 -0.283916 3.561 0.574656 4.56345L2.63075 6.98445L0.568104 9.41623C-0.272133 10.4106 -0.166523 11.9125 0.827835 12.7714C1.81372 13.6243 3.34308 13.5062 4.19036 12.5171L5.93026 10.4683Z" fill="currentColor"/>
|
|
1839
|
+
</svg>
|
|
1840
|
+
`;
|
|
1841
|
+
} else {
|
|
1842
|
+
icon.innerHTML = `
|
|
1843
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
1844
|
+
<path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path>
|
|
1845
|
+
</svg>
|
|
1846
|
+
<img src="${triggerButtonIcon}" class="fish-icon visible" alt="Trigger button icon" height="32" width="32" aria-hidden="true" aria-label="help button icon" />
|
|
1847
|
+
`;
|
|
1848
|
+
}
|
|
1849
|
+
button.setAttribute("aria-label", "Open Brainfish widget");
|
|
1850
|
+
button.appendChild(icon);
|
|
1851
|
+
return { button, icon };
|
|
1852
|
+
}
|
|
1853
|
+
function createIframeContainer({ widgetUrl, widgetType, props }) {
|
|
1854
|
+
const containerClass = widgetType === WidgetType.Searchbar ? SEARCH_BAR_IFRAME_CONTAINER_CLASS : IFRAME_CONTAINER_CLASS;
|
|
1855
|
+
const iframeContainer = createElementWithClass(
|
|
1856
|
+
"div",
|
|
1857
|
+
containerClass,
|
|
1858
|
+
__spreadValues({
|
|
1859
|
+
id: containerClass,
|
|
1860
|
+
"aria-live": "polite",
|
|
1861
|
+
"aria-hidden": "true"
|
|
1862
|
+
}, props || {})
|
|
1863
|
+
);
|
|
1864
|
+
const loadingIndicator = createElementWithClass("div", "iframe-loading-indicator");
|
|
1865
|
+
const spinner = createElementWithClass("div", "spinner");
|
|
1866
|
+
loadingIndicator.setAttribute("aria-label", "Loading content");
|
|
1867
|
+
loadingIndicator.setAttribute("role", "status");
|
|
1868
|
+
loadingIndicator.appendChild(spinner);
|
|
1869
|
+
iframeContainer.appendChild(loadingIndicator);
|
|
1870
|
+
const iframe = createElementWithClass("iframe", "trigger-iframe", {
|
|
1871
|
+
src: widgetUrl,
|
|
1872
|
+
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms",
|
|
1873
|
+
allow: "clipboard-write",
|
|
1874
|
+
role: "dialog"
|
|
1875
|
+
});
|
|
1876
|
+
iframe.style.opacity = "0";
|
|
1877
|
+
iframe.addEventListener("load", () => {
|
|
1878
|
+
loadingIndicator.style.display = "none";
|
|
1879
|
+
iframe.style.opacity = "1";
|
|
1880
|
+
});
|
|
1881
|
+
iframe.addEventListener("error", (error) => {
|
|
1882
|
+
console.error("Error loading iframe:", error);
|
|
1883
|
+
loadingIndicator.innerHTML = "";
|
|
1884
|
+
const errorIcon = createElementWithClass("div", "loading-error");
|
|
1885
|
+
loadingIndicator.appendChild(errorIcon);
|
|
1886
|
+
loadingIndicator.setAttribute("aria-label", "Failed to load content");
|
|
1887
|
+
});
|
|
1888
|
+
iframeContainer.appendChild(iframe);
|
|
1889
|
+
return { iframeContainer, iframe };
|
|
1890
|
+
}
|
|
1891
|
+
function toggleIframeSize() {
|
|
1892
|
+
const iframeContainer = document.querySelector(
|
|
1893
|
+
`.${IFRAME_CONTAINER_CLASS}`
|
|
1894
|
+
);
|
|
1895
|
+
if (iframeContainer.classList.contains("expanded")) {
|
|
1896
|
+
iframeContainer.classList.remove("expanded");
|
|
1897
|
+
} else {
|
|
1898
|
+
iframeContainer.classList.add("expanded");
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
function initColorSchemeListener(iframe, signal) {
|
|
1902
|
+
const updateIframeBodyClass = (isDarkMode) => {
|
|
1903
|
+
var _a;
|
|
1904
|
+
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(
|
|
1905
|
+
{ type: "UPDATE_BODY_CLASS", isDarkMode },
|
|
1906
|
+
"*"
|
|
1907
|
+
);
|
|
1908
|
+
};
|
|
1909
|
+
const checkAndUpdateDarkMode = () => {
|
|
1910
|
+
const isDarkMode = document.body.classList.contains("dark");
|
|
1911
|
+
updateIframeBodyClass(isDarkMode);
|
|
1912
|
+
};
|
|
1913
|
+
const observeBodyClassChanges = () => {
|
|
1914
|
+
const observer = new MutationObserver(checkAndUpdateDarkMode);
|
|
1915
|
+
observer.observe(document.body, {
|
|
1916
|
+
attributes: true,
|
|
1917
|
+
attributeFilter: ["class"]
|
|
1918
|
+
});
|
|
1919
|
+
signal.addEventListener("abort", () => observer.disconnect());
|
|
1920
|
+
};
|
|
1921
|
+
checkAndUpdateDarkMode();
|
|
1922
|
+
observeBodyClassChanges();
|
|
1923
|
+
}
|
|
1924
|
+
const clientActionHandlerMap = /* @__PURE__ */ new Map();
|
|
1925
|
+
const registerClientActionHandler = (key, handler) => {
|
|
1926
|
+
clientActionHandlerMap.set(key, handler);
|
|
1927
|
+
};
|
|
1928
|
+
const formatErrorReason = (key, err) => {
|
|
1929
|
+
const details = err instanceof Error ? err.message : String(err);
|
|
1930
|
+
return `Error executing Client Action with key ${key}. Details: ${details}`;
|
|
1825
1931
|
};
|
|
1826
|
-
const
|
|
1932
|
+
const isPlainObject = (obj) => {
|
|
1933
|
+
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
1934
|
+
};
|
|
1935
|
+
const executeClientActionHandler = (key, input) => __async(null, null, function* () {
|
|
1936
|
+
if (clientActionHandlerMap.has(key)) {
|
|
1937
|
+
const handler = clientActionHandlerMap.get(key);
|
|
1938
|
+
if (typeof handler !== "function") {
|
|
1939
|
+
return {
|
|
1940
|
+
success: false,
|
|
1941
|
+
reason: `Client Action registered with key ${key} is not a function`
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
try {
|
|
1945
|
+
const result = yield handler(input);
|
|
1946
|
+
if (!isPlainObject(result)) {
|
|
1947
|
+
throw new TypeError("Invalid result, expecting object type");
|
|
1948
|
+
}
|
|
1949
|
+
return {
|
|
1950
|
+
success: true,
|
|
1951
|
+
data: result
|
|
1952
|
+
};
|
|
1953
|
+
} catch (e) {
|
|
1954
|
+
return {
|
|
1955
|
+
success: false,
|
|
1956
|
+
reason: formatErrorReason(key, e)
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
return {
|
|
1961
|
+
success: false,
|
|
1962
|
+
reason: `No Client Action registered with key ${key}`
|
|
1963
|
+
};
|
|
1964
|
+
});
|
|
1965
|
+
function initMessageListener(iframe, {
|
|
1966
|
+
widgetHost,
|
|
1967
|
+
apiHost,
|
|
1968
|
+
widgetKey,
|
|
1969
|
+
widgetType,
|
|
1970
|
+
signal,
|
|
1971
|
+
stateManager
|
|
1972
|
+
}) {
|
|
1973
|
+
const messageHandler = (event) => __async(null, null, function* () {
|
|
1974
|
+
var _a;
|
|
1975
|
+
if (event.origin !== widgetHost) return;
|
|
1976
|
+
const { type, widgetKey: messageWidgetKey } = event.data;
|
|
1977
|
+
if (messageWidgetKey && messageWidgetKey !== widgetKey) return;
|
|
1978
|
+
if (type === "TOGGLE_WIDGET_SIZE") {
|
|
1979
|
+
toggleIframeSize();
|
|
1980
|
+
}
|
|
1981
|
+
if (type === "TRACK_EVENT") {
|
|
1982
|
+
const { eventName, data } = event.data;
|
|
1983
|
+
stateManager.trackCustomEvent(eventName, data);
|
|
1984
|
+
}
|
|
1985
|
+
if (type === "CLOSE_WIDGET") {
|
|
1986
|
+
stateManager.closeWidget();
|
|
1987
|
+
}
|
|
1988
|
+
if (type === "NEXT_BEST_ACTION_CLICKED") {
|
|
1989
|
+
const { action, searchQueryId, query, answer } = event.data;
|
|
1990
|
+
const context = { action, searchQueryId };
|
|
1991
|
+
if (!["function", "callback"].includes(action.type)) {
|
|
1992
|
+
console.error("Invalid action type", action);
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
window.__bfCallbacks = window.__bfCallbacks || {};
|
|
1996
|
+
if (window.__bfCallbacks[action.id]) {
|
|
1997
|
+
window.__bfCallbacks[action.id](query, answer, context);
|
|
1998
|
+
return;
|
|
1999
|
+
}
|
|
2000
|
+
const scriptUrl = `${apiHost}/api/searchWidgets.callback.codeblocks?apiKey=${widgetKey}&codeblockId=${action.id}`;
|
|
2001
|
+
const script = document.createElement("script");
|
|
2002
|
+
script.src = scriptUrl;
|
|
2003
|
+
document.head.appendChild(script);
|
|
2004
|
+
script.onload = () => {
|
|
2005
|
+
window.__bfCallbacks[action.id](query, answer, context);
|
|
2006
|
+
setTimeout(() => {
|
|
2007
|
+
document.head.removeChild(script);
|
|
2008
|
+
}, 300);
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
if (type === "CLIENT_EXECUTION") {
|
|
2012
|
+
const { actionKey, inputs, messageId } = event.data;
|
|
2013
|
+
const result = yield executeClientActionHandler(actionKey, inputs);
|
|
2014
|
+
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(
|
|
2015
|
+
{
|
|
2016
|
+
type: "CLIENT_EXECUTION_RESULT",
|
|
2017
|
+
messageId,
|
|
2018
|
+
result
|
|
2019
|
+
},
|
|
2020
|
+
"*"
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
});
|
|
2024
|
+
window.addEventListener("message", messageHandler, { signal });
|
|
2025
|
+
}
|
|
2026
|
+
function observeColorSchemeChanges(iframe, signal, stateManager) {
|
|
2027
|
+
const updateIframeBodyClass = (isMobile) => {
|
|
2028
|
+
var _a;
|
|
2029
|
+
const message = { type: "UPDATE_BODY_CLASS", isMobile };
|
|
2030
|
+
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(message, "*");
|
|
2031
|
+
if (isMobile) {
|
|
2032
|
+
if (stateManager.isWidgetOpen) {
|
|
2033
|
+
stateManager.hideTriggerButton();
|
|
2034
|
+
} else {
|
|
2035
|
+
stateManager.showTriggerButton();
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
let resizeTimeout;
|
|
2040
|
+
const checkAndUpdateIsMobile = () => {
|
|
2041
|
+
const isMobile = document.body.clientWidth <= MOBILE_BREAKPOINT;
|
|
2042
|
+
updateIframeBodyClass(isMobile);
|
|
2043
|
+
};
|
|
2044
|
+
const debouncedCheckAndUpdateIsMobile = () => {
|
|
2045
|
+
if (resizeTimeout) {
|
|
2046
|
+
clearTimeout(resizeTimeout);
|
|
2047
|
+
}
|
|
2048
|
+
resizeTimeout = window.setTimeout(checkAndUpdateIsMobile, 300);
|
|
2049
|
+
};
|
|
2050
|
+
const observeBodyResize = () => {
|
|
2051
|
+
const resizeObserver = new ResizeObserver(debouncedCheckAndUpdateIsMobile);
|
|
2052
|
+
resizeObserver.observe(document.body);
|
|
2053
|
+
signal.addEventListener("abort", () => resizeObserver.disconnect());
|
|
2054
|
+
};
|
|
2055
|
+
checkAndUpdateIsMobile();
|
|
2056
|
+
observeBodyResize();
|
|
2057
|
+
}
|
|
2058
|
+
const initializedWidgets$1 = /* @__PURE__ */ new Set();
|
|
1827
2059
|
function isWidgetInitialized(widgetKey) {
|
|
1828
|
-
return initializedWidgets.has(widgetKey);
|
|
2060
|
+
return initializedWidgets$1.has(widgetKey);
|
|
1829
2061
|
}
|
|
1830
2062
|
function isButtonExisting(widgetKey) {
|
|
1831
2063
|
return !!document.getElementById(`trigger-button-${widgetKey}`);
|
|
@@ -1835,47 +2067,40 @@ function createWidgetWithButton(widgetKey, widgetUrl, {
|
|
|
1835
2067
|
triggerButtonIcon
|
|
1836
2068
|
}) {
|
|
1837
2069
|
const fragment = document.createDocumentFragment();
|
|
2070
|
+
let stateManager;
|
|
1838
2071
|
if (!isButtonHidden) {
|
|
1839
2072
|
const { button, icon } = createTriggerButton(widgetKey, triggerButtonIcon);
|
|
1840
2073
|
fragment.appendChild(button);
|
|
1841
|
-
IframeStateManager.initialize({
|
|
2074
|
+
stateManager = IframeStateManager.initialize({
|
|
2075
|
+
button,
|
|
2076
|
+
icon,
|
|
2077
|
+
widgetType: WidgetType.Popup,
|
|
2078
|
+
widgetKey
|
|
2079
|
+
});
|
|
1842
2080
|
} else {
|
|
1843
|
-
IframeStateManager.initialize({
|
|
2081
|
+
stateManager = IframeStateManager.initialize({
|
|
2082
|
+
isButtonHidden,
|
|
2083
|
+
widgetType: WidgetType.Popup,
|
|
2084
|
+
widgetKey
|
|
2085
|
+
});
|
|
1844
2086
|
}
|
|
1845
|
-
const { iframeContainer, iframe } = createIframeContainer(widgetUrl);
|
|
2087
|
+
const { iframeContainer, iframe } = createIframeContainer({ widgetUrl, widgetType: WidgetType.Popup });
|
|
1846
2088
|
fragment.appendChild(iframeContainer);
|
|
1847
|
-
return { fragment, iframe };
|
|
2089
|
+
return { fragment, iframe, stateManager };
|
|
1848
2090
|
}
|
|
1849
|
-
function handleInitializationError(apiHost, error, widgetKey) {
|
|
2091
|
+
function handleInitializationError$1(apiHost, error, widgetKey) {
|
|
1850
2092
|
sendBrainfishWidgetError(apiHost, error, error.message, widgetKey);
|
|
1851
2093
|
}
|
|
1852
|
-
const
|
|
1853
|
-
|
|
1854
|
-
const apiHost = getApiHost(options.overrides);
|
|
1855
|
-
const widgetHost = getWidgetHost(options.overrides);
|
|
1856
|
-
const { theme, settings } = config;
|
|
1857
|
-
const encodedRules = base64Encode(
|
|
1858
|
-
JSON.stringify((_a = options.overrides) == null ? void 0 : _a.redirectRules)
|
|
1859
|
-
);
|
|
1860
|
-
const widgetParams = {
|
|
1861
|
-
theme: base64Encode(JSON.stringify(theme)),
|
|
1862
|
-
settings: base64Encode(JSON.stringify(settings)),
|
|
1863
|
-
redirectRules: encodedRules
|
|
1864
|
-
};
|
|
1865
|
-
if ((_b = options.overrides) == null ? void 0 : _b.regions) {
|
|
1866
|
-
widgetParams.regions = base64Encode(
|
|
1867
|
-
JSON.stringify((_c = options.overrides) == null ? void 0 : _c.regions)
|
|
1868
|
-
);
|
|
1869
|
-
}
|
|
1870
|
-
const widgetUrl = `${widgetHost}/?widgetKey=${options.widgetKey}#${new URLSearchParams(widgetParams).toString()}`;
|
|
2094
|
+
const initWidgetButton = ({ config, widgetUrl, apiHost, widgetHost, widgetKey }) => {
|
|
2095
|
+
const { settings } = config;
|
|
1871
2096
|
const isButtonHidden = settings == null ? void 0 : settings.hideTriggerButton;
|
|
1872
2097
|
const triggerButtonIcon = settings == null ? void 0 : settings.triggerButtonIcon;
|
|
1873
2098
|
try {
|
|
1874
|
-
if (isWidgetInitialized(
|
|
1875
|
-
if (isButtonExisting(
|
|
2099
|
+
if (isWidgetInitialized(widgetKey)) return void 0;
|
|
2100
|
+
if (isButtonExisting(widgetKey)) return void 0;
|
|
1876
2101
|
insertStylesIfNeeded(config);
|
|
1877
|
-
const { fragment, iframe } = createWidgetWithButton(
|
|
1878
|
-
|
|
2102
|
+
const { fragment, iframe, stateManager } = createWidgetWithButton(
|
|
2103
|
+
widgetKey,
|
|
1879
2104
|
widgetUrl,
|
|
1880
2105
|
{
|
|
1881
2106
|
isButtonHidden: isButtonHidden || false,
|
|
@@ -1887,17 +2112,110 @@ const initIframeTrigger = (options, config) => {
|
|
|
1887
2112
|
iframe.onload = () => {
|
|
1888
2113
|
setTimeout(() => {
|
|
1889
2114
|
initColorSchemeListener(iframe, signal);
|
|
1890
|
-
initMessageListener({
|
|
2115
|
+
initMessageListener(iframe, {
|
|
1891
2116
|
widgetHost,
|
|
1892
2117
|
apiHost,
|
|
1893
|
-
widgetKey
|
|
1894
|
-
|
|
2118
|
+
widgetKey,
|
|
2119
|
+
widgetType: WidgetType.Popup,
|
|
2120
|
+
signal,
|
|
2121
|
+
stateManager
|
|
1895
2122
|
});
|
|
1896
|
-
observeColorSchemeChanges(iframe, signal);
|
|
2123
|
+
observeColorSchemeChanges(iframe, signal, stateManager);
|
|
1897
2124
|
}, 0);
|
|
1898
2125
|
};
|
|
1899
2126
|
document.body.appendChild(fragment);
|
|
1900
|
-
initializedWidgets.add(
|
|
2127
|
+
initializedWidgets$1.add(widgetKey);
|
|
2128
|
+
const cleanup = () => {
|
|
2129
|
+
controller.abort();
|
|
2130
|
+
window.removeEventListener("beforeunload", cleanup);
|
|
2131
|
+
};
|
|
2132
|
+
window.addEventListener("beforeunload", cleanup);
|
|
2133
|
+
return void 0;
|
|
2134
|
+
} catch (error) {
|
|
2135
|
+
handleInitializationError$1(apiHost, error, widgetKey);
|
|
2136
|
+
}
|
|
2137
|
+
};
|
|
2138
|
+
const SEARCH_BAR_SELECTOR = "brainfish-search-widget";
|
|
2139
|
+
function createSearchTrigger({ widgetKey, settings }) {
|
|
2140
|
+
const searchBar = document.querySelector(SEARCH_BAR_SELECTOR);
|
|
2141
|
+
if (!searchBar) return void 0;
|
|
2142
|
+
searchBar.setAttribute("data-widget-key", widgetKey);
|
|
2143
|
+
searchBar.setAttribute("tabindex", "0");
|
|
2144
|
+
const placeholderText = (settings == null ? void 0 : settings.placeholder) || "Ask your question here...";
|
|
2145
|
+
searchBar.setAttribute("data-placeholder", placeholderText);
|
|
2146
|
+
searchBar.setAttribute("aria-label", `${placeholderText} - Click to open search`);
|
|
2147
|
+
searchBar.setAttribute("role", "button");
|
|
2148
|
+
searchBar.setAttribute("aria-expanded", "false");
|
|
2149
|
+
searchBar.setAttribute("aria-haspopup", "dialog");
|
|
2150
|
+
return searchBar;
|
|
2151
|
+
}
|
|
2152
|
+
function handleInitializationError(apiHost, error, widgetKey) {
|
|
2153
|
+
sendBrainfishWidgetError(apiHost, error, error.message, widgetKey);
|
|
2154
|
+
}
|
|
2155
|
+
function isSearchBarExisting(widgetKey) {
|
|
2156
|
+
return !!document.querySelector(`.${SEARCH_BAR_IFRAME_CONTAINER_CLASS}[data-widget-key="${widgetKey}"]`);
|
|
2157
|
+
}
|
|
2158
|
+
const initSearchBar = ({ config, widgetUrl, apiHost, widgetHost, widgetKey }) => {
|
|
2159
|
+
const { settings } = config;
|
|
2160
|
+
let stateManager = IframeStateManager.getInstance(widgetKey);
|
|
2161
|
+
const controller = new AbortController();
|
|
2162
|
+
const searchBar = createSearchTrigger({ widgetKey, settings });
|
|
2163
|
+
if (!searchBar) return void 0;
|
|
2164
|
+
insertStylesIfNeeded(config);
|
|
2165
|
+
try {
|
|
2166
|
+
if (!isSearchBarExisting(widgetKey)) {
|
|
2167
|
+
const fragment = document.createDocumentFragment();
|
|
2168
|
+
if (!stateManager) {
|
|
2169
|
+
stateManager = IframeStateManager.initialize({
|
|
2170
|
+
isButtonHidden: true,
|
|
2171
|
+
widgetType: WidgetType.Searchbar,
|
|
2172
|
+
widgetKey
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
const { iframeContainer, iframe } = createIframeContainer({
|
|
2176
|
+
widgetUrl,
|
|
2177
|
+
widgetType: WidgetType.Searchbar,
|
|
2178
|
+
props: {
|
|
2179
|
+
"data-widget-type": "searchbar",
|
|
2180
|
+
"data-widget-key": widgetKey
|
|
2181
|
+
}
|
|
2182
|
+
});
|
|
2183
|
+
const { signal } = controller;
|
|
2184
|
+
iframe.onload = () => {
|
|
2185
|
+
setTimeout(() => {
|
|
2186
|
+
initColorSchemeListener(iframe, signal);
|
|
2187
|
+
initMessageListener(iframe, {
|
|
2188
|
+
widgetHost,
|
|
2189
|
+
apiHost,
|
|
2190
|
+
widgetKey,
|
|
2191
|
+
widgetType: WidgetType.Searchbar,
|
|
2192
|
+
signal,
|
|
2193
|
+
stateManager
|
|
2194
|
+
});
|
|
2195
|
+
observeColorSchemeChanges(iframe, signal, stateManager);
|
|
2196
|
+
}, 0);
|
|
2197
|
+
};
|
|
2198
|
+
fragment.appendChild(iframeContainer);
|
|
2199
|
+
document.body.appendChild(fragment);
|
|
2200
|
+
}
|
|
2201
|
+
const displaySearchBar = () => {
|
|
2202
|
+
if (document.body.clientWidth >= DESKTOP_BREAKPOINT) {
|
|
2203
|
+
const backdrop = createElementWithClass("div", SEARCH_BAR_IFRAME_BACKDROP_CLASS);
|
|
2204
|
+
backdrop.onclick = () => {
|
|
2205
|
+
backdrop.remove();
|
|
2206
|
+
stateManager == null ? void 0 : stateManager.closeWidget();
|
|
2207
|
+
};
|
|
2208
|
+
document.body.appendChild(backdrop);
|
|
2209
|
+
}
|
|
2210
|
+
WidgetGlobalAPI.closeCurrentlyOpenWidget();
|
|
2211
|
+
stateManager == null ? void 0 : stateManager.openWidget({ newConversation: true });
|
|
2212
|
+
};
|
|
2213
|
+
searchBar.onclick = () => {
|
|
2214
|
+
displaySearchBar();
|
|
2215
|
+
};
|
|
2216
|
+
searchBar.onfocus = () => {
|
|
2217
|
+
displaySearchBar();
|
|
2218
|
+
};
|
|
1901
2219
|
const cleanup = () => {
|
|
1902
2220
|
controller.abort();
|
|
1903
2221
|
window.removeEventListener("beforeunload", cleanup);
|
|
@@ -1905,7 +2223,32 @@ const initIframeTrigger = (options, config) => {
|
|
|
1905
2223
|
window.addEventListener("beforeunload", cleanup);
|
|
1906
2224
|
return void 0;
|
|
1907
2225
|
} catch (error) {
|
|
1908
|
-
handleInitializationError(apiHost, error,
|
|
2226
|
+
handleInitializationError(apiHost, error, widgetKey);
|
|
2227
|
+
}
|
|
2228
|
+
};
|
|
2229
|
+
const initIframeTrigger = (options, config) => {
|
|
2230
|
+
var _a, _b, _c;
|
|
2231
|
+
const apiHost = getApiHost(options.overrides);
|
|
2232
|
+
const widgetHost = getWidgetHost(options.overrides);
|
|
2233
|
+
const { theme, settings } = config;
|
|
2234
|
+
const encodedRules = base64Encode(
|
|
2235
|
+
JSON.stringify((_a = options.overrides) == null ? void 0 : _a.redirectRules)
|
|
2236
|
+
);
|
|
2237
|
+
const widgetParams = {
|
|
2238
|
+
theme: base64Encode(JSON.stringify(theme)),
|
|
2239
|
+
settings: base64Encode(JSON.stringify(settings)),
|
|
2240
|
+
redirectRules: encodedRules
|
|
2241
|
+
};
|
|
2242
|
+
if ((_b = options.overrides) == null ? void 0 : _b.regions) {
|
|
2243
|
+
widgetParams.regions = base64Encode(
|
|
2244
|
+
JSON.stringify((_c = options.overrides) == null ? void 0 : _c.regions)
|
|
2245
|
+
);
|
|
2246
|
+
}
|
|
2247
|
+
const widgetUrl = `${widgetHost}/?widgetKey=${options.widgetKey}#${new URLSearchParams(widgetParams).toString()}`;
|
|
2248
|
+
if (config.widgetType === "Search") {
|
|
2249
|
+
initSearchBar({ config, widgetUrl, apiHost, widgetHost, widgetKey: options.widgetKey });
|
|
2250
|
+
} else {
|
|
2251
|
+
initWidgetButton({ config, widgetUrl, apiHost, widgetHost, widgetKey: options.widgetKey });
|
|
1909
2252
|
}
|
|
1910
2253
|
return void 0;
|
|
1911
2254
|
};
|
|
@@ -1973,6 +2316,45 @@ const initNudgeWidget = (apiHost, widgetKey) => __async(null, null, function* ()
|
|
|
1973
2316
|
);
|
|
1974
2317
|
}
|
|
1975
2318
|
});
|
|
2319
|
+
let routeChangeController = void 0;
|
|
2320
|
+
let isHistoryPatched = false;
|
|
2321
|
+
let originalPushState;
|
|
2322
|
+
let originalReplaceState;
|
|
2323
|
+
const listenToRouteChanges = (handler) => {
|
|
2324
|
+
routeChangeController == null ? void 0 : routeChangeController.abort();
|
|
2325
|
+
routeChangeController = new AbortController();
|
|
2326
|
+
const { signal } = routeChangeController;
|
|
2327
|
+
let currentPath = window.location.pathname;
|
|
2328
|
+
const onRouteChange = () => {
|
|
2329
|
+
if (signal.aborted) return;
|
|
2330
|
+
const newPath = window.location.pathname;
|
|
2331
|
+
if (newPath !== currentPath) {
|
|
2332
|
+
currentPath = newPath;
|
|
2333
|
+
handler();
|
|
2334
|
+
}
|
|
2335
|
+
};
|
|
2336
|
+
window.addEventListener("popstate", onRouteChange, { signal });
|
|
2337
|
+
if (!isHistoryPatched) {
|
|
2338
|
+
originalPushState = history.pushState;
|
|
2339
|
+
originalReplaceState = history.replaceState;
|
|
2340
|
+
history.pushState = function(...args) {
|
|
2341
|
+
originalPushState.apply(this, args);
|
|
2342
|
+
setTimeout(onRouteChange, 0);
|
|
2343
|
+
};
|
|
2344
|
+
history.replaceState = function(...args) {
|
|
2345
|
+
originalReplaceState.apply(this, args);
|
|
2346
|
+
setTimeout(onRouteChange, 0);
|
|
2347
|
+
};
|
|
2348
|
+
isHistoryPatched = true;
|
|
2349
|
+
}
|
|
2350
|
+
signal.addEventListener("abort", () => {
|
|
2351
|
+
if (isHistoryPatched) {
|
|
2352
|
+
history.pushState = originalPushState;
|
|
2353
|
+
history.replaceState = originalReplaceState;
|
|
2354
|
+
isHistoryPatched = false;
|
|
2355
|
+
}
|
|
2356
|
+
});
|
|
2357
|
+
};
|
|
1976
2358
|
let globalBrainfish = null;
|
|
1977
2359
|
function getBrainfishInstance() {
|
|
1978
2360
|
if (typeof window !== "undefined" && window.Brainfish) {
|
|
@@ -1987,15 +2369,35 @@ function getBrainfishInstance() {
|
|
|
1987
2369
|
return globalBrainfish;
|
|
1988
2370
|
}
|
|
1989
2371
|
const Brainfish = getBrainfishInstance();
|
|
1990
|
-
|
|
2372
|
+
const initializationPromises = /* @__PURE__ */ new Map();
|
|
2373
|
+
const initializedWidgets = /* @__PURE__ */ new Map();
|
|
2374
|
+
let routeChangeListenerSetup = false;
|
|
1991
2375
|
function initializeBrainfish(options, config, apiHost, analyticsApiHost) {
|
|
1992
2376
|
return __async(this, null, function* () {
|
|
1993
2377
|
var _a, _b, _c, _d, _e, _f;
|
|
1994
2378
|
const enableRecording = ((_a = options.overrides) == null ? void 0 : _a.enableRecording) || ((_b = config == null ? void 0 : config.settings) == null ? void 0 : _b.enableRecording) || false;
|
|
1995
2379
|
const requestedVersion = ((_c = options.overrides) == null ? void 0 : _c.version) || (config == null ? void 0 : config.version);
|
|
2380
|
+
initializedWidgets.set(options.widgetKey, {
|
|
2381
|
+
options,
|
|
2382
|
+
config,
|
|
2383
|
+
apiHost,
|
|
2384
|
+
analyticsApiHost
|
|
2385
|
+
});
|
|
1996
2386
|
const initPromises = [];
|
|
1997
2387
|
if (requestedVersion == null ? void 0 : requestedVersion.startsWith("2.")) {
|
|
1998
2388
|
initIframeTrigger(options, config);
|
|
2389
|
+
if (!routeChangeListenerSetup) {
|
|
2390
|
+
routeChangeListenerSetup = true;
|
|
2391
|
+
listenToRouteChanges(() => {
|
|
2392
|
+
initializedWidgets.forEach(({ options: widgetOptions, config: widgetConfig }) => {
|
|
2393
|
+
var _a2;
|
|
2394
|
+
const widgetVersion = ((_a2 = widgetOptions.overrides) == null ? void 0 : _a2.version) || (widgetConfig == null ? void 0 : widgetConfig.version);
|
|
2395
|
+
if (widgetVersion == null ? void 0 : widgetVersion.startsWith("2.")) {
|
|
2396
|
+
initIframeTrigger(widgetOptions, widgetConfig);
|
|
2397
|
+
}
|
|
2398
|
+
});
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
1999
2401
|
} else {
|
|
2000
2402
|
initPromises.push(initSearchWidget(options, config));
|
|
2001
2403
|
}
|
|
@@ -2071,6 +2473,7 @@ Brainfish.Widgets.init = (options) => __async(null, null, function* () {
|
|
|
2071
2473
|
});
|
|
2072
2474
|
config = fetchedConfig;
|
|
2073
2475
|
}
|
|
2476
|
+
let initializationPromise = initializationPromises.get(options.widgetKey);
|
|
2074
2477
|
if (!initializationPromise) {
|
|
2075
2478
|
initializationPromise = initializeBrainfish(
|
|
2076
2479
|
options,
|
|
@@ -2078,12 +2481,16 @@ Brainfish.Widgets.init = (options) => __async(null, null, function* () {
|
|
|
2078
2481
|
apiHost,
|
|
2079
2482
|
analyticsApiHost
|
|
2080
2483
|
);
|
|
2484
|
+
initializationPromises.set(options.widgetKey, initializationPromise);
|
|
2081
2485
|
}
|
|
2082
2486
|
yield initializationPromise;
|
|
2083
2487
|
yield initHandOffs(config);
|
|
2084
2488
|
Brainfish.Widgets.isReady = true;
|
|
2085
2489
|
window.dispatchEvent(new Event("onBrainfishReady"));
|
|
2086
2490
|
});
|
|
2491
|
+
Brainfish.Widgets.registerClientActionHandler = (key, handler) => {
|
|
2492
|
+
registerClientActionHandler(key, handler);
|
|
2493
|
+
};
|
|
2087
2494
|
const BrainfishAnalytics = (...args) => {
|
|
2088
2495
|
if (typeof window !== "undefined" && window.BrainfishAnalytics) {
|
|
2089
2496
|
window.BrainfishAnalytics(...args);
|