TypeScript and React
Use the official widget types, React component, and hooks from the @senlerio/widget package.
Main section: Public API and Events.
Install the package
The @senlerio/widget package includes API, configuration, and event types, plus a loader. It does not install the UI library or require React for ordinary JavaScript or TypeScript:
npm install https://github.com/SenlerBot/senler-widget/archive/refs/tags/v2.2.0.tar.gz
The SDK requires a loader and iframe that support initialization success and error callbacks (onReady and onError). surfaceVisible, settings selected through resolveRuntime / refreshRuntime, and pageElementActions.navigate require matching loader and iframe support. Installing the package updates types and integration code, but not the hosted loader script or widget application.
import { loadSenlerWidget, type SenlerWidgetInitConfig } from "@senlerio/widget";
const config = { channel_id: "CHANNEL_ID" } satisfies SenlerWidgetInitConfig;
const widget = await loadSenlerWidget({ src: "LOADER_URL_FROM_CABINET" });
widget.init(config);
If the script is already installed manually, import "@senlerio/widget/global" adds types for window.SenlerWidget and window events. Use import type for type-only imports. The loader shares concurrent requests, checks protocol compatibility, and rejects on timeout.
React component
For React 18/19, use the component from a separate entry point in the same package:
import { useMemo } from "react";
import { SenlerWidget } from "@senlerio/widget/react";
export function Chat({ channelId }: { channelId: string }) {
const config = useMemo(() => ({ channel_id: channelId }), [channelId]);
return <SenlerWidget
src="LOADER_URL_FROM_CABINET"
config={config}
containerProps={{ style: { height: 600 } }}
/>;
}
The component creates an embedded container and releases the instance on unmount, including React StrictMode. Use useSenlerWidgetController for an existing container; SenlerWidgetProvider and useSenlerWidget expose the API and loading status to child components. Keep config stable with useMemo so an ordinary render does not recreate the widget. A page supports one instance at a time. Changing retryKey retries loading after an error.
config={null} defers startup, for example until signed user data is available. The controller and useSenlerWidget return { api, status, error }; status is idle, loading, ready, or failed. ready means the chat has initialized and authenticated, not just that the script has loaded.
To change the greeting, language, theme, border radius, shell, surfaceVisible, customActions, their language, autoExecuteCustomActionNames, or pageContextItems, pass runtime to SenlerWidget or SenlerWidgetProvider. This updates the current instance without another init:
<SenlerWidget
src="LOADER_URL_FROM_CABINET"
config={config}
runtime={{ lang: "ru", theme_mode: "dark", border_radius: 16 }}
containerProps={{ style: { height: 600 } }}
/>
Run one-shot commands, including sending a message or selecting a dialog, through api.open(...), api.updateRuntime(...), or api.selectDialog(...) in a user-action handler. They are excluded from the runtime prop to prevent a render from sending the message again. The standalone useSenlerWidgetController does not accept runtime: update settings through its returned api.