@thoughtspot/visual-embed-sdk
Version:
ThoughtSpot Embed SDK
420 lines • 15.3 kB
JavaScript
'use client';
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ListPageColumns = exports.getSessionInfo = exports.LogLevel = exports.HomepageModule = exports.HomeLeftNavItem = exports.Action = exports.HostEvent = exports.EmbedEvent = exports.RuntimeFilterOp = exports.Page = exports.useSpotterAgent = exports.useInit = exports.useEmbedRef = exports.PreRenderedConversationEmbed = exports.SpotterMessage = exports.ConversationMessage = exports.ConversationEmbed = exports.SpotterEmbed = exports.PreRenderedSageEmbed = exports.SageEmbed = exports.PreRenderedSearchBarEmbed = exports.SearchBarEmbed = exports.PreRenderedPinboardEmbed = exports.PreRenderedLiveboardEmbed = exports.PinboardEmbed = exports.LiveboardEmbed = exports.PreRenderedAppEmbed = exports.AppEmbed = exports.PreRenderedSearchEmbed = exports.SearchEmbed = void 0;
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importStar(require("react"));
const use_deep_compare_effect_1 = tslib_1.__importDefault(require("use-deep-compare-effect"));
const utils_1 = require("../utils");
const search_bar_1 = require("../embed/search-bar");
const sage_1 = require("../embed/sage");
const search_1 = require("../embed/search");
const app_1 = require("../embed/app");
const liveboard_1 = require("../embed/liveboard");
const bodyless_conversation_1 = require("../embed/bodyless-conversation");
const util_1 = require("./util");
const conversation_1 = require("../embed/conversation");
const base_1 = require("../embed/base");
const errors_1 = require("../errors");
const componentFactory = (EmbedConstructor,
// isPreRenderedComponent: Specifies whether the component being returned is
// intended for preRendering. If set to true, the component will call the
// Embed.preRender() method instead of the usual render method, and it will
// not be destroyed when the component is unmounted.
isPreRenderedComponent = false) => react_1.default.forwardRef((props, forwardedRef) => {
const ref = react_1.default.useRef(null);
const { className, style, ...embedProps } = props;
const { viewConfig, listeners } = (0, util_1.getViewPropsAndListeners)(embedProps);
const handleDestroy = (tsEmbed) => {
// do not destroy if it is a preRender component
if (isPreRenderedComponent)
return;
// if component is connected to a preRendered component
if (props.preRenderId) {
tsEmbed.hidePreRender();
return;
}
tsEmbed.destroy();
};
const handlePreRenderRendering = (tsEmbed) => {
tsEmbed.preRender();
};
const handleDefaultRendering = (tsEmbed) => {
// if component is connected to a preRendered component
if (props.preRenderId) {
tsEmbed.showPreRender();
return;
}
tsEmbed.render();
};
const handleRendering = (tsEmbed) => {
if (isPreRenderedComponent) {
handlePreRenderRendering(tsEmbed);
return;
}
handleDefaultRendering(tsEmbed);
};
(0, use_deep_compare_effect_1.default)(() => {
const tsEmbed = new EmbedConstructor(ref.current, (0, utils_1.deepMerge)({
insertAsSibling: viewConfig.insertAsSibling,
frameParams: {
class: viewConfig.insertAsSibling ? className || '' : '',
},
}, viewConfig));
Object.keys(listeners).forEach((eventName) => {
tsEmbed.on(eventName, listeners[eventName]);
});
handleRendering(tsEmbed);
if (forwardedRef) {
// eslint-disable-next-line no-param-reassign
forwardedRef.current = tsEmbed;
}
return () => {
handleDestroy(tsEmbed);
};
}, [viewConfig, listeners]);
return viewConfig.insertAsSibling ? (react_1.default.createElement("span", { "data-testid": "tsEmbed", ref: ref, style: { position: 'absolute' } })) : (react_1.default.createElement("div", { "data-testid": "tsEmbed", ref: ref, style: style, className: `ts-embed-container ${className}` }));
});
/**
* React component for Search Embed.
* @example
* ```tsx
* function Search() {
* return <SearchEmbed
* dataSource="dataSourceId"
* searchOptions={{ searchTokenString: "[revenue]" }}
* />
* }
* ```
*/
exports.SearchEmbed = componentFactory(search_1.SearchEmbed);
exports.PreRenderedSearchEmbed = componentFactory(search_1.SearchEmbed, true);
/**
* React component for Full app Embed.
* @example
* ```tsx
* function Search() {
* return <AppEmbed
* showPrimaryNavbar={false}
* pageId={Page.Liveboards}
* onError={(error) => console.error(error)}
* />
* }
* ```
*/
exports.AppEmbed = componentFactory(app_1.AppEmbed);
/**
* React component for PreRendered Liveboard embed.
*
* PreRenderedAppEmbed will preRender the SearchBarEmbed and will be hidden by
* default.
*
* AppEmbed with preRenderId passed will call showPreRender on the embed.
* @example
* ```tsx
* function LandingPageComponent() {
* return <PreRenderedAppEmbed preRenderId="someId" showPrimaryNavbar={false} />
* }
* ```
* function MyComponent() {
* return <AppEmbed preRenderId="someId" showPrimaryNavbar={false} />
* }
* ```
*/
exports.PreRenderedAppEmbed = componentFactory(app_1.AppEmbed, true);
/**
* React component for Liveboard embed.
* @example
* ```tsx
* function Liveboard() {
* return <LiveboardEmbed
* liveboardId="liveboardId"
* fullHeight={true} {/* default false *\/}
* onLiveboardRendered={() => console.log('Liveboard rendered')}
* vizId="vizId" {/* if doing viz embed *\/}
* />
* }
* ```
*/
exports.LiveboardEmbed = componentFactory(liveboard_1.LiveboardEmbed);
exports.PinboardEmbed = exports.LiveboardEmbed;
/**
* React component for PreRendered Liveboard embed.
*
* PreRenderedLiveboardEmbed will preRender the liveboard and will be hidden by default.
*
* LiveboardEmbed with preRenderId passed will call showPreRender on the embed.
*
* If LiveboardEmbed is rendered before PreRenderedLiveboardEmbed is rendered it
* tries to preRender the LiveboardEmbed, so it is recommended to use pass the
* liveboardId to both the components.
* @example
* ```tsx
* function LandingPageComponent() {
* return <PreRenderedLiveboardEmbed preRenderId="someId" liveboardId="libId" />
* }
* ```
* function MyComponent() {
* return <LiveboardEmbed preRenderId="someId" liveboardId="libId" />
* }
* ```
*/
exports.PreRenderedLiveboardEmbed = componentFactory(liveboard_1.LiveboardEmbed, true);
exports.PreRenderedPinboardEmbed = exports.PreRenderedLiveboardEmbed;
/**
* React component for Search bar embed.
* @example
* ```tsx
* function SearchBar() {
* return <SearchBarEmbed
* dataSource="dataSourceId"
* searchOptions={{ searchTokenString: "[revenue]" }}
* />
* }
* ```
*/
exports.SearchBarEmbed = componentFactory(search_bar_1.SearchBarEmbed);
/**
* React component for PreRendered Liveboard embed.
*
* PreRenderedSearchBarEmbed will preRender the SearchBarEmbed and will be hidden by
* default.
*
* SearchBarEmbed with preRenderId passed will call showPreRender on the embed.
* @example
* ```tsx
* function LandingPageComponent() {
* return <PreRenderedSearchBarEmbed preRenderId="someId" dataSource="dataSourceId" />
* }
* ```
* function MyComponent() {
* return <SearchBarEmbed preRenderId="someId" dataSource="dataSourceId" />
* }
* ```
*/
exports.PreRenderedSearchBarEmbed = componentFactory(search_bar_1.SearchBarEmbed, true);
/**
* React component for LLM based search Sage embed.
* @example
* ```tsx
* function Sage() {
* return <SageEmbed
* showObjectResults={true}
* ... other view config props or event listeners.
* />
* }
* ```
*/
exports.SageEmbed = componentFactory(sage_1.SageEmbed);
/**
* React component for PreRendered Liveboard embed.
*
* PreRenderedSageEmbed will preRender the SearchBarEmbed and will be hidden by
* default.
*
* SageEmbed with preRenderId passed will call showPreRender on the embed.
* @example
* ```tsx
* function LandingPageComponent() {
* return <PreRenderedSageEmbed preRenderId="someId" showObjectResults={true} />
* }
* ```
* function MyComponent() {
* return <SageEmbed preRenderId="someId" showObjectResults={true} />
* }
* ```
*/
exports.PreRenderedSageEmbed = componentFactory(sage_1.SageEmbed, true);
/**
* React component for LLM based conversation BI.
* @example
* ```tsx
* function Sage() {
* return <SpotterEmbed
* worksheetId="<worksheet-id-here>"
* searchOptions={{
* searchQuery: "<search query to start with>"
* }}
* ... other view config props or event listeners.
* />
* }
* ```
*/
exports.SpotterEmbed = componentFactory(conversation_1.SpotterEmbed);
/**
* React component for LLM based conversation BI.
* @deprecated from SDK: 1.39.0 | ThoughtSpot: 10.10.0.cl
* Use {@link SpotterEmbed} instead
* @example
* ```tsx
* function Sage() {
* return <ConversationEmbed
* worksheetId="<worksheet-id-here>"
* searchOptions={{
* searchQuery: "<search query to start with>"
* }}
* ... other view config props or event listeners.
* />
* }
* ```
*/
exports.ConversationEmbed = componentFactory(conversation_1.ConversationEmbed);
exports.ConversationMessage = componentFactory(bodyless_conversation_1.ConversationMessage);
/**
* React component for displaying individual conversation messages from SpotterAgent.
*
* This component renders a single message response from your ThoughtSpot conversation,
* showing charts, visualizations, or text responses based on the user's query.
*
* @example
* ```tsx
* const { sendMessage } = useSpotterAgent({ worksheetId: 'worksheetId' });
* const result = await sendMessage('show me sales by region');
*
* if (!result.error) {
* // Simple usage - just pass the message data
* <SpotterMessage message={result.message} />
*
* // With optional query for context
* <SpotterMessage
* message={result.message}
* query={result.query}
* />
* }
* ```
* @version SDK: 1.39.0 | ThoughtSpot: 10.11.0.cl
*/
exports.SpotterMessage = react_1.default.forwardRef((props, ref) => {
const { message, query: _, ...otherProps } = props;
return (react_1.default.createElement(exports.ConversationMessage, { ref: ref, ...message, ...otherProps }));
});
/**
* React component for PreRendered Conversation embed.
*
* PreRenderedConversationEmbed will preRender the SpotterEmbed and will be hidden by
* default.
*
* SageEmbed with preRenderId passed will call showPreRender on the embed.
* @example
* ```tsx
* function LandingPageComponent() {
* return <PreRenderedConversationEmbed preRenderId="someId" worksheetId={"id-"} />
* }
* ```
* function MyComponent() {
* return <SpotterEmbed preRenderId="someId" worksheetId="id" />
* }
* ```
*/
exports.PreRenderedConversationEmbed = componentFactory(conversation_1.SpotterEmbed, true);
/**
* Get a reference to the embed component to trigger events on the component.
* @example
* ```
* function Component() {
* const ref = useEmbedRef();
* useEffect(() => {
* ref.current.trigger(
* EmbedEvent.UpdateRuntimeFilter,
* [{ columnName: 'name', operator: 'EQ', values: ['value']}]);
* }, [])
* return <LiveboardEmbed ref={ref} liveboardId={<id>} />
* }
* ```
* @returns {React.MutableRefObject<T extends TsEmbed>} ref
*/
function useEmbedRef() {
return react_1.default.useRef(null);
}
exports.useEmbedRef = useEmbedRef;
/**
*
* @param config - EmbedConfig
* @returns AuthEventEmitter
* @example
* ```
* function Component() {
* const authEE = useInit({ ...initConfig });
* return <LiveboardEmbed ref={ref} liveboardId={<id>} />
* }
* ```
* @version SDK: 1.36.2 | ThoughtSpot: *
*/
function useInit(config) {
const ref = (0, react_1.useRef)(null);
(0, use_deep_compare_effect_1.default)(() => {
const authEE = (0, base_1.init)(config);
ref.current = authEE;
}, [config]);
return ref;
}
exports.useInit = useInit;
/**
* React hook for interacting with SpotterAgent AI conversations.
*
* This hook provides a sendMessage function that allows you to send natural language
* queries to your data and get back AI-generated responses with visualizations.
*
* @param config - Configuration object containing worksheetId and other options
* @returns Object with sendMessage function that returns conversation results
* @example
* ```tsx
* const { sendMessage } = useSpotterAgent({ worksheetId: 'worksheetId' });
*
* const handleQuery = async () => {
* const result = await sendMessage('show me sales by region');
*
* if (!result.error) {
* // Display the message response
* <SpotterMessage message={result.message} />
* } else {
* console.error('Error:', result.error);
* }
* };
* ```
* @version SDK: 1.39.0 | ThoughtSpot: 10.11.0.cl
*/
function useSpotterAgent(config) {
const serviceRef = (0, react_1.useRef)(null);
(0, use_deep_compare_effect_1.default)(() => {
if (serviceRef.current) {
serviceRef.current = null;
}
serviceRef.current = new bodyless_conversation_1.SpotterAgentEmbed(config);
return () => {
serviceRef.current = null;
};
}, [config]);
const sendMessage = (0, react_1.useCallback)(async (query) => {
if (!serviceRef.current) {
return { error: new Error(errors_1.ERROR_MESSAGE.SPOTTER_AGENT_NOT_INITIALIZED) };
}
const result = await serviceRef.current.sendMessageData(query);
if (result.error) {
return { error: result.error };
}
return {
query: query,
message: {
...result.data,
worksheetId: config.worksheetId,
},
};
}, [config.worksheetId]);
return {
sendMessage,
};
}
exports.useSpotterAgent = useSpotterAgent;
var index_1 = require("../index");
Object.defineProperty(exports, "Page", { enumerable: true, get: function () { return index_1.Page; } });
Object.defineProperty(exports, "RuntimeFilterOp", { enumerable: true, get: function () { return index_1.RuntimeFilterOp; } });
Object.defineProperty(exports, "EmbedEvent", { enumerable: true, get: function () { return index_1.EmbedEvent; } });
Object.defineProperty(exports, "HostEvent", { enumerable: true, get: function () { return index_1.HostEvent; } });
Object.defineProperty(exports, "Action", { enumerable: true, get: function () { return index_1.Action; } });
Object.defineProperty(exports, "HomeLeftNavItem", { enumerable: true, get: function () { return index_1.HomeLeftNavItem; } });
Object.defineProperty(exports, "HomepageModule", { enumerable: true, get: function () { return index_1.HomepageModule; } });
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return index_1.LogLevel; } });
Object.defineProperty(exports, "getSessionInfo", { enumerable: true, get: function () { return index_1.getSessionInfo; } });
Object.defineProperty(exports, "ListPageColumns", { enumerable: true, get: function () { return index_1.ListPageColumns; } });
//# sourceMappingURL=index.js.map