UNPKG

@sheerid/jslib-nightly

Version:

SheerID JavaScript Library

396 lines (394 loc) • 14 kB
/** * VERSION: 2.154.0-alpha.1 * BUILD_TIMESTAMP: 1763401559038 * BUILD_DATE: Mon Nov 17 2025 17:45:59 GMT+0000 (Coordinated Universal Time) * BUILD_COMMIT: 73f4468155aaed0f31ab0d59dc3394018b939b6d */ const S = "installPageUrl", A = "installType", T = { INLINE_IFRAME_CONTENT: "sid-inline-iframe", MODAL_WRAPPER: "sid-modal__wrapper", MODAL_IFRAME: "sid-modal__iframe", OVERLAY: "sid-modal__overlay", CLOSE_BUTTON: "sid-modal__close-button", CLOSE_TEXT: "sid-modal__close-text", CLOSE_ICON: "sid-modal__close-icon" }, v = "SheerID Verification Form", o = { CLASS_NAMES: T, DEFAULT_MOBILE_THRESHOLD_WIDTH: 620, MODAL_OPACITY_TRANSITION_PERIOD: 300 }, _ = {}, M = async () => _, y = () => window.navigator.globalPrivacyControl, d = () => window.NREUM && !y(); function a(i, e) { try { return i(); } catch { return e; } } let h = 4, c = ""; const I = { info: 1, log: 2, warn: 3, error: 4, silent: 5 }, f = { info: "#26c1db", log: "#09f979", warn: "#f6b13f", error: "#e12046" }, m = "color: white; font-weight: bold; padding: 2px 10px;"; let p; const O = (i) => i && i.stack && i.message, u = (...i) => { h <= 3 && console.warn(`%c${c} warn`, `background: ${f.warn};${m}`, ...i); }, N = (...i) => { h <= 2 && console.log(`%c${c} log`, `background: ${f.log};${m}`, ...i); }, R = (...i) => { h <= 1 && console.log(`%c${c} info`, `background: ${f.info};${m}`, ...i); }, P = async (i, e = "unknown group", t = {}) => { if (h <= 4) { if (!i) { console.error(new Error("An error must be supplied")); return; } let s; typeof i == "string" && (s = new Error(i)), O(i) && (s = i), s || (s = new Error("Unknown error")); let n = { errorMessageGroup: e }; try { n = { ...await M(), ...n }, delete n.jslibVersionActual; } catch (r) { d() ? window.NREUM.noticeError(s, n) : u("Unable to assemble GA error attributes", r); } try { if (p && p.getState) { const r = p.getState(), w = a(() => r.verificationResponse.errorIds); n = { ...n, programId: a(() => r.programId), isLoading: a(() => r.isLoading), isErrored: a(() => r.isErrored), errorIdsFromVerRsp: Array.isArray(w) ? w.join(", ") : void 0, verificationId: a(() => r.verificationResponse.verificationId), currentStep: a(() => r.verificationResponse.currentStep), locale: a(() => r.programTheme.intl.locale), isTestMode: a(() => r.programTheme.isTestMode), openOrgSearchEnabled: a(() => r.programTheme.openOrgSearchEnabled), jslibVerActual: a(() => "2.154.0-alpha.1", "?"), ...t }; } } catch (r) { d() ? window.NREUM.noticeError(s, n) : u("Unable to assemble useful error attributes", r); } d() && window.NREUM.noticeError(s, n), console.error( `%c${c} error`, `background: ${f.error};${m}`, s, n ); } }, C = (i, e = {}) => { d() && window.NREUM.addPageAction(i, e); }, D = (i, e) => { C("API-calls-timing", { api_call: i, api_response_time: e }); }, L = { error: P, warn: u, log: N, info: R, /** @deprecated use newRelicPageAction() instead */ logAPIResponseTime: D, setLogLevel: (i) => { if (!I.hasOwnProperty(i)) throw new Error(`Unknown logLevel '${i}'`); h = I[i], console.log( `%c${c} log level set to ${i}`, `background: ${f[i]};${m}` ), d() || u("Offsite logging not enabled"); }, setPrefix: (i) => { c = i; }, init: (i) => { p = i; } }, x = (i) => { i.forEach((e) => { e.classList.add("fade-in"); }); }, g = (i, e) => { i.classList.remove("fade-in"), window.setTimeout(() => { document.body.style.overflow = "auto", i.parentNode.removeChild(i); }, e); }, b = (i) => { const e = new URL(i); return new URL(window.location.href).searchParams.forEach((s, n) => { e.searchParams.has(n) || e.searchParams.set(n, s); }), e.href; }; class B { subscribers = /* @__PURE__ */ new Set(); sub(e) { return this.subscribers.add(e), () => this.subscribers.delete(e); } pub(e) { this.subscribers.forEach((t) => t(e)); } } class $ { events = /* @__PURE__ */ new Map(); /** * Registers a listener that will be called when the named event is emitted * @returns An unsubscribe function that will turn off this listener. */ on(e, t) { return this.events.has(e) || this.events.set(e, new B()), this.events.get(e).sub(t); } /** * Registers a listener that will be called a single time when the named event * is emitted * @returns An unsubscribe function that will turn off this listener. */ once(e, t) { const s = this.on(e, (n) => (s(), t(n))); return s; } /** * Removes all event listeners for the given key * @returns void */ off(e) { this.events.delete(e); } /** * Used to emit events to all registered hook listeners * * @private */ emit(e, t) { this.events.has(e) && this.events.get(e).pub(t); } } const U = { className: o.CLASS_NAMES.INLINE_IFRAME_CONTENT, title: v }, W = (i) => { if (typeof i != "function") throw new Error(`Expected type "function", but received ${typeof i}`); }; class l extends $ { containerElement; verificationUrl; isMobileDevice; iframe; verificationIframeUid; locale; hasLoaded = !1; onLoadEvents = []; onCleanupEvents = []; installType = "cdn_inline_iframe"; constructor(e, t) { super(), l.isValidHttpUrl(t) ? (this.containerElement = e, this.verificationUrl = new URL(b(t)), this.verificationIframeUid = l.createUniqueId()) : L.error("Invalid URL. Provide a proper URL: https://example.com/", "iframe url"); } cleanup() { this.onCleanupEvents.forEach((e) => e()); } static createUniqueId() { return Math.random().toString(36).substr(2, 9); } static isValidHttpUrl(e) { try { const t = new URL(e); return t.protocol === "http:" || t.protocol === "https:"; } catch { return !1; } } createIframe(e) { return this.iframe = document.createElement("iframe"), this.iframe.classList.add(e.className), this.iframe.title = e.title, this.iframe.src = this.getIframeUrl(), this.iframe.allow = "camera *;microphone *;geolocation *;clipboard-read *;clipboard-write *", this.iframe.onload = () => this.onLoad(), this.iframe; } getIframeUrl() { const e = new URL(this.verificationUrl); return e.searchParams.set("verificationIframeUid", this.verificationIframeUid), e.searchParams.set(S, window.location.href), e.searchParams.set(A, this.installType), this.locale && e.searchParams.set("locale", this.locale), e.toString(); } // If iFrame hasn't loaded yet, queue up the callback // otherwise call it immediately addOnLoadEvent(e) { try { W(e); } catch { L.error("Invalid callback provided to iFrame.onLoad()", "iframe addOnLoadEvent"); return; } this.hasLoaded ? e() : this.onLoadEvents.push(e); } onLoad() { this.hasLoaded = !0, this.onLoadEvents.forEach((e) => e()); } /** * Using this to add parent window message listeners gives us * - Event Cleanup for modals * - verification of origin, verificationIframeUid, and message data structure */ addWindowMessageListener(e) { const t = (s) => { this.verificationUrl.origin === s.origin && s.data.verificationIframeUid === this.verificationIframeUid && (s.data.action && s.data.action.type ? e(s.data.action) : s.data.action && s.data.height && e(s.data)); }; window.addEventListener("message", t), this.onCleanupEvents.push(() => window.removeEventListener("message", t)); } addActionListener() { this.addWindowMessageListener((e) => { e.type === "hook" && this.emit(e.hook.name, e.hook.data), (e.action && e.action === "updateHeight" || e.type === "updateHeight") && (this.iframe.scrolling = "no", this.iframe.style.height = `${e.height}px`); }); } setViewModel(e) { const t = { action: "setViewModel", viewModel: e }; this.addOnLoadEvent(() => { this.iframe.contentWindow.postMessage(t, this.verificationUrl.origin); }); } setOptions(e) { const t = { action: "setOptions", options: e }; if (!this.hasLoaded && e.locale) { this.locale = e.locale; const s = this.getIframeUrl(); s !== this.iframe.src && (this.iframe.src = s); } this.addOnLoadEvent(() => { this.iframe.contentWindow.postMessage(t, this.verificationUrl.origin); }); } setInstallType(e) { this.installType = e; } init(e = !0) { e && this.createIframe(U), this.addActionListener(), this.containerElement.appendChild(this.iframe); } } class F extends l { constructor(e, t) { super(e, t), this.verificationUrl = new URL(this.getAffinityUrlWithUID(t)); } static createUniqueId() { return Math.random().toString(36).substr(2, 9); } getAffinityUrlWithUID(e) { const t = new URL(e); return t.searchParams.set("affinityIframeUid", this.verificationIframeUid), t.toString(); } addWindowMessageListener(e) { const t = (s) => { this.verificationUrl.origin === s.origin && s.data.affinityIframeUid === this.verificationIframeUid && s.data.action && s.data.action.type && e(s.data.action); }; window.addEventListener("message", t), this.onCleanupEvents.push(() => window.removeEventListener("message", t)); } createIframe(e) { return this.iframe = document.createElement("iframe"), this.iframe.classList.add(e.className), this.iframe.title = e.title, this.iframe.src = this.verificationUrl.href, this.iframe.allow = "camera;microphone", this.iframe.onload = () => this.onLoad(), this.iframe; } init() { this.createIframe({ ...U, title: "SheerID Affinity Offers" }), this.addActionListener(), this.containerElement.appendChild(this.iframe); } } class E { verificationUrl; redirectOnMobile; overlay; wrapper; iframeInstance; on; once; isMobileDevice; closeButtonText; closeButton; stopPropagation; constructor(e, t) { const s = t.mobileThreshold ? t.mobileThreshold : o.DEFAULT_MOBILE_THRESHOLD_WIDTH; this.verificationUrl = b(e), this.redirectOnMobile = t.mobileRedirect || !1, this.isMobileDevice = window.document.body.clientWidth <= Number(s), this.closeButtonText = t.closeButtonText ? t.closeButtonText : "", this.closeButton = null, this.stopPropagation = t.stopPropagation || !1, this.overlay = E.createOverlay(), this.wrapper = this.createWrapper(), this.addFocusListener(); } createCloseBtn() { if (this.closeButton = document.createElement("button"), this.closeButton.classList.add(o.CLASS_NAMES.CLOSE_BUTTON), this.closeButton.setAttribute("aria-label", "close"), this.closeButtonText) { const t = document.createElement("div"); t.classList.add(o.CLASS_NAMES.CLOSE_TEXT), t.innerHTML = this.closeButtonText, this.closeButton.appendChild(t); } const e = document.createElement("span"); return e.classList.add(o.CLASS_NAMES.CLOSE_ICON), e.setAttribute("role", "img"), this.closeButton.appendChild(e), this.closeButton.addEventListener("click", (t) => { t.preventDefault(), this.stopPropagation && t.stopPropagation(), this.closeModal(); }), this.closeButton; } closeModal() { window.removeEventListener("popstate", this.popStateEventHandler); const e = o.MODAL_OPACITY_TRANSITION_PERIOD; g(this.overlay, e), g(this.wrapper, e), this.iframeInstance.cleanup(); } static createOverlay() { const e = document.createElement("div"); return e.classList.add(o.CLASS_NAMES.OVERLAY), e; } createWrapper() { const e = document.createElement("div"); e.classList.add(o.CLASS_NAMES.MODAL_WRAPPER), e.tabIndex = -1, e.setAttribute("role", "dialog"), e.appendChild(this.createCloseBtn()), this.iframeInstance = new l(e, this.verificationUrl), this.iframeInstance.setInstallType("cdn_modal_iframe"), this.on = this.iframeInstance.on.bind(this.iframeInstance), this.once = this.iframeInstance.once.bind(this.iframeInstance); const t = { className: o.CLASS_NAMES.MODAL_IFRAME, title: v }; return this.iframeInstance.createIframe(t), e.appendChild(this.iframeInstance.iframe), e; } popStateEventHandler = () => this.closeModal(); addPopStateListener() { window.addEventListener("popstate", this.popStateEventHandler); } addFocusListener() { this.iframeInstance.addWindowMessageListener((e) => { e.type === "focus" && e.focusOn === "firstElement" && this.closeButton.focus(); }), document.addEventListener("keydown", (e) => { e.key === "Tab" && e.shiftKey && document.activeElement === this.closeButton && (this.iframeInstance.iframe.contentWindow.postMessage({ focusOn: "lastElement" }, "*"), e.preventDefault()); }); } isInLightboxPostMessage(e) { this.iframeInstance.iframe.contentWindow.postMessage({ isInLightBox: e }, "*"); } displayModal() { this.iframeInstance.iframe.addEventListener("load", () => { x([this.overlay, this.wrapper]), document.body.style.overflow = "hidden", this.isInLightboxPostMessage("true"); }), document.body.appendChild(this.overlay), document.body.appendChild(this.wrapper), this.addPopStateListener(); } init() { this.redirectOnMobile && this.isMobileDevice ? window.top.location.href = this.verificationUrl : (this.displayModal(), this.iframeInstance.init(!1)); } setViewModel(e) { this.iframeInstance.setViewModel(e); } setOptions(e) { this.iframeInstance.setOptions(e); } } function k(i, e) { const t = new l(i, e); return t.init(), t; } function H(i, e = {}) { const t = new E(i, e); return t.init(), t; } function V(i, e) { const t = new F(i, e); return t.init(), t; } const Y = { loadInModal: H, loadInlineIframe: k }; export { Y as default, V as loadAffinityIFrame, H as loadInModal, k as loadInlineIframe };