@sherpahow/sherpa-sdk
Version:
Sherpa JavaScript SDK for in-app help and product tours. Built with TypeScript, Lit web components, and Nano Stores.
784 lines (783 loc) • 35 kB
JavaScript
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e2) {
reject(e2);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e2) {
reject(e2);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
function t(...t2) {
const [e2, ...n2] = t2;
switch (g || (g = new SherpaSDK()), e2) {
case "boot":
const [t3, e3] = n2;
g.boot(t3, e3);
break;
case "shutdown":
g.shutdown();
break;
case "startTour":
const [i2, s2, o2] = n2;
g.startTour(i2, s2, o2);
break;
case "endTour":
g.endTour();
break;
case "showSearch":
g.showSearch();
break;
case "hideSearch":
g.hideSearch();
break;
case "openDocs":
const [a2, r2] = n2;
g.openDocs(a2, r2);
break;
case "closeDocs":
const [c2] = n2;
g.closeDocs(c2);
break;
case "closeAllDocs":
g.closeAllDocs();
break;
case "track":
const [h2, u2] = n2;
g.track(h2, u2);
break;
case "updateUser":
const [d2, w2] = n2;
g.updateUser(d2, w2);
break;
case "onTourStarted":
const [l2] = n2;
g.onTourStarted(l2);
break;
case "onTourEnded":
const [p2] = n2;
g.onTourEnded(p2);
break;
case "onStepChanged":
const [m2] = n2;
g.onStepChanged(m2);
break;
case "onShowSearch":
const [f2] = n2;
g.onSearchShown(f2);
break;
case "onHideSearch":
const [y] = n2;
g.onSearchHidden(y);
break;
case "clearCallbacks":
g.clearCallbacks();
}
}
import { T as e, t as n, u as i, c as s, a as o, i as a, b as r, d as c } from "./sherpa-search-components-0.0.13.DiA6EslJ.min.js";
import { c as h, b as u, d } from "./sherpa-guide-components-0.0.13.BkF4XA9G.min.js";
class w {
constructor() {
this.guideComponentsLoaded = null, this.searchComponentLoaded = null, this.docs = /* @__PURE__ */ new Map(), this.storeUnsubscribers = [], this.handleApplyRecommendation = (t2) => __async(this, null, function* () {
const e2 = t2, { stepId: n2 } = e2.detail;
yield this.tourController.applyRecommendation(n2);
}), this.handleNextStep = () => __async(this, null, function* () {
yield this.tourController.nextStep();
}), this.handlePreviousStep = () => __async(this, null, function* () {
yield this.tourController.previousStep();
}), this.handleGoToStep = (t2) => __async(this, null, function* () {
const e2 = t2, { stepId: n2 } = e2.detail;
yield this.tourController.goToStep(n2);
}), this.handleEndTour = () => __async(this, null, function* () {
yield this.tourController.endTour();
}), this.handleCloseTooltip = () => __async(this, null, function* () {
this.hideTooltip();
}), this.handleDocsClose = (t2) => {
const e2 = t2, { documentId: n2 } = e2.detail;
n2 && this.closeDocs(n2);
}, this.handleDocsOpen = (t2) => __async(this, null, function* () {
const e2 = t2, { docs: n2 } = e2.detail;
try {
yield this.openDocs(n2);
} catch (i2) {
}
}), this.tourController = e.getInstance(), this.guideComponentsLoadedPromise = this.ensureGuideComponents(), this.searchComponentsLoadedPromise = this.ensureSearchComponent(), this.setupStoreSubscriptions(), this.setupEventListeners();
}
static getInstance() {
return w.instance || (w.instance = new w()), w.instance;
}
ensureGuideComponents() {
return __async(this, null, function* () {
return this.guideComponentsLoaded || (this.guideComponentsLoaded = Promise.all([import("./sherpa-guide-components-0.0.13.BkF4XA9G.min.js").then((t2) => t2.j), import("./sherpa-guide-components-0.0.13.BkF4XA9G.min.js").then((t2) => t2.k), import("./sherpa-guide-components-0.0.13.BkF4XA9G.min.js").then((t2) => t2.l), import("./sherpa-guide-components-0.0.13.BkF4XA9G.min.js").then((t2) => t2.m)]).then(() => {
}).catch((t2) => {
throw this.guideComponentsLoaded = null, t2;
}).then(() => {
})), this.guideComponentsLoaded;
});
}
ensureSearchComponent() {
return __async(this, null, function* () {
return this.searchComponentLoaded || (this.searchComponentLoaded = Promise.all([import("./sherpa-search-components-0.0.13.DiA6EslJ.min.js").then((t2) => t2.f)]).then(() => {
}).catch((t2) => {
throw this.searchComponentLoaded = null, t2;
})), this.searchComponentLoaded;
});
}
setupStoreSubscriptions() {
return __async(this, null, function* () {
yield this.guideComponentsLoadedPromise, yield this.searchComponentsLoadedPromise;
const t2 = n.subscribe((t3) => {
t3.isActive ? (this.closeAllDocs(), this.showControlPanel().catch(() => {
})) : this.performTourEndCleanup();
}), e2 = i.subscribe((t3) => {
t3.currentTooltip ? this.showTooltip(t3.currentTooltip.stepId, t3.currentTooltip.element, t3.currentTooltip.guide, t3.currentTooltip.isPersonalizing).catch(() => {
}) : this.hideTooltip(), t3.currentBeacon ? this.showBeacon(t3.currentBeacon.stepId, t3.currentBeacon.element).catch(() => {
}) : this.hideBeacon(), t3.controlPanelVisible ? this.showControlPanel().catch(() => {
}) : this.hideControlPanel(), t3.searchVisible ? this.showSearch().catch(() => {
}) : this.hideSearch();
});
this.storeUnsubscribers.push(t2, e2);
});
}
setupEventListeners() {
return __async(this, null, function* () {
yield Promise.all([this.guideComponentsLoadedPromise, this.searchComponentsLoadedPromise]), document.addEventListener("apply-recommendation", this.handleApplyRecommendation), document.addEventListener("next-step", this.handleNextStep), document.addEventListener("previous-step", this.handlePreviousStep), document.addEventListener("go-to-step", this.handleGoToStep), document.addEventListener("end-tour", this.handleEndTour), document.addEventListener("close-tooltip", this.handleCloseTooltip), document.addEventListener("close-docs", this.handleDocsClose);
});
}
showTooltip(t2, e2, i2, o2) {
return __async(this, null, function* () {
if (yield this.guideComponentsLoadedPromise, this.hideTooltip(), this.hideBeacon(), !n.get().isActive) return;
const a2 = document.createElement("sherpa-tooltip");
a2.stepId = t2, a2.targetElement = e2, a2.guide = i2, a2.isPersonalizing = o2 || 0, a2.step = s.get(), document.body.appendChild(a2), this.currentTooltip = a2;
});
}
hideTooltip() {
this.currentTooltip && (this.currentTooltip.remove(), this.currentTooltip = void 0, o.hideTooltip()), document.querySelectorAll("sherpa-tooltip").forEach((t2) => {
t2.remove();
});
}
updateTooltipPersonalizingState(t2) {
this.currentTooltip && (this.currentTooltip.isPersonalizing = t2);
}
showBeacon(t2, e2) {
return __async(this, null, function* () {
if (yield this.guideComponentsLoadedPromise, this.hideBeacon(), this.hideTooltip(), !n.get().isActive) return;
const i2 = document.createElement("sherpa-beacon");
i2.stepId = t2, i2.targetElement = e2, this.addTargetElementHighlight(e2), this.makeElementClickableForBeacon(e2), document.body.appendChild(i2), this.currentBeacon = i2;
});
}
hideBeacon() {
if (this.currentBeacon) {
const t2 = this.currentBeacon;
t2.targetElement && (this.removeTargetElementHighlight(t2.targetElement), this.removeBeaconClickableState(t2.targetElement)), this.currentBeacon.remove(), this.currentBeacon = void 0, o.hideBeacon();
}
document.querySelectorAll("sherpa-beacon").forEach((t2) => {
t2.remove();
});
}
addTargetElementHighlight(t2) {
const e2 = t2, n2 = e2.style.boxShadow, i2 = e2.style.transition;
e2.dataset.sherpaOriginalBoxShadow = n2, e2.dataset.sherpaOriginalTransition = i2, e2.dataset.sherpaHighlighted = "true", e2.style.transition = "box-shadow 0.3s ease-in-out", e2.style.boxShadow = "\n ".concat(n2 ? n2 + ", " : "", "\n 0 0 0 2px rgba(34, 197, 94, 0.6),\n 0 0 0 4px rgba(34, 197, 94, 0.3),\n 0 0 20px rgba(34, 197, 94, 0.2)\n ");
const s2 = document.createElement("style");
s2.id = "sherpa-target-highlight-animation", s2.textContent = "\n @keyframes sherpa-target-pulse {\n 0%, 100% {\n box-shadow: ".concat(n2 ? n2 + ", " : "", "\n 0 0 0 2px rgba(34, 197, 94, 0.6),\n 0 0 0 4px rgba(34, 197, 94, 0.3),\n 0 0 20px rgba(34, 197, 94, 0.2);\n }\n 50% {\n box-shadow: ").concat(n2 ? n2 + ", " : "", '\n 0 0 0 2px rgba(34, 197, 94, 0.8),\n 0 0 0 6px rgba(34, 197, 94, 0.4),\n 0 0 30px rgba(34, 197, 94, 0.3);\n }\n }\n \n [data-sherpa-highlighted="true"] {\n animation: sherpa-target-pulse 2s ease-in-out infinite;\n }\n\n @media (prefers-reduced-motion: reduce) {\n [data-sherpa-highlighted="true"] {\n animation: none;\n }\n }\n '), document.getElementById("sherpa-target-highlight-animation") || document.head.appendChild(s2);
}
removeTargetElementHighlight(t2) {
const e2 = t2;
"true" === e2.dataset.sherpaHighlighted && (e2.style.boxShadow = e2.dataset.sherpaOriginalBoxShadow || "", e2.style.transition = e2.dataset.sherpaOriginalTransition || "", delete e2.dataset.sherpaOriginalBoxShadow, delete e2.dataset.sherpaOriginalTransition, delete e2.dataset.sherpaHighlighted);
}
makeElementClickableForBeacon(t2) {
const e2 = t2, n2 = e2.style.cursor;
e2.dataset.sherpaOriginalPointerEvents = e2.style.pointerEvents, e2.dataset.sherpaOriginalCursor = n2, e2.dataset.sherpaBeaconClickable = "true", "none" === e2.style.pointerEvents && (e2.style.pointerEvents = "auto"), e2.style.cursor = "pointer";
}
removeBeaconClickableState(t2) {
const e2 = t2;
"true" === e2.dataset.sherpaBeaconClickable && (e2.style.pointerEvents = e2.dataset.sherpaOriginalPointerEvents || "", e2.style.cursor = e2.dataset.sherpaOriginalCursor || "", delete e2.dataset.sherpaOriginalPointerEvents, delete e2.dataset.sherpaOriginalCursor, delete e2.dataset.sherpaBeaconClickable);
}
showControlPanel() {
return __async(this, null, function* () {
if (yield this.guideComponentsLoadedPromise, this.currentControlPanel) return;
const t2 = document.createElement("sherpa-control-panel"), e2 = () => {
t2.tourState = n.get(), t2.isFirstStep = a.get(), t2.isLastStep = r.get(), t2.progress = c.get();
};
e2();
const i2 = [n.subscribe(e2), a.subscribe(e2), r.subscribe(e2), c.subscribe(e2)];
t2.t = i2, document.body.appendChild(t2), this.currentControlPanel = t2;
});
}
hideControlPanel() {
if (this.currentControlPanel) {
const t2 = this.currentControlPanel.t;
t2 && t2.forEach((t3) => t3()), this.currentControlPanel.remove(), this.currentControlPanel = void 0;
}
}
showSearch() {
return __async(this, null, function* () {
try {
if (yield this.searchComponentsLoadedPromise, this.currentSearch) return;
const t2 = document.createElement("sherpa-search");
t2.addEventListener("docs-open", this.handleDocsOpen.bind(this)), document.body.appendChild(t2), this.currentSearch = t2;
} catch (t2) {
throw t2;
}
});
}
hideSearch() {
this.currentSearch && (this.currentSearch.remove(), this.currentSearch = void 0);
}
getNextDocsPosition() {
const t2 = (window.innerWidth - 400) / 2, e2 = (window.innerHeight - 500) / 2, n2 = window.innerWidth - 450, i2 = window.innerHeight - 550;
return { x: Math.max(50, Math.min(t2, n2)), y: Math.max(50, Math.min(e2, i2)) };
}
openDocs(t2, e2) {
return __async(this, null, function* () {
yield this.guideComponentsLoadedPromise, this.closeAllDocs();
const n2 = (e2 == null ? void 0 : e2.position) || this.getNextDocsPosition(), i2 = document.createElement("sherpa-docs");
i2.document = t2, i2.initialPosition = n2, i2.style.position = "fixed", i2.style.top = "0", i2.style.left = "0", i2.style.width = "100%", i2.style.height = "100%", i2.style.pointerEvents = "none", document.body.appendChild(i2), requestAnimationFrame(() => {
i2.visible = 1;
}), this.docs.set(t2.id, { document: t2, position: n2, size: "Medium", element: i2 });
});
}
closeDocs(t2) {
const e2 = this.docs.get(t2);
e2 && e2.element && e2.element.remove(), this.docs.delete(t2);
}
closeAllDocs() {
this.docs.forEach((t2) => {
t2.element && t2.element.remove();
}), this.docs.clear();
}
bringDocsToFront(t2) {
const e2 = this.docs.get(t2);
e2 && this.docs.set(t2, e2);
}
hasOpenDocs() {
return this.docs.size > 0;
}
getOpenDocsIds() {
return Array.from(this.docs.keys());
}
getDocsState(t2) {
return this.docs.get(t2);
}
performTourEndCleanup() {
this.hideTooltip(), this.hideBeacon(), this.hideControlPanel(), this.closeAllDocs(), this.cleanupAnimationStyles(), this.cleanupAllElementHighlights(), this.showSearch().catch(() => {
});
}
cleanupAnimationStyles() {
const t2 = document.getElementById("sherpa-target-highlight-animation");
t2 && t2.remove();
}
cleanupAllElementHighlights() {
document.querySelectorAll('[data-sherpa-highlighted="true"]').forEach((t2) => {
this.removeTargetElementHighlight(t2);
}), document.querySelectorAll('[data-sherpa-beacon-clickable="true"]').forEach((t2) => {
this.removeBeaconClickableState(t2);
});
}
resetComponentLoadingPromises() {
this.guideComponentsLoaded = null, this.searchComponentLoaded = null;
}
cleanupStoreSubscriptions() {
this.storeUnsubscribers.forEach((t2) => {
try {
t2();
} catch (e2) {
}
}), this.storeUnsubscribers = [];
}
static resetInstance() {
w.instance && (w.instance.destroy(), w.instance = null);
}
destroy() {
this.hideTooltip(), this.hideBeacon(), this.hideControlPanel(), this.hideSearch(), this.closeAllDocs(), this.cleanupAnimationStyles(), this.cleanupAllElementHighlights(), this.cleanupStoreSubscriptions(), this.resetComponentLoadingPromises(), document.removeEventListener("apply-recommendation", this.handleApplyRecommendation), document.removeEventListener("next-step", this.handleNextStep), document.removeEventListener("previous-step", this.handlePreviousStep), document.removeEventListener("go-to-step", this.handleGoToStep), document.removeEventListener("end-tour", this.handleEndTour), document.removeEventListener("close-tooltip", this.handleCloseTooltip), document.removeEventListener("close-docs", this.handleDocsClose);
}
getDebugInfo() {
return { hasTooltip: !!this.currentTooltip, hasBeacon: !!this.currentBeacon, hasControlPanel: !!this.currentControlPanel, hasSearch: !!this.currentSearch, openDocs: this.getOpenDocsIds(), docsCount: this.docs.size, tourState: n.get(), uiState: i.get() };
}
}
class l {
constructor(t2, e2) {
this.navigateFunction = t2, this.location = e2;
}
navigate(t2) {
return __async(this, null, function* () {
const e2 = this.capturePageState();
try {
let n2;
if (t2.startsWith("http://") || t2.startsWith("https://")) {
const e3 = new URL(t2);
n2 = e3.pathname + e3.search + e3.hash;
} else n2 = t2;
if (this.navigateFunction(n2), !(yield this.verifyNavigation(t2, n2, e2))) throw Error("React Router navigation verification failed - content may not have loaded");
} catch (n2) {
yield this.fallbackToFullPageNavigation(t2);
}
});
}
getCurrentUrl() {
return window.location.origin + this.location.pathname + this.location.search + this.location.hash;
}
canHandle(t2) {
try {
return t2.startsWith("http://") || t2.startsWith("https://") ? new URL(t2).origin === window.location.origin : 1;
} catch (e2) {
return 0;
}
}
updateLocation(t2) {
this.location = t2;
}
capturePageState() {
return { url: window.location.href, path: window.location.pathname + window.location.search + window.location.hash, title: document.title, bodyHash: this.generateContentHash(document.body), timestamp: Date.now() };
}
generateContentHash(t2) {
const e2 = t2.textContent || "", n2 = t2.querySelectorAll("*").length, i2 = t2.querySelectorAll("script").length, s2 = t2.querySelectorAll("a").length, o2 = "".concat(e2.length, "-").concat(n2, "-").concat(i2, "-").concat(s2);
let a2 = 0;
for (let r2 = 0; o2.length > r2; r2++) a2 = (a2 << 5) - a2 + o2.charCodeAt(r2), a2 &= a2;
return "" + a2;
}
verifyNavigation(t2, e2, n2) {
return __async(this, null, function* () {
for (let s2 = 0; 25 > s2; s2++) {
yield this.delay(250);
const i3 = this.capturePageState();
if (this.checkUrlMatch(i3.url, i3.path, t2, e2)) {
if (i3.bodyHash !== n2.bodyHash || i3.title !== n2.title || 3 > s2) return 1;
if (s2 > 10 && (yield this.checkForReactContent(n2))) return 1;
}
}
const i2 = this.capturePageState();
return this.checkUrlMatch(i2.url, i2.path, t2, e2) ? 1 : 0;
});
}
checkUrlMatch(t2, e2, n2, i2) {
if (t2 === n2) return 1;
if (e2 === i2) return 1;
const s2 = (t3) => t3.replace(/\/+$/, "") || "/";
if (s2(e2) === s2(i2)) return 1;
const o2 = e2.split("?")[0].split("#")[0], a2 = i2.split("?")[0].split("#")[0];
return s2(o2) === s2(a2) ? 1 : 0;
}
checkForReactContent(t2) {
return __async(this, null, function* () {
yield this.delay(500);
const e2 = this.capturePageState();
return [e2.bodyHash !== t2.bodyHash, e2.title !== t2.title, !!document.querySelector("[data-reactroot]"), !!document.querySelector("#root"), !!window.React, !document.querySelector('.loading, .spinner, [data-loading="true"]'), !!document.querySelector('main, [role="main"], .main-content, #main, #content')].some((t3) => t3);
});
}
fallbackToFullPageNavigation(t2) {
return __async(this, null, function* () {
window.location.href = t2;
});
}
delay(t2) {
return new Promise((e2) => setTimeout(e2, t2));
}
}
class p {
constructor(t2) {
this.router = t2, this.routerType = void 0 !== t2.asPath ? "pages" : "app";
}
navigate(t2) {
return __async(this, null, function* () {
const e2 = this.capturePageState();
try {
let n2;
if (t2.startsWith("http://") || t2.startsWith("https://")) {
const e3 = new URL(t2);
n2 = e3.pathname + e3.search + e3.hash;
} else n2 = t2;
const i2 = this.router.push(n2);
if (i2 && "function" == typeof i2.then && (yield i2), !(yield this.verifyNavigation(t2, n2, e2))) throw Error("Next.js navigation verification failed - content may not have loaded");
} catch (n2) {
yield this.fallbackToFullPageNavigation(t2);
}
});
}
getCurrentUrl() {
return "pages" === this.routerType && this.router.asPath ? window.location.origin + this.router.asPath : window.location.href;
}
canHandle(t2) {
try {
return t2.startsWith("http://") || t2.startsWith("https://") ? new URL(t2).origin === window.location.origin : 1;
} catch (e2) {
return 0;
}
}
capturePageState() {
return { url: window.location.href, path: window.location.pathname + window.location.search + window.location.hash, title: document.title, bodyHash: this.generateContentHash(document.body), timestamp: Date.now() };
}
generateContentHash(t2) {
const e2 = t2.textContent || "", n2 = t2.querySelectorAll("*").length, i2 = t2.querySelectorAll("script").length, s2 = t2.querySelectorAll("a").length, o2 = "".concat(e2.length, "-").concat(n2, "-").concat(i2, "-").concat(s2);
let a2 = 0;
for (let r2 = 0; o2.length > r2; r2++) a2 = (a2 << 5) - a2 + o2.charCodeAt(r2), a2 &= a2;
return "" + a2;
}
verifyNavigation(t2, e2, n2) {
return __async(this, null, function* () {
for (let s2 = 0; 25 > s2; s2++) {
yield this.delay(250);
const i3 = this.capturePageState();
if (this.checkUrlMatch(i3.url, i3.path, t2, e2)) {
if (i3.bodyHash !== n2.bodyHash || i3.title !== n2.title || 3 > s2) return 1;
if (s2 > 10 && (yield this.checkForNextjsContent(n2))) return 1;
}
}
const i2 = this.capturePageState();
return this.checkUrlMatch(i2.url, i2.path, t2, e2) ? 1 : 0;
});
}
checkUrlMatch(t2, e2, n2, i2) {
if (t2 === n2) return 1;
if (e2 === i2) return 1;
const s2 = (t3) => t3.replace(/\/+$/, "") || "/";
if (s2(e2) === s2(i2)) return 1;
const o2 = e2.split("?")[0].split("#")[0], a2 = i2.split("?")[0].split("#")[0];
return s2(o2) === s2(a2) ? 1 : 0;
}
checkForNextjsContent(t2) {
return __async(this, null, function* () {
yield this.delay(500);
const e2 = this.capturePageState();
return [e2.bodyHash !== t2.bodyHash, e2.title !== t2.title, !!document.querySelector("[data-nextjs-scroll-focus-boundary]"), !!document.querySelector("#__next"), !!window.__NEXT_DATA__, !document.querySelector('.loading, .spinner, [data-loading="true"]'), !!document.querySelector('main, [role="main"], .main-content, #main, #content')].some((t3) => t3);
});
}
fallbackToFullPageNavigation(t2) {
return __async(this, null, function* () {
window.location.href = t2;
});
}
delay(t2) {
return new Promise((e2) => setTimeout(e2, t2));
}
}
class m {
constructor() {
this.detectedRouter = null, this.routerInstance = null, this.detectRouter();
}
detectRouter() {
const t2 = [{ name: "react-router-v6", detect: () => {
var _a, _b;
return !!window.__reactRouterVersion || document.querySelector("[data-react-router]") || window.React && document.querySelector("a[href]") && !((_b = (_a = document.querySelector("a[href]")) == null ? void 0 : _a.getAttribute("href")) == null ? void 0 : _b.startsWith("http"));
}, getInstance: () => window.__reactRouter || window.router }, { name: "nextjs-pages", detect: () => {
var _a;
return !!window.__NEXT_DATA__ && !!((_a = window.next) == null ? void 0 : _a.router);
}, getInstance: () => window.next.router }, { name: "nextjs-app", detect: () => {
var _a;
return !!window.__NEXT_DATA__ && !((_a = window.next) == null ? void 0 : _a.router);
}, getInstance: () => null }, { name: "vue-router-v4", detect: () => !!window.__VUE__ || !!window.Vue || document.querySelector("[data-v-]") || !!window.$router, getInstance: () => window.$router || window.__vueRouter }, { name: "angular", detect: () => !!window.ng || document.querySelector("[ng-app]") || document.querySelector("app-root") || !!window.Zone, getInstance: () => {
var _a, _b, _c;
return (_c = (_b = (_a = window.ng) == null ? void 0 : _a.getComponent) == null ? void 0 : _b.call(_a, document.querySelector("app-root"))) == null ? void 0 : _c.router;
} }, { name: "svelte", detect: () => document.querySelector("[data-sveltekit-hydrate]") || document.querySelector("#svelte") || !!window.__SVELTEKIT__, getInstance: () => {
var _a;
return ((_a = window.__sveltekit) == null ? void 0 : _a.router) || window.goto;
} }, { name: "reach-router", detect: () => !!window.ReachRouter, getInstance: () => window.ReachRouter }, { name: "generic", detect: () => ["router", "$router", "Router", "__router__"].some((t3) => window[t3] && "function" == typeof window[t3].push), getInstance() {
const t3 = ["router", "$router", "Router", "__router__"];
return t3.find((t4) => window[t4] && "function" == typeof window[t4].push) ? window[t3.find((t4) => window[t4] && "function" == typeof window[t4].push)] : null;
} }];
for (const n2 of t2) try {
if (n2.detect()) {
this.detectedRouter = n2.name, this.routerInstance = n2.getInstance();
break;
}
} catch (e2) {
}
}
navigate(t2) {
return __async(this, null, function* () {
const e2 = this.extractPath(t2), n2 = this.capturePageState();
try {
switch (this.detectedRouter) {
case "nextjs-pages":
yield this.navigateNextjsPages(e2);
break;
case "nextjs-app":
yield this.navigateNextjsApp(e2);
break;
case "vue-router-v4":
yield this.navigateVueRouter(e2);
break;
case "angular":
yield this.navigateAngular(e2);
break;
case "svelte":
yield this.navigateSvelte(e2);
break;
case "react-router-v6":
case "reach-router":
case "generic":
yield this.navigateGeneric(e2);
break;
default:
throw Error("Navigation not supported for router: " + this.detectedRouter);
}
if (!(yield this.verifyNavigation(t2, e2, n2))) throw Error("Navigation verification failed - content may not have loaded");
} catch (i2) {
yield this.fallbackToFullPageNavigation(t2);
}
});
}
getCurrentUrl() {
var _a, _b, _c, _d;
switch (this.detectedRouter) {
case "nextjs-pages":
return window.location.origin + (((_a = this.routerInstance) == null ? void 0 : _a.asPath) || window.location.pathname);
case "vue-router-v4":
return window.location.origin + (((_d = (_c = (_b = this.routerInstance) == null ? void 0 : _b.currentRoute) == null ? void 0 : _c.value) == null ? void 0 : _d.fullPath) || window.location.pathname);
default:
return window.location.href;
}
}
canHandle(t2) {
if (!this.detectedRouter) return 0;
try {
return t2.startsWith("http://") || t2.startsWith("https://") ? new URL(t2).origin === window.location.origin : 1;
} catch (e2) {
return 0;
}
}
extractPath(t2) {
if (t2.startsWith("http://") || t2.startsWith("https://")) {
const e2 = new URL(t2);
return e2.pathname + e2.search + e2.hash;
}
return t2;
}
navigateNextjsPages(t2) {
return __async(this, null, function* () {
if (!this.routerInstance || "function" != typeof this.routerInstance.push) throw Error("Next.js Pages Router instance not available");
yield this.routerInstance.push(t2);
});
}
navigateNextjsApp(t2) {
return __async(this, null, function* () {
var _a;
const e2 = window.__nextRouter || ((_a = window.next) == null ? void 0 : _a.router) || window.__NEXT_ROUTER__;
e2 && "function" == typeof e2.push ? yield e2.push(t2) : (window.history.pushState({}, "", t2), window.dispatchEvent(new PopStateEvent("popstate")));
});
}
navigateVueRouter(t2) {
return __async(this, null, function* () {
if (!this.routerInstance || "function" != typeof this.routerInstance.push) throw Error("Vue Router instance not available");
yield this.routerInstance.push(t2);
});
}
navigateAngular(t2) {
return __async(this, null, function* () {
var _a, _b, _c, _d;
if (this.routerInstance && "function" == typeof this.routerInstance.navigate) yield this.routerInstance.navigate([t2]);
else {
const e2 = (_d = (_c = (_b = (_a = window.ng) == null ? void 0 : _a.getInjector) == null ? void 0 : _b.call(_a, document.body)) == null ? void 0 : _c.get) == null ? void 0 : _d.call(_c, "Router");
if (!e2 || "function" != typeof e2.navigate) throw Error("Angular Router instance not available");
yield e2.navigate([t2]);
}
});
}
navigateSvelte(t2) {
return __async(this, null, function* () {
var _a;
if ("function" == typeof this.routerInstance) yield this.routerInstance(t2);
else if (this.routerInstance && "function" == typeof this.routerInstance.goto) yield this.routerInstance.goto(t2);
else {
const e2 = window.goto || ((_a = window.__sveltekit) == null ? void 0 : _a.goto);
if ("function" != typeof e2) throw Error("Svelte navigation function not available");
yield e2(t2);
}
});
}
navigateGeneric(t2) {
return __async(this, null, function* () {
if (!this.routerInstance) throw Error("Generic router instance not available");
if ("function" == typeof this.routerInstance.push) {
const e2 = this.routerInstance.push(t2);
e2 && "function" == typeof e2.then && (yield e2);
} else {
if ("function" != typeof this.routerInstance.navigate) throw Error("Generic router navigation method not found");
{
const e2 = this.routerInstance.navigate(t2);
e2 && "function" == typeof e2.then && (yield e2);
}
}
});
}
getRouterInfo() {
return { type: this.detectedRouter, instance: this.routerInstance };
}
redetectRouter() {
this.detectedRouter = null, this.routerInstance = null, this.detectRouter();
}
capturePageState() {
return { url: window.location.href, path: window.location.pathname + window.location.search + window.location.hash, title: document.title, bodyHash: this.generateContentHash(document.body), timestamp: Date.now() };
}
generateContentHash(t2) {
const e2 = t2.textContent || "", n2 = t2.querySelectorAll("*").length, i2 = t2.querySelectorAll("script").length, s2 = t2.querySelectorAll("a").length, o2 = "".concat(e2.length, "-").concat(n2, "-").concat(i2, "-").concat(s2);
let a2 = 0;
for (let r2 = 0; o2.length > r2; r2++) a2 = (a2 << 5) - a2 + o2.charCodeAt(r2), a2 &= a2;
return "" + a2;
}
verifyNavigation(t2, e2, n2) {
return __async(this, null, function* () {
for (let s2 = 0; 30 > s2; s2++) {
yield this.delay(250);
const i3 = this.capturePageState();
if (this.checkUrlMatch(i3.url, i3.path, t2, e2)) {
if (i3.bodyHash !== n2.bodyHash || i3.title !== n2.title || 5 > s2) return 1;
if (s2 > 15 && (yield this.checkForNewContent(n2))) return 1;
}
}
const i2 = this.capturePageState();
return this.checkUrlMatch(i2.url, i2.path, t2, e2) ? 1 : 0;
});
}
checkUrlMatch(t2, e2, n2, i2) {
if (t2 === n2) return 1;
if (e2 === i2) return 1;
const s2 = (t3) => t3.replace(/\/+$/, "") || "/";
if (s2(e2) === s2(i2)) return 1;
const o2 = e2.split("?")[0].split("#")[0], a2 = i2.split("?")[0].split("#")[0];
return s2(o2) === s2(a2) ? 1 : 0;
}
checkForNewContent(t2) {
return __async(this, null, function* () {
yield this.delay(500);
const e2 = this.capturePageState();
return [e2.bodyHash !== t2.bodyHash, e2.title !== t2.title, !document.querySelector('.loading, .spinner, [data-loading="true"]'), !!document.querySelector('main, [role="main"], .main-content, #main, #content'), this.checkFrameworkSpecificContent()].some((t3) => t3);
});
}
checkFrameworkSpecificContent() {
switch (this.detectedRouter) {
case "nextjs-pages":
case "nextjs-app":
return !!document.querySelector("[data-nextjs-scroll-focus-boundary]") || !!document.querySelector("#__next") || !!window.__NEXT_DATA__;
case "vue-router-v4":
return !!document.querySelector("[data-v-]") || !!document.querySelector("#app") || !!window.__VUE__;
case "angular":
return !!document.querySelector("app-root") || !!document.querySelector("[ng-version]") || !!window.ng;
case "svelte":
return !!document.querySelector("[data-sveltekit-hydrate]") || !!document.querySelector("#svelte") || !!window.__SVELTEKIT__;
case "react-router-v6":
return !!document.querySelector("[data-reactroot]") || !!document.querySelector("#root") || !!window.React;
default:
return 0;
}
}
fallbackToFullPageNavigation(t2) {
return __async(this, null, function* () {
window.location.href = t2;
});
}
delay(t2) {
return new Promise((e2) => setTimeout(e2, t2));
}
}
const f = Object.freeze({ __proto__: null, UniversalRouterAdapter: m });
let g = null;
class SherpaSDK {
constructor() {
this.isInitialized = 0, this.cssResetApplied = 0, this.tourController = e.getInstance(), this.uiManager = w.getInstance();
}
boot(t2, e2) {
return __async(this, null, function* () {
if (!this.isInitialized) try {
(t2 == null ? void 0 : t2.key) && h({ serviceKey: t2.key }), (t2 == null ? void 0 : t2.applyCSSReset) && (u(), this.cssResetApplied = 1), this.isInitialized = 1, e2 && e2(), (t2 == null ? void 0 : t2.showSearch) && o.showSearch(), yield this.checkAndStartPendingTour();
} catch (n2) {
throw n2;
}
});
}
shutdown() {
this.isInitialized && (this.uiManager.destroy(), o.hideSearch(), this.cssResetApplied && (d(), this.cssResetApplied = 0), this.isInitialized = 0);
}
startTour(t2, e2, n2) {
return __async(this, null, function* () {
if (!this.isInitialized) throw Error("SDK not initialized. Call boot() first.");
return this.tourController.startTour(t2, e2, n2);
});
}
endTour() {
return __async(this, null, function* () {
return this.tourController.endTour();
});
}
showSearch() {
o.showSearch();
}
hideSearch() {
o.hideSearch();
}
openDocs(t2, e2) {
this.uiManager.openDocs(t2, e2);
}
closeDocs(t2) {
this.uiManager.closeDocs(t2);
}
closeAllDocs() {
this.uiManager.closeAllDocs();
}
hasOpenDocs() {
return this.uiManager.hasOpenDocs();
}
track(t2, e2) {
}
updateUser(t2, e2) {
}
onTourStarted(t2) {
}
onTourEnded(t2) {
}
onStepChanged(t2) {
}
onSearchShown(t2) {
}
onSearchHidden(t2) {
}
clearCallbacks() {
}
checkAndStartPendingTour() {
return __async(this, null, function* () {
yield e.checkAndStartPendingTour(), yield this.checkUrlParametersForTour();
});
}
checkUrlParametersForTour() {
return __async(this, null, function* () {
try {
const t2 = new URLSearchParams(window.location.search), e2 = t2.get("sherpa") || t2.get("tour");
if (e2) {
const [t3, n2 = "url-parameter"] = e2.split(":");
t3 && (yield this.startTour(t3, n2, { source: "url-parameter", originalUrl: window.location.href }));
}
} catch (t2) {
}
});
}
getDebugInfo() {
return { error: "Debug info not available in production" };
}
}
if ("undefined" != typeof window && window.Sherpa) {
const e2 = window.Sherpa.q || [];
window.Sherpa = t, e2.forEach((e3) => {
try {
t(...e3);
} catch (n2) {
}
});
}
export {
p as N,
l as R,
SherpaSDK as S,
w as U,
m as a,
f as u
};