UNPKG

@thoughtspot/visual-embed-sdk

Version:
1,300 lines (1,296 loc) 1.04 MB
/* @thoughtspot/visual-embed-sdk version 1.40.0 */ 'use client'; (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.tsembed = {})); })(this, (function (exports) { 'use strict'; function _mergeNamespaces(n, m) { m.forEach(function (e) { e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) { if (k !== 'default' && !(k in n)) { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); }); return Object.freeze(n); } // istanbul ignore next const isObject$1 = (obj) => { if (typeof obj === "object" && obj !== null) { if (typeof Object.getPrototypeOf === "function") { const prototype = Object.getPrototypeOf(obj); return prototype === Object.prototype || prototype === null; } return Object.prototype.toString.call(obj) === "[object Object]"; } return false; }; const merge = (...objects) => objects.reduce((result, current) => { if (Array.isArray(current)) { throw new TypeError("Arguments provided to ts-deepmerge must be objects, not arrays."); } Object.keys(current).forEach((key) => { if (["__proto__", "constructor", "prototype"].includes(key)) { return; } if (Array.isArray(result[key]) && Array.isArray(current[key])) { result[key] = merge.options.mergeArrays ? merge.options.uniqueArrayItems ? Array.from(new Set(result[key].concat(current[key]))) : [...result[key], ...current[key]] : current[key]; } else if (isObject$1(result[key]) && isObject$1(current[key])) { result[key] = merge(result[key], current[key]); } else { result[key] = current[key] === undefined ? merge.options.allowUndefinedOverrides ? current[key] : result[key] : current[key]; } }); return result; }, {}); const defaultOptions = { allowUndefinedOverrides: true, mergeArrays: true, uniqueArrayItems: true, }; merge.options = defaultOptions; merge.withOptions = (options, ...objects) => { merge.options = Object.assign(Object.assign({}, defaultOptions), options); const result = merge(...objects); merge.options = defaultOptions; return result; }; /** * Copyright (c) 2023 * * Common utility functions for ThoughtSpot Visual Embed SDK * @summary Utils * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com> */ /** * Construct a runtime filters query string from the given filters. * Refer to the following docs for more details on runtime filter syntax: * https://cloud-docs.thoughtspot.com/admin/ts-cloud/apply-runtime-filter.html * https://cloud-docs.thoughtspot.com/admin/ts-cloud/runtime-filter-operators.html * @param runtimeFilters */ const getFilterQuery = (runtimeFilters) => { if (runtimeFilters && runtimeFilters.length) { const filters = runtimeFilters.map((filter, valueIndex) => { const index = valueIndex + 1; const filterExpr = []; filterExpr.push(`col${index}=${encodeURIComponent(filter.columnName)}`); filterExpr.push(`op${index}=${filter.operator}`); filterExpr.push(filter.values.map((value) => { const encodedValue = typeof value === 'bigint' ? value.toString() : value; return `val${index}=${encodeURIComponent(String(encodedValue))}`; }).join('&')); return filterExpr.join('&'); }); return `${filters.join('&')}`; } return null; }; /** * Construct a runtime parameter override query string from the given option. * @param runtimeParameters */ const getRuntimeParameters = (runtimeParameters) => { if (runtimeParameters && runtimeParameters.length) { const params = runtimeParameters.map((param, valueIndex) => { const index = valueIndex + 1; const filterExpr = []; filterExpr.push(`param${index}=${encodeURIComponent(param.name)}`); filterExpr.push(`paramVal${index}=${encodeURIComponent(param.value)}`); return filterExpr.join('&'); }); return `${params.join('&')}`; } return null; }; /** * Convert a value to a string representation to be sent as a query * parameter to the ThoughtSpot app. * @param value Any parameter value */ const serializeParam = (value) => { // do not serialize primitive types if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { return value; } return JSON.stringify(value); }; /** * Convert a value to a string: * in case of an array, we convert it to CSV. * in case of any other type, we directly return the value. * @param value */ const paramToString = (value) => (Array.isArray(value) ? value.join(',') : value); /** * Return a query param string composed from the given params object * @param queryParams * @param shouldSerializeParamValues */ const getQueryParamString = (queryParams, shouldSerializeParamValues = false) => { const qp = []; const params = Object.keys(queryParams); params.forEach((key) => { const val = queryParams[key]; if (val !== undefined) { const serializedValue = shouldSerializeParamValues ? serializeParam(val) : paramToString(val); qp.push(`${key}=${serializedValue}`); } }); if (qp.length) { return qp.join('&'); } return null; }; /** * Get a string representation of a dimension value in CSS * If numeric, it is considered in pixels. * @param value */ const getCssDimension = (value) => { if (typeof value === 'number') { return `${value}px`; } return value; }; const getSSOMarker = (markerId) => { const encStringToAppend = encodeURIComponent(markerId); return `tsSSOMarker=${encStringToAppend}`; }; /** * Append a string to a URL's hash fragment * @param url A URL * @param stringToAppend The string to append to the URL hash */ const appendToUrlHash = (url, stringToAppend) => { let outputUrl = url; const encStringToAppend = encodeURIComponent(stringToAppend); const marker = `tsSSOMarker=${encStringToAppend}`; let splitAdder = ''; if (url.indexOf('#') >= 0) { // If second half of hash contains a '?' already add a '&' instead of // '?' which appends to query params. splitAdder = url.split('#')[1].indexOf('?') >= 0 ? '&' : '?'; } else { splitAdder = '#?'; } outputUrl = `${outputUrl}${splitAdder}${marker}`; return outputUrl; }; /** * * @param url * @param stringToAppend * @param path */ function getRedirectUrl(url, stringToAppend, path = '') { const targetUrl = path ? new URL(path, window.location.origin).href : url; return appendToUrlHash(targetUrl, stringToAppend); } const getEncodedQueryParamsString = (queryString) => { if (!queryString) { return queryString; } return btoa(queryString).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); }; const getOffsetTop = (element) => { const rect = element.getBoundingClientRect(); return rect.top + window.scrollY; }; const embedEventStatus = { START: 'start', END: 'end', }; const setAttributes = (element, attributes) => { Object.keys(attributes).forEach((key) => { element.setAttribute(key, attributes[key].toString()); }); }; const isCloudRelease = (version) => version.endsWith('.cl'); /* For Search Embed: ReleaseVersionInBeta */ const checkReleaseVersionInBeta = (releaseVersion, suppressBetaWarning) => { if (releaseVersion !== '' && !isCloudRelease(releaseVersion)) { const splittedReleaseVersion = releaseVersion.split('.'); const majorVersion = Number(splittedReleaseVersion[0]); const isBetaVersion = majorVersion < 8; return !suppressBetaWarning && isBetaVersion; } return false; }; const getCustomisations = (embedConfig, viewConfig) => { var _a, _b, _c, _d; const customizationsFromViewConfig = viewConfig.customizations; const customizationsFromEmbedConfig = embedConfig.customizations || embedConfig.customisations; const customizations = { style: { ...customizationsFromEmbedConfig === null || customizationsFromEmbedConfig === void 0 ? void 0 : customizationsFromEmbedConfig.style, ...customizationsFromViewConfig === null || customizationsFromViewConfig === void 0 ? void 0 : customizationsFromViewConfig.style, customCSS: { ...(_a = customizationsFromEmbedConfig === null || customizationsFromEmbedConfig === void 0 ? void 0 : customizationsFromEmbedConfig.style) === null || _a === void 0 ? void 0 : _a.customCSS, ...(_b = customizationsFromViewConfig === null || customizationsFromViewConfig === void 0 ? void 0 : customizationsFromViewConfig.style) === null || _b === void 0 ? void 0 : _b.customCSS, }, customCSSUrl: ((_c = customizationsFromViewConfig === null || customizationsFromViewConfig === void 0 ? void 0 : customizationsFromViewConfig.style) === null || _c === void 0 ? void 0 : _c.customCSSUrl) || ((_d = customizationsFromEmbedConfig === null || customizationsFromEmbedConfig === void 0 ? void 0 : customizationsFromEmbedConfig.style) === null || _d === void 0 ? void 0 : _d.customCSSUrl), }, content: { ...customizationsFromEmbedConfig === null || customizationsFromEmbedConfig === void 0 ? void 0 : customizationsFromEmbedConfig.content, ...customizationsFromViewConfig === null || customizationsFromViewConfig === void 0 ? void 0 : customizationsFromViewConfig.content, }, }; return customizations; }; const getRuntimeFilters = (runtimefilters) => getFilterQuery(runtimefilters || []); /** * Gets a reference to the DOM node given * a selector. * @param domSelector */ function getDOMNode(domSelector) { return typeof domSelector === 'string' ? document.querySelector(domSelector) : domSelector; } const deepMerge = (target, source) => merge(target, source); const getOperationNameFromQuery = (query) => { const regex = /(?:query|mutation)\s+(\w+)/; const matches = query.match(regex); return matches === null || matches === void 0 ? void 0 : matches[1]; }; /** * * @param obj */ function removeTypename(obj) { if (!obj || typeof obj !== 'object') return obj; for (const key in obj) { if (key === '__typename') { delete obj[key]; } else if (typeof obj[key] === 'object') { removeTypename(obj[key]); } } return obj; } /** * Sets the specified style properties on an HTML element. * @param {HTMLElement} element - The HTML element to which the styles should be applied. * @param {Partial<CSSStyleDeclaration>} styleProperties - An object containing style * property names and their values. * @example * // Apply styles to an element * const element = document.getElementById('myElement'); * const styles = { * backgroundColor: 'red', * fontSize: '16px', * }; * setStyleProperties(element, styles); */ const setStyleProperties = (element, styleProperties) => { if (!(element === null || element === void 0 ? void 0 : element.style)) return; Object.keys(styleProperties).forEach((styleProperty) => { const styleKey = styleProperty; const value = styleProperties[styleKey]; if (value !== undefined) { element.style[styleKey] = value.toString(); } }); }; /** * Removes specified style properties from an HTML element. * @param {HTMLElement} element - The HTML element from which the styles should be removed. * @param {string[]} styleProperties - An array of style property names to be removed. * @example * // Remove styles from an element * const element = document.getElementById('myElement'); * element.style.backgroundColor = 'red'; * const propertiesToRemove = ['backgroundColor']; * removeStyleProperties(element, propertiesToRemove); */ const removeStyleProperties = (element, styleProperties) => { if (!(element === null || element === void 0 ? void 0 : element.style)) return; styleProperties.forEach((styleProperty) => { element.style.removeProperty(styleProperty); }); }; const isUndefined$1 = (value) => value === undefined; // Return if the value is a string, double or boolean. const getTypeFromValue = (value) => { if (typeof value === 'string') { return ['char', 'string']; } if (typeof value === 'number') { return ['double', 'double']; } if (typeof value === 'boolean') { return ['boolean', 'boolean']; } return ['', '']; }; const sdkWindowKey = '_tsEmbedSDK'; /** * Stores a value in the global `window` object under the `_tsEmbedSDK` namespace. * @param key - The key under which the value will be stored. * @param value - The value to store. * @param options - Additional options. * @param options.ignoreIfAlreadyExists - Does not set if value for key is set. * * @returns The stored value. * * @version SDK: 1.36.2 | ThoughtSpot: * */ function storeValueInWindow(key, value, options = {}) { if (!window[sdkWindowKey]) { window[sdkWindowKey] = {}; } if (options.ignoreIfAlreadyExists && key in window[sdkWindowKey]) { return window[sdkWindowKey][key]; } window[sdkWindowKey][key] = value; return value; } /** * Retrieves a stored value from the global `window` object under the `_tsEmbedSDK` namespace. * @param key - The key whose value needs to be retrieved. * @returns The stored value or `undefined` if the key is not found. */ const getValueFromWindow = (key) => { var _a; return (_a = window === null || window === void 0 ? void 0 : window[sdkWindowKey]) === null || _a === void 0 ? void 0 : _a[key]; }; /** * Check if the document is currently in fullscreen mode */ const isInFullscreen = () => { return !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement); }; /** * Handle Present HostEvent by entering fullscreen mode * @param iframe The iframe element to make fullscreen */ const handlePresentEvent = async (iframe) => { if (isInFullscreen()) { return; // Already in fullscreen } // Browser-specific methods to enter fullscreen mode const fullscreenMethods = [ 'requestFullscreen', 'webkitRequestFullscreen', 'mozRequestFullScreen', 'msRequestFullscreen' // IE/Edge ]; for (const method of fullscreenMethods) { if (typeof iframe[method] === 'function') { try { const result = iframe[method](); await Promise.resolve(result); return; } catch (error) { logger$3.warn(`Failed to enter fullscreen using ${method}:`, error); } } } logger$3.error('Fullscreen API is not supported by this browser.'); }; /** * Handle ExitPresentMode EmbedEvent by exiting fullscreen mode */ const handleExitPresentMode = async () => { if (!isInFullscreen()) { return; // Not in fullscreen } const exitFullscreenMethods = [ 'exitFullscreen', 'webkitExitFullscreen', 'mozCancelFullScreen', 'msExitFullscreen' // IE/Edge ]; // Try each method until one works for (const method of exitFullscreenMethods) { if (typeof document[method] === 'function') { try { const result = document[method](); await Promise.resolve(result); return; } catch (error) { logger$3.warn(`Failed to exit fullscreen using ${method}:`, error); } } } logger$3.warn('Exit fullscreen API is not supported by this browser.'); }; const calculateVisibleElementData = (element) => { const rect = element.getBoundingClientRect(); const windowHeight = window.innerHeight; const windowWidth = window.innerWidth; const frameRelativeTop = Math.max(rect.top, 0); const frameRelativeLeft = Math.max(rect.left, 0); const frameRelativeBottom = Math.min(windowHeight, rect.bottom); const frameRelativeRight = Math.min(windowWidth, rect.right); const data = { top: Math.max(0, rect.top * -1), height: Math.max(0, frameRelativeBottom - frameRelativeTop), left: Math.max(0, rect.left * -1), width: Math.max(0, frameRelativeRight - frameRelativeLeft), }; return data; }; /** * Copyright (c) 2023 * * TypeScript type definitions for ThoughtSpot Visual Embed SDK * @summary Type definitions for Embed SDK * @author Ayon Ghosh <ayon.ghosh@thoughtspot.com> */ /** * The authentication mechanism for allowing access to the * the embedded app * @group Authentication / Init */ // eslint-disable-next-line no-shadow exports.AuthType = void 0; (function (AuthType) { /** * No authentication on the SDK. Pass-through to the embedded App. Alias for * `Passthrough`. * @example * ```js * init({ * // ... * authType: AuthType.None, * }); * ``` */ AuthType["None"] = "None"; /** * Passthrough SSO to the embedded application within the iframe. Requires least * configuration, but may not be supported by all IDPs. This will behave like `None` * if SSO is not configured on ThoughtSpot. * * To use this: * Your SAML or OpenID provider must allow iframe redirects. * For example, if you are using Okta as IdP, you can enable iframe embedding. * @example * ```js * init({ * // ... * authType: AuthType.EmbeddedSSO, * }); * ``` * @version: SDK: 1.15.0 | ThoughtSpot: 8.8.0.cl */ AuthType["EmbeddedSSO"] = "EmbeddedSSO"; /** * SSO using SAML * @deprecated Use {@link SAMLRedirect} instead * @hidden */ AuthType["SSO"] = "SSO_SAML"; /** * SSO using SAML * @deprecated Use {@link SAMLRedirect} instead * @hidden */ AuthType["SAML"] = "SSO_SAML"; /** * SSO using SAML * Makes the host application redirect to the SAML IdP. Use this * if your IdP does not allow itself to be embedded. * * This redirects the host application to the SAML IdP. The host application * will be redirected back to the ThoughtSpot app after authentication. * @example * ```js * init({ * // ... * authType: AuthType.SAMLRedirect, * }); * ``` * * This opens the SAML IdP in a popup window. The popup is triggered * when the user clicks the trigger button. The popup window will be * closed automatically after authentication. * @example * ```js * init({ * // ... * authType: AuthType.SAMLRedirect, * authTriggerText: 'Login with SAML', * authTriggerContainer: '#tsEmbed', * inPopup: true, * }); * ``` * * Can also use the event to trigger the popup flow. Works the same * as the above example. * @example * ```js * const authEE = init({ * // ... * authType: AuthType.SAMLRedirect, * inPopup: true, * }); * * someButtonOnYourPage.addEventListener('click', () => { * authEE.emit(AuthEvent.TRIGGER_SSO_POPUP); * }); * ``` */ AuthType["SAMLRedirect"] = "SSO_SAML"; /** * SSO using OIDC * @hidden * @deprecated Use {@link OIDCRedirect} instead */ AuthType["OIDC"] = "SSO_OIDC"; /** * SSO using OIDC * Will make the host application redirect to the OIDC IdP. * See code samples in {@link SAMLRedirect}. */ AuthType["OIDCRedirect"] = "SSO_OIDC"; /** * Trusted authentication server * @hidden * @deprecated Use {@link TrustedAuth} instead */ AuthType["AuthServer"] = "AuthServer"; /** * Trusted authentication server. Use your own authentication server * which returns a bearer token, generated using the `secret_key` obtained * from ThoughtSpot. * @example * ```js * init({ * // ... * authType: AuthType.TrustedAuthToken, * getAuthToken: () => { * return fetch('https://my-backend.app/ts-token') * .then((response) => response.json()) * .then((data) => data.token); * } * }); * ``` */ AuthType["TrustedAuthToken"] = "AuthServer"; /** * Trusted authentication server Cookieless, Use your own authentication * server which returns a bearer token, generated using the `secret_key` * obtained from ThoughtSpot. This uses a cookieless authentication * approach, recommended to bypass the third-party cookie-blocking restriction * implemented by some browsers. * @example * ```js * init({ * // ... * authType: AuthType.TrustedAuthTokenCookieless, * getAuthToken: () => { * return fetch('https://my-backend.app/ts-token') * .then((response) => response.json()) * .then((data) => data.token); * } * ``` * @version SDK: 1.22.0| ThoughtSpot: 9.3.0.cl, 9.5.1.sw */ AuthType["TrustedAuthTokenCookieless"] = "AuthServerCookieless"; /** * Use the ThoughtSpot login API to authenticate to the cluster directly. * * Warning: This feature is primarily intended for developer testing. It is * strongly advised not to use this authentication method in production. */ AuthType["Basic"] = "Basic"; })(exports.AuthType || (exports.AuthType = {})); /** * * This option does not apply to the classic homepage experience. * To access the updated modular homepage, * set `modularHomeExperience` to `true` * (available as Early Access feature in 9.12.5.cl). * */ exports.HomeLeftNavItem = void 0; (function (HomeLeftNavItem) { /** * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl */ HomeLeftNavItem["SearchData"] = "search-data"; /** * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl */ HomeLeftNavItem["Home"] = "insights-home"; /** * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl */ HomeLeftNavItem["Liveboards"] = "liveboards"; /** * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl */ HomeLeftNavItem["Answers"] = "answers"; /** * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl */ HomeLeftNavItem["MonitorSubscription"] = "monitor-alerts"; /** * @version SDK: 1.28.0| ThoughtSpot: 9.12.5.cl */ HomeLeftNavItem["SpotIQAnalysis"] = "spotiq-analysis"; /** * @version SDK: 1.34.0| ThoughtSpot: 10.3.0.cl */ HomeLeftNavItem["LiveboardSchedules"] = "liveboard-schedules"; /** * Create new options in the insights left navigation, * available when new navigation V3 is enabled. * @version SDK: 1.40.0 | ThoughtSpot: 10.11.0.cl */ HomeLeftNavItem["Create"] = "create"; /** * Spotter option in the insights left navigation, * available when new navigation V3 is enabled. * @version SDK: 1.40.0 | ThoughtSpot: 10.11.0.cl */ HomeLeftNavItem["Spotter"] = "spotter"; /** * Favorites option in the insights left navigation, * available when new navigation V3 is enabled. * @version SDK: 1.41.0 | ThoughtSpot: 10.12.0.cl */ HomeLeftNavItem["Favorites"] = "favorites"; })(exports.HomeLeftNavItem || (exports.HomeLeftNavItem = {})); /** * A map of the supported runtime filter operations */ // eslint-disable-next-line no-shadow exports.RuntimeFilterOp = void 0; (function (RuntimeFilterOp) { /** * Equals */ RuntimeFilterOp["EQ"] = "EQ"; /** * Does not equal */ RuntimeFilterOp["NE"] = "NE"; /** * Less than */ RuntimeFilterOp["LT"] = "LT"; /** * Less than or equal to */ RuntimeFilterOp["LE"] = "LE"; /** * Greater than */ RuntimeFilterOp["GT"] = "GT"; /** * Greater than or equal to */ RuntimeFilterOp["GE"] = "GE"; /** * Contains */ RuntimeFilterOp["CONTAINS"] = "CONTAINS"; /** * Begins with */ RuntimeFilterOp["BEGINS_WITH"] = "BEGINS_WITH"; /** * Ends with */ RuntimeFilterOp["ENDS_WITH"] = "ENDS_WITH"; /** * Between, inclusive of higher value */ RuntimeFilterOp["BW_INC_MAX"] = "BW_INC_MAX"; /** * Between, inclusive of lower value */ RuntimeFilterOp["BW_INC_MIN"] = "BW_INC_MIN"; /** * Between, inclusive of both higher and lower value */ RuntimeFilterOp["BW_INC"] = "BW_INC"; /** * Between, non-inclusive */ RuntimeFilterOp["BW"] = "BW"; /** * Is included in this list of values */ RuntimeFilterOp["IN"] = "IN"; /** * Is not included in this list of values */ RuntimeFilterOp["NOT_IN"] = "NOT_IN"; })(exports.RuntimeFilterOp || (exports.RuntimeFilterOp = {})); /** * Home page module that can be hidden. * **Note**: This option does not apply to the classic homepage. * To access the updated modular homepage, set * `modularHomeExperience` to `true` (available as Early Access feature in 9.12.5.cl). * @version SDK: 1.28.0 | ThoughtSpot: 9.12.5.cl, 10.1.0.sw */ // eslint-disable-next-line no-shadow exports.HomepageModule = void 0; (function (HomepageModule) { /** * Search bar */ HomepageModule["Search"] = "SEARCH"; /** * kPI watchlist module */ HomepageModule["Watchlist"] = "WATCHLIST"; /** * favorite objects */ HomepageModule["Favorite"] = "FAVORITE"; /** * List of answers and Liveboards */ HomepageModule["MyLibrary"] = "MY_LIBRARY"; /** * Trending list */ HomepageModule["Trending"] = "TRENDING"; /** * Learning videos */ HomepageModule["Learning"] = "LEARNING"; })(exports.HomepageModule || (exports.HomepageModule = {})); /** * List page columns that can be hidden. * **Note**: This option is applicable to full app embedding only. * @version SDK: 1.38.0 | ThoughtSpot: 10.9.0.cl */ // eslint-disable-next-line no-shadow exports.ListPageColumns = void 0; (function (ListPageColumns) { /** * Favourite */ ListPageColumns["Favourite"] = "FAVOURITE"; /** * Tags */ ListPageColumns["Tags"] = "TAGS"; /** * Author */ ListPageColumns["Author"] = "AUTHOR"; /** * Last viewed/Last modified */ ListPageColumns["DateSort"] = "DATE_SORT"; /** * Share */ ListPageColumns["Share"] = "SHARE"; })(exports.ListPageColumns || (exports.ListPageColumns = {})); /** * Event types emitted by the embedded ThoughtSpot application. * * To add an event listener use the corresponding * {@link LiveboardEmbed.on} or {@link AppEmbed.on} or {@link SearchEmbed.on} method. * @example * ```js * import { EmbedEvent } from '@thoughtspot/visual-embed-sdk'; * // Or * // const { EmbedEvent } = window.tsembed; * * // create the liveboard embed. * * liveboardEmbed.on(EmbedEvent.Drilldown, (drilldown) => { * console.log('Drilldown event', drilldown); * })); * ``` * * If you are using React components for embedding, you can register to any * events from the `EmbedEvent` list by using the `on<EventName>` convention. * For example,`onAlert`, `onCopyToClipboard` and so on. * @example * ```js * // ... * const MyComponent = ({ dataSources }) => { * const onLoad = () => { * console.log(EmbedEvent.Load, {}); * }; * * return ( * <SearchEmbed * dataSources={dataSources} * onLoad = {logEvent("Load")} * /> * ); * }; * ``` * @group Events */ // eslint-disable-next-line no-shadow exports.EmbedEvent = void 0; (function (EmbedEvent) { /** * Rendering has initialized. * @example *```js * liveboardEmbed.on(EmbedEvent.Init, showLoader) * //show a loader * function showLoader() { * document.getElementById("loader"); * } *``` * @returns timestamp - The timestamp when the event was generated. */ EmbedEvent["Init"] = "init"; /** * Authentication has either succeeded or failed. * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example *```js * appEmbed.on(EmbedEvent.AuthInit, payload => { * console.log('AuthInit', payload); * }) *``` * @returns isLoggedIn - A Boolean specifying whether authentication was successful. */ EmbedEvent["AuthInit"] = "authInit"; /** * The embed object container has loaded. * @returns timestamp - The timestamp when the event was generated. * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example *```js * liveboardEmbed.on(EmbedEvent.Load, hideLoader) * //hide loader * function hideLoader() { * document.getElementById("loader"); * } *``` */ EmbedEvent["Load"] = "load"; /** * Data pertaining to an Answer or Liveboard is received. * The event payload includes the raw data of the object. * @return data - Answer of Liveboard data * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example *```js * liveboardEmbed.on(EmbedEvent.Data, payload => { * console.log('data', payload); * }) *``` * @important */ EmbedEvent["Data"] = "data"; /** * Search query has been updated by the user. * @version SDK: 1.4.0 | ThoughtSpot: ts7.sep.cl, 8.4.1.sw * @example *```js * searchEmbed.on(EmbedEvent.QueryChanged, payload => console.log('data', payload)) *``` */ EmbedEvent["QueryChanged"] = "queryChanged"; /** * A drill-down operation has been performed. * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @returns additionalFilters - Any additional filters applied * @returns drillDownColumns - The columns on which drill down was performed * @returns nonFilteredColumns - The columns that were not filtered * @example *```js * searchEmbed.on(EmbedEvent.DrillDown, { * points: { * clickedPoint, * selectedPoints: selectedPoint * }, * autoDrillDown: true, * }) *``` * In this example, `VizPointDoubleClick` event is used for * triggering the `DrillDown` event when an area or specific * data point on a table or chart is double-clicked. * @example *```js * searchEmbed.on(EmbedEvent.VizPointDoubleClick, (payload) => { * console.log(payload); * const clickedPoint = payload.data.clickedPoint; * const selectedPoint = payload.data.selectedPoints; * console.log('>>> called', clickedPoint); * embed.trigger(HostEvent.DrillDown, { * points: { * clickedPoint, * selectedPoints: selectedPoint * }, * autoDrillDown: true, * }) * }) *``` */ EmbedEvent["Drilldown"] = "drillDown"; /** * One or more data sources have been selected. * @returns dataSourceIds - the list of data sources * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example * ```js * searchEmbed.on(EmbedEvent.DataSourceSelected, payload => { * console.log('DataSourceSelected', payload); * }) * ``` */ EmbedEvent["DataSourceSelected"] = "dataSourceSelected"; /** * One or more data columns have been selected. * @returns columnIds - the list of columns * @version SDK: 1.10.0 | ThoughtSpot: 8.2.0.cl, 8.4.1.sw * @example * ```js * appEmbed.on(EmbedEvent.AddRemoveColumns, payload => { * console.log('AddRemoveColumns', payload); * }) * ``` */ EmbedEvent["AddRemoveColumns"] = "addRemoveColumns"; /** * A custom action has been triggered. * @returns actionId - ID of the custom action * @returns payload {@link CustomActionPayload} - Response payload with the * Answer or Liveboard data * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example * ```js * appEmbed.on(EmbedEvent.customAction, payload => { * const data = payload.data; * if (data.id === 'insert Custom Action ID here') { * console.log('Custom Action event:', data.embedAnswerData); * } * }) * ``` */ EmbedEvent["CustomAction"] = "customAction"; /** * Listen to double click actions on a visualization. * @return ContextMenuInputPoints - Data point that is double-clicked * @version SDK: 1.5.0 | ThoughtSpot: ts7.oct.cl, 7.2.1 * @example * ```js * LiveboardEmbed.on(EmbedEvent.VizPointDoubleClick, payload => { * console.log('VizPointDoubleClick', payload); * }) * ``` */ EmbedEvent["VizPointDoubleClick"] = "vizPointDoubleClick"; /** * Listen to clicks on a visualization in a Liveboard or Search result. * @return viz, clickedPoint - metadata about the point that is clicked * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw * @important * @example * ```js * embed.on(EmbedEvent.VizPointClick, ({data}) => { * console.log( * data.vizId, // viz id * data.clickedPoint.selectedAttributes[0].value, * data.clickedPoint.selectedAttributes[0].column.name, * data.clickedPoint.selectedMeasures[0].value, * data.clickedPoint.selectedMeasures[0].column.name, * ) * }); * ``` */ EmbedEvent["VizPointClick"] = "vizPointClick"; /** * An error has occurred. This event is fired for the following error types: * * `API` - API call failure error. * `FULLSCREEN` - Error when presenting a Liveboard or visualization in full screen * mode. `SINGLE_VALUE_FILTER` - Error due to multiple values in the single value * filter. `NON_EXIST_FILTER` - Error due to a non-existent filter. * `INVALID_DATE_VALUE` - Invalid date value error. * `INVALID_OPERATOR` - Use of invalid operator during filter application. * * For more information, see https://developers.thoughtspot.com/docs/events-app-integration#errorType * @returns error - An error object or message * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example * ```js * // API error * SearchEmbed.on(EmbedEvent.Error, (error) => { * console.log(error); * // { type: "Error", data: { errorType: "API", error: { message: '...', error: '...' } } } * }); * ``` * @example * ```js * // Fullscreen error (Errors during presenting of a liveboard) * LiveboardEmbed.on(EmbedEvent.Error, (error) => { * console.log(error); * // { type: "Error", data: { errorType: "FULLSCREEN", error: { * // message: "Fullscreen API is not enabled", * // stack: "..." * // } }} * }) * ``` */ EmbedEvent["Error"] = "Error"; /** * The embedded object has sent an alert. * @returns alert - An alert object * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 8.4.1.sw * @example * ```js * searchEmbed.on(EmbedEvent.Alert) * ``` */ EmbedEvent["Alert"] = "alert"; /** * The ThoughtSpot authentication session has expired. * @version SDK: 1.4.0 | ThoughtSpot: ts7.sep.cl, 8.4.1.sw * @example *```js * appEmbed.on(EmbedEvent.AuthExpire, showAuthExpired) * //show auth expired banner * function showAuthExpired() { * document.getElementById("authExpiredBanner"); * } *``` */ EmbedEvent["AuthExpire"] = "ThoughtspotAuthExpired"; /** * ThoughtSpot failed to validate the auth session. * @hidden */ EmbedEvent["AuthFailure"] = "ThoughtspotAuthFailure"; /** * ThoughtSpot failed to re validate the auth session. * @hidden */ EmbedEvent["IdleSessionTimeout"] = "IdleSessionTimeout"; /** * ThoughtSpot failed to validate the auth session. * @hidden */ EmbedEvent["AuthLogout"] = "ThoughtspotAuthLogout"; /** * The height of the embedded Liveboard or visualization has been computed. * @returns data - The height of the embedded Liveboard or visualization * @hidden */ EmbedEvent["EmbedHeight"] = "EMBED_HEIGHT"; /** * The center of visible iframe viewport is calculated. * @returns data - The center of the visible Iframe viewport. * @hidden */ EmbedEvent["EmbedIframeCenter"] = "EmbedIframeCenter"; /** * Emitted when the **Get Data** action is initiated. * Applicable to `SearchBarEmbed` only. * @version SDK: 1.19.0 | ThoughtSpot: 9.0.0.cl, 9.0.1.sw * @example *```js * searchbarEmbed.on(EmbedEvent.GetDataClick) * .then(data => { * console.log('Answer Data:', data); * }) *``` */ EmbedEvent["GetDataClick"] = "getDataClick"; /** * Detects the route change. * @version SDK: 1.7.0 | ThoughtSpot: 8.0.0.cl, 8.4.1.sw * @example *```js * searchEmbed.on(EmbedEvent.RouteChange, payload => * console.log('data', payload)) *``` */ EmbedEvent["RouteChange"] = "ROUTE_CHANGE"; /** * The v1 event type for Data * @hidden */ EmbedEvent["V1Data"] = "exportVizDataToParent"; /** * Emitted when the embed does not have cookie access. This happens * when Safari and other Web browsers block third-party cookies * are blocked by default. `NoCookieAccess` can trigger. * @example *```js * appEmbed.on(EmbedEvent.NoCookieAccess) *``` * @version SDK: 1.1.0 | ThoughtSpot: ts7.may.cl, 7.2.1.sw */ EmbedEvent["NoCookieAccess"] = "noCookieAccess"; /** * Emitted when SAML is complete * @private * @hidden */ EmbedEvent["SAMLComplete"] = "samlComplete"; /** * Emitted when any modal is opened in the app * @version SDK: 1.6.0 | ThoughtSpot: ts8.nov.cl, 8.4.1.sw * @example *```js * appEmbed.on(EmbedEvent.DialogOpen, payload => { * console.log('dialog open', payload); * }) *``` */ EmbedEvent["DialogOpen"] = "dialog-open"; /** * Emitted when any modal is closed in the app * @version SDK: 1.6.0 | ThoughtSpot: ts8.nov.cl, 8.4.1.sw * @example *```js * appEmbed.on(EmbedEvent.DialogClose, payload => { * console.log('dialog close', payload); * }) *``` */ EmbedEvent["DialogClose"] = "dialog-close"; /** * Emitted when the Liveboard shell loads. * You can use this event as a hook to trigger * other events on the rendered Liveboard. * @version SDK: 1.9.1 | ThoughtSpot: 8.1.0.cl, 8.4.1.sw * @example *```js * liveboardEmbed.on(EmbedEvent.LiveboardRendered, payload => { console.log('Liveboard is rendered', payload); }) *``` * The following example shows how to trigger * `SetVisibleVizs` event using LiveboardRendered embed event: * @example *```js * const embedRef = useEmbedRef(); * const onLiveboardRendered = () => { * embed.trigger(HostEvent.SetVisibleVizs, ['viz1', 'viz2']); * }; *``` */ EmbedEvent["LiveboardRendered"] = "PinboardRendered"; /** * Emits all events. * @Version SDK: 1.10.0 | ThoughtSpot: 8.2.0.cl, 8.4.1.sw * @example *```js * appEmbed.on(EmbedEvent.ALL, payload => { * console.log('Embed Events', payload) * }) *``` */ EmbedEvent["ALL"] = "*"; /** * Emitted when an Answer is saved in the app * @Version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw * @example *```js * //Emit when action starts * searchEmbed.on(EmbedEvent.Save, payload => { * console.log('Save', payload) * }, { * start: true * }) * //emit when action ends * searchEmbed.on(EmbedEvent.Save, payload => { * console.log('Save', payload) * }) *``` */ EmbedEvent["Save"] = "save"; /** * Emitted when the download action is triggered on an Answer. * * **Note**: This event is deprecated in v1.21.0. * To fire an event when a download action is initiated on a chart or table, * use `EmbedEvent.DownloadAsPng`, `EmbedEvent.DownloadAsPDF`, * `EmbedEvent.DownloadAsCSV`, or `EmbedEvent.DownloadAsXLSX` * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw * @example *```js * liveboardEmbed.on(EmbedEvent.Download, { * vizId: '730496d6-6903-4601-937e-2c691821af3c' * }) *``` */ EmbedEvent["Download"] = "download"; /** * Emitted when the download action is triggered on an Answer. * @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl, 9.4.0.sw * @example *```js * //emit when action starts * searchEmbed.on(EmbedEvent.DownloadAsPng, payload => { * console.log('download PNG', payload)}, {start: true }) * //emit when action ends * searchEmbed.on(EmbedEvent.DownloadAsPng, payload => { * console.log('download PNG', payload)}) *``` */ EmbedEvent["DownloadAsPng"] = "downloadAsPng"; /** * Emitted when the Download as PDF action is triggered on an Answer * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw * @example *```js * //emit when action starts * searchEmbed.on(EmbedEvent.DownloadAsPdf, payload => { * console.log('download PDF', payload)}, {start: true }) * //emit when action ends * searchEmbed.on(EmbedEvent.DownloadAsPdf, payload => { * console.log('download PDF', payload)}) *``` */ EmbedEvent["DownloadAsPdf"] = "downloadAsPdf"; /** * Emitted when the Download as CSV action is triggered on an Answer. * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw * @example *```js * //emit when action starts * searchEmbed.on(EmbedEvent.DownloadAsCSV, payload => { * console.log('download CSV', payload)}, {start: true }) * //emit when action ends * searchEmbed.on(EmbedEvent.DownloadAsCSV, payload => { * console.log('download CSV', payload)}) *``` */ EmbedEvent["DownloadAsCsv"] = "downloadAsCsv"; /** * Emitted when the Download as XLSX action is triggered on an Answer. * @version SDK: 1.11.0 | ThoughtSpot: 8.3.0.cl, 8.4.1.sw * @example *```js * //emit when action starts * searchEmbed.on(EmbedEvent.DownloadAsXlsx, payload => { * console.log('download Xlsx', payload)}, { start: true }) * //