@brainfish-ai/widgets-initiator 1.14.0 → 1.15.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.
- package/dist/types/initIframeTrigger/components/IframeContainer.d.ts +5 -1
- package/dist/types/initIframeTrigger/constants/breakpoints.d.ts +2 -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 +31 -12
- package/dist/types/initIframeTrigger/managers/WidgetDOMController.d.ts +30 -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/web.cjs.js +1 -1
- package/dist/web.js +791 -360
- 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] = "b7e03632-b8f6-4e30-853d-71b4f1715105", e._sentryDebugIdIdentifier = "sentry-dbid-b7e03632-b8f6-4e30-853d-71b4f1715105");
|
|
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: "ba785fa494052261526991f6c76ddbcdcd23c732" };
|
|
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.1"}. ${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) {
|
|
@@ -512,284 +512,38 @@ const createQueues = () => {
|
|
|
512
512
|
};
|
|
513
513
|
}
|
|
514
514
|
};
|
|
515
|
-
function
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const TRIGGER_BUTTON_CLASS = "bf-trigger-button";
|
|
525
|
-
function createTriggerButton(widgetKey, triggerButtonIcon) {
|
|
526
|
-
const button = createElementWithClass("button", TRIGGER_BUTTON_CLASS, {
|
|
527
|
-
id: `trigger-button-${widgetKey}`,
|
|
528
|
-
"aria-controls": IFRAME_CONTAINER_CLASS,
|
|
529
|
-
"aria-expanded": "false",
|
|
530
|
-
"data-name": TRIGGER_BUTTON_CLASS
|
|
531
|
-
});
|
|
532
|
-
const icon = createElementWithClass("div", "trigger-button-icon", {
|
|
533
|
-
"aria-hidden": "true"
|
|
534
|
-
});
|
|
535
|
-
if (!triggerButtonIcon) {
|
|
536
|
-
icon.innerHTML = `
|
|
537
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
538
|
-
<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>
|
|
539
|
-
</svg>
|
|
540
|
-
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="fish-icon visible">
|
|
541
|
-
<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"/>
|
|
542
|
-
</svg>
|
|
543
|
-
`;
|
|
544
|
-
} else {
|
|
545
|
-
icon.innerHTML = `
|
|
546
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
547
|
-
<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>
|
|
548
|
-
</svg>
|
|
549
|
-
<img src="${triggerButtonIcon}" class="fish-icon visible" alt="Trigger button icon" height="32" width="32" aria-hidden="true" aria-label="help button icon" />
|
|
550
|
-
`;
|
|
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);
|
|
551
524
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
return { button, icon };
|
|
555
|
-
}
|
|
556
|
-
function createIframeContainer(widgetUrl) {
|
|
557
|
-
const iframeContainer = createElementWithClass(
|
|
558
|
-
"div",
|
|
559
|
-
IFRAME_CONTAINER_CLASS,
|
|
560
|
-
{
|
|
561
|
-
id: IFRAME_CONTAINER_CLASS,
|
|
562
|
-
"aria-live": "polite",
|
|
563
|
-
"aria-hidden": "true"
|
|
564
|
-
}
|
|
565
|
-
);
|
|
566
|
-
const loadingIndicator = createElementWithClass("div", "iframe-loading-indicator");
|
|
567
|
-
const spinner = createElementWithClass("div", "spinner");
|
|
568
|
-
loadingIndicator.setAttribute("aria-label", "Loading content");
|
|
569
|
-
loadingIndicator.setAttribute("role", "status");
|
|
570
|
-
loadingIndicator.appendChild(spinner);
|
|
571
|
-
iframeContainer.appendChild(loadingIndicator);
|
|
572
|
-
const iframe = createElementWithClass("iframe", "trigger-iframe", {
|
|
573
|
-
src: widgetUrl,
|
|
574
|
-
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms",
|
|
575
|
-
allow: "clipboard-write",
|
|
576
|
-
role: "dialog"
|
|
577
|
-
});
|
|
578
|
-
iframe.style.opacity = "0";
|
|
579
|
-
iframe.addEventListener("load", () => {
|
|
580
|
-
loadingIndicator.style.display = "none";
|
|
581
|
-
iframe.style.opacity = "1";
|
|
582
|
-
});
|
|
583
|
-
iframe.addEventListener("error", (error) => {
|
|
584
|
-
console.error("Error loading iframe:", error);
|
|
585
|
-
loadingIndicator.innerHTML = "";
|
|
586
|
-
const errorIcon = createElementWithClass("div", "loading-error");
|
|
587
|
-
loadingIndicator.appendChild(errorIcon);
|
|
588
|
-
loadingIndicator.setAttribute("aria-label", "Failed to load content");
|
|
589
|
-
});
|
|
590
|
-
iframeContainer.appendChild(iframe);
|
|
591
|
-
return { iframeContainer, iframe };
|
|
592
|
-
}
|
|
593
|
-
function toggleIframeSize() {
|
|
594
|
-
const iframeContainer = document.querySelector(
|
|
595
|
-
`.${IFRAME_CONTAINER_CLASS}`
|
|
596
|
-
);
|
|
597
|
-
if (iframeContainer.classList.contains("expanded")) {
|
|
598
|
-
iframeContainer.classList.remove("expanded");
|
|
599
|
-
} else {
|
|
600
|
-
iframeContainer.classList.add("expanded");
|
|
525
|
+
if (typeof Buffer !== "undefined") {
|
|
526
|
+
return Buffer.from(uint8Array).toString("base64");
|
|
601
527
|
}
|
|
528
|
+
throw new Error("[utils.base64Encode]: Unsupported environment");
|
|
602
529
|
}
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
icon,
|
|
611
|
-
isButtonHidden
|
|
612
|
-
}) {
|
|
613
|
-
var _a, _b;
|
|
614
|
-
this.button = button || null;
|
|
615
|
-
this.icon = icon || null;
|
|
616
|
-
this.isButtonHidden = isButtonHidden || false;
|
|
617
|
-
if (button) {
|
|
618
|
-
button.addEventListener("click", () => this.toggleIframeVisibility());
|
|
619
|
-
}
|
|
620
|
-
if ((_a = window.Brainfish) == null ? void 0 : _a.HelpWidget) {
|
|
621
|
-
window.Brainfish.HelpWidget.close = () => this.closeWidget();
|
|
622
|
-
window.Brainfish.HelpWidget.open = () => this.openWidget();
|
|
623
|
-
}
|
|
624
|
-
if ((_b = window.Brainfish) == null ? void 0 : _b.Widgets) {
|
|
625
|
-
window.Brainfish.Widgets.open = () => this.openWidget();
|
|
626
|
-
window.Brainfish.Widgets.close = () => this.closeWidget();
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
static toggleIframeVisibility() {
|
|
630
|
-
this.isOpen = !this.isOpen;
|
|
631
|
-
if (this.isOpen) {
|
|
632
|
-
this.openWidget();
|
|
633
|
-
} else {
|
|
634
|
-
this.closeWidget();
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
// Open the widget programmatically
|
|
638
|
-
static openWidget() {
|
|
639
|
-
var _a;
|
|
640
|
-
this.isOpen = true;
|
|
641
|
-
const iframeContainer = document.querySelector(".bf-iframe-container");
|
|
642
|
-
const iframe = iframeContainer == null ? void 0 : iframeContainer.querySelector("iframe");
|
|
643
|
-
iframeContainer == null ? void 0 : iframeContainer.classList.add("open");
|
|
644
|
-
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "false");
|
|
645
|
-
(_a = iframe == null ? void 0 : iframe.contentWindow) == null ? void 0 : _a.postMessage({ type: "FOCUS_SEARCH_FIELD" }, "*");
|
|
646
|
-
if (this.button && this.icon) {
|
|
647
|
-
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
648
|
-
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
649
|
-
this.button.setAttribute("aria-expanded", "true");
|
|
650
|
-
fishIconSVG.classList.remove("visible");
|
|
651
|
-
closeIconSVG.classList.add("visible");
|
|
652
|
-
if (document.body.clientWidth <= MOBILE_BREAKPOINT) {
|
|
653
|
-
this.hideTriggerButton();
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
window.dispatchEvent(new Event("onBrainfishWidgetOpen"));
|
|
657
|
-
window.BrainfishAnalytics("track", "Open Widget");
|
|
658
|
-
}
|
|
659
|
-
// Close the widget programmatically
|
|
660
|
-
static closeWidget() {
|
|
661
|
-
this.isOpen = false;
|
|
662
|
-
const iframeContainer = document.querySelector(".bf-iframe-container");
|
|
663
|
-
iframeContainer == null ? void 0 : iframeContainer.classList.remove("open");
|
|
664
|
-
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "true");
|
|
665
|
-
if (this.button && this.icon) {
|
|
666
|
-
this.button.setAttribute("aria-expanded", "false");
|
|
667
|
-
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
668
|
-
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
669
|
-
fishIconSVG.classList.add("visible");
|
|
670
|
-
closeIconSVG.classList.remove("visible");
|
|
671
|
-
if (document.body.clientWidth <= MOBILE_BREAKPOINT) {
|
|
672
|
-
this.showTriggerButton();
|
|
673
|
-
}
|
|
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);
|
|
674
537
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}
|
|
678
|
-
static showTriggerButton() {
|
|
679
|
-
var _a;
|
|
680
|
-
(_a = this.button) == null ? void 0 : _a.classList.remove("hidden");
|
|
538
|
+
const decoder2 = new TextDecoder();
|
|
539
|
+
return decoder2.decode(bytes);
|
|
681
540
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
(_a = this.button) == null ? void 0 : _a.classList.add("hidden");
|
|
541
|
+
if (typeof Buffer !== "undefined") {
|
|
542
|
+
return Buffer.from(text, "base64").toString("utf-8");
|
|
685
543
|
}
|
|
686
|
-
|
|
687
|
-
__publicField(IframeStateManager, "isOpen", false);
|
|
688
|
-
__publicField(IframeStateManager, "button", null);
|
|
689
|
-
__publicField(IframeStateManager, "icon", null);
|
|
690
|
-
__publicField(IframeStateManager, "isButtonHidden", false);
|
|
691
|
-
const clientActionHandlerMap = /* @__PURE__ */ new Map();
|
|
692
|
-
const registerClientActionHandler = (key, handler) => {
|
|
693
|
-
clientActionHandlerMap.set(key, handler);
|
|
694
|
-
};
|
|
695
|
-
const formatErrorReason = (key, err) => {
|
|
696
|
-
const details = err instanceof Error ? err.message : String(err);
|
|
697
|
-
return `Error executing Client Action with key ${key}. Details: ${details}`;
|
|
698
|
-
};
|
|
699
|
-
const isPlainObject = (obj) => {
|
|
700
|
-
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
544
|
+
throw new Error("[utils.base64Decode]: Unsupported environment");
|
|
701
545
|
};
|
|
702
|
-
const
|
|
703
|
-
if (clientActionHandlerMap.has(key)) {
|
|
704
|
-
const handler = clientActionHandlerMap.get(key);
|
|
705
|
-
if (typeof handler !== "function") {
|
|
706
|
-
return {
|
|
707
|
-
success: false,
|
|
708
|
-
reason: `Client Action registered with key ${key} is not a function`
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
try {
|
|
712
|
-
const result = yield handler(input);
|
|
713
|
-
if (!isPlainObject(result)) {
|
|
714
|
-
throw new TypeError("Invalid result, expecting object type");
|
|
715
|
-
}
|
|
716
|
-
return {
|
|
717
|
-
success: true,
|
|
718
|
-
data: result
|
|
719
|
-
};
|
|
720
|
-
} catch (e) {
|
|
721
|
-
return {
|
|
722
|
-
success: false,
|
|
723
|
-
reason: formatErrorReason(key, e)
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
return {
|
|
728
|
-
success: false,
|
|
729
|
-
reason: `No Client Action registered with key ${key}`
|
|
730
|
-
};
|
|
731
|
-
});
|
|
732
|
-
function initMessageListener(iframe, {
|
|
733
|
-
widgetHost,
|
|
734
|
-
apiHost,
|
|
735
|
-
widgetKey,
|
|
736
|
-
signal
|
|
737
|
-
}) {
|
|
738
|
-
const messageHandler = (event) => __async(null, null, function* () {
|
|
739
|
-
var _a;
|
|
740
|
-
if (event.origin !== widgetHost) return;
|
|
741
|
-
const { type } = event.data;
|
|
742
|
-
if (type === "TOGGLE_WIDGET_SIZE") {
|
|
743
|
-
toggleIframeSize();
|
|
744
|
-
}
|
|
745
|
-
if (type === "TRACK_EVENT") {
|
|
746
|
-
if (!window.BrainfishAnalytics) return;
|
|
747
|
-
const { eventName, data } = event.data;
|
|
748
|
-
window.BrainfishAnalytics("track", eventName, data);
|
|
749
|
-
}
|
|
750
|
-
if (type === "CLOSE_WIDGET") {
|
|
751
|
-
window.BrainfishAnalytics("track", "Close Widget");
|
|
752
|
-
IframeStateManager.toggleIframeVisibility();
|
|
753
|
-
}
|
|
754
|
-
if (type === "NEXT_BEST_ACTION_CLICKED") {
|
|
755
|
-
const { action, searchQueryId, query, answer } = event.data;
|
|
756
|
-
const context = { action, searchQueryId };
|
|
757
|
-
if (!["function", "callback"].includes(action.type)) {
|
|
758
|
-
console.error("Invalid action type", action);
|
|
759
|
-
return;
|
|
760
|
-
}
|
|
761
|
-
window.__bfCallbacks = window.__bfCallbacks || {};
|
|
762
|
-
if (window.__bfCallbacks[action.id]) {
|
|
763
|
-
window.__bfCallbacks[action.id](query, answer, context);
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
const scriptUrl = `${apiHost}/api/searchWidgets.callback.codeblocks?apiKey=${widgetKey}&codeblockId=${action.id}`;
|
|
767
|
-
const script = document.createElement("script");
|
|
768
|
-
script.src = scriptUrl;
|
|
769
|
-
document.head.appendChild(script);
|
|
770
|
-
script.onload = () => {
|
|
771
|
-
window.__bfCallbacks[action.id](query, answer, context);
|
|
772
|
-
setTimeout(() => {
|
|
773
|
-
document.head.removeChild(script);
|
|
774
|
-
}, 300);
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
if (type === "CLIENT_EXECUTION") {
|
|
778
|
-
const { actionKey, inputs, messageId } = event.data;
|
|
779
|
-
const result = yield executeClientActionHandler(actionKey, inputs);
|
|
780
|
-
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(
|
|
781
|
-
{
|
|
782
|
-
type: "CLIENT_EXECUTION_RESULT",
|
|
783
|
-
messageId,
|
|
784
|
-
result
|
|
785
|
-
},
|
|
786
|
-
"*"
|
|
787
|
-
);
|
|
788
|
-
}
|
|
789
|
-
});
|
|
790
|
-
window.addEventListener("message", messageHandler, { signal });
|
|
791
|
-
}
|
|
792
|
-
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)}';
|
|
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);overflow:hidden}.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{min-height:30px;overflow:hidden;&.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;max-height:70vh;top:50%;left:50%;transform:translateY(-50%) translate(-50%)}}@media (min-width: 1200px){.bf-search-bar-iframe-container.open{width:50vw;min-width:770px;max-width:1024px}}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)}`;
|
|
793
547
|
function getDefaultExportFromCjs(x) {
|
|
794
548
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
795
549
|
}
|
|
@@ -1770,6 +1524,10 @@ function requireLighten() {
|
|
|
1770
1524
|
}
|
|
1771
1525
|
var lightenExports = /* @__PURE__ */ requireLighten();
|
|
1772
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";
|
|
1773
1531
|
function insertStyles(primaryColor = "#000", foreground = "FFF") {
|
|
1774
1532
|
const style = document.createElement("style");
|
|
1775
1533
|
style.attributes.setNamedItem(document.createAttribute("data-widget-styles"));
|
|
@@ -1792,18 +1550,453 @@ function insertStylesIfNeeded(config) {
|
|
|
1792
1550
|
insertStyles(buttonColor, iconColor);
|
|
1793
1551
|
}
|
|
1794
1552
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
}
|
|
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
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
const MOBILE_BREAKPOINT = 576;
|
|
1574
|
+
const TABLET_BREAKPOINT = 768;
|
|
1575
|
+
const DESKTOP_BREAKPOINT = 962;
|
|
1576
|
+
function createElementWithClass(tagName, className, attributes = {}) {
|
|
1577
|
+
const element = document.createElement(tagName);
|
|
1578
|
+
element.className = className;
|
|
1579
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
1580
|
+
element.setAttribute(key, value);
|
|
1581
|
+
});
|
|
1582
|
+
return element;
|
|
1583
|
+
}
|
|
1584
|
+
const SEARCH_BAR_SELECTOR = "brainfish-search-widget";
|
|
1585
|
+
class WidgetDOMController {
|
|
1586
|
+
constructor(widgetType) {
|
|
1587
|
+
__publicField(this, "button", null);
|
|
1588
|
+
__publicField(this, "icon", null);
|
|
1589
|
+
__publicField(this, "closeCallback", null);
|
|
1590
|
+
this.widgetType = widgetType;
|
|
1591
|
+
}
|
|
1592
|
+
setCloseCallback(callback) {
|
|
1593
|
+
this.closeCallback = callback;
|
|
1594
|
+
}
|
|
1595
|
+
get containerClass() {
|
|
1596
|
+
return this.widgetType === WidgetType.Searchbar ? SEARCH_BAR_IFRAME_CONTAINER_CLASS : IFRAME_CONTAINER_CLASS;
|
|
1597
|
+
}
|
|
1598
|
+
get container() {
|
|
1599
|
+
return document.querySelector(
|
|
1600
|
+
`.${this.containerClass}`
|
|
1601
|
+
);
|
|
1602
|
+
}
|
|
1603
|
+
get iframe() {
|
|
1604
|
+
var _a;
|
|
1605
|
+
return (_a = this.container) == null ? void 0 : _a.querySelector("iframe");
|
|
1606
|
+
}
|
|
1607
|
+
get backdrop() {
|
|
1608
|
+
return document.querySelector(
|
|
1609
|
+
`.${SEARCH_BAR_IFRAME_BACKDROP_CLASS}`
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
setElements(button, icon) {
|
|
1613
|
+
this.button = button || null;
|
|
1614
|
+
this.icon = icon || null;
|
|
1615
|
+
}
|
|
1616
|
+
openWidget(options = {}) {
|
|
1617
|
+
var _a, _b;
|
|
1618
|
+
const iframeContainer = document.querySelector(`.${this.containerClass}`);
|
|
1619
|
+
const iframe = iframeContainer == null ? void 0 : iframeContainer.querySelector("iframe");
|
|
1620
|
+
if (options.newConversation) {
|
|
1621
|
+
(_a = iframe == null ? void 0 : iframe.contentWindow) == null ? void 0 : _a.postMessage({ type: "NEW_CONVERSATION" }, "*");
|
|
1622
|
+
}
|
|
1623
|
+
(_b = iframe == null ? void 0 : iframe.contentWindow) == null ? void 0 : _b.postMessage({ type: "FOCUS_SEARCH_FIELD" }, "*");
|
|
1624
|
+
iframeContainer == null ? void 0 : iframeContainer.classList.add("open");
|
|
1625
|
+
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "false");
|
|
1626
|
+
if (document.body.clientWidth >= DESKTOP_BREAKPOINT && this.widgetType === WidgetType.Searchbar && this.backdrop === null) {
|
|
1627
|
+
const backdrop = createElementWithClass(
|
|
1628
|
+
"div",
|
|
1629
|
+
SEARCH_BAR_IFRAME_BACKDROP_CLASS
|
|
1630
|
+
);
|
|
1631
|
+
if (this.closeCallback) {
|
|
1632
|
+
backdrop.addEventListener("click", this.closeCallback);
|
|
1633
|
+
}
|
|
1634
|
+
document.body.appendChild(backdrop);
|
|
1635
|
+
}
|
|
1636
|
+
this.updateButtonForOpen();
|
|
1637
|
+
}
|
|
1638
|
+
focusNextElement() {
|
|
1639
|
+
const searchInput = document.querySelector(
|
|
1640
|
+
SEARCH_BAR_SELECTOR
|
|
1641
|
+
);
|
|
1642
|
+
if (searchInput) {
|
|
1643
|
+
const focusableElements = Array.from(
|
|
1644
|
+
document.querySelectorAll(
|
|
1645
|
+
'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
|
|
1646
|
+
)
|
|
1647
|
+
).filter((el) => !el.hasAttribute("disabled"));
|
|
1648
|
+
const currentIndex = focusableElements.indexOf(searchInput);
|
|
1649
|
+
if (currentIndex !== -1) {
|
|
1650
|
+
const nextElement = focusableElements[currentIndex + 1];
|
|
1651
|
+
if (nextElement) {
|
|
1652
|
+
nextElement.focus();
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
closeWidget() {
|
|
1658
|
+
const iframeContainer = document.querySelector(`.${this.containerClass}`);
|
|
1659
|
+
iframeContainer == null ? void 0 : iframeContainer.classList.remove("open");
|
|
1660
|
+
iframeContainer == null ? void 0 : iframeContainer.setAttribute("aria-hidden", "true");
|
|
1661
|
+
if (this.backdrop) {
|
|
1662
|
+
this.backdrop.remove();
|
|
1663
|
+
this.focusNextElement();
|
|
1664
|
+
}
|
|
1665
|
+
this.updateButtonForClose();
|
|
1666
|
+
}
|
|
1667
|
+
updateButtonForOpen() {
|
|
1668
|
+
if (!this.button || !this.icon) return;
|
|
1669
|
+
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
1670
|
+
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
1671
|
+
this.button.setAttribute("aria-expanded", "true");
|
|
1672
|
+
fishIconSVG == null ? void 0 : fishIconSVG.classList.remove("visible");
|
|
1673
|
+
closeIconSVG == null ? void 0 : closeIconSVG.classList.add("visible");
|
|
1674
|
+
if (this.isMobile()) {
|
|
1675
|
+
this.hideTriggerButton();
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
updateButtonForClose() {
|
|
1679
|
+
if (!this.button || !this.icon) return;
|
|
1680
|
+
const fishIconSVG = this.icon.querySelector(".fish-icon");
|
|
1681
|
+
const closeIconSVG = this.icon.querySelector(".close-icon");
|
|
1682
|
+
this.button.setAttribute("aria-expanded", "false");
|
|
1683
|
+
fishIconSVG == null ? void 0 : fishIconSVG.classList.add("visible");
|
|
1684
|
+
closeIconSVG == null ? void 0 : closeIconSVG.classList.remove("visible");
|
|
1685
|
+
if (this.isMobile()) {
|
|
1686
|
+
this.showTriggerButton();
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
showTriggerButton() {
|
|
1690
|
+
var _a;
|
|
1691
|
+
(_a = this.button) == null ? void 0 : _a.classList.remove("hidden");
|
|
1692
|
+
}
|
|
1693
|
+
hideTriggerButton() {
|
|
1694
|
+
var _a;
|
|
1695
|
+
(_a = this.button) == null ? void 0 : _a.classList.add("hidden");
|
|
1696
|
+
}
|
|
1697
|
+
resizeContainer(height) {
|
|
1698
|
+
var _a, _b;
|
|
1699
|
+
if (this.widgetType !== WidgetType.Searchbar) {
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
if (!this.container || !this.iframe) return;
|
|
1703
|
+
if (window.innerWidth < TABLET_BREAKPOINT) {
|
|
1704
|
+
this.container.style.removeProperty("height");
|
|
1705
|
+
this.iframe.style.removeProperty("height");
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
if (document.body.clientWidth <= DESKTOP_BREAKPOINT) {
|
|
1709
|
+
this.container.style.removeProperty("height");
|
|
1710
|
+
} else {
|
|
1711
|
+
this.container.style.height = `${height}px`;
|
|
1712
|
+
}
|
|
1713
|
+
this.iframe.style.height = `${height}px`;
|
|
1714
|
+
if (height === 0) {
|
|
1715
|
+
const message = { type: "CONSTRAINED_HEIGHT", height };
|
|
1716
|
+
(_a = this.iframe.contentWindow) == null ? void 0 : _a.postMessage(message, "*");
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1719
|
+
const maxHeight = window.innerHeight * 0.7;
|
|
1720
|
+
if (height > maxHeight) {
|
|
1721
|
+
this.container.style.height = `${maxHeight}px`;
|
|
1722
|
+
this.iframe.style.height = `${maxHeight}px`;
|
|
1723
|
+
const message = { type: "CONSTRAINED_HEIGHT", height: maxHeight };
|
|
1724
|
+
(_b = this.iframe.contentWindow) == null ? void 0 : _b.postMessage(message, "*");
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
isMobile() {
|
|
1728
|
+
return document.body.clientWidth <= MOBILE_BREAKPOINT;
|
|
1729
|
+
}
|
|
1730
|
+
setupButtonClickListener(callback) {
|
|
1731
|
+
if (this.button) {
|
|
1732
|
+
this.button.addEventListener("click", callback);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
class WidgetRegistry {
|
|
1737
|
+
static register(widgetKey, instance) {
|
|
1738
|
+
this.instances.set(widgetKey, instance);
|
|
1739
|
+
}
|
|
1740
|
+
static getInstance(widgetKey) {
|
|
1741
|
+
return this.instances.get(widgetKey);
|
|
1742
|
+
}
|
|
1743
|
+
static unregister(widgetKey) {
|
|
1744
|
+
this.instances.delete(widgetKey);
|
|
1745
|
+
}
|
|
1746
|
+
static getAllInstances() {
|
|
1747
|
+
return Array.from(this.instances.values());
|
|
1748
|
+
}
|
|
1749
|
+
static getOpenInstance() {
|
|
1750
|
+
return this.getAllInstances().find((instance) => instance.isWidgetOpen);
|
|
1751
|
+
}
|
|
1752
|
+
static getClosedPopupInstance() {
|
|
1753
|
+
return this.getAllInstances().find(
|
|
1754
|
+
(instance) => !instance.isWidgetOpen && instance.widgetType === WidgetType.Popup
|
|
1755
|
+
);
|
|
1756
|
+
}
|
|
1757
|
+
static clear() {
|
|
1758
|
+
this.instances.clear();
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
__publicField(WidgetRegistry, "instances", /* @__PURE__ */ new Map());
|
|
1762
|
+
class WidgetGlobalAPI {
|
|
1763
|
+
static initialize() {
|
|
1764
|
+
if (this.isInitialized) return;
|
|
1765
|
+
this.setupDeprecatedAPI();
|
|
1766
|
+
this.setupNewAPI();
|
|
1767
|
+
this.isInitialized = true;
|
|
1768
|
+
}
|
|
1769
|
+
static setupDeprecatedAPI() {
|
|
1770
|
+
var _a;
|
|
1771
|
+
if ((_a = window.Brainfish) == null ? void 0 : _a.HelpWidget) {
|
|
1772
|
+
window.Brainfish.HelpWidget.close = (trigger) => this.closeCurrentlyOpenWidget();
|
|
1773
|
+
window.Brainfish.HelpWidget.open = (trigger) => this.openCurrentlyClosedPopupWidget(trigger);
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
static setupNewAPI() {
|
|
1777
|
+
var _a;
|
|
1778
|
+
if ((_a = window.Brainfish) == null ? void 0 : _a.Widgets) {
|
|
1779
|
+
window.Brainfish.Widgets.open = () => this.openCurrentlyClosedPopupWidget();
|
|
1780
|
+
window.Brainfish.Widgets.close = () => this.closeCurrentlyOpenWidget();
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
static closeCurrentlyOpenWidget() {
|
|
1784
|
+
const openInstance = WidgetRegistry.getOpenInstance();
|
|
1785
|
+
if (openInstance) {
|
|
1786
|
+
openInstance.closeWidget();
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
static openCurrentlyClosedPopupWidget(trigger) {
|
|
1790
|
+
const closedPopupInstance = WidgetRegistry.getClosedPopupInstance();
|
|
1791
|
+
if (closedPopupInstance) {
|
|
1792
|
+
const options = trigger ? { newConversation: true, trigger } : {};
|
|
1793
|
+
closedPopupInstance.openWidget(options);
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
__publicField(WidgetGlobalAPI, "isInitialized", false);
|
|
1798
|
+
class AnalyticsTracker {
|
|
1799
|
+
constructor(widgetType, widgetKey) {
|
|
1800
|
+
this.widgetType = widgetType;
|
|
1801
|
+
this.widgetKey = widgetKey;
|
|
1802
|
+
}
|
|
1803
|
+
trackOpenWidget(trigger) {
|
|
1804
|
+
this.dispatchEvent("onBrainfishWidgetOpen");
|
|
1805
|
+
if (trigger) {
|
|
1806
|
+
this.trackAnalytics("Open Widget - Custom Trigger", { trigger });
|
|
1807
|
+
} else {
|
|
1808
|
+
this.trackAnalytics("Open Widget");
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
trackCloseWidget() {
|
|
1812
|
+
this.dispatchEvent("onBrainfishWidgetClose");
|
|
1813
|
+
this.trackAnalytics("Close Widget");
|
|
1814
|
+
}
|
|
1815
|
+
trackCustomEvent(eventName, data = {}) {
|
|
1816
|
+
this.trackAnalytics(eventName, data);
|
|
1817
|
+
}
|
|
1818
|
+
dispatchEvent(eventName) {
|
|
1819
|
+
window.dispatchEvent(new Event(eventName));
|
|
1820
|
+
}
|
|
1821
|
+
trackAnalytics(eventName, data = {}) {
|
|
1822
|
+
if (window.BrainfishAnalytics) {
|
|
1823
|
+
window.BrainfishAnalytics("track", eventName, __spreadProps(__spreadValues({}, data), {
|
|
1824
|
+
widgetKey: this.widgetKey
|
|
1825
|
+
}), {
|
|
1826
|
+
source: this.widgetType,
|
|
1827
|
+
widgetKey: this.widgetKey
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
class IframeStateManager {
|
|
1833
|
+
constructor(widgetKey, widgetType) {
|
|
1834
|
+
__publicField(this, "state");
|
|
1835
|
+
__publicField(this, "domController");
|
|
1836
|
+
__publicField(this, "analyticsTracker");
|
|
1837
|
+
this.state = new WidgetState(widgetKey, widgetType);
|
|
1838
|
+
this.domController = new WidgetDOMController(widgetType);
|
|
1839
|
+
this.domController.setCloseCallback(() => this.closeWidget());
|
|
1840
|
+
this.analyticsTracker = new AnalyticsTracker(widgetType, widgetKey);
|
|
1841
|
+
}
|
|
1842
|
+
static getInstance(widgetKey) {
|
|
1843
|
+
return WidgetRegistry.getInstance(widgetKey);
|
|
1844
|
+
}
|
|
1845
|
+
get widgetKey() {
|
|
1846
|
+
return this.state.widgetKey;
|
|
1847
|
+
}
|
|
1848
|
+
get widgetType() {
|
|
1849
|
+
return this.state.widgetType;
|
|
1850
|
+
}
|
|
1851
|
+
get isWidgetOpen() {
|
|
1852
|
+
return this.state.isWidgetOpen;
|
|
1853
|
+
}
|
|
1854
|
+
get containerClass() {
|
|
1855
|
+
return this.domController.containerClass;
|
|
1856
|
+
}
|
|
1857
|
+
initialize({
|
|
1858
|
+
button,
|
|
1859
|
+
icon,
|
|
1860
|
+
isButtonHidden
|
|
1861
|
+
}) {
|
|
1862
|
+
this.domController.setElements(button, icon);
|
|
1863
|
+
this.domController.setupButtonClickListener(() => this.toggleIframeVisibility());
|
|
1864
|
+
WidgetRegistry.register(this.widgetKey, this);
|
|
1865
|
+
WidgetGlobalAPI.initialize();
|
|
1866
|
+
}
|
|
1867
|
+
toggleIframeVisibility() {
|
|
1868
|
+
const wasOpen = this.state.toggleWidget();
|
|
1869
|
+
if (wasOpen) {
|
|
1870
|
+
this.openWidget();
|
|
1871
|
+
} else {
|
|
1872
|
+
this.closeWidget();
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
// Open the widget programmatically
|
|
1876
|
+
openWidget(options = {}) {
|
|
1877
|
+
this.state.openWidget();
|
|
1878
|
+
this.domController.openWidget(options);
|
|
1879
|
+
this.analyticsTracker.trackOpenWidget(options.trigger);
|
|
1880
|
+
}
|
|
1881
|
+
// Close the widget programmatically
|
|
1882
|
+
closeWidget() {
|
|
1883
|
+
this.state.closeWidget();
|
|
1884
|
+
this.domController.closeWidget();
|
|
1885
|
+
this.analyticsTracker.trackCloseWidget();
|
|
1886
|
+
}
|
|
1887
|
+
showTriggerButton() {
|
|
1888
|
+
this.domController.showTriggerButton();
|
|
1889
|
+
}
|
|
1890
|
+
hideTriggerButton() {
|
|
1891
|
+
this.domController.hideTriggerButton();
|
|
1892
|
+
}
|
|
1893
|
+
resizeContainer(height) {
|
|
1894
|
+
this.domController.resizeContainer(height);
|
|
1895
|
+
}
|
|
1896
|
+
trackCustomEvent(eventName, data = {}) {
|
|
1897
|
+
this.analyticsTracker.trackCustomEvent(eventName, data);
|
|
1898
|
+
}
|
|
1899
|
+
// Cleanup method to remove this instance
|
|
1900
|
+
destroy() {
|
|
1901
|
+
WidgetRegistry.unregister(this.widgetKey);
|
|
1902
|
+
}
|
|
1903
|
+
static initialize(options) {
|
|
1904
|
+
const instance = new IframeStateManager(options.widgetKey, options.widgetType);
|
|
1905
|
+
instance.initialize(options);
|
|
1906
|
+
return instance;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
function createTriggerButton(widgetKey, triggerButtonIcon) {
|
|
1910
|
+
const button = createElementWithClass("button", TRIGGER_BUTTON_CLASS, {
|
|
1911
|
+
id: `trigger-button-${widgetKey}`,
|
|
1912
|
+
"aria-controls": IFRAME_CONTAINER_CLASS,
|
|
1913
|
+
"aria-expanded": "false",
|
|
1914
|
+
"data-name": TRIGGER_BUTTON_CLASS
|
|
1915
|
+
});
|
|
1916
|
+
const icon = createElementWithClass("div", "trigger-button-icon", {
|
|
1917
|
+
"aria-hidden": "true"
|
|
1918
|
+
});
|
|
1919
|
+
if (!triggerButtonIcon) {
|
|
1920
|
+
icon.innerHTML = `
|
|
1921
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
1922
|
+
<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>
|
|
1923
|
+
</svg>
|
|
1924
|
+
<svg width="24" height="14" viewBox="0 0 24 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="fish-icon visible">
|
|
1925
|
+
<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"/>
|
|
1926
|
+
</svg>
|
|
1927
|
+
`;
|
|
1928
|
+
} else {
|
|
1929
|
+
icon.innerHTML = `
|
|
1930
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256" class="close-icon">
|
|
1931
|
+
<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>
|
|
1932
|
+
</svg>
|
|
1933
|
+
<img src="${triggerButtonIcon}" class="fish-icon visible" alt="Trigger button icon" height="32" width="32" aria-hidden="true" aria-label="help button icon" />
|
|
1934
|
+
`;
|
|
1935
|
+
}
|
|
1936
|
+
button.setAttribute("aria-label", "Open Brainfish widget");
|
|
1937
|
+
button.appendChild(icon);
|
|
1938
|
+
return { button, icon };
|
|
1939
|
+
}
|
|
1940
|
+
function createIframeContainer({ widgetUrl, widgetType, props }) {
|
|
1941
|
+
const containerClass = widgetType === WidgetType.Searchbar ? SEARCH_BAR_IFRAME_CONTAINER_CLASS : IFRAME_CONTAINER_CLASS;
|
|
1942
|
+
const iframeContainer = createElementWithClass(
|
|
1943
|
+
"div",
|
|
1944
|
+
containerClass,
|
|
1945
|
+
__spreadValues({
|
|
1946
|
+
id: containerClass,
|
|
1947
|
+
"aria-live": "polite",
|
|
1948
|
+
"aria-hidden": "true"
|
|
1949
|
+
}, props || {})
|
|
1950
|
+
);
|
|
1951
|
+
const loadingIndicator = createElementWithClass("div", "iframe-loading-indicator");
|
|
1952
|
+
const spinner = createElementWithClass("div", "spinner");
|
|
1953
|
+
loadingIndicator.setAttribute("aria-label", "Loading content");
|
|
1954
|
+
loadingIndicator.setAttribute("role", "status");
|
|
1955
|
+
loadingIndicator.appendChild(spinner);
|
|
1956
|
+
iframeContainer.appendChild(loadingIndicator);
|
|
1957
|
+
const iframe = createElementWithClass("iframe", "trigger-iframe", {
|
|
1958
|
+
src: widgetUrl,
|
|
1959
|
+
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms",
|
|
1960
|
+
allow: "clipboard-write",
|
|
1961
|
+
role: "dialog"
|
|
1962
|
+
});
|
|
1963
|
+
iframe.style.opacity = "0";
|
|
1964
|
+
iframe.addEventListener("load", () => {
|
|
1965
|
+
loadingIndicator.style.display = "none";
|
|
1966
|
+
iframe.style.opacity = "1";
|
|
1967
|
+
});
|
|
1968
|
+
iframe.addEventListener("error", (error) => {
|
|
1969
|
+
console.error("Error loading iframe:", error);
|
|
1970
|
+
loadingIndicator.innerHTML = "";
|
|
1971
|
+
const errorIcon = createElementWithClass("div", "loading-error");
|
|
1972
|
+
loadingIndicator.appendChild(errorIcon);
|
|
1973
|
+
loadingIndicator.setAttribute("aria-label", "Failed to load content");
|
|
1974
|
+
});
|
|
1975
|
+
iframeContainer.appendChild(iframe);
|
|
1976
|
+
return { iframeContainer, iframe };
|
|
1977
|
+
}
|
|
1978
|
+
function toggleIframeSize() {
|
|
1979
|
+
const iframeContainer = document.querySelector(
|
|
1980
|
+
`.${IFRAME_CONTAINER_CLASS}`
|
|
1981
|
+
);
|
|
1982
|
+
if (iframeContainer.classList.contains("expanded")) {
|
|
1983
|
+
iframeContainer.classList.remove("expanded");
|
|
1984
|
+
} else {
|
|
1985
|
+
iframeContainer.classList.add("expanded");
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
function initColorSchemeListener(iframe, signal) {
|
|
1989
|
+
const updateIframeBodyClass = (isDarkMode) => {
|
|
1990
|
+
var _a;
|
|
1991
|
+
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(
|
|
1992
|
+
{ type: "UPDATE_BODY_CLASS", isDarkMode },
|
|
1993
|
+
"*"
|
|
1994
|
+
);
|
|
1995
|
+
};
|
|
1996
|
+
const checkAndUpdateDarkMode = () => {
|
|
1997
|
+
const isDarkMode = document.body.classList.contains("dark");
|
|
1998
|
+
updateIframeBodyClass(isDarkMode);
|
|
1999
|
+
};
|
|
1807
2000
|
const observeBodyClassChanges = () => {
|
|
1808
2001
|
const observer = new MutationObserver(checkAndUpdateDarkMode);
|
|
1809
2002
|
observer.observe(document.body, {
|
|
@@ -1815,16 +2008,122 @@ function initColorSchemeListener(iframe, signal) {
|
|
|
1815
2008
|
checkAndUpdateDarkMode();
|
|
1816
2009
|
observeBodyClassChanges();
|
|
1817
2010
|
}
|
|
1818
|
-
|
|
2011
|
+
const clientActionHandlerMap = /* @__PURE__ */ new Map();
|
|
2012
|
+
const registerClientActionHandler = (key, handler) => {
|
|
2013
|
+
clientActionHandlerMap.set(key, handler);
|
|
2014
|
+
};
|
|
2015
|
+
const formatErrorReason = (key, err) => {
|
|
2016
|
+
const details = err instanceof Error ? err.message : String(err);
|
|
2017
|
+
return `Error executing Client Action with key ${key}. Details: ${details}`;
|
|
2018
|
+
};
|
|
2019
|
+
const isPlainObject = (obj) => {
|
|
2020
|
+
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
2021
|
+
};
|
|
2022
|
+
const executeClientActionHandler = (key, input) => __async(null, null, function* () {
|
|
2023
|
+
if (clientActionHandlerMap.has(key)) {
|
|
2024
|
+
const handler = clientActionHandlerMap.get(key);
|
|
2025
|
+
if (typeof handler !== "function") {
|
|
2026
|
+
return {
|
|
2027
|
+
success: false,
|
|
2028
|
+
reason: `Client Action registered with key ${key} is not a function`
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
try {
|
|
2032
|
+
const result = yield handler(input);
|
|
2033
|
+
if (!isPlainObject(result)) {
|
|
2034
|
+
throw new TypeError("Invalid result, expecting object type");
|
|
2035
|
+
}
|
|
2036
|
+
return {
|
|
2037
|
+
success: true,
|
|
2038
|
+
data: result
|
|
2039
|
+
};
|
|
2040
|
+
} catch (e) {
|
|
2041
|
+
return {
|
|
2042
|
+
success: false,
|
|
2043
|
+
reason: formatErrorReason(key, e)
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
return {
|
|
2048
|
+
success: false,
|
|
2049
|
+
reason: `No Client Action registered with key ${key}`
|
|
2050
|
+
};
|
|
2051
|
+
});
|
|
2052
|
+
function initMessageListener(iframe, {
|
|
2053
|
+
widgetHost,
|
|
2054
|
+
apiHost,
|
|
2055
|
+
widgetKey,
|
|
2056
|
+
widgetType,
|
|
2057
|
+
signal,
|
|
2058
|
+
stateManager
|
|
2059
|
+
}) {
|
|
2060
|
+
const messageHandler = (event) => __async(null, null, function* () {
|
|
2061
|
+
var _a;
|
|
2062
|
+
if (event.origin !== widgetHost) return;
|
|
2063
|
+
const { type, widgetKey: messageWidgetKey } = event.data;
|
|
2064
|
+
if (messageWidgetKey && messageWidgetKey !== widgetKey) return;
|
|
2065
|
+
if (type === "TOGGLE_WIDGET_SIZE") {
|
|
2066
|
+
toggleIframeSize();
|
|
2067
|
+
}
|
|
2068
|
+
if (type === "RESIZE_IFRAME") {
|
|
2069
|
+
const { height } = event.data;
|
|
2070
|
+
stateManager.resizeContainer(height);
|
|
2071
|
+
}
|
|
2072
|
+
if (type === "TRACK_EVENT") {
|
|
2073
|
+
const { eventName, data } = event.data;
|
|
2074
|
+
stateManager.trackCustomEvent(eventName, data);
|
|
2075
|
+
}
|
|
2076
|
+
if (type === "CLOSE_WIDGET") {
|
|
2077
|
+
stateManager.closeWidget();
|
|
2078
|
+
}
|
|
2079
|
+
if (type === "NEXT_BEST_ACTION_CLICKED") {
|
|
2080
|
+
const { action, searchQueryId, query, answer } = event.data;
|
|
2081
|
+
const context = { action, searchQueryId };
|
|
2082
|
+
if (!["function", "callback"].includes(action.type)) {
|
|
2083
|
+
console.error("Invalid action type", action);
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
window.__bfCallbacks = window.__bfCallbacks || {};
|
|
2087
|
+
if (window.__bfCallbacks[action.id]) {
|
|
2088
|
+
window.__bfCallbacks[action.id](query, answer, context);
|
|
2089
|
+
return;
|
|
2090
|
+
}
|
|
2091
|
+
const scriptUrl = `${apiHost}/api/searchWidgets.callback.codeblocks?apiKey=${widgetKey}&codeblockId=${action.id}`;
|
|
2092
|
+
const script = document.createElement("script");
|
|
2093
|
+
script.src = scriptUrl;
|
|
2094
|
+
document.head.appendChild(script);
|
|
2095
|
+
script.onload = () => {
|
|
2096
|
+
window.__bfCallbacks[action.id](query, answer, context);
|
|
2097
|
+
setTimeout(() => {
|
|
2098
|
+
document.head.removeChild(script);
|
|
2099
|
+
}, 300);
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
if (type === "CLIENT_EXECUTION") {
|
|
2103
|
+
const { actionKey, inputs, messageId } = event.data;
|
|
2104
|
+
const result = yield executeClientActionHandler(actionKey, inputs);
|
|
2105
|
+
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(
|
|
2106
|
+
{
|
|
2107
|
+
type: "CLIENT_EXECUTION_RESULT",
|
|
2108
|
+
messageId,
|
|
2109
|
+
result
|
|
2110
|
+
},
|
|
2111
|
+
"*"
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
});
|
|
2115
|
+
window.addEventListener("message", messageHandler, { signal });
|
|
2116
|
+
}
|
|
2117
|
+
function observeColorSchemeChanges(iframe, signal, stateManager) {
|
|
1819
2118
|
const updateIframeBodyClass = (isMobile) => {
|
|
1820
2119
|
var _a;
|
|
1821
2120
|
const message = { type: "UPDATE_BODY_CLASS", isMobile };
|
|
1822
2121
|
(_a = iframe.contentWindow) == null ? void 0 : _a.postMessage(message, "*");
|
|
1823
2122
|
if (isMobile) {
|
|
1824
|
-
if (
|
|
1825
|
-
|
|
2123
|
+
if (stateManager.isWidgetOpen) {
|
|
2124
|
+
stateManager.hideTriggerButton();
|
|
1826
2125
|
} else {
|
|
1827
|
-
|
|
2126
|
+
stateManager.showTriggerButton();
|
|
1828
2127
|
}
|
|
1829
2128
|
}
|
|
1830
2129
|
};
|
|
@@ -1847,40 +2146,9 @@ function observeColorSchemeChanges(iframe, signal) {
|
|
|
1847
2146
|
checkAndUpdateIsMobile();
|
|
1848
2147
|
observeBodyResize();
|
|
1849
2148
|
}
|
|
1850
|
-
|
|
1851
|
-
const encoder = new TextEncoder();
|
|
1852
|
-
const uint8Array = encoder.encode(text);
|
|
1853
|
-
if (typeof window !== "undefined" && typeof window.btoa === "function") {
|
|
1854
|
-
const binaryString = Array.from(
|
|
1855
|
-
uint8Array,
|
|
1856
|
-
(byte) => String.fromCharCode(byte)
|
|
1857
|
-
).join("");
|
|
1858
|
-
return btoa(binaryString);
|
|
1859
|
-
}
|
|
1860
|
-
if (typeof Buffer !== "undefined") {
|
|
1861
|
-
return Buffer.from(uint8Array).toString("base64");
|
|
1862
|
-
}
|
|
1863
|
-
throw new Error("[utils.base64Encode]: Unsupported environment");
|
|
1864
|
-
}
|
|
1865
|
-
const base64Decode = (text) => {
|
|
1866
|
-
if (typeof window !== "undefined" && typeof window.atob === "function") {
|
|
1867
|
-
const binaryString = atob(text);
|
|
1868
|
-
const len = binaryString.length;
|
|
1869
|
-
const bytes = new Uint8Array(len);
|
|
1870
|
-
for (let i = 0; i < len; i++) {
|
|
1871
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
1872
|
-
}
|
|
1873
|
-
const decoder2 = new TextDecoder();
|
|
1874
|
-
return decoder2.decode(bytes);
|
|
1875
|
-
}
|
|
1876
|
-
if (typeof Buffer !== "undefined") {
|
|
1877
|
-
return Buffer.from(text, "base64").toString("utf-8");
|
|
1878
|
-
}
|
|
1879
|
-
throw new Error("[utils.base64Decode]: Unsupported environment");
|
|
1880
|
-
};
|
|
1881
|
-
const initializedWidgets = /* @__PURE__ */ new Set();
|
|
2149
|
+
const initializedWidgets$1 = /* @__PURE__ */ new Set();
|
|
1882
2150
|
function isWidgetInitialized(widgetKey) {
|
|
1883
|
-
return initializedWidgets.has(widgetKey);
|
|
2151
|
+
return initializedWidgets$1.has(widgetKey);
|
|
1884
2152
|
}
|
|
1885
2153
|
function isButtonExisting(widgetKey) {
|
|
1886
2154
|
return !!document.getElementById(`trigger-button-${widgetKey}`);
|
|
@@ -1890,47 +2158,40 @@ function createWidgetWithButton(widgetKey, widgetUrl, {
|
|
|
1890
2158
|
triggerButtonIcon
|
|
1891
2159
|
}) {
|
|
1892
2160
|
const fragment = document.createDocumentFragment();
|
|
2161
|
+
let stateManager;
|
|
1893
2162
|
if (!isButtonHidden) {
|
|
1894
2163
|
const { button, icon } = createTriggerButton(widgetKey, triggerButtonIcon);
|
|
1895
2164
|
fragment.appendChild(button);
|
|
1896
|
-
IframeStateManager.initialize({
|
|
2165
|
+
stateManager = IframeStateManager.initialize({
|
|
2166
|
+
button,
|
|
2167
|
+
icon,
|
|
2168
|
+
widgetType: WidgetType.Popup,
|
|
2169
|
+
widgetKey
|
|
2170
|
+
});
|
|
1897
2171
|
} else {
|
|
1898
|
-
IframeStateManager.initialize({
|
|
2172
|
+
stateManager = IframeStateManager.initialize({
|
|
2173
|
+
isButtonHidden,
|
|
2174
|
+
widgetType: WidgetType.Popup,
|
|
2175
|
+
widgetKey
|
|
2176
|
+
});
|
|
1899
2177
|
}
|
|
1900
|
-
const { iframeContainer, iframe } = createIframeContainer(widgetUrl);
|
|
2178
|
+
const { iframeContainer, iframe } = createIframeContainer({ widgetUrl, widgetType: WidgetType.Popup });
|
|
1901
2179
|
fragment.appendChild(iframeContainer);
|
|
1902
|
-
return { fragment, iframe };
|
|
2180
|
+
return { fragment, iframe, stateManager };
|
|
1903
2181
|
}
|
|
1904
|
-
function handleInitializationError(apiHost, error, widgetKey) {
|
|
2182
|
+
function handleInitializationError$1(apiHost, error, widgetKey) {
|
|
1905
2183
|
sendBrainfishWidgetError(apiHost, error, error.message, widgetKey);
|
|
1906
2184
|
}
|
|
1907
|
-
const
|
|
1908
|
-
|
|
1909
|
-
const apiHost = getApiHost(options.overrides);
|
|
1910
|
-
const widgetHost = getWidgetHost(options.overrides);
|
|
1911
|
-
const { theme, settings } = config;
|
|
1912
|
-
const encodedRules = base64Encode(
|
|
1913
|
-
JSON.stringify((_a = options.overrides) == null ? void 0 : _a.redirectRules)
|
|
1914
|
-
);
|
|
1915
|
-
const widgetParams = {
|
|
1916
|
-
theme: base64Encode(JSON.stringify(theme)),
|
|
1917
|
-
settings: base64Encode(JSON.stringify(settings)),
|
|
1918
|
-
redirectRules: encodedRules
|
|
1919
|
-
};
|
|
1920
|
-
if ((_b = options.overrides) == null ? void 0 : _b.regions) {
|
|
1921
|
-
widgetParams.regions = base64Encode(
|
|
1922
|
-
JSON.stringify((_c = options.overrides) == null ? void 0 : _c.regions)
|
|
1923
|
-
);
|
|
1924
|
-
}
|
|
1925
|
-
const widgetUrl = `${widgetHost}/?widgetKey=${options.widgetKey}#${new URLSearchParams(widgetParams).toString()}`;
|
|
2185
|
+
const initWidgetButton = ({ config, widgetUrl, apiHost, widgetHost, widgetKey }) => {
|
|
2186
|
+
const { settings } = config;
|
|
1926
2187
|
const isButtonHidden = settings == null ? void 0 : settings.hideTriggerButton;
|
|
1927
2188
|
const triggerButtonIcon = settings == null ? void 0 : settings.triggerButtonIcon;
|
|
1928
2189
|
try {
|
|
1929
|
-
if (isWidgetInitialized(
|
|
1930
|
-
if (isButtonExisting(
|
|
2190
|
+
if (isWidgetInitialized(widgetKey)) return void 0;
|
|
2191
|
+
if (isButtonExisting(widgetKey)) return void 0;
|
|
1931
2192
|
insertStylesIfNeeded(config);
|
|
1932
|
-
const { fragment, iframe } = createWidgetWithButton(
|
|
1933
|
-
|
|
2193
|
+
const { fragment, iframe, stateManager } = createWidgetWithButton(
|
|
2194
|
+
widgetKey,
|
|
1934
2195
|
widgetUrl,
|
|
1935
2196
|
{
|
|
1936
2197
|
isButtonHidden: isButtonHidden || false,
|
|
@@ -1945,14 +2206,98 @@ const initIframeTrigger = (options, config) => {
|
|
|
1945
2206
|
initMessageListener(iframe, {
|
|
1946
2207
|
widgetHost,
|
|
1947
2208
|
apiHost,
|
|
1948
|
-
widgetKey
|
|
1949
|
-
|
|
2209
|
+
widgetKey,
|
|
2210
|
+
widgetType: WidgetType.Popup,
|
|
2211
|
+
signal,
|
|
2212
|
+
stateManager
|
|
1950
2213
|
});
|
|
1951
|
-
observeColorSchemeChanges(iframe, signal);
|
|
2214
|
+
observeColorSchemeChanges(iframe, signal, stateManager);
|
|
1952
2215
|
}, 0);
|
|
1953
2216
|
};
|
|
1954
2217
|
document.body.appendChild(fragment);
|
|
1955
|
-
initializedWidgets.add(
|
|
2218
|
+
initializedWidgets$1.add(widgetKey);
|
|
2219
|
+
const cleanup = () => {
|
|
2220
|
+
controller.abort();
|
|
2221
|
+
window.removeEventListener("beforeunload", cleanup);
|
|
2222
|
+
};
|
|
2223
|
+
window.addEventListener("beforeunload", cleanup);
|
|
2224
|
+
return void 0;
|
|
2225
|
+
} catch (error) {
|
|
2226
|
+
handleInitializationError$1(apiHost, error, widgetKey);
|
|
2227
|
+
}
|
|
2228
|
+
};
|
|
2229
|
+
function createSearchTrigger({ widgetKey, settings }) {
|
|
2230
|
+
const searchBar = document.querySelector(SEARCH_BAR_SELECTOR);
|
|
2231
|
+
if (!searchBar) return void 0;
|
|
2232
|
+
searchBar.setAttribute("data-widget-key", widgetKey);
|
|
2233
|
+
searchBar.setAttribute("tabindex", "0");
|
|
2234
|
+
const placeholderText = (settings == null ? void 0 : settings.placeholder) || "Ask your question here...";
|
|
2235
|
+
searchBar.setAttribute("data-placeholder", placeholderText);
|
|
2236
|
+
searchBar.setAttribute("aria-label", `${placeholderText} - Click to open search`);
|
|
2237
|
+
searchBar.setAttribute("role", "button");
|
|
2238
|
+
searchBar.setAttribute("aria-expanded", "false");
|
|
2239
|
+
searchBar.setAttribute("aria-haspopup", "dialog");
|
|
2240
|
+
return searchBar;
|
|
2241
|
+
}
|
|
2242
|
+
function handleInitializationError(apiHost, error, widgetKey) {
|
|
2243
|
+
sendBrainfishWidgetError(apiHost, error, error.message, widgetKey);
|
|
2244
|
+
}
|
|
2245
|
+
function isSearchBarExisting(widgetKey) {
|
|
2246
|
+
return !!document.querySelector(`.${SEARCH_BAR_IFRAME_CONTAINER_CLASS}[data-widget-key="${widgetKey}"]`);
|
|
2247
|
+
}
|
|
2248
|
+
const initSearchBar = ({ config, widgetUrl, apiHost, widgetHost, widgetKey }) => {
|
|
2249
|
+
const { settings } = config;
|
|
2250
|
+
let stateManager = IframeStateManager.getInstance(widgetKey);
|
|
2251
|
+
const controller = new AbortController();
|
|
2252
|
+
const searchBar = createSearchTrigger({ widgetKey, settings });
|
|
2253
|
+
if (!searchBar) return void 0;
|
|
2254
|
+
insertStylesIfNeeded(config);
|
|
2255
|
+
try {
|
|
2256
|
+
if (!isSearchBarExisting(widgetKey)) {
|
|
2257
|
+
const fragment = document.createDocumentFragment();
|
|
2258
|
+
if (!stateManager) {
|
|
2259
|
+
stateManager = IframeStateManager.initialize({
|
|
2260
|
+
isButtonHidden: true,
|
|
2261
|
+
widgetType: WidgetType.Searchbar,
|
|
2262
|
+
widgetKey
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
const { iframeContainer, iframe } = createIframeContainer({
|
|
2266
|
+
widgetUrl,
|
|
2267
|
+
widgetType: WidgetType.Searchbar,
|
|
2268
|
+
props: {
|
|
2269
|
+
"data-widget-type": "searchbar",
|
|
2270
|
+
"data-widget-key": widgetKey
|
|
2271
|
+
}
|
|
2272
|
+
});
|
|
2273
|
+
const { signal } = controller;
|
|
2274
|
+
iframe.onload = () => {
|
|
2275
|
+
setTimeout(() => {
|
|
2276
|
+
initColorSchemeListener(iframe, signal);
|
|
2277
|
+
initMessageListener(iframe, {
|
|
2278
|
+
widgetHost,
|
|
2279
|
+
apiHost,
|
|
2280
|
+
widgetKey,
|
|
2281
|
+
widgetType: WidgetType.Searchbar,
|
|
2282
|
+
signal,
|
|
2283
|
+
stateManager
|
|
2284
|
+
});
|
|
2285
|
+
observeColorSchemeChanges(iframe, signal, stateManager);
|
|
2286
|
+
}, 0);
|
|
2287
|
+
};
|
|
2288
|
+
fragment.appendChild(iframeContainer);
|
|
2289
|
+
document.body.appendChild(fragment);
|
|
2290
|
+
}
|
|
2291
|
+
const displaySearchBar = () => {
|
|
2292
|
+
WidgetGlobalAPI.closeCurrentlyOpenWidget();
|
|
2293
|
+
stateManager == null ? void 0 : stateManager.openWidget({ newConversation: true });
|
|
2294
|
+
};
|
|
2295
|
+
searchBar.onclick = () => {
|
|
2296
|
+
displaySearchBar();
|
|
2297
|
+
};
|
|
2298
|
+
searchBar.onfocus = () => {
|
|
2299
|
+
displaySearchBar();
|
|
2300
|
+
};
|
|
1956
2301
|
const cleanup = () => {
|
|
1957
2302
|
controller.abort();
|
|
1958
2303
|
window.removeEventListener("beforeunload", cleanup);
|
|
@@ -1960,7 +2305,32 @@ const initIframeTrigger = (options, config) => {
|
|
|
1960
2305
|
window.addEventListener("beforeunload", cleanup);
|
|
1961
2306
|
return void 0;
|
|
1962
2307
|
} catch (error) {
|
|
1963
|
-
handleInitializationError(apiHost, error,
|
|
2308
|
+
handleInitializationError(apiHost, error, widgetKey);
|
|
2309
|
+
}
|
|
2310
|
+
};
|
|
2311
|
+
const initIframeTrigger = (options, config) => {
|
|
2312
|
+
var _a, _b, _c;
|
|
2313
|
+
const apiHost = getApiHost(options.overrides);
|
|
2314
|
+
const widgetHost = getWidgetHost(options.overrides);
|
|
2315
|
+
const { theme, settings } = config;
|
|
2316
|
+
const encodedRules = base64Encode(
|
|
2317
|
+
JSON.stringify((_a = options.overrides) == null ? void 0 : _a.redirectRules)
|
|
2318
|
+
);
|
|
2319
|
+
const widgetParams = {
|
|
2320
|
+
theme: base64Encode(JSON.stringify(theme)),
|
|
2321
|
+
settings: base64Encode(JSON.stringify(settings)),
|
|
2322
|
+
redirectRules: encodedRules
|
|
2323
|
+
};
|
|
2324
|
+
if ((_b = options.overrides) == null ? void 0 : _b.regions) {
|
|
2325
|
+
widgetParams.regions = base64Encode(
|
|
2326
|
+
JSON.stringify((_c = options.overrides) == null ? void 0 : _c.regions)
|
|
2327
|
+
);
|
|
2328
|
+
}
|
|
2329
|
+
const widgetUrl = `${widgetHost}/?widgetKey=${options.widgetKey}#${new URLSearchParams(widgetParams).toString()}`;
|
|
2330
|
+
if (config.widgetType === "Search") {
|
|
2331
|
+
initSearchBar({ config, widgetUrl, apiHost, widgetHost, widgetKey: options.widgetKey });
|
|
2332
|
+
} else {
|
|
2333
|
+
initWidgetButton({ config, widgetUrl, apiHost, widgetHost, widgetKey: options.widgetKey });
|
|
1964
2334
|
}
|
|
1965
2335
|
return void 0;
|
|
1966
2336
|
};
|
|
@@ -2028,6 +2398,45 @@ const initNudgeWidget = (apiHost, widgetKey) => __async(null, null, function* ()
|
|
|
2028
2398
|
);
|
|
2029
2399
|
}
|
|
2030
2400
|
});
|
|
2401
|
+
let routeChangeController = void 0;
|
|
2402
|
+
let isHistoryPatched = false;
|
|
2403
|
+
let originalPushState;
|
|
2404
|
+
let originalReplaceState;
|
|
2405
|
+
const listenToRouteChanges = (handler) => {
|
|
2406
|
+
routeChangeController == null ? void 0 : routeChangeController.abort();
|
|
2407
|
+
routeChangeController = new AbortController();
|
|
2408
|
+
const { signal } = routeChangeController;
|
|
2409
|
+
let currentPath = window.location.pathname;
|
|
2410
|
+
const onRouteChange = () => {
|
|
2411
|
+
if (signal.aborted) return;
|
|
2412
|
+
const newPath = window.location.pathname;
|
|
2413
|
+
if (newPath !== currentPath) {
|
|
2414
|
+
currentPath = newPath;
|
|
2415
|
+
handler();
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
window.addEventListener("popstate", onRouteChange, { signal });
|
|
2419
|
+
if (!isHistoryPatched) {
|
|
2420
|
+
originalPushState = history.pushState;
|
|
2421
|
+
originalReplaceState = history.replaceState;
|
|
2422
|
+
history.pushState = function(...args) {
|
|
2423
|
+
originalPushState.apply(this, args);
|
|
2424
|
+
setTimeout(onRouteChange, 0);
|
|
2425
|
+
};
|
|
2426
|
+
history.replaceState = function(...args) {
|
|
2427
|
+
originalReplaceState.apply(this, args);
|
|
2428
|
+
setTimeout(onRouteChange, 0);
|
|
2429
|
+
};
|
|
2430
|
+
isHistoryPatched = true;
|
|
2431
|
+
}
|
|
2432
|
+
signal.addEventListener("abort", () => {
|
|
2433
|
+
if (isHistoryPatched) {
|
|
2434
|
+
history.pushState = originalPushState;
|
|
2435
|
+
history.replaceState = originalReplaceState;
|
|
2436
|
+
isHistoryPatched = false;
|
|
2437
|
+
}
|
|
2438
|
+
});
|
|
2439
|
+
};
|
|
2031
2440
|
let globalBrainfish = null;
|
|
2032
2441
|
function getBrainfishInstance() {
|
|
2033
2442
|
if (typeof window !== "undefined" && window.Brainfish) {
|
|
@@ -2042,15 +2451,35 @@ function getBrainfishInstance() {
|
|
|
2042
2451
|
return globalBrainfish;
|
|
2043
2452
|
}
|
|
2044
2453
|
const Brainfish = getBrainfishInstance();
|
|
2045
|
-
|
|
2454
|
+
const initializationPromises = /* @__PURE__ */ new Map();
|
|
2455
|
+
const initializedWidgets = /* @__PURE__ */ new Map();
|
|
2456
|
+
let routeChangeListenerSetup = false;
|
|
2046
2457
|
function initializeBrainfish(options, config, apiHost, analyticsApiHost) {
|
|
2047
2458
|
return __async(this, null, function* () {
|
|
2048
2459
|
var _a, _b, _c, _d, _e, _f;
|
|
2049
2460
|
const enableRecording = ((_a = options.overrides) == null ? void 0 : _a.enableRecording) || ((_b = config == null ? void 0 : config.settings) == null ? void 0 : _b.enableRecording) || false;
|
|
2050
2461
|
const requestedVersion = ((_c = options.overrides) == null ? void 0 : _c.version) || (config == null ? void 0 : config.version);
|
|
2462
|
+
initializedWidgets.set(options.widgetKey, {
|
|
2463
|
+
options,
|
|
2464
|
+
config,
|
|
2465
|
+
apiHost,
|
|
2466
|
+
analyticsApiHost
|
|
2467
|
+
});
|
|
2051
2468
|
const initPromises = [];
|
|
2052
2469
|
if (requestedVersion == null ? void 0 : requestedVersion.startsWith("2.")) {
|
|
2053
2470
|
initIframeTrigger(options, config);
|
|
2471
|
+
if (!routeChangeListenerSetup) {
|
|
2472
|
+
routeChangeListenerSetup = true;
|
|
2473
|
+
listenToRouteChanges(() => {
|
|
2474
|
+
initializedWidgets.forEach(({ options: widgetOptions, config: widgetConfig }) => {
|
|
2475
|
+
var _a2;
|
|
2476
|
+
const widgetVersion = ((_a2 = widgetOptions.overrides) == null ? void 0 : _a2.version) || (widgetConfig == null ? void 0 : widgetConfig.version);
|
|
2477
|
+
if (widgetVersion == null ? void 0 : widgetVersion.startsWith("2.")) {
|
|
2478
|
+
initIframeTrigger(widgetOptions, widgetConfig);
|
|
2479
|
+
}
|
|
2480
|
+
});
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2054
2483
|
} else {
|
|
2055
2484
|
initPromises.push(initSearchWidget(options, config));
|
|
2056
2485
|
}
|
|
@@ -2126,6 +2555,7 @@ Brainfish.Widgets.init = (options) => __async(null, null, function* () {
|
|
|
2126
2555
|
});
|
|
2127
2556
|
config = fetchedConfig;
|
|
2128
2557
|
}
|
|
2558
|
+
let initializationPromise = initializationPromises.get(options.widgetKey);
|
|
2129
2559
|
if (!initializationPromise) {
|
|
2130
2560
|
initializationPromise = initializeBrainfish(
|
|
2131
2561
|
options,
|
|
@@ -2133,6 +2563,7 @@ Brainfish.Widgets.init = (options) => __async(null, null, function* () {
|
|
|
2133
2563
|
apiHost,
|
|
2134
2564
|
analyticsApiHost
|
|
2135
2565
|
);
|
|
2566
|
+
initializationPromises.set(options.widgetKey, initializationPromise);
|
|
2136
2567
|
}
|
|
2137
2568
|
yield initializationPromise;
|
|
2138
2569
|
yield initHandOffs(config);
|