/** * @license * Copyright 2023 Nuraly, Laabidi Aymen * SPDX-License-Identifier: MIT */ import { LitElement, TemplateResult } from 'lit'; import { ChatbotMessage, ChatbotSuggestion, ChatbotSize, ChatbotVariant, ChatbotLoadingType, ChatbotThread, ChatbotModule, ChatbotFile, ChatbotAction, ChatbotArtifact, ChatbotI18nOverrides } from './chatbot.types.js'; import { ChatbotCoreController } from './core/chatbot-core.controller.js'; declare const NrChatbotElement_base: (new (...args: any[]) => import("@nuralyui/common/mixins").DependencyAware) & (new (...args: any[]) => import("@nuralyui/common/mixins").ThemeAware) & (new (...args: any[]) => import("@nuralyui/common/mixins").EventHandlerCapable) & (new (...args: any[]) => import("packages/common/src/shared/base-mixin.js").LightDomContent) & typeof LitElement; /** * Enhanced chatbot component powered by ChatbotCoreController. * * Requires an external ChatbotCoreController to function. * * @example With ChatbotCoreController * ```javascript * import { ChatbotCoreController, OpenAIProvider } from '@nuraly/chatbot'; * * const controller = new ChatbotCoreController({ * provider: new OpenAIProvider(), * ui: { * onStateChange: (state) => { * chatbot.messages = state.messages; * chatbot.threads = state.threads; * }, * onTypingStart: () => chatbot.isBotTyping = true, * onTypingEnd: () => chatbot.isBotTyping = false * } * }); * * chatbot.controller = controller; * ``` * * @fires nr-chatbot-message-sent - Message sent by user * @fires nr-chatbot-input-changed - Input value changed */ export declare class NrChatbotElement extends NrChatbotElement_base { static useShadowDom: boolean; static styles: import("lit").CSSResult; requiredComponents: string[]; /** Array of chat messages (synced from controller) */ messages: ChatbotMessage[]; /** Current input value */ currentInput: string; /** Bot typing indicator state */ isBotTyping: boolean; /** Query running state (for stop button) */ isQueryRunning: boolean; /** Array of suggestion objects */ suggestions: ChatbotSuggestion[]; /** Whether chat has started */ chatStarted: boolean; /** Right-to-left text direction */ isRTL: boolean; /** Chatbot size variant */ size: ChatbotSize; /** Chatbot visual variant */ variant: ChatbotVariant; /** Loading indicator type */ loadingIndicator: ChatbotLoadingType; /** Loading text message */ loadingText: string; /** Disable input and interactions */ disabled: boolean; /** Custom placeholder text */ placeholder: string; /** * Override any UI string. Falls back to the default * (from `@lit/localize`) when a key or section is omitted. */ i18n?: ChatbotI18nOverrides; /** Show send button */ showSendButton: boolean; /** Auto-scroll to new messages */ autoScroll: boolean; /** Show thread sidebar */ showThreads: boolean; /** Enable creation of new threads */ enableThreadCreation: boolean; /** Array of conversation threads */ threads: ChatbotThread[]; /** * Currently active thread ID. Set this from a route loader to pre-select a * conversation; when a controller is attached, the chatbot will call * `controller.switchThread(activeThreadId)` to load that thread's messages. * Emits an `nr-thread-change` event when the active thread changes via the * sidebar (so a router can sync the URL back). */ activeThreadId?: string; /** Chatbot mode (chat, assistant, etc.) */ mode: string; /** Enable boxed layout for large widths (ChatGPT-style) */ boxed: boolean; /** * When true, the chatbot listens to `hashchange` and feeds the * `#conversation/` hash into `activeThreadId` (so back/forward * navigation switches threads). The chatbot itself never writes to * `window.location` — wire `nr-thread-change` to your router for that. */ enableUrlSync: boolean; /** Show messages area (set to false for input-only mode) */ showMessages: boolean; /** Welcome heading shown in the empty state. Overridden by a slotted `empty-state` child if provided. */ welcomeMessage?: string; /** Enable file upload functionality */ enableFileUpload: boolean; /** * Allowed file types for upload validation. Each entry is either a MIME * type (`application/pdf`), a MIME wildcard (`image/*`), or an extension * (`.docx`). When unset, the chatbot reads `controller.config.allowedFileTypes`. * When neither is set, any file type is accepted. */ allowedFileTypes?: string[]; /** * Maximum file size in bytes. Files larger than this are rejected with a * visible error pill. When unset, the chatbot reads * `controller.config.maxFileSize`. When neither is set, no size limit applies. */ maxFileSize?: number; private _fileRejectionMessage?; private _fileRejectionTimer?; /** Uploaded files (synced from controller) */ uploadedFiles: ChatbotFile[]; /** Action buttons configuration. `enableFileUpload` unions an attach entry into the resolved list unless one is already present. */ actionButtons: ChatbotAction[]; get resolvedActionButtons(): ChatbotAction[]; /** Enable module selection dropdown */ enableModuleSelection: boolean; /** Available modules for selection */ modules: ChatbotModule[]; /** Selected module IDs (for multi-select) */ selectedModules: string[]; /** Module selection label */ moduleSelectionLabel: string; /** Enable artifact mode: code blocks collapse into cards with a preview panel */ enableArtifacts: boolean; /** Show the mic button to record a voice message */ showAudioButton: boolean; /** * Callback fired after recording stops and the blob is compressed. * Consumer is responsible for upload / transcription. */ onAudioRecorded?: (blob: Blob, mimeType: string, duration: string, mode: 'transcribe' | 'message') => void; /** Optional custom renderer for artifact panel content area. Header remains default. */ renderArtifactContent?: (artifact: ChatbotArtifact) => TemplateResult; /** * ChatbotCoreController instance (REQUIRED). * The component delegates all business logic to this controller. */ controller: ChatbotCoreController; private statusText?; private focused; private isArtifactPanelOpen; private selectedArtifact; private isThreadSidebarOpen; private _editingThreadId?; private isUrlModalOpen; private urlInput; private urlModalError; private isUrlLoading; private selectedUrlFileName; private isFilePreviewModalOpen; private previewFile; private _isDragging; private _dragDepth; private controllerUnsubscribes; private _audio; private _audioMode; private _artifactResizeBound; private _artifactResizeCleanup?; private _hashChangeHandler?; /** Convert modules to select options */ private get moduleSelectOptions(); connectedCallback(): void; firstUpdated(): void; disconnectedCallback(): void; updated(changedProperties: Map): void; /** * Scroll messages container to the bottom to show the latest message */ private scrollToLatestMessage; private setupControllerIntegration; private cleanupControllerIntegration; /** * Wire up the hashchange listener for URL sync. * Safe to call multiple times — will not duplicate listeners. */ private setupUrlSync; /** * Remove the hashchange listener for URL sync. */ private teardownUrlSync; private handleHashChange; private _pendingThreadId?; private _expandedMessageIds; private _loadingMessages; /** * Character count above which a user message is collapsed with a "Show more" * toggle and a bubble-colored gradient. Set to 0 to disable. Default 600. */ messageCollapseThreshold: number; /** * Anchor the messages column to the bottom. New messages stay at the bottom * automatically (browser-native scroll anchoring via flex-direction column-reverse). * When the user scrolls up to read history, new arriving messages do not pull * them back down. Implies that auto-scroll JS is skipped. */ invertedScroll: boolean; private syncActiveThreadToController; private handleControllerStateChange; private handleControllerMessageSent; private handleControllerMessageReceived; private handleControllerError; private get resolvedI18n(); render(): TemplateResult<1>; private renderModuleSelectedDisplay; private toggleThreadSidebar; private handleContentEditableInput; private handleInputFocus; private handleInputBlur; private clearInput; /** * Focus the input element (called by controller via UI callback) */ focusInput(): void; private handleAudioStart; private handleAudioCancel; private handleAudioSend; private handleKeyDown; private handleSendMessage; private handleStopQuery; private handleRetry; private handleCopyMessage; /** * Fallback copy method for non-secure contexts where navigator.clipboard is unavailable. * Uses a hidden textarea + execCommand('copy') which, while deprecated, is the only * option when the Clipboard API is not available (HTTP origins, older browsers). */ private copyViaFallback; private handleSuggestionClick; private handleModuleSelectionChange; private handleFileDropdownClick; private resolvedAllowedFileTypes; private openFileDialog; private openUrlModal; private handleUrlModalClose; private handleUrlInputChange; private handleUrlInputKeydown; private handleUrlConfirm; private handleUrlAttachFile; private handleFileRemove; private dragHasFiles; private handleDragEnter; private handleDragOver; private handleDragLeave; private handleDrop; private partitionAcceptedFiles; private fileRejectionReason; private showFileRejection; private dismissFileRejection; private handleFilePreview; private handleArtifactClick; private handleArtifactPanelClose; /** Attach drag-to-resize on the artifact panel's left edge handle. */ private updateArtifactPanelResize; private handleArtifactCopy; private getArtifactPlugin; /** * Look through registered plugins for one that provides renderArtifactContent. * Returns a TemplateResult wrapper if found, undefined otherwise. * The wrapper returns undefined for artifacts the plugin doesn't handle, * so the template falls back to the default renderer. */ private getPluginArtifactRenderer; private handleFilePreviewModalClose; /** * Public API: Add a message to the chat */ addMessage(message: Partial): ChatbotMessage; /** * Public API: Clear all messages */ clearMessages(): void; } declare global { interface HTMLElementTagNameMap { 'nr-chatbot': NrChatbotElement; } } export {}; //# sourceMappingURL=chatbot.component.d.ts.map