import ' rollup-plugin-inject-process-env';
import { WidgetEnv } from "@xapp/stentor-chat-widget";
import { FC } from "react";
import { MessageMiddleware } from "../../middlewares";
import { CONNECTION_STATUS_TYPE } from "../../store/ChatAction";
import "./ChatWidget.scss";
/**
* Preview message structure for preview mode.
* Allows rendering sample messages with suggestions and lists.
*
* **Important:** At least one of `displayText` or `html` should be provided for
* the message to render content. Messages without both fields will render empty.
*/
export interface PreviewMessage {
/**
* The main text to display in the message bubble.
* If neither displayText nor html is provided, the message will render empty.
*/
readonly displayText?: string;
/**
* HTML content to render in the message bubble.
* Takes precedence over displayText if both are provided.
*
* **Security Warning:** This field renders raw HTML without sanitization.
* Only use with trusted content. If preview messages may come from untrusted
* sources (user input, external APIs), sanitize the HTML using a library
* like DOMPurify before passing it to this field.
*
* @example
* ```tsx
* // Safe: hardcoded content
* { html: "Welcome!" }
*
* // Unsafe without sanitization: external content
* // import DOMPurify from 'dompurify';
* // { html: DOMPurify.sanitize(untrustedContent) }
* ```
*/
readonly html?: string;
/**
* Suggestion chips to display below the message.
* Suggestions without URLs will use "#" as a fallback to prevent navigation.
*/
readonly suggestions?: ReadonlyArray<{
readonly title: string;
/**
* URL to navigate to when the suggestion is clicked.
* Defaults to "#" if not provided.
*/
readonly url?: string;
}>;
/**
* List or carousel to display with the message.
* Note: The `description` field maps to `subTitle` in the internal representation.
*/
readonly list?: {
readonly type: "LIST" | "CAROUSEL";
readonly title?: string;
readonly items: ReadonlyArray<{
readonly title: string;
/**
* Description text shown below the title.
* Internally mapped to `subTitle` in ChatServerListItem.
*/
readonly description?: string;
readonly url?: string;
readonly imageUrl?: string;
/**
* When true, hides the URL text and external link icon while
* still allowing the item to be clickable.
*/
readonly hideUrl?: boolean;
}>;
};
}
/**
* Props for the ChatWidget component.
*
* This interface defines all available configuration options for the chat widget,
* including display modes, configuration loading strategies, and event callbacks.
*/
export interface ChatWidgetProps {
/**
* Enable pre-chat form before starting the conversation.
* When enabled, users must fill out a form (name, email, etc.) before accessing chat.
*
* @default false
* @example
* ```tsx
*
* ```
*/
readonly preChatFormEnabled?: boolean;
/**
* Widget environment configuration containing server connection details, theme, and behavior settings.
*
* This is the primary configuration object that defines how the widget connects to your backend,
* how it appears visually, and how it behaves. Can be provided directly or via the `getConfig` callback.
*
* **Note:** If both `config` and `getConfig` are provided, `getConfig` takes precedence.
*
* @see WidgetEnv for the full configuration schema
* @example
* ```tsx
* const config: WidgetEnv = {
* connection: {
* serverUrl: 'wss://chat.example.com',
* type: 'websocketraw'
* },
* channelId: 'support-channel',
* theme: {
* header: { background: { color: '#007AFF' } }
* }
* };
*
*
* ```
*/
readonly config?: WidgetEnv;
/**
* Display mode for the widget.
*
* - **`'normal'`** (default): Floating chat button that expands into a chat window.
* User can minimize/maximize. Best for desktop websites.
*
* - **`'docked'`**: Always visible, docked to the side or bottom of the screen.
* Cannot be minimized. Best for mobile apps and WebViews.
*
* - **`'static'`**: Embedded inline in the page content, takes up fixed space.
* Cannot be minimized or moved. Best for dedicated chat pages.
*
* @default 'normal'
* @example
* ```tsx
* // Docked mode for mobile
*
*
* // Static mode for dedicated chat page
*
* ```
*/
readonly mode?: ChatWidgetMode;
/**
* Enable preview mode for displaying static sample messages without server connections.
*
* When `true`, the widget renders in a read-only state with:
* - No server connection attempts
* - Static messages from `previewMessages` prop
* - Disabled input and interactions
*
* Can be combined with any `mode` for different visual layouts:
* - `mode="docked" preview` - Docked layout with preview data
* - `mode="static" preview` - Static layout with preview data
* - `mode="normal" preview` - Floating layout with preview data
*
* @default false
* @example
* ```tsx
* // Docked preview for settings page
*
* ```
*/
readonly preview?: boolean;
/**
* Custom middleware for processing and transforming chat messages before rendering.
*
* Middleware allows you to intercept messages and render custom components for specific
* message types or modify message content. Useful for adding custom UI elements,
* formatting, or handling special message types.
*
* @see MessageMiddleware
* @example
* ```tsx
* const customMiddleware = (next) => (props) => {
* const { msg } = props;
*
* // Handle custom message type
* if (msg.type === 'SPECIAL_CARD') {
* return ;
* }
*
* // Pass to next middleware
* return next(props);
* };
*
*
* ```
*/
readonly messageMiddleware?: MessageMiddleware;
/**
* Callback fired when the connection status changes.
*
* Use this to monitor the widget's connection state and display custom UI or
* handle connection issues. Connection status changes throughout the widget lifecycle
* as it connects, disconnects, reconnects, or encounters errors.
*
* @param status - Current connection status
* - `'online'`: Successfully connected to server
* - `'offline'`: Disconnected from server
* - `'pending'`: Connecting or reconnecting (loading state)
*
* @example
* ```tsx
* const [status, setStatus] = useState('pending');
*
* {
* setStatus(newStatus);
* if (newStatus === 'offline') {
* alert('Chat is currently unavailable');
* }
* }}
* />
* ```
*/
onConnectionStatusChange?(status: CONNECTION_STATUS_TYPE): void;
/**
* Optional async callback to load configuration dynamically.
*
* When provided, the widget will wait for this Promise to resolve before initializing.
* This prevents race conditions where the widget attempts to connect before configuration
* is available. Particularly useful for:
*
* - **React Native apps**: Where props may propagate with delays across the native bridge
* - **API-based config**: When configuration needs to be fetched from a server
* - **Dynamic config**: When config depends on user authentication or other async operations
* - **Native modules**: When waiting for React Native native modules to initialize
*
* While the Promise is pending, the widget displays a loading spinner. If the Promise
* rejects, an error message is shown to the user.
*
* **Important:** If both `config` and `getConfig` are provided, `getConfig` takes precedence
* and the `config` prop is ignored.
*
* @returns Promise that resolves to the WidgetEnv configuration
* @throws Error if configuration cannot be loaded (will be displayed to user)
*
* @example
* ```tsx
* // Basic usage - fetch from API
* {
* const response = await fetch('/api/chat-config');
* return response.json();
* }}
* />
* ```
*
* @example
* ```tsx
* // React Native - wait for native module
* import { NativeModules } from 'react-native';
*
* {
* await NativeModules.ChatModule.initialize();
* return await NativeModules.ChatModule.getConfig();
* }}
* />
* ```
*
* @example
* ```tsx
* // Wait for authentication with error handling
* {
* // Wait for auth
* while (!window.auth?.user) {
* await new Promise(resolve => setTimeout(resolve, 100));
* }
*
* // Fetch config with user context
* try {
* const config = await fetchConfigForUser(window.auth.user);
* return config;
* } catch (error) {
* throw new Error('Failed to load chat configuration. Please try again.');
* }
* }}
* />
* ```
*
* @example
* ```tsx
* // With timeout protection
* {
* const timeout = new Promise((_, reject) =>
* setTimeout(() => reject(new Error('Config load timeout')), 10000)
* );
*
* const configPromise = fetch('/api/config').then(r => r.json());
*
* return Promise.race([configPromise, timeout]);
* }}
* />
* ```
*/
getConfig?(): Promise;
/**
* Disable automatic scrolling behavior when messages change.
*
* When enabled, prevents the widget from scrolling to the bottom when new messages
* arrive or when the component mounts. This is particularly useful for:
*
* - **Embedded preview contexts**: When the widget is used as a static preview in settings pages
* - **Multi-widget pages**: When multiple widgets are on the same page
* - **Custom scroll control**: When you want to manage scrolling behavior externally
*
* @default false
* @example
* ```tsx
* // Use in an embedded preview
*
* ```
*/
readonly disableAutoScroll?: boolean;
/**
* Preview messages to display when mode="preview".
*
* Array of sample messages to show in preview mode. Each message can include
* text, HTML, suggestion chips, and lists. Only applies when mode is set to "preview".
*
* @example
* ```tsx
*
* ```
*/
readonly previewMessages?: readonly PreviewMessage[];
}
/**
* Props for ChatWidgetWrapper component.
* Extends ChatWidgetProps with the same interface.
*/
export interface ChatWidgetWrapperProps extends ChatWidgetProps {
}
/**
* Display modes for the chat widget (visual layout).
*
* - **`'normal'`**: Default floating button mode - chat button appears as a floating action button,
* clicking it opens the chat window. User can minimize/maximize the window.
*
* - **`'docked'`**: Always-visible docked mode - widget is permanently visible and docked to the
* side or bottom of the screen. Cannot be minimized. Ideal for mobile apps and WebViews.
*
* - **`'static'`**: Static embedded mode - widget is embedded inline in the page content as a
* fixed element. Cannot be minimized or repositioned. Ideal for dedicated chat pages.
*
* - **`'preview'`**: (Deprecated) Shorthand for `mode="static" preview={true}`.
* Prefer using the `preview` prop with any mode for clearer intent.
*
* @see {@link ChatWidgetProps.preview} for enabling preview mode with any layout.
*/
export type ChatWidgetMode = "normal" | "docked" | "static" | "preview";
/**
* Inner ChatWidget component that renders the actual UI.
* Exported for use by StaticChatWidgetContainer to avoid infinite loops.
*/
export declare const ChatWidgetUI: FC;
/**
* Top-level wrapper that dispatches between preview mode and connected mode.
* This separation ensures React hooks rules are not violated.
*/
declare const ChatWidgetWrapper: FC;
export default ChatWidgetWrapper;